changeset 19603:9b90d8579c61

maint: Periodic merge of gui-release to default.
author Rik <rik@octave.org>
date Mon, 12 Jan 2015 09:17:35 -0800
parents c36c22808d11 (diff) f88ee85d4da9 (current diff)
children 62ca016dbb2a
files libgui/src/history-dock-widget.cc scripts/plot/util/private/__ghostscript__.m scripts/plot/util/private/__print_parse_opts__.m
diffstat 1102 files changed, 47324 insertions(+), 20983 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile.am	Mon Jan 12 09:13:19 2015 -0800
+++ b/Makefile.am	Mon Jan 12 09:17:35 2015 -0800
@@ -129,6 +129,11 @@
 check: all
 	$(MAKE) -C test check
 
+if AMCOND_HAVE_LLVM
+check-jit: all
+	$(MAKE) -C test check-jit
+endif
+
 run-octave: run-octave.in Makefile
 	@$(do_subst_script_vals)
 	chmod a+rx "$@"
--- a/NEWS	Mon Jan 12 09:13:19 2015 -0800
+++ b/NEWS	Mon Jan 12 09:17:35 2015 -0800
@@ -1,3 +1,210 @@
+Summary of important user-visible changes for version 4.2:
+---------------------------------------------------------
+
+ ** A new syntax for object oriented programming termed classdef has been
+    introduced.  See the manual for more extensive documentation of the
+    classdef interface.
+
+    New keywords:
+
+      classdef      endclassdef
+      enumeration   endenumeration
+      events        endevents
+      methods       endmethods
+      properties    endproperties
+
+ ** New audio functions and classes:
+
+      audiodevinfo  audioread
+      audioinfo     audiorecorder
+      audioplayer   audiowrite
+
+ ** Other new classes in Octave 4.2:
+
+      audioplayer    inputParser
+      audiorecorder  
+
+ ** Optional stricter Matlab compatibility for ranges, diagonal matrices,
+    and permutation matrices.
+
+    Octave has internal optimizations which use space-efficient storage
+    for the three data types above.  Three new functions have been added
+    which control whether the optimizations are used (default), or whether
+    the data types are stored as full matrices.
+
+    disable_range   disable_diagonal_matrix   disable_permutation_matrix
+
+    All three optimizations are disabled if Octave is started with the
+    --braindead command line option.
+
+ ** Interpolation function changes for Matlab compatibility
+
+    The interpolation method 'cubic' is now equivalent to 'pchip'
+    for interp1, interp2, and interp3.  Previously, 'cubic' was equivalent
+    to 'spline' for interp2.  This may produce different results as 'spline'
+    has continuous 1st and 2nd derivatives while 'pchip' only has a continuous
+    1st derivative.  The methods 'next' and 'previous' have been added to
+    interp1 for compatibility.
+
+ ** The delaunay function has been extended to accept 3-D inputs for
+    Matlab compatibility.  The delaunay function no longer plots the
+    triangulation if no output argument is requested, instead, the
+    triangulation is always returned.  The delaunay3 function which
+    handles 3-D inputs has been deprecated in favor of delaunay.
+
+ ** The trigonometric functions asin and acos return different phase values
+    from previous versions of Octave when the input is outside the principal
+    branch ([-1, 1]).  If the real portion of the input is greater than 1 then
+    the limit from below is taken.  If the real portion is less than 1 then the
+    limit from above is taken.  This criteria is consistent with several other
+    numerical analysis software packages.
+
+ ** strfind changes when using empty pattern ("") for Matlab compatibility
+
+    strfind now returns an empty array when the pattern itself is empty.
+    In previous versions of Octave, strfind matched at every character
+    location when the pattern was empty.
+
+      NEW
+      strfind ("abc", "") => []
+      OLD
+      strfind ("abc", "") => [1, 2, 3, 4]
+
+ ** Integer formats used in the printf family of functions now work for
+    64-bit integers and are more compatible with Matlab when printing
+    non-integer values.  Now instead of truncating, Octave will switch
+    the effective format to '%g' in the following circumstances:
+
+      * the value of an integer type (int8, uint32, etc.) value exceeds
+        the maximum for the format specifier.  For '%d', the limit is
+        intmax ('int64') and for '%u' it is intmax ('uint64').
+
+      * round(x) != x or the value is outside the range allowed by the
+        integer format specifier.
+
+    There is still one difference:  Matlab switches to '%e' and Octave
+    is currently switching to '%g'.
+
+ ** The archive family of functions (bzip2, gzip, zip, tar) and their
+    unpacking routines (bunzip2, gunzip, unzip, untar, unpack) have
+    been recoded.  Excepting unpack, the default is now to place files
+    in the same directory as the archive (on unpack) or as the original
+    files (on archiving).
+
+ ** Z-order stacking issues with patches, grid lines, and line object
+    plot markers for on screen display and printing have all been resolved.
+    For 2-D plots the axis grid lines can be placed on top of the plot
+    with set (gca, "layer", "top").
+
+ ** The patch graphic object has been overhauled.  It now produces visual
+    results equivalent to Matlab even for esoteric combinations of
+    faces/vertices/cdata.
+
+ ** The polar() plot function now draws a circular theta axis and
+    radial rho axis rather than using a rectangular x/y axis.
+
+ ** linkprop has been completely re-coded for performance and Matlab
+    compatibility.  It now returns a linkprop object which must be stored
+    in a variable for as long as the graphic objects should remain linked.
+    To unlink properties use 'clear hlink' where hlink is the variable
+    containing the linkprop object.
+
+ ** isprime has been extended to operate on negative and complex inputs.
+
+ ** xor has been extended to accept more than two arguments in which case
+    it performs cumulative XOR reduction.
+
+ ** The following functions now support N-dimensional arrays:
+
+      fliplr   flipud   rot90
+
+ ** The new warning ID "Octave:data-file-in-path" replaces the three
+    previous separate warning IDs "Octave:fopen-file-in-path",
+    "Octave:load-file-in-path", and "Octave:md5sum-file-in-path".
+
+ ** Other new functions added in 4.2:
+
+      bandwidth
+      cubehelix
+      dir_in_loadpath
+      flip
+      frame2im
+      hgload
+      hgsave
+      ichol
+      ilu
+      im2frame
+      isbanded
+      isdiag
+      istril
+      istriu
+      javachk
+      linkaxes
+      lscov
+      numfields
+      qmr
+      rotate
+      sylvester
+      unsetenv
+      zoom
+
+ ** inline() scheduled for eventual deprecation by Matlab
+
+    Functions created through the use of inline are scheduled for deprecation
+    by Matlab.  When this occurs Octave will continue to support inline
+    functions for an indeterminate amount of time before also removing support.
+    All new code should use anonymous functions in place of inline functions. 
+
+ ** Deprecated functions.
+
+    The following functions have been deprecated in Octave 4.2 and will
+    be removed from Octave 4.6 (or whatever version is the second major
+    release after 4.2):
+
+      Function             | Replacement
+      ---------------------|------------------
+      bicubic              | interp2
+      delaunay3            | delaunay
+      dump_prefs           | individual preference get/set routines
+      find_dir_in_path     | dir_in_loadpath
+      finite               | isfinite
+      fmod                 | rem
+      fnmatch              | glob or regexp
+      luinc                | ilu or ichol
+      nfields              | numfields
+      octave_tmp_file_name | tempname
+      syl                  | sylvester
+      usage                | print_usage
+
+    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_unsigned_conversion
+      interp1q                javafields
+      isequalwithequalnans    javamethods
+      java_convert_matrix     re_read_readline_init_file
+      java_debug              read_readline_init_file
+      java_invoke             saving_history
+
+    The following keywords were deprecated in Octave 3.8 and have been
+    removed from Octave 4.2
+
+      static
+
+    The following configuration variables were deprecated in Octave 3.8
+    and have been removed from Octave 4.2
+
+      CC_VERSION  (now GCC_VERSION)
+      CXX_VERSION (now GXX_VERSION)
+
+    The internal class <Octave_map> was deprecated in Octave 3.8 and has
+    been removed from Octave 4.2.  Replacement classes are
+    <octave_map> (struct array) or <octave_scalar_map> for a single structure.
+
+ ** The warning ID Octave:singular-matrix-div has been replaced by
+    Octave:nearly-singular-matrix and Octave:singular-matrix.
+
 Summary of important user-visible changes for version 4.0:
 ---------------------------------------------------------
 
@@ -27,18 +234,18 @@
 
  ** Other new functions added in 4.0.0:
 
-    validateattributes
+      validateattributes
 
  ** Deprecated functions.
 
     The following functions were deprecated in Octave 3.6 and have been
     removed from Octave 4.0.
-                                           
-      cut                polyderiv        
-      cor                shell_cmd        
-      corrcoef           studentize       
-      __error_text__     sylvester_matrix 
-      error_text         
+
+      cut                polyderiv
+      cor                shell_cmd
+      corrcoef           studentize
+      __error_text__     sylvester_matrix
+      error_text
 
     The following functions have been deprecated in Octave 4.0 and will
     be removed from Octave 4.4 (or whatever version is the second major
@@ -46,7 +253,7 @@
 
       allow_noninteger_range_as_index
       do_braindead_shortcircuit_evaluation
-      
+
     The internal function atan2 of the sparse matrix class has been deprecated
     in Octave 4.0 and will be removed from Octave 4.4 (or whatever version is
     the second major release after 4.0).  Use the Fatan2 function with sparse
--- a/README	Mon Jan 12 09:13:19 2015 -0800
+++ b/README	Mon Jan 12 09:17:35 2015 -0800
@@ -49,9 +49,9 @@
 features of GNU Make that are not present in other versions of make.
 GNU Make is very portable and easy to install.
 
-See the notes in the files INSTALL and the system-specific README files
-in the etc directory of the Octave source distribution for more specific
-installation instructions.
+See the notes in the files INSTALL.OCTAVE and the system-specific README
+files in the etc directory of the Octave source distribution for more
+specific installation instructions.
 
 Bugs and Patches
 ----------------
--- a/bootstrap.conf	Mon Jan 12 09:13:19 2015 -0800
+++ b/bootstrap.conf	Mon Jan 12 09:17:35 2015 -0800
@@ -50,10 +50,12 @@
   isatty
   largefile
   link
+  log
   log2
   log2-ieee
   log2f
   log2f-ieee
+  logf
   lstat
   malloc-gnu
   mbrtowc
@@ -66,8 +68,8 @@
   open
   opendir
   pathmax
+  progname
   putenv
-  progname
   readdir
   readlink
   realloc-gnu
@@ -91,6 +93,7 @@
   sys_stat
   sys_time
   sys_times
+  tempname
   time
   times
   tmpfile
@@ -99,6 +102,7 @@
   uname
   unistd
   unlink
+  unsetenv
   vasprintf
 "
 
--- a/build-aux/common.mk	Mon Jan 12 09:13:19 2015 -0800
+++ b/build-aux/common.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -107,14 +107,11 @@
 # 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@
 WARN_CFLAGS = @WARN_CFLAGS@
 AM_CFLAGS = $(XTRA_CFLAGS)
-ALL_CPPFLAGS = $(CPPFLAGS) $(HDF5_CPPFLAGS) $(Z_CPPFLAGS) $(LLVM_CPPFLAGS)
 
 BUILD_CC = @BUILD_CC@
 BUILD_CFLAGS = @BUILD_CFLAGS@
@@ -131,8 +128,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@
@@ -318,11 +313,6 @@
 USE_64_BIT_IDX_T = @USE_64_BIT_IDX_T@
 OCTAVE_IDX_TYPE = @OCTAVE_IDX_TYPE@
 
-TEXINFO_COLAMD = @TEXINFO_COLAMD@
-TEXINFO_CHOLMOD = @TEXINFO_CHOLMOD@
-TEXINFO_UMFPACK = @TEXINFO_UMFPACK@
-TEXINFO_QHULL = @TEXINFO_QHULL@
-
 # The arguments passed to configure.
 config_opts = @config_opts@
 
@@ -448,6 +438,9 @@
 localapioctfiledir = @localapioctfiledir@
 localveroctfiledir = @localveroctfiledir@
 
+# Where Octave will search for example data files shipped with distribution.
+octdatadir = @octdatadir@
+
 # Where Octave will search to find image files.
 imagedir = @imagedir@
 
@@ -518,7 +511,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}\"|" \
@@ -692,6 +684,7 @@
   -e "s|%OCTAVE_MAN1DIR%|\"${man1dir}\"|" \
   -e "s|%OCTAVE_MAN1EXT%|\"${man1ext}\"|" \
   -e "s|%OCTAVE_MANDIR%|\"${mandir}\"|" \
+  -e "s|%OCTAVE_OCTDATADIR%|\"${octdatadir}\"|" \
   -e "s|%OCTAVE_OCTFILEDIR%|\"${octfiledir}\"|" \
   -e "s|%OCTAVE_OCTETCDIR%|\"${octetcdir}\"|" \
   -e "s|%OCTAVE_OCTINCLUDEDIR%|\"${octincludedir}\"|" \
--- a/configure.ac	Mon Jan 12 09:13:19 2015 -0800
+++ b/configure.ac	Mon Jan 12 09:17:35 2015 -0800
@@ -19,13 +19,13 @@
 ### <http://www.gnu.org/licenses/>.
 
 AC_PREREQ([2.62])
-AC_INIT([GNU Octave], [3.9.0+], [http://octave.org/bugs.html], [octave])
+AC_INIT([GNU Octave], [4.1.0+], [http://octave.org/bugs.html], [octave])
 
 dnl Note that the version number is duplicated here and in AC_INIT
 dnl because AC_INIT requires it to be static, not computed from
 dnl shell variables.
-OCTAVE_MAJOR_VERSION=3
-OCTAVE_MINOR_VERSION=9
+OCTAVE_MAJOR_VERSION=4
+OCTAVE_MINOR_VERSION=1
 OCTAVE_PATCH_VERSION=0+
 
 dnl PACKAGE_VERSION is set by the AC_INIT VERSION arg
@@ -113,6 +113,7 @@
 OCTAVE_SET_DEFAULT([octtestsdir], '$(octetcdir)/tests')
 OCTAVE_SET_DEFAULT([texi_macros_file], '$(octetcdir)/macros.texi')
 OCTAVE_SET_DEFAULT([imagedir], '$(datadir)/octave/$(version)/imagelib')
+OCTAVE_SET_DEFAULT([octdatadir], '$(datadir)/octave/$(version)/data')
 OCTAVE_SET_DEFAULT([man1dir], '$(mandir)/man1')
 OCTAVE_SET_DEFAULT([man1ext], '.1')
 OCTAVE_SET_DEFAULT([infofile], '$(infodir)/octave.info')
@@ -315,24 +316,6 @@
 AC_PROG_CXX
 AC_PROG_CXXCPP
 
-### Check version number when using g++.
-
-GXX_VERSION=
-if test "$GXX" = yes; then
-  gxx_version=`$CXX -v 2>&1 | $GREP "^.*g.. version" | \
-    $SED -e 's/^.*g.. version *//' -e 's/cygnus-//' -e 's/egcs-//' -e 's/ .*//'`
-
-  AX_COMPARE_VERSION([$gxx_version], [lt], [3.5],
-    [AC_MSG_ERROR([g++ version $gxx_version will probably fail to compile Octave])])
-
-  GXX_VERSION=$gxx_version
-fi
-AC_SUBST(GXX_VERSION)
-
-## FIXME: CXX_VERSION is deprecated and should be removed in Octave version 3.12
-CXX_VERSION=$gxx_version
-AC_SUBST(CXX_VERSION)
-
 ### Determine which C compiler to use (we expect to find gcc).
 
 AC_PROG_CC
@@ -379,12 +362,8 @@
 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.
+### Check version number when using g++ .
+### It might be different from the gcc version number.
 
 GXX_VERSION=
 if test "$GXX" = yes; then
@@ -392,7 +371,7 @@
   gxx_version=`$CXX -v 2>&1 | $GREP "^.*g.. version" | \
     $SED -e 's/^.*g.. version *//' -e 's/cygnus-//' -e 's/egcs-//' -e 's/ .*//'`
 
-  AX_COMPARE_VERSION([$gxx_version], [lt], [3],
+  AX_COMPARE_VERSION([$gxx_version], [lt], [4.1],
     [warn_gxx_version="g++ version $gxx_version is likely to cause problems"
      OCTAVE_CONFIGURE_WARNING([warn_gxx_version])])
 
@@ -734,8 +713,7 @@
   [warn_qhull=
   OCTAVE_CHECK_QHULL_VERSION
   OCTAVE_CHECK_LIB_QHULL_OK(
-    [TEXINFO_QHULL="@set HAVE_QHULL"
-    AC_DEFINE(HAVE_QHULL, 1, [Define to 1 if Qhull is available.])],
+    [AC_DEFINE(HAVE_QHULL, 1, [Define to 1 if Qhull is available.])],
     [warn_qhull="Qhull library found, but does not seem to work properly.  This will result in loss of functionality of some geometry functions.  Please try recompiling the library with -fno-strict-aliasing."])])
 
 ### Check for PCRE regex library.
@@ -870,9 +848,13 @@
       warn_llvm="Missing LLVM file TargetData.h.  JIT compiler is disabled."
     fi
 
+    AC_CHECK_HEADERS([llvm/IR/Verifier.h])
+
     OCTAVE_LLVM_FUNCTION_ADDATTRIBUTE_API
     OCTAVE_LLVM_FUNCTION_ADDFNATTR_API
     OCTAVE_LLVM_CALLINST_ADDATTRIBUTE_API
+    OCTAVE_LLVM_RAW_FD_OSTREAM_API
+    OCTAVE_LLVM_LEGACY_PASSMANAGER_API
     AC_LANG_POP(C++)
     CPPFLAGS="$save_CPPFLAGS"
     CXXFLAGS="$save_CXXFLAGS"
@@ -900,6 +882,7 @@
 AC_SUBST(LLVM_CXXFLAGS)
 AC_SUBST(LLVM_LDFLAGS)
 AC_SUBST(LLVM_LIBS)
+AM_CONDITIONAL([AMCOND_HAVE_LLVM], [test -z "$warn_llvm"])
 
 ### Check for HDF5 library.
 
@@ -912,7 +895,6 @@
   [hdf5.h], [H5Gget_num_objs], [], [],
   [warn_hdf5=
    OCTAVE_CHECK_HDF5_HAS_VER_16_API
-   TEXINFO_HDF5="@set HAVE_HDF5"
    AC_DEFINE(HAVE_HDF5, 1,
      [Define to 1 if HDF5 is available and newer than version 1.6.])
    if test $have_msvc = yes; then
@@ -979,8 +961,7 @@
   [glpk/glpk.h glpk.h], [glp_simplex], [], [],
   [warn_glpk=
    OCTAVE_CHECK_LIB_GLPK_OK(
-    [TEXINFO_GLPK="@set HAVE_GLPK"
-    AC_DEFINE(HAVE_GLPK, 1, [Define to 1 if GLPK is available.])],
+    [AC_DEFINE(HAVE_GLPK, 1, [Define to 1 if GLPK is available.])],
     [warn_glpk="GLPK library found, but does not seem to work properly -- disabling glpk function"])])
 LIBS="$save_LIBS"
 CPPFLAGS="$save_CPPFLAGS"
@@ -1014,6 +995,76 @@
 LIBS="$save_LIBS"
 CPPFLAGS="$save_CPPFLAGS"
 
+### Check for sndfile
+
+warn_sndfile="sndfile library fails tests.  The audioinfo, audioread and audiowrite functions for reading and writing audio files will not be fully functional."
+
+check_sndfile=no
+AC_ARG_WITH([sndfile],
+  [AS_HELP_STRING([--without-sndfile],
+    [don't use sndfile library, disable audio file I/O])],
+  [if test x"$withval" = x"no"; then
+     warn_sndfile="--without-sndfile specified.  The audioinfo, audioread and audiowrite functions for reading and writing audio files will not be fully functional."
+   else
+     check_sndfile=yes
+   fi],
+  [check_sndfile=yes])
+
+if test $check_sndfile = yes; then
+  PKG_CHECK_EXISTS([sndfile], [
+    SNDFILE_CPPFLAGS=`$PKG_CONFIG --cflags-only-I sndfile`
+    SNDFILE_LDFLAGS=`$PKG_CONFIG --libs-only-L sndfile`
+    SNDFILE_LIBS=`$PKG_CONFIG --libs-only-l sndfile`
+    warn_sndfile=
+  ])
+fi
+
+if test -z "$warn_sndfile"; then
+  AC_DEFINE(HAVE_SNDFILE, 1, [Define to 1 if sndfile is available.])
+else
+  SNDFILE_CPPFLAGS=
+  SNDFILE_LDFLAGS=
+  SNDFILE_LIBS=
+fi
+AC_SUBST(SNDFILE_CPPFLAGS)
+AC_SUBST(SNDFILE_LDFLAGS)
+AC_SUBST(SNDFILE_LIBS)
+
+### Check for PortAudio
+
+warn_portaudio="PortAudio library fails tests.  The audioplayer, audiorecorder classes and audiodevinfo function for audio playback and recording will not be fully functional."
+
+check_portaudio=no
+AC_ARG_WITH([portaudio],
+  [AS_HELP_STRING([--without-portaudio],
+    [don't use PortAudio library, disable audio playback and recording])],
+  [if test x"$withval" = x"no"; then
+     warn_portaudio="--without-portaudio specified.  The audioplayer, audiorecorder classes and audiodevinfo function for audio playback and recording will not be fully functional."
+   else
+     check_portaudio=yes
+   fi],
+  [check_portaudio=yes])
+
+if test $check_portaudio = yes; then
+  PKG_CHECK_EXISTS([portaudio-2.0 >= 19], [
+    PORTAUDIO_CPPFLAGS=`$PKG_CONFIG --cflags-only-I portaudio-2.0`
+    PORTAUDIO_LDFLAGS=`$PKG_CONFIG --libs-only-L portaudio-2.0`
+    PORTAUDIO_LIBS=`$PKG_CONFIG --libs-only-l portaudio-2.0`
+    warn_portaudio=
+  ])
+fi
+
+if test -z "$warn_portaudio"; then
+  AC_DEFINE(HAVE_PORTAUDIO, 1, [Define to 1 if PortAudio is available.])
+else
+  PORTAUDIO_CPPFLAGS=
+  PORTAUDIO_LDFLAGS=
+  PORTAUDIO_LIBS=
+fi
+AC_SUBST(PORTAUDIO_CPPFLAGS)
+AC_SUBST(PORTAUDIO_LDFLAGS)
+AC_SUBST(PORTAUDIO_LIBS)
+
 ### Check for either of Graphics/ImageMagick++ libraries
 
 AC_ARG_WITH([magick],
@@ -2197,7 +2248,7 @@
 AC_CHECK_FUNCS([log1p log1pf pipe])
 AC_CHECK_FUNCS([realpath resolvepath roundl])
 AC_CHECK_FUNCS([select setgrent setpwent siglongjmp strsignal])
-AC_CHECK_FUNCS([tcgetattr tcsetattr tempnam tgammaf toascii])
+AC_CHECK_FUNCS([tcgetattr tcsetattr tgammaf toascii])
 AC_CHECK_FUNCS([umask waitpid])
 AC_CHECK_FUNCS([_kbhit])
 
@@ -2858,7 +2909,8 @@
 fi
 
 AM_CONDITIONAL([AMCOND_BUILD_GUI], [test $build_gui = yes])
-AM_CONDITIONAL([AMCOND_HAVE_QSCINTILLA], [test "$octave_cv_lib_qscintilla" = yes])
+AM_CONDITIONAL([AMCOND_HAVE_QSCINTILLA],
+               [test "$octave_cv_lib_qscintilla" = yes])
 AM_CONDITIONAL([WIN32_TERMINAL], [test $win32_terminal = yes])
 AC_SUBST(QT_CPPFLAGS)
 AC_SUBST(QT_LDFLAGS)
@@ -2894,11 +2946,12 @@
   doc/refcard/Makefile
   etc/icons/Makefile
   examples/Makefile
+  examples/code/Makefile
+  examples/data/Makefile
   libgnu/Makefile
   libgui/Makefile
   libinterp/Makefile
   liboctave/Makefile
-  liboctave/cruft/Makefile
   liboctave/cruft/mkf77def
   scripts/Makefile
   src/Makefile
@@ -2980,6 +3033,9 @@
   OPENGL libraries:            $OPENGL_LIBS
   PCRE CPPFLAGS:               $PCRE_CPPFLAGS
   PCRE libraries:              $PCRE_LIBS
+  PortAudio CPPFLAGS:          $PORTAUDIO_CPPFLAGS
+  PortAudio LDFLAGS:           $PORTAUDIO_LDFLAGS
+  PortAudio libraries:         $PORTAUDIO_LIBS
   PTHREAD flags:               $PTHREAD_CFLAGS
   PTHREAD libraries:           $PTHREAD_LIBS
   QHULL CPPFLAGS:              $QHULL_CPPFLAGS
@@ -2992,6 +3048,9 @@
   Qt LDFLAGS:                  $QT_LDFLAGS
   Qt libraries:                $QT_LIBS
   READLINE libraries:          $READLINE_LIBS
+  Sndfile CPPFLAGS:            $SNDFILE_CPPFLAGS
+  Sndfile LDFLAGS:             $SNDFILE_LDFLAGS
+  Sndfile libraries:           $SNDFILE_LIBS
   TERM libraries:              $TERM_LIBS
   UMFPACK CPPFLAGS:            $UMFPACK_CPPFLAGS
   UMFPACK LDFLAGS:             $UMFPACK_LDFLAGS
@@ -3015,6 +3074,7 @@
   Dynamic Linking:                    $ENABLE_DYNAMIC_LINKING $DL_API_MSG
   Include support for GNU readline:   $USE_READLINE
   64-bit array dims and indexing:     $USE_64_BIT_IDX_T
+  Experimental SMP multithreading:    $USE_OPENMP
 ])
 
 warn_msg_printed=false
--- a/doc/interpreter/Makefile.am	Mon Jan 12 09:13:19 2015 -0800
+++ b/doc/interpreter/Makefile.am	Mon Jan 12 09:17:35 2015 -0800
@@ -40,43 +40,43 @@
 ## They are dependencies for the documentation.
 ## They must not be distributed from this directory.
 EXAMPLE_FILES = \
-  $(top_srcdir)/examples/@FIRfilter/FIRfilter.m \
-  $(top_srcdir)/examples/@FIRfilter/FIRfilter_aggregation.m \
-  $(top_srcdir)/examples/@FIRfilter/display.m \
-  $(top_srcdir)/examples/@FIRfilter/subsasgn.m \
-  $(top_srcdir)/examples/@FIRfilter/subsref.m \
-  $(top_srcdir)/examples/@polynomial/display.m \
-  $(top_srcdir)/examples/@polynomial/double.m \
-  $(top_srcdir)/examples/@polynomial/end.m \
-  $(top_srcdir)/examples/@polynomial/get.m \
-  $(top_srcdir)/examples/@polynomial/mtimes.m \
-  $(top_srcdir)/examples/@polynomial/plot.m \
-  $(top_srcdir)/examples/@polynomial/polynomial.m \
-  $(top_srcdir)/examples/@polynomial/polynomial_superiorto.m \
-  $(top_srcdir)/examples/@polynomial/polyval.m \
-  $(top_srcdir)/examples/@polynomial/set.m \
-  $(top_srcdir)/examples/@polynomial/subsref.m \
-  $(top_srcdir)/examples/addtwomatrices.cc \
-  $(top_srcdir)/examples/celldemo.cc \
-  $(top_srcdir)/examples/embedded.cc \
-  $(top_srcdir)/examples/fortrandemo.cc \
-  $(top_srcdir)/examples/fortransub.f \
-  $(top_srcdir)/examples/funcdemo.cc \
-  $(top_srcdir)/examples/globaldemo.cc \
-  $(top_srcdir)/examples/helloworld.cc \
-  $(top_srcdir)/examples/mycell.c \
-  $(top_srcdir)/examples/myfeval.c \
-  $(top_srcdir)/examples/myfunc.c \
-  $(top_srcdir)/examples/myhello.c \
-  $(top_srcdir)/examples/mypow2.c \
-  $(top_srcdir)/examples/mysparse.c \
-  $(top_srcdir)/examples/mystring.c \
-  $(top_srcdir)/examples/mystruct.c \
-  $(top_srcdir)/examples/paramdemo.cc \
-  $(top_srcdir)/examples/standalone.cc \
-  $(top_srcdir)/examples/stringdemo.cc \
-  $(top_srcdir)/examples/structdemo.cc \
-  $(top_srcdir)/examples/unwinddemo.cc
+  $(top_srcdir)/examples/code/@FIRfilter/FIRfilter.m \
+  $(top_srcdir)/examples/code/@FIRfilter/FIRfilter_aggregation.m \
+  $(top_srcdir)/examples/code/@FIRfilter/display.m \
+  $(top_srcdir)/examples/code/@FIRfilter/subsasgn.m \
+  $(top_srcdir)/examples/code/@FIRfilter/subsref.m \
+  $(top_srcdir)/examples/code/@polynomial/display.m \
+  $(top_srcdir)/examples/code/@polynomial/double.m \
+  $(top_srcdir)/examples/code/@polynomial/end.m \
+  $(top_srcdir)/examples/code/@polynomial/get.m \
+  $(top_srcdir)/examples/code/@polynomial/mtimes.m \
+  $(top_srcdir)/examples/code/@polynomial/plot.m \
+  $(top_srcdir)/examples/code/@polynomial/polynomial.m \
+  $(top_srcdir)/examples/code/@polynomial/polynomial_superiorto.m \
+  $(top_srcdir)/examples/code/@polynomial/polyval.m \
+  $(top_srcdir)/examples/code/@polynomial/set.m \
+  $(top_srcdir)/examples/code/@polynomial/subsref.m \
+  $(top_srcdir)/examples/code/addtwomatrices.cc \
+  $(top_srcdir)/examples/code/celldemo.cc \
+  $(top_srcdir)/examples/code/embedded.cc \
+  $(top_srcdir)/examples/code/fortrandemo.cc \
+  $(top_srcdir)/examples/code/fortransub.f \
+  $(top_srcdir)/examples/code/funcdemo.cc \
+  $(top_srcdir)/examples/code/globaldemo.cc \
+  $(top_srcdir)/examples/code/helloworld.cc \
+  $(top_srcdir)/examples/code/mycell.c \
+  $(top_srcdir)/examples/code/myfeval.c \
+  $(top_srcdir)/examples/code/myfunc.c \
+  $(top_srcdir)/examples/code/myhello.c \
+  $(top_srcdir)/examples/code/mypow2.c \
+  $(top_srcdir)/examples/code/mysparse.c \
+  $(top_srcdir)/examples/code/mystring.c \
+  $(top_srcdir)/examples/code/mystruct.c \
+  $(top_srcdir)/examples/code/paramdemo.cc \
+  $(top_srcdir)/examples/code/standalone.cc \
+  $(top_srcdir)/examples/code/stringdemo.cc \
+  $(top_srcdir)/examples/code/structdemo.cc \
+  $(top_srcdir)/examples/code/unwinddemo.cc
 
 
 include images.mk
@@ -170,8 +170,11 @@
 
 TXI_SRC = $(MUNGED_TEXI_SRC:.texi=.txi)
 
+include graphics_properties.mk
+
 BUILT_TEXINFOS = \
   contributors.texi \
+  $(GRAPH_PROP_TEXI_SRC) \
   $(MUNGED_TEXI_SRC)
 
 info_TEXINFOS = octave.texi
@@ -271,6 +274,8 @@
   contributors.in \
   doc-cache \
   find-docstring-files.sh \
+  genpropdoc.m \
+  graphics_properties.mk \
   images \
   images.awk \
   images.mk \
--- a/doc/interpreter/audio.txi	Mon Jan 12 09:13:19 2015 -0800
+++ b/doc/interpreter/audio.txi	Mon Jan 12 09:17:35 2015 -0800
@@ -21,6 +21,135 @@
 @node Audio Processing
 @chapter Audio Processing
 
+@menu
+* Audio File Utilities::
+* Audio Device Information::
+* Audio Player::
+* Audio Recorder::
+* Audio Data Processing::
+@end menu
+
+@node Audio File Utilities
+@section Audio File Utilities
+
+The following functions allow you to read, write and retrieve
+information about audio files. Various formats are supported including
+wav, flac and ogg vorbis.
+
+@DOCSTRING(audioinfo)
+
+@DOCSTRING(audioread)
+
+@DOCSTRING(audiowrite)
+
+@node Audio Device Information
+@section Audio Device Information
+
+@DOCSTRING(audiodevinfo)
+
+@node Audio Player
+@section Audio Player
+
+The following methods are used to create and use audioplayer
+objects. These objects can be used to play back audio data stored in
+Octave matrices and arrays. The audioplayer object supports playback
+from various devices available to the system, blocking and non-blocking
+playback, convenient pausing and resuming and much more.
+
+@DOCSTRING(@audioplayer/audioplayer)
+
+@menu
+* Playback::
+* Player Properties::
+@end menu
+
+@node Playback
+@subsection Playback
+
+The following methods are used to control player playback.
+
+@DOCSTRING(@audioplayer/play)
+
+@DOCSTRING(@audioplayer/playblocking)
+
+@DOCSTRING(@audioplayer/pause)
+
+@DOCSTRING(@audioplayer/resume)
+
+@DOCSTRING(@audioplayer/stop)
+
+@DOCSTRING(@audioplayer/isplaying)
+
+@node Player Properties
+@subsection Properties
+
+The remaining couple of methods are used to get and set various
+properties of the audioplayer object.
+
+@DOCSTRING(@audioplayer/get)
+
+@DOCSTRING(@audioplayer/set)
+
+@node Audio Recorder
+@section Audio Recorder
+
+The following methods are used to create and use audiorecorder
+objects. These objects can be used to record audio data from various
+devices available to the system. You can use convenient methods to
+retrieve that data or audioplayer objects created from that
+data. Methods for blocking and non-blocking recording, pausing and
+resuming recording and much more is available.
+
+@DOCSTRING(@audiorecorder/audiorecorder)
+
+@menu
+* Recording::
+* Data Retrieval::
+* Recorder Properties::
+@end menu
+
+@node Recording
+@subsection Recording
+
+The following methods control the recording process.
+
+@DOCSTRING(@audiorecorder/record)
+
+@DOCSTRING(@audiorecorder/recordblocking)
+
+@DOCSTRING(@audiorecorder/pause)
+
+@DOCSTRING(@audiorecorder/resume)
+
+@DOCSTRING(@audiorecorder/stop)
+
+@DOCSTRING(@audiorecorder/isrecording)
+
+@node Data Retrieval
+@subsection Data Retrieval
+
+The following methods allow you to retrieve recorded audio data in
+various ways.
+
+@DOCSTRING(@audiorecorder/getaudiodata)
+
+@DOCSTRING(@audiorecorder/getplayer)
+
+@DOCSTRING(@audiorecorder/play)
+
+@node Recorder Properties
+@subsection Properties
+
+The remaining two methods allow you to read or alter the properties of
+audiorecorder objects.
+
+@DOCSTRING(@audiorecorder/get)
+
+@DOCSTRING(@audiorecorder/set)
+
+@node Audio Data Processing
+@section Audio Data Processing
+
 Octave provides a few functions for dealing with audio data.  An audio
 `sample' is a single output value from an A/D converter, i.e., a small
 integer number (usually 8 or 16 bits), and audio data is just a series
@@ -32,8 +161,8 @@
 There are many different formats for representing such data.  Currently,
 only the two most popular, @emph{linear encoding} and @emph{mu-law
 encoding}, are supported by Octave.  There is an excellent FAQ on audio
-formats by Guido van Rossum @email{guido@@cwi.nl} which can be found at any
-FAQ ftp site, in particular in the directory
+formats by @nospell{Guido van Rossum} @email{guido@@cwi.nl} which can be
+found at any FAQ ftp site, in particular in the directory
 @file{/pub/usenet/news.answers/audio-fmts} of the archive site
 @code{rtfm.mit.edu}.
 
--- a/doc/interpreter/basics.txi	Mon Jan 12 09:13:19 2015 -0800
+++ b/doc/interpreter/basics.txi	Mon Jan 12 09:17:35 2015 -0800
@@ -247,11 +247,14 @@
 beep_on_error                   = true
 confirm_recursive_rmdir         = false
 crash_dumps_octave_core         = false
-save_default_options            = "-mat-binary"
+disable_diagonal_matrix         = true
+disable_permutation_matrix      = true
+disable_range                   = true
 fixed_point_format              = true
 history_timestamp_format_string = "%%-- %D %I:%M %p --%%"
 page_screen_output              = false
 print_empty_dimensions          = false
+save_default_options            = "-mat-binary"
 struct_levels_to_print          = 0
 @end group
 @end example
@@ -377,15 +380,19 @@
 invoke Octave with the @option{--verbose} option but without the
 @option{--silent} option.
 
-The @code{dump_prefs} function is useful for determining what customizations
-to Octave are possible and which are in effect.
-
-@DOCSTRING(dump_prefs)
-
 @node Quitting Octave
 @section Quitting Octave
 @cindex exiting octave
 @cindex quitting octave
+@cindex finish.m
+@cindex site exiting file
+
+Shutdown is initiated with the @code{exit} or @code{quit} commands (they are
+equivalent).  Similar to startup, Octave has a shutdown process that can be
+customized by user script files.  During shutdown Octave will search for the
+script file @file{finish.m} in the function load path.  Commands to save all
+workspace variables or cleanup temporary files may be placed there.  Additional
+functions to execute on shutdown may be registered with @code{atexit}.
 
 @DOCSTRING(quit)
 
--- a/doc/interpreter/container.txi	Mon Jan 12 09:13:19 2015 -0800
+++ b/doc/interpreter/container.txi	Mon Jan 12 09:17:35 2015 -0800
@@ -507,7 +507,7 @@
 
 Other functions that can manipulate the fields of a structure are given below.
 
-@DOCSTRING(nfields)
+@DOCSTRING(numfields)
 
 @DOCSTRING(fieldnames)
 
@@ -891,8 +891,8 @@
 Strings}), @code{strcmp}, @code{strncmp}, @code{strcmpi},
 @code{strncmpi} (@pxref{Comparing Strings}), @code{str2double},
 @code{deblank}, @code{strtrim}, @code{strtrunc}, @code{strfind},
-@code{strmatch}, , @code{regexp}, @code{regexpi} (@pxref{Manipulating 
-Strings}) and @code{str2double} (@pxref{String Conversions}).
+@code{regexp}, @code{regexpi} (@pxref{Manipulating Strings}) and
+@code{str2double} (@pxref{String Conversions}).
 
 The function @code{iscellstr} can be used to test if an object is a
 cell array of strings.
--- a/doc/interpreter/contrib.txi	Mon Jan 12 09:13:19 2015 -0800
+++ b/doc/interpreter/contrib.txi	Mon Jan 12 09:17:35 2015 -0800
@@ -198,6 +198,7 @@
 comment header (use appropriate year, name and comment marks):
 
 @example
+@group
 ## Copyright (C) 1996-2013 John W. Eaton <jwe@@octave.org>
 ##
 ## This file is part of Octave.
@@ -215,6 +216,7 @@
 ## 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/>.
+@end group
 @end example
 
 Always include commit messages in changesets.  After making your source
@@ -284,8 +286,10 @@
 An exception are matrix or cell constructors:
 
 @example
+@group
   [sin(x), cos(x)]
   @{sin(x), cos(x)@}
+@end group
 @end example
 
 @noindent
--- a/doc/interpreter/contributors.in	Mon Jan 12 09:13:19 2015 -0800
+++ b/doc/interpreter/contributors.in	Mon Jan 12 09:17:35 2015 -0800
@@ -1,8 +1,10 @@
 Ben Abbott
+Drew Abbot
 Andy Adler
 Adam H. Aitkenhead
 Giles Anderson
 Joel Andersson
+Pedro Angelo
 Muthiah Annamalai
 Markus Appel
 Branden Archer
@@ -15,6 +17,7 @@
 Heinz Bauschke
 Julien Bect
 Roman Belov
+Markus Bergholz
 Karl Berry
 David Billinghurst
 Don Bindner
@@ -69,6 +72,7 @@
 Peter Ekberg
 Rolf Fabian
 Gunnar Farnebäck
+Massimiliano Fasi
 Stephen Fegan
 Ramon Garcia Fernandez
 Torsten Finke
@@ -80,6 +84,7 @@
 Walter Gautschi
 Klaus Gebhardt
 Driss Ghaddab
+Eugenio Gianniti 
 Nicolo Giorgetti
 Arun Giridhar
 Michael D. Godfrey
@@ -88,6 +93,7 @@
 Tomislav Goles
 Keith Goodman
 Brian Gough
+Michael C. Grant
 Steffen Groot
 Etienne Grossmann
 David Grundberg
@@ -119,6 +125,7 @@
 John Hunt
 Teemu Ikonen
 Alan W. Irwin
+Allan Jacobs
 Geoff Jacobsen
 Mats Jansson
 Cai Jianming
@@ -188,6 +195,7 @@
 Júlio Hoffimann Mendes
 Ed Meyer
 Thorsten Meyer
+Stefan Miereis
 Petr Mikulik
 Mike Miller
 Stefan Monnier
@@ -210,12 +218,14 @@
 Michael O'Brien
 Peter O'Gorman
 Thorsten Ohl
+Kai T. Ohlhus
 Arno Onken
 Valentin Ortega-Clavero
 Luis F. Ortiz
 Carl Osterwisch
 Janne Olavi Paanajärvi
 Scott Pakin
+Jason Alan Palmer
 Gabriele Pannocchia
 Sylvain Pelissier
 Per Persson
@@ -234,6 +244,8 @@
 Francesco Potortì
 Konstantinos Poulios
 Jarno Rajahalme
+Eduardo Ramos
+Pooja Rao
 James B. Rawlings
 Eric S. Raymond
 Balint Reczey
@@ -259,6 +271,7 @@
 Toni Saarela
 Juhani Saastamoinen
 Radek Salac
+Mike Sander
 Ben Sapp
 Aleksej Saushev
 Alois Schlögl
@@ -266,6 +279,7 @@
 Julian Schnidder
 Nicol N. Schraudolph
 Sebastian Schubert
+Lasse Schuirmann
 Ludwig Schwardt
 Thomas L. Scofield
 Daniel J. Sebald
@@ -282,6 +296,7 @@
 Joerg Specht
 Quentin H. Spencer
 Christoph Spiel
+David Spies
 Richard Stallman
 Russell Standish
 Brett Stewart
@@ -325,6 +340,7 @@
 Martin Weiser
 Michael Weitzel
 David Wells
+Joachim Wiesemann
 Fook Fah Yap
 Sean Young
 Michael Zeising
--- a/doc/interpreter/diagperm.txi	Mon Jan 12 09:13:19 2015 -0800
+++ b/doc/interpreter/diagperm.txi	Mon Jan 12 09:17:35 2015 -0800
@@ -59,7 +59,26 @@
 Octave provides special treatment of real and complex rectangular diagonal
 matrices, as well as permutation matrices.  They are stored as special objects,
 using efficient storage and algorithms, facilitating writing both readable and
-efficient matrix algebra expressions in the Octave language.
+efficient matrix algebra expressions in the Octave language.  The special
+treatment may be disabled by using the functions @dfn{disable_diagonal_matrix}
+and @dfn{disable_permutation_matrix}.
+
+@DOCSTRING(disable_diagonal_matrix)
+
+@DOCSTRING(disable_permutation_matrix)
+
+The space savings are significant as demonstrated by the following code.
+
+@example
+@group
+x = diag (rand (10, 1));
+xf = full (x);
+sizeof (x)
+@result{} 80
+sizeof (xf)
+@result{} 800
+@end group
+@end example
 
 @menu
 * Creating Diagonal Matrices::
@@ -462,7 +481,8 @@
 
 @noindent
 Finally, here's how to solve a linear system @code{A*x = b}
-with Tikhonov regularization (ridge regression) using SVD (a skeleton only):
+with @nospell{Tikhonov} regularization (ridge regression) using SVD (a skeleton
+only):
 
 @example
 @group
@@ -489,21 +509,18 @@
 right and the consequent usage of smarter algorithms for certain operations
 implies, as a side effect, small differences in treating zeros.
 The contents of this section apply also to sparse matrices, discussed in
-the following chapter. (@pxref{Sparse Matrices})
+the following chapter.  (@pxref{Sparse Matrices})
 
-The IEEE floating point standard defines the result of the expressions @code{0*Inf} and 
-@code{0*NaN} as @code{NaN}. This is widely agreed to be a good
-compromise.
-Numerical software dealing with structured and sparse matrices (including
-Octave) however, almost always makes a distinction between a "numerical zero"
-and an "assumed zero". 
-A "numerical zero" is a zero value occurring in a place where any floating-point
-value could occur.  It is normally stored somewhere in memory as an explicit
-value. 
-An "assumed zero", on the contrary, is a zero matrix element implied by the
-matrix structure (diagonal, triangular) or a sparsity pattern; its value is
-usually not stored explicitly anywhere, but is implied by the underlying
-data structure.
+The IEEE floating point standard defines the result of the expressions
+@code{0*Inf} and @code{0*NaN} as @code{NaN}.  This is widely agreed to be a
+good compromise.  Numerical software dealing with structured and sparse matrices
+(including Octave) however, almost always makes a distinction between a
+"numerical zero" and an "assumed zero".  A "numerical zero" is a zero value
+occurring in a place where any floating-point value could occur.  It is
+normally stored somewhere in memory as an explicit value.  An "assumed zero", on
+the contrary, is a zero matrix element implied by the matrix structure
+(diagonal, triangular) or a sparsity pattern; its value is usually not stored
+explicitly anywhere, but is implied by the underlying data structure.
 
 The primary distinction is that an assumed zero, when multiplied 
 by any number, or divided by any nonzero number,
--- a/doc/interpreter/diffeq.txi	Mon Jan 12 09:13:19 2015 -0800
+++ b/doc/interpreter/diffeq.txi	Mon Jan 12 09:17:35 2015 -0800
@@ -54,7 +54,7 @@
 @end ifnottex
 
 @noindent
-using Hindmarsh's ODE solver @sc{lsode}.
+using @nospell{Hindmarsh's} ODE solver @sc{lsode}.
 
 
 
@@ -106,9 +106,10 @@
 @end group
 @end example
 
-See Alan C. Hindmarsh, @cite{ODEPACK, A Systematized Collection of ODE
-Solvers}, in Scientific Computing, R. S. Stepleman, editor, (1983) for
-more information about the inner workings of @code{lsode}.
+See @nospell{Alan C. Hindmarsh},
+@cite{ODEPACK, A Systematized Collection of ODE Solvers},
+in Scientific Computing, @nospell{R. S. Stepleman}, editor, (1983)
+for more information about the inner workings of @code{lsode}.
 
 An m-file for the differential equation used above is included with the
 Octave distribution in the examples directory under the name
@@ -139,8 +140,8 @@
 @ifnottex
 @math{x-dot}
 @end ifnottex
-is the derivative of @math{x}.  The equation is solved using Petzold's
-DAE solver @sc{daspk}.
+is the derivative of @math{x}.  The equation is solved using
+@nospell{Petzold's} DAE solver @sc{daspk}.
 
 @DOCSTRING(daspk)
 
@@ -158,6 +159,6 @@
 
 @DOCSTRING(dasrt_options)
 
-See K. E. Brenan, et al., @cite{Numerical Solution of Initial-Value
+See @nospell{K. E. Brenan}, et al., @cite{Numerical Solution of Initial-Value
 Problems in Differential-Algebraic Equations}, North-Holland (1989) for
 more information about the implementation of @sc{dassl}.
--- a/doc/interpreter/doccheck/aspell-octave.en.pws	Mon Jan 12 09:13:19 2015 -0800
+++ b/doc/interpreter/doccheck/aspell-octave.en.pws	Mon Jan 12 09:17:35 2015 -0800
@@ -1,5 +1,4 @@
 personal_ws-1.1 en 1
-Abramowitz
 accumarray
 Acknowledgements
 acknowledgements
@@ -7,11 +6,9 @@
 adams
 Affero
 afterwards
-Ahalt
 aifm
 AIX
 al
-Alamos
 aleph
 alnum
 alphanum
@@ -28,7 +25,6 @@
 ARMA
 arpack
 ascii
-Ashok
 ast
 async
 atan
@@ -52,10 +48,10 @@
 backend
 Backends
 backends
+backtrace
 bartlett
 BaseValue
 basevalue
-Bateman
 BDF
 bdf
 betacdf
@@ -64,8 +60,9 @@
 betapdf
 betarnd
 BFGS
+BICG
+BiConjugate
 bigtriangledown
-Bilbert
 bincoeff
 binocdf
 binoinv
@@ -90,9 +87,7 @@
 brackety
 braindead
 breakpoint
-Brenan
 broadcastable
-Brockwell
 BSX
 builtin
 builtins
@@ -120,7 +115,6 @@
 changelogs
 changeset
 changesets
-Chaves
 chdir
 Chebyshev
 chisq
@@ -136,7 +130,6 @@
 circum
 classpath
 classpaths
-Clenshaw
 CLI
 clim
 climmode
@@ -168,7 +161,6 @@
 conformant
 cong
 const
-constuctors
 contextless
 contourc
 convhull
@@ -181,8 +173,11 @@
 CPLEX
 CreateFcn
 CRLF
+Crout
+crout
 csymamd
 ctranspose
+Ctrl
 CTRL
 CTS
 cummax
@@ -194,7 +189,6 @@
 CurrentFigure
 CurrentObject
 currentpoint
-Cuthill
 cxsparse
 Cygwin
 DAE
@@ -222,10 +216,10 @@
 delim
 deltaX
 demi
-Demmel
 DeskJet
 det
 diag
+diagcomp
 diamondsuit
 dir
 disp
@@ -234,7 +228,7 @@
 displayrange
 dMatrix
 dmperm
-Dobkin
+docstring
 docstrings
 dOmega
 doNotSpecify
@@ -244,11 +238,9 @@
 downarrow
 downdate
 dpi
-Driebeck
+droptol
 dt
 Dt
-Dulmage
-Durbin
 dx
 dy
 EastOutside
@@ -259,9 +251,7 @@
 eigenvector
 eigenvectors
 eigs
-Ekerdt
 elementwise
-Elfers
 elseif
 emacs
 emptyvalue
@@ -270,7 +260,6 @@
 Endian
 endif
 endofline
-Engle's
 eof
 EOF
 EOLs
@@ -290,7 +279,6 @@
 errordlg
 ErrorHandler
 ESC
-Esmond
 et
 etree
 etreeplot
@@ -314,12 +302,13 @@
 fftpack
 FFTs
 fftw
-Fiedler
 fieldname
 fieldnames
 filename
 filenames
+filepaths
 Filesystem
+filetype
 FinDiffType
 finv
 FIRfilter
@@ -333,7 +322,6 @@
 forall
 foregroundcolor
 formfeed
-Forsythe
 Fortran
 fpdf
 fprintf
@@ -353,7 +341,6 @@
 gaminv
 gampdf
 gamrnd
-Gautschi
 gca
 gcbo
 GCC
@@ -378,15 +365,15 @@
 globbing
 glpk
 GLS
+GMRES
 gnulib
 gnuplot
 Gnuplot
 gnuplot's
-Golub
-Gonnet
 goto
 Goto
 gotos
+gperf
 GPL
 GPLK
 gplot
@@ -396,7 +383,6 @@
 GraphicsMagick
 Graymap
 grayscale
-Graz
 griddata
 gswin
 GUIs
@@ -404,16 +390,13 @@
 gz
 gzip
 gzipped
-Hackbusch
 Hadamard
-Haddad
 HandleVisibility
 Hankel
 hanning
 Hanning
 hardcode
 hardcoding
-Hauberg
 HDF
 hdf
 headerlines
@@ -427,11 +410,7 @@
 hggroups
 hh
 HH
-Higham
-Hindmarsh
-Hindmarsh's
 histc
-Hodel
 holomorphic
 Horner's
 horzcat
@@ -440,15 +419,14 @@
 Hotelling's
 HSV
 html
-Hudak
-Huhdanpaa
 hygecdf
 hygeinv
 hygepdf
 hygernd
-Hyndman
 Hypergeometric
 hypergeometric
+ichol
+ict
 IEC
 ieee
 IEEE
@@ -457,10 +435,11 @@
 ifftn
 ignorecase
 ij
+ilu
+ilutp
 Im
 imag
 ImageMagick
-Imenu
 Indices
 indices
 infty
@@ -478,6 +457,7 @@
 interpolant
 Interpolants
 interquartile
+inuse
 inv
 involutory
 ipermute
@@ -499,14 +479,13 @@
 javaaddpath
 javamem
 jbig
+JDK
 JIT
 jpeg
 JPEG
 jpg
 jvm
 JVM's
-Kac
-Kahan
 kendall
 keybindings
 keypress
@@ -514,10 +493,8 @@
 Kolmogorov
 kolmogorov
 Konrod
-Krishnamurthy
 kron
 kruskal
-Kruskal
 Krylov
 kurtosis
 LabelSpacing
@@ -525,9 +502,7 @@
 Lanzcos
 lapack
 laplace
-Larimore
 LaserJet
-Lauchli
 lceil
 ldiv
 ldivide
@@ -538,10 +513,7 @@
 leftarrow
 Leftrightarrow
 leftrightarrow
-Lehmer
-Lehoucq
 leq
-Levinson
 LF
 lfloor
 li
@@ -563,12 +535,12 @@
 ListSize
 ListString
 literalspacing
-Liu
 LLVM
 LM
 lm
 loadpath
 Lobatto
+logfile
 logit
 logncdf
 logninv
@@ -578,8 +550,6 @@
 lookup
 Lookup
 lookups
-Los
-Lotkin
 Lovato
 lpx
 lr
@@ -595,7 +565,6 @@
 lz
 lzma
 lzw
-Magnus
 Mahalanobis
 makefile
 makefiles
@@ -607,19 +576,15 @@
 markerfacecolor
 markersize
 markerstyle
-Marsaglia
-Maschhoff
 matchcase
 matlab
-Matsumoto
 MaxFunEvals
 maxima
 MaxIntervalCount
 MaxIter
 mcnemar
-McNemar's
+mdl
 meansq
-Mendelsohn
 menubars
 Mersenne
 meshgrid
@@ -630,7 +595,7 @@
 Metafont
 mex
 mget
-Michelsen
+michol
 Microsystems
 MinGW
 minima
@@ -639,7 +604,6 @@
 minval
 MIP
 miscompiled
-Misra
 mkdir
 mkoctfile
 mldivide
@@ -649,8 +613,6 @@
 mmmm
 mmmyy
 mmmyyyy
-Moler
-Montanet
 mpoles
 mpower
 mput
@@ -678,29 +640,32 @@
 nbininv
 nbinpdf
 nbinrnd
+ncols
 nd
 ndgrid
+ndims
 ne
-Nelder
 neq
-Neudecker
 Neumann
 NeXT
 NextPlot
 nfev
 nfft
-Ng
 ni
-Nishimura
 NLP
 nnls
 nnz
 nocompute
 nodither
+nofill
 nolabel
 noncommercially
 nonconformant
+nondecreasing
+nonincreasing
+nonnan
 nonsmooth
+nonsparse
 nonzeros
 NOP
 noperm
@@ -713,9 +678,11 @@
 noscal
 noshare
 notin
+nrows
 nthargout
 NTSC
 ntsc
+numel
 Numpy
 nzmax
 oct
@@ -726,13 +693,14 @@
 onCleanup
 online
 OpenGL
+OpenJDK
 oplus
-Oppenheim
 Ord
 oregonator
 Orthogonalize
 oslash
 otimes
+outerposition
 OutputFcn
 outputfcn
 overridable
@@ -743,7 +711,6 @@
 paperunits
 PaperUnits
 parseparams
-Parter
 pbm
 PBM
 PBMplus
@@ -762,7 +729,6 @@
 pentadiagonal
 periodogram
 perp
-Petzold's
 PGF
 pgm
 PGMRES
@@ -787,10 +753,10 @@
 POSIX
 postorder
 PostScript
-Pothen
 powerset
 pre
 preconditioner
+preconditioners
 premultiplied
 Prepend
 prepended
@@ -799,6 +765,7 @@
 priori
 Profiler
 profiler
+programmatically
 prolate
 PromptString
 propto
@@ -832,20 +799,17 @@
 qz
 QZ
 radices
-Rajamanickam
 randn
 randperm
 rangle
 ranlib
 ras
-Rawlings
 rceil
 rdivide
 Readline
 readline
 RECT
 recursing
-Redheffer
 reentrant
 regex
 regressor
@@ -880,15 +844,11 @@
 rnd
 roffset
 Rosser
-Rossum
 rpath
 RPMs
 runtime
 sa
-Saad
-Sandia
 SAS
-Schafer
 schar
 Schur
 SCO
@@ -899,7 +859,6 @@
 SelectionMode
 semidefinite
 Sep
-Shampine
 shiftdim
 si
 signum
@@ -912,10 +871,10 @@
 simplematrix
 simplices
 sinetone
+slx
 sm
 smirnov
 Smirnov
-Sorensen
 SouthOutside
 sp
 spadesuit
@@ -943,16 +902,13 @@
 sqrtm
 sr
 ss
-Stadlober
 stairstep
-Stallman
 startup
 Startup
 statinfo
+stdin
 stdnormal
 stdout
-Stegun
-Stepleman
 stepsize
 STFT
 STL
@@ -967,6 +923,7 @@
 struct
 structs
 subarrays
+subdiagonals
 subdirectories
 subdirectory
 subexpressions
@@ -998,8 +955,10 @@
 SuiteSparse
 sumsq
 SunOS
+superdiagonal
+superdiagonals
 superiorto
-supradiagonal
+superscripting
 supset
 supseteq
 SV
@@ -1015,7 +974,7 @@
 symamd
 symbfact
 symrcm
-Szego
+Syntaxes
 tcdf
 Tcv
 terminal's
@@ -1029,12 +988,9 @@
 th
 ths
 tif
-Tikhonov
 TikZ
 Timestamp
 tinv
-Tisseur
-Tisseur's
 tmp
 Toeplitz
 tokenExtents
@@ -1058,7 +1014,6 @@
 trnd
 truecolor
 TrueColor
-Tsang
 Tukey
 tuples
 Tx
@@ -1127,14 +1082,12 @@
 versa
 vertcat
 vertices
-Villadsen
 voronoi
 Voronoi
 waitbar
 waitbars
 wallis
 warndlg
-Wathen
 WAV
 WayPoints
 wblcdf
@@ -1155,17 +1108,16 @@
 wildcard
 Wildcards
 wildcards
-Wilks
 windowbuttondownfcn
 windowbuttonmotionfcn
 windowbuttonupfcn
 windowstyle
-WinRand
 WIPO
 wireframe
 wp
 wspace
 xb
+xboxes
 xc
 xcorr
 xdata
@@ -1180,17 +1132,21 @@
 xl
 xmax
 xmin
+xon
 xPBTRF
 xPOTRF
 xPTSV
 xtest
+xtests
 xTRTRS
 xu
 xwd
 xy
+xyboxes
 xyerrorbar
 xyerrorbars
 xyz
+yboxes
 yc
 ydata
 yerrorbar
@@ -1204,7 +1160,6 @@
 YYYY
 yyyymmdd
 yyyymmddTHHMMSS
-Zechner
 Ziggurat
 zlib
 zlim
--- a/doc/interpreter/emacs.txi	Mon Jan 12 09:13:19 2015 -0800
+++ b/doc/interpreter/emacs.txi	Mon Jan 12 09:17:35 2015 -0800
@@ -351,8 +351,8 @@
 @code{font-lock-function-name-face}.
 @end itemize
 
-There is also rudimentary support for Imenu (currently, function names
-can be indexed).
+There is also rudimentary support for @nospell{Imenu} (currently, function
+names can be indexed).
 
 @cindex TAGS
 @cindex Emacs TAGS files
--- a/doc/interpreter/errors.txi	Mon Jan 12 09:13:19 2015 -0800
+++ b/doc/interpreter/errors.txi	Mon Jan 12 09:17:35 2015 -0800
@@ -126,8 +126,6 @@
 
 @DOCSTRING(print_usage)
 
-@DOCSTRING(usage)
-
 @DOCSTRING(beep)
 
 @DOCSTRING(beep_on_error)
@@ -285,7 +283,7 @@
 @group
 function rand42
   old_state = rand ("state");
-  restore_state = onCleanup (@@() rand ("state", old_state);
+  restore_state = onCleanup (@@() rand ("state", old_state));
   rand ("state", 42);
   @dots{}
 endfunction  # rand generator state restored by onCleanup
--- a/doc/interpreter/expr.txi	Mon Jan 12 09:13:19 2015 -0800
+++ b/doc/interpreter/expr.txi	Mon Jan 12 09:17:35 2015 -0800
@@ -1009,10 +1009,10 @@
 
 @sc{matlab} has special behavior that allows the operators @samp{&} and
 @samp{|} to short-circuit when used in the truth expression for @code{if} and 
-@code{while} statements.  The Octave parser may be instructed to behave in the
-same manner, but its use is strongly discouraged.
-
-@DOCSTRING(do_braindead_shortcircuit_evaluation)
+@code{while} statements.  Octave also behaves the same way by default,
+though the use of the @samp{&} and @samp{|} operators in this way is
+strongly discouraged.  Instead, you should use the @samp{&&} and @samp{||}
+operators that always have short-circuit behavior.
 
 Finally, the ternary operator (?:) is not supported in Octave.  If
 short-circuiting is not important, it can be replaced by the @code{ifelse}
@@ -1243,8 +1243,10 @@
 is evaluated as
 
 @example
+@group
 @var{temp} = @var{expr2}
 @var{expr1} = (@var{expr1}) @var{op} @var{temp}
+@end group
 @end example
 
 @noindent
--- a/doc/interpreter/external.txi	Mon Jan 12 09:13:19 2015 -0800
+++ b/doc/interpreter/external.txi	Mon Jan 12 09:17:35 2015 -0800
@@ -589,7 +589,7 @@
 @subsubsection Array and Sparse Class Differences
 
 The number of elements in a sparse matrix is considered to be the number
-of non-zero elements rather than the product of the dimensions.  Therefore
+of nonzero elements rather than the product of the dimensions.  Therefore
 
 @example
 @group
@@ -600,13 +600,13 @@
 @end example
 
 @noindent
-returns the number of non-zero elements.  If the user really requires the
-number of elements in the matrix, including the non-zero elements, they
+returns the number of nonzero elements.  If the user really requires the
+number of elements in the matrix, including the nonzero elements, they
 should use @code{numel} rather than @code{nelem}.  Note that for very
 large matrices, where the product of the two dimensions is larger than
 the representation of an unsigned int, then @code{numel} can overflow.
 An example is @code{speye (1e6)} which will create a matrix with a million
-rows and columns, but only a million non-zero elements.  Therefore the
+rows and columns, but only a million nonzero elements.  Therefore the
 number of rows by the number of columns in this case is more than two
 hundred times the maximum value that can be represented by an unsigned int.
 The use of @code{numel} should therefore be avoided useless it is known
@@ -707,7 +707,7 @@
 technique for creating a sparse matrix.
 
 The alternative is to first create a sparse matrix with the desired
-number of non-zero elements and then later fill those elements in.
+number of nonzero elements and then later fill those elements in.
 Sample code:
 
 @example
@@ -748,7 +748,7 @@
 @var{nz} greater than 4 is also valid.  The disadvantage is that the matrix
 occupies more memory than strictly needed.
 
-It is not always possible to know the number of non-zero elements prior
+It is not always possible to know the number of nonzero elements prior
 to filling a matrix.  For this reason the additional unused storage of 
 a sparse matrix can be removed after its creation with the
 @code{maybe_compress} function.  In addition, @code{maybe_compress} can
@@ -850,7 +850,7 @@
 sm.maybe_mutate ();  // If don't know a priori the final # of nz.
 @end example
 
-Note that both increasing and decreasing the number of non-zero elements in
+Note that both increasing and decreasing the number of nonzero elements in
 a sparse matrix is expensive as it involves memory reallocation.  Also as
 parts of the matrix, though not its entirety, exist as old and new copies
 at the same time, additional memory is needed.  Therefore, if possible this
@@ -1607,6 +1607,7 @@
 An example of the behavior of this function within Octave is then
 
 @example
+@group
 a(1).f1 = "f11"; a(1).f2 = "f12"; 
 a(2).f1 = "f21"; a(2).f2 = "f22";
 b = mystruct (a);
@@ -1625,6 +1626,7 @@
 
      this = this3
      that = that3
+@end group
 @end example
 
 @node Sparse Matrices with Mex-Files
@@ -1653,11 +1655,11 @@
 
 @noindent
 @code{mxGetNzmax} gets the maximum number of elements that can be stored
-in the sparse matrix.  This is not necessarily the number of non-zero
+in the sparse matrix.  This is not necessarily the number of nonzero
 elements in the sparse matrix.  @code{mxGetJc} returns an array with one
 additional value than the number of columns in the sparse matrix.  The
 difference between consecutive values of the array returned by
-@code{mxGetJc} define the number of non-zero elements in each column of
+@code{mxGetJc} define the number of nonzero elements in each column of
 the sparse matrix.  Therefore,
 
 @example
@@ -1673,10 +1675,10 @@
 @end example
 
 @noindent
-returns the actual number of non-zero elements stored in the matrix in
+returns the actual number of nonzero elements stored in the matrix in
 @code{nz}.  As the arrays returned by @code{mxGetPr} and @code{mxGetPi}
-only contain the non-zero values of the matrix, we also need a pointer
-to the rows of the non-zero elements, and this is given by
+only contain the nonzero values of the matrix, we also need a pointer
+to the rows of the nonzero elements, and this is given by
 @code{mxGetIr}.  A complete example of the use of sparse matrices in
 mex-files is given by the file @file{mysparse.c} shown below.
 
@@ -1692,7 +1694,7 @@
 mysparse (sm)
 @result{}
 Matrix is 2-by-2 real sparse matrix with 2 elements
-last non-zero element (2, 2) = 3.14159
+last nonzero element (2, 2) = 3.14159
 @end group
 @end example
 
@@ -1790,8 +1792,8 @@
 This feature should be used with care as the list of built-in functions can
 change.  No guarantees can be made that a function that is currently built in
 won't be implemented as a .m file or as a dynamically linked function in the
-future.  An example of how to call built-in functions from C++ can be seen in the
-code
+future.  An example of how to call built-in functions from C++ can be seen in
+the code
 
 @example
 @EXAMPLEFILE(standalonebuiltin.cc)
--- a/doc/interpreter/func.txi	Mon Jan 12 09:13:19 2015 -0800
+++ b/doc/interpreter/func.txi	Mon Jan 12 09:17:35 2015 -0800
@@ -393,17 +393,27 @@
 which stops the function execution and prints a message about the correct
 way to call the function whenever the number of inputs is wrong.
 
-@DOCSTRING(validateattributes)
-
-For compatibility with @sc{matlab}, @code{nargchk}, @code{narginchk} and
-@code{nargoutchk} are available which provide similar error checking.
-
-@DOCSTRING(nargchk)
+For compatibility with @sc{matlab}, @code{narginchk} and @code{nargoutchk} are
+available which provide similar error checking.
 
 @DOCSTRING(narginchk)
 
 @DOCSTRING(nargoutchk)
 
+Besides the number of arguments, inputs can be checked for various properties.
+@code{validatestring} is used for string arguments and
+@code{validateattributes} for numeric arguments.
+
+@DOCSTRING(validatestring)
+
+@DOCSTRING(validateattributes)
+
+If none of the preceding functions is sufficient there is also the class
+@code{inputParser} which can perform extremely complex input checking for
+functions.
+
+@DOCSTRING(inputParser)
+
 @anchor{XREFvarargin} @anchor{XREFvarargout}
 @node Variable-length Argument Lists
 @section Variable-length Argument Lists
@@ -802,7 +812,7 @@
 
 @DOCSTRING(command_line_path)
 
-@DOCSTRING(find_dir_in_path)
+@DOCSTRING(dir_in_loadpath)
 
 @node Subfunctions
 @subsection Subfunctions
@@ -1126,7 +1136,7 @@
 which contains the current function.
 
 @item Class constructor
-A function that constuctors a user class as defined in chapter 
+A function that constructs a user class as defined in chapter
 @ref{Object Oriented Programming}.
 
 @item Class method
@@ -1379,6 +1389,32 @@
 are passed to @code{betainc} are inherited from the current
 environment.
 
+Note that for performance reasons it is better to use handles to existing
+Octave functions, rather than to define anonymous functions which wrap an
+existing function.  The integration of @code{sin (x)} is 5X faster if the code
+is written as
+
+@example
+quad (@@sin, 0, pi)
+@end example
+
+rather than using the anonymous function @code{@@(x) sin (x)}.  There are many
+operators which have functional equivalents that may be better choices than an
+anonymous function.  Instead of writing
+
+@example
+f = @@(x, y) x + y 
+@end example
+
+this should be coded as
+
+@example
+f = @@plus
+@end example
+
+@xref{Operator Overloading}, for a list of operators which also have a
+functional form.
+
 @node Inline Functions
 @subsection Inline Functions
 
@@ -1394,6 +1430,11 @@
 After this it is possible to evaluate @math{f} at any @math{x} by
 writing @code{f(x)}.
 
+@strong{Caution}: @sc{matlab} has begun the process of deprecating inline
+functions.  At some point in the future support will be dropped and eventually
+Octave will follow @sc{matlab} and also remove inline functions.  Use anonymous
+functions in all new code.
+
 @DOCSTRING(inline)
 
 @DOCSTRING(argnames)
@@ -1488,7 +1529,7 @@
 @item general
 Miscellaneous matrix manipulations, like @code{flipud}, @code{rot90},
 and @code{triu}, as well as other basic functions, like
-@code{ismatrix}, @code{nargchk}, etc.
+@code{ismatrix}, @code{narginchk}, etc.
 
 @item geometry
 Functions related to Delaunay triangulation.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/interpreter/genpropdoc.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,1305 @@
+## Copyright (C) 2014 Pantxo Diribarne
+## 
+## This program is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or
+## (at your option) any later version.
+## 
+## This program 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 this program.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*- 
+## @deftypefn {Function File} {@var{retval} =} genpropdoc (@var{OBJNAME}, @var{FILENAME})
+##
+## Print FILENAME texinfo source file associated to OBJNAME objects.
+## This function is meant to be run for generating octave
+## documentation (see doc/interpreter/graphics_properties.mk).
+##
+## All the hard coded documentation is written in getdoc
+## function.  See the comments in getdoc bellow for instruction on how
+## to document a graphics property.
+## 
+## @seealso{}
+## @end deftypefn
+
+function genpropdoc (objname, fname)  
+  objnames = {"root", "figure", "axes", "line", ...
+              "text", "image", "patch", "surface"};
+
+  ## Base properties
+  base = getstructure ("base");
+
+  ## Object properties
+  if (any (strcmp (objname, objnames)))
+    obj = getstructure (objname, base);
+  else
+    error ("genpropdoc: unknown object %s", objname);
+  endif
+
+  ## Docstring
+  str = printdoc (objname, obj);
+  
+  fid = fopen (fname,  "w+");
+  if (fid < 0)
+    error ("genpropdoc: couldn't open %s.", fname);
+  endif
+  
+  fprintf (fid, str);
+  fclose (fid);
+endfunction
+
+function s = getdoc (objname, field, base)
+  ## Properties are represented by a struct with fields :
+  ## 
+  ## -"doc": string to be printed verbatim after being expanded
+  ##   through expand_doc function.  Special keywords are:
+  ##   "__objname__" further replaced by the current object name;
+  ##   "__prop__"  further replaced by the current property name;
+  ##   "__modemsg__"  further replaced by a message explaining that
+  ##   the propmode will be toggled to "manual".
+  ##   You may also cross reference properties using the label format
+  ##   OBJNAMEPROPERTY, e.g, "@xref{XREFaxescolor, , axes color
+  ##   property}." 
+  ## 
+  ## -"valid": string that describes valid values for the
+  ##   current property.  Use "packopt" function to join options with
+  ##   " | " separator and "markdef" to mark default among valid
+  ##   values between curly braces. 
+  ##   If not provided, valid values for radio properties are
+  ##   automatically retrieved using set function.
+  ## 
+  ## -"default": string.  If not provided the default value is
+  ##   automatically retrieved using get function.
+  ##
+  ## -"printdefault": a boolean (def. true) that specifies whether the
+  ## default value should be printed.  It is useful for properties
+  ## like root "screendepth" that default to screen dependant values. 
+
+  packopt = @(c) strjoin (c, ' | ');
+  markdef = @(s) ["@{" s "@}"];
+  
+  ## Some generic templates: 
+  valid_color = "colorspec";
+  valid_handle = "graphics handle";
+  valid_string = "string";
+  valid_fcn = packopt ({"string", "function handle"});
+  valid_cellstring = packopt ({"string", "cell array of strings"});
+  valid_2elvec = "two elements vector";
+  valid_3elvec = "three elements vector";
+  valid_4elvec = "four elements vector";
+  valid_vecmat = packopt ({"vector", "matrix"});
+  valid_scalmat = packopt ({"scalar", "matrix"});
+  
+  doc_notimpl =  "%s is not yet implemented for __objname__ \
+objects.  __prop__ is unused.";
+  doc_unused =  "__prop__ is unused.";
+
+
+  ## Initialize structure
+  if (isfield (base, field))
+    s = base.(field);
+  else
+    s = struct ("valid", "", "default", "", "doc", "", ...
+                "printdefault", true);
+  endif
+
+  ## Base properties: write generic documentation as it will, by
+  ## default, be included in the list of each graphics object.
+  ## If a given graphics object interprets the property differently
+  ## than most others, the doc will have to be rewritten for this object. 
+  if (strcmp (objname, "base"))
+    switch field
+      case "beingdeleted"
+      case "busyaction"
+      case "buttondownfcn"
+        s.valid = valid_fcn;
+      case "children"
+        s.doc = "Graphics handles of the __objname__'s children.";
+        s.valid = "vector of graphics handles";
+        
+      case "clipping"
+        s.doc = "If __prop__ is @qcode{\"on\"}, the __objname__ is \
+clipped in its parent axes limits.";
+        
+      case "createfcn"
+        s.doc = "Callback functions to be executed right after \
+the __objname__ has been created.  Those functions have to be set by \
+default using e.g.  @code{set (0, \"default__objname__createfcn\", \
+'disp (\"__objname__ created!\")') }.";
+        s.valid = valid_fcn;
+        
+      case "deletefcn"
+        s.doc = "Callback functions to be executed right before \
+the __objname__ is deleted.";
+        s.valid = valid_fcn;
+        
+      case "handlevisibility"
+        s.doc = "If __prop__ is @qcode{\"off\"}, the __objname__'s \
+handle is not visible into its parent's children list.";
+        
+      case "hittest"
+      case "interruptible"
+      case "parent"
+        s.doc = "Handle of the parent graphics object.";
+        s.valid = valid_handle;
+        
+      case "selected"
+      case "selectionhighlight"
+      case "tag"
+        s.valid = valid_string;
+        
+      case "type"
+        s.doc = "Class name of the graphics object.  __prop__ is \
+always @qcode{\"__objname__\"}";
+        s.valid = valid_string;
+        s.printdefault = false;
+        
+      case "uicontextmenu"
+      case "userdata"
+      case "visible"
+        s.doc = "If __prop__ is @qcode{\"off\"}, the __objname__ is \
+not rendered on screen.";
+    endswitch
+    
+  ## Root properties: 
+  elseif (strcmp (objname, "root"))
+    switch field
+      ## Overridden shared properties
+      case {"beingdeleted", "busyaction", "buttondownfcn", ...
+            "clipping", "createfcn", "deletefcn", "handlevisibility", ...
+            "hittest", "interruptible", "selected", ...
+            "selectionhighlight", "uicontextmenu", "visible"}
+        s.doc = doc_unused;
+        
+      case "parent"
+        s.doc = "Root figure has no parent graphics object.  __prop__ \
+is always empty.";
+        
+      ## Specific properties
+      case "callbackobject"
+        s.valid = valid_handle;
+        
+      case "commandwindowsize"
+      case "currentfigure"
+        s.doc = "Graphics handle of the current figure.";
+        s.valid = valid_handle;
+        
+      case "diary"
+        s.doc = "If __prop__ is @qcode{\"on\"}, the octave \
+command window session is saved to file.  @xref{XREFrootdiaryfile, , \
+diaryfile property}.";
+        s.valid = valid_string;
+        
+      case "diaryfile"
+        s.doc = "The name of the diary file.  \
+@xref{XREFdiary, , diary function}.";
+        s.valid = valid_string;
+        
+      case "echo"
+        s.doc = "Control whether octave displays commands executed \
+from scripts.  @xref{XREFecho, , echo function}.";
+        
+      case "errormessage"
+        s.doc = "The last error message octave raised.  \
+@xref{XREFlasterr, , lasterr function}.";
+        s.valid = valid_string;
+        
+      case "fixedwidthfontname"
+        s.valid = valid_string;
+        
+      case "format"
+        s.doc = "This property is a wrapper around @code{format} \
+function.  @xref{XREFformat, , format function}.";
+        
+      case "formatspacing"
+        s.doc = "This property is a wrapper around @code{format} \
+function.  @xref{XREFformat, , format function}.";
+        
+      case "language"
+        s.valid = valid_string;
+        
+      case "monitorpositions"
+        s.valid = valid_4elvec;
+        
+      case "pointerlocation"
+        s.valid = valid_2elvec;
+        
+      case "pointerwindow"
+        s.valid = valid_handle;
+        
+      case "recursionlimit"
+        s.doc = "The maximum number of times a function can be \
+called recursively.  @xref{XREFmax_recursion_depth, , \
+max_recursion_depth function}.";
+        s.valid = "double";
+        
+      case "screendepth"
+        s.valid = "double";
+        s.printdefault = false;
+        
+      case "screenpixelsperinch"
+        s.valid = "double";
+        s.printdefault = false;
+        
+      case "screensize"
+        s.valid = valid_4elvec;
+        s.printdefault = false;
+        
+      case "showhiddenhandles"
+        s.doc = "If __prop__ is @qcode{\"on\"}, all graphics objects \
+handle are visible in their parents' children list, regardless of \
+the value of their @code{handlevisibility} property."; 
+        
+      case "units"
+    endswitch
+
+  ## Figure properties
+  elseif (strcmp (objname, "figure"))
+    switch field
+      ## Overridden shared properties
+      case "clipping"
+        s.doc = doc_unused;
+
+      ## Specific properties
+      case "alphamap"
+        s.doc = sprintf (doc_notimpl, "Transparency");
+      case "closerequestfcn"
+        s.valid = valid_fcn;
+        
+      case "color"
+        s.doc = "Color of the figure background.  @xref{Colors, , \
+colorspec}.";
+        s.valid = valid_color;
+        
+      case "colormap"
+        s.doc = "A matrix containing the RGB color map for \
+the current axes.";
+        s.valid = "N-by-3 matrix";
+        
+      case "currentaxes"
+        s.doc = "Handle to the graphics object of the current axes.";
+        s.valid = valid_handle;
+        
+      case "currentcharacter"
+        s.doc = doc_unused;
+        
+      case "currentobject"
+        s.valid = valid_handle;
+        
+      case "currentpoint"
+        s.doc = "A 1-by-2 matrix which holds the coordinates of \
+the point over which the mouse pointer was when a mouse event \
+occurred.  The x and y coordinates are in units defined by the \
+figures @qcode{\"units\"} property and their origin is the lower \
+left corner of the plotting area.\
+\n\nEvents which set @qcode{\"currentpoint\"} are\n\
+@table @asis\n\
+@item A mouse button was pressed\n\
+always\n\
+@item A mouse button was released\n\
+only if the figures callback @qcode{\"windowbuttonupfcn\"} is defined\n\
+@item The pointer was moved while pressing mouse button (drag)\n\
+ only if the figures callback @qcode{\"windowbuttonmotionfcn\"} is \
+defined \n\
+@end table";
+        s.valid = valid_2elvec;
+        
+      case "dockcontrols"
+        s.doc = doc_unused;
+        
+      case "doublebuffer"
+      case "filename"
+      case "integerhandle"
+      case "inverthardcopy"
+      case "keypressfcn"
+        s.valid = valid_fcn;
+        
+      case "keyreleasefcn"
+        s.doc = "With @code{keypressfcn}, the keyboard callback \
+functions.  These callback functions get called when a key is \
+pressed/released respectively.  The functions are called with two \
+input arguments.  The first argument holds the handle of the calling \
+figure.  The second argument holds the event structure which has the \
+following members:\n\
+@table @code\n\
+@item Character:\n\
+The ASCII value of the key\n\
+@item Key:\n\
+lowercase value of the key\n\
+@item Modifier:\n\
+A cell array containing strings representing the modifiers pressed \
+with the key.\n\
+@end table";
+        s.valid = valid_fcn;
+        
+      case "menubar"
+      case "mincolormap"
+      case "name"
+        s.doc = "Name to be displayed in the figure title bar.  If \
+__prop__ is empty, the title of the figure is \"figure\" followed \
+by the figure handle value.";
+        s.valid = valid_string;
+        
+      case "nextplot"
+      case "numbertitle"
+      case "outerposition"
+        s.valid = valid_4elvec;
+        
+      case "paperorientation"
+      case "paperposition"
+        s.doc = "Vector @qcode{[x0 y0 width height]} defining the \
+position of the figure (in @code{paperunits} units) in the printed \
+page.  __modemsg__."; 
+        s.valid = valid_4elvec;
+        
+      case "paperpositionmode"
+        s.doc = "If __prop__ is set to @qcode{\"auto\"}, the \
+@qcode{\"paperposition\"} property is automatically computed: the \
+printed figure will have the same size as on-screen figure and will \
+be centered in the output page."; 
+      case "papersize"
+        s.doc = "Vector @qcode{[width height]} defining the size of the \
+printing paper.  Setting this property forces the @code{papertype} \
+property to be set to @qcode{\"<custom>\"}.";
+        s.valid = valid_2elvec;
+        
+      case "papertype"
+        s.doc = "Name of the paper to be used for printed output.  \
+Setting __prop__ also changes @code{papersize} accordingly.";
+        
+      case "paperunits"
+        s.doc = "The unit used to compute the @code{paperposition} \
+property.";
+        
+      case "pointer"
+      case "pointershapecdata"
+        s.doc = doc_unused;
+        
+      case "pointershapehotspot"
+        s.doc = doc_unused;
+        
+      case "position"
+        s.valid = valid_4elvec;
+        
+      case "renderer"
+      case "renderermode"
+      case "resize"
+      case "resizefcn"
+        s.valid = valid_fcn;
+        
+      case "selectiontype"
+      case "toolbar"
+      case "units"
+        s.doc = "The unit used to compute the @code{position} and \
+@code{outerposition} properties.";
+      case "windowbuttondownfcn" 
+        s.doc = "@xref{XREFfigurewindowbuttonupfcn, , \
+windowbuttonupfcn property}.";
+        s.valid = valid_fcn;
+        
+      case "windowbuttonmotionfcn"
+        s.doc = "@xref{XREFfigurewindowbuttonupfcn, , \
+windowbuttonupfcn property}.";
+        s.valid = valid_fcn;
+        
+      case "windowbuttonupfcn"
+        s.doc = "With @code{windowbuttondownfcn} and \
+@code{windowbuttonmotionfcn}, the mouse callback functions.  These \
+callback functions get called when the mouse button is pressed, \
+dragged, and released respectively.  When these callback functions \
+are called, the @code{currentpoint} property holds the current \
+coordinates of the cursor.";
+        s.valid = valid_fcn;
+        
+      case "windowkeypressfcn"
+        s.valid = valid_fcn;
+        
+      case "windowkeyreleasefcn"
+        s.valid = valid_fcn;
+        
+      case "windowscrollwheelfcn"
+        s.valid = valid_fcn;
+        
+      case "windowstyle"
+      case "wvisual"
+      case "wvisualmode"
+      case "xdisplay"
+      case "xvisual"
+      case "xvisualmode"
+      case "__graphics_toolkit__"
+        s.doc = "The graphics toolkit that is used to render the \
+figure.  @xref{XREFavailable_graphics_toolkits, , \
+available_graphics_toolkits function}.";
+    endswitch
+    
+  ## Axes properties
+  elseif (strcmp (objname, "axes"))
+    switch field
+      ## Overridden shared properties
+      case "clipping"
+        s.doc = doc_unused;
+
+      ## Specific properties
+      case "activepositionproperty"
+      case "alim"
+        s.doc = sprintf (doc_notimpl, "Transparency");
+      case "alimmode"
+      case "ambientlightcolor"
+        s.doc = sprintf (doc_notimpl, "Light");
+      case "box"
+        s.doc = "Control wether the axes has a surrounding box.";
+        
+      case "cameraposition"
+        s.valid = valid_3elvec;
+        
+      case "camerapositionmode"
+      case "cameratarget"
+        s.valid = valid_3elvec;
+        
+      case "cameratargetmode"
+      case "cameraupvector"
+        s.valid = valid_3elvec;
+        
+      case "cameraupvectormode"
+      case "cameraviewangle"
+        s.valid = "scalar";
+        
+      case "cameraviewanglemode"
+      case "clim"
+        s.valid = valid_2elvec;
+        s.doc = "Define the limits for the color axis of image \
+children.  __modemsg__.  @xref{XREFpcolor, , pcolor function}.";
+        
+      case "climmode"
+      case "color"
+        s.doc = "Color of the axes background.  @xref{Colors, , \
+colorspec}.";
+        s.valid = valid_color;
+        
+      case "colororder"
+        s.doc = "RGB values to be used by plot function for \
+automatic line coloring.";
+        s.valid = "N-by-3 RGB matrix";
+        
+      case "currentpoint"
+        s.doc = "Matrix @qcode{[xf, yf, zf; xb, yb, zb]} which holds \
+the coordinates of the point over which the mouse pointer was when \
+the mouse button was pressed in axes data units.  If a mouse \
+callback function is defined, @code{currentpoint} holds the \
+pointer coordinates at the time the mouse button was pressed.  For \
+3D plots, the first row of the returned matrix specifies the point \
+nearest to the current camera position and the second rows the \
+furthest point.  The two points forms a line which is perpendicular \
+to the screen.";
+        s.valid = "2-by-3 matrix";
+        
+      case "dataaspectratio"
+        s.doc = "Specify the relative height and width of the data \
+displayed in the axes.  Setting @code{dataaspectratio} to @samp{[1, \
+2]} causes the length of one unit as displayed on the y-axis to be \
+the same as the length of 2 units on the x-axis.  __modemsg__.";
+        s.valid = valid_3elvec;
+        
+      case "dataaspectratiomode"
+      case "drawmode"
+      case "fontangle"
+      case "fontname"
+        s.doc = "Name of the font to be used for axes annotations.";
+        s.valid = valid_string;
+        
+      case "fontsize"
+        s.doc = "Size of the font to be used for axes annotations.  \
+@xref{XREFaxesfontunits, , fontunits property}.";
+        s.valid = "scalar";
+        
+      case "fontunits"
+        s.doc = "Unit used to interpret @code{fontsize} property.";
+        
+      case "fontweight"
+      case "gridlinestyle"
+      case "interpreter"
+      case "layer"
+      case "linestyleorder"
+      case "linewidth"
+      case "minorgridlinestyle"
+      case "nextplot"
+      case "outerposition"
+        s.doc = "Specify the position of the plot, including titles, \
+axes and legend.  The four elements of the vector are the \
+coordinates of the lower left corner and width and height of the \
+plot, in units normalized to the width and height of the plot \
+window.  For example, @qcode{[0.2, 0.3, 0.4, 0.5]} sets the lower \
+left corner of the axes at @math{(0.2, 0.3)} and the width and \
+height to be 0.4 and 0.5 respectively.  @xref{XREFaxesposition, , position property}.";
+        s.valid = valid_4elvec;
+        
+      case "plotboxaspectratio"
+      case "plotboxaspectratiomode"
+      case "position"
+        s.doc = "Specify the position of the plot, excluding titles, \
+axes and legend.  The four elements of the vector are the \
+coordinates of the lower left corner and width and height of the \
+plot, in units normalized to the width and height of the plot \
+window.  For example, @qcode{[0.2, 0.3, 0.4, 0.5]} sets the lower \
+left corner of the axes at @math{(0.2, 0.3)} and the width and \
+height to be 0.4 and 0.5 respectively.  @xref{XREFaxesouterposition, , \
+outerposition property}."; 
+        s.valid = valid_4elvec;
+        
+      case "projection"
+      case "tickdir"
+      case "tickdirmode"
+      case "ticklength"
+      case "tightinset"
+      case "title"
+        s.doc = "Graphics handle of the title text object.";
+        s.valid = valid_handle;
+        
+      case "units"
+      case "view"
+        s.doc = "Specify the view point for three-dimensional plots";
+        s.valid = valid_2elvec;
+        
+      case "xaxislocation"
+      case "xcolor"
+        s.doc = "Color of the x-axis.  @xref{Colors, , colorspec}.";
+        s.valid = packopt ({markdef(valid_color), ...
+                            "@qcode{\"none\"}"});
+        
+      case "xdir"
+      case "xgrid"
+        s.doc = "Control wether major x grid lines are displayed.";
+        
+      case "xlabel"
+        s.doc = "Graphics handle of the x label text object.";
+        s.valid = valid_handle;
+        
+      case "xlim"
+        s.doc = "Specify the limits for x-axis.  __modemsg__.  \
+@xref{XREFxlim, , xlim function}.";
+        s.valid = valid_2elvec;
+        
+      case "xlimmode"
+      case "xminorgrid"
+        s.doc = "Control wether minor x grid lines are displayed.";
+        
+      case "xminortick"
+      case "xscale"
+      case "xtick"
+        s.doc = "Position of x tick marks.  __modemsg__.";
+        s.valid = "vector";
+        
+      case "xticklabel"
+        s.doc = "Labels of x tick marks.  __modemsg__.";
+        s.valid = valid_cellstring;
+        
+      case "xticklabelmode"
+      case "xtickmode"
+      case "yaxislocation"
+      case "ycolor"
+        s.doc = "Color of the y-axis.  @xref{Colors, , colorspec}.";
+        s.valid = packopt ({markdef(valid_color), ...
+                            "@qcode{\"none\"}"});
+        
+      case "ydir"
+      case "ygrid"
+        s.doc = "Control wether major y grid lines are displayed.";
+        
+      case "ylabel"
+        s.doc = "Graphics handle of the y label text object.";
+        s.valid = valid_handle;
+        
+      case "ylim"
+        s.doc = "Specify the limits for y-axis.  __modemsg__.  \
+@xref{XREFylim, , ylim function}.";
+        s.valid = valid_2elvec;
+        
+      case "ylimmode"
+      case "yminorgrid"
+        s.doc = "Control wether minor y grid lines are displayed.";
+        
+      case "yminortick"
+      case "yscale"
+      case "ytick"
+        s.doc = "Position of y tick marks.  __modemsg__.";
+        s.valid = "vector";
+        
+      case "yticklabel"
+        s.doc = "Labels of y tick marks.  __modemsg__.";
+        s.valid = valid_cellstring;
+        
+      case "yticklabelmode"
+      case "ytickmode"
+      case "zcolor"
+        s.doc = "Color of the z-axis.  @xref{Colors, , colorspec}.";
+        s.valid = packopt ({markdef(valid_color), ...
+                            "@qcode{\"none\"}"});
+        
+      case "zdir"
+      case "zgrid"
+        s.doc = "Control wether major z grid lines are displayed.";
+        
+      case "zlabel"
+        s.doc = "Graphics handle of the z label text object.";
+        s.valid = valid_handle;
+        
+      case "zlim"
+        s.doc = "Specify the limits for z-axis.  __modemsg__.  \
+@xref{XREFzlim, , zlim function}.";
+        s.valid = valid_2elvec;
+        
+      case "zlimmode"
+      case "zminorgrid"
+        s.doc = "Control wether minor z grid lines are displayed.";
+        
+      case "zminortick"
+      case "zscale"
+      case "ztick"
+        s.doc = "Position of z tick marks.  __modemsg__.";
+        s.valid = "vector";
+        
+      case "zticklabel"
+        s.doc = "Labels of z tick marks.  __modemsg__.";
+        s.valid = valid_cellstring;
+        
+      case "zticklabelmode"
+      case "ztickmode"
+    endswitch
+    
+  ## Line properties
+  elseif (strcmp (objname, "line"))
+    switch field
+      ## Overridden shared properties
+      case "children"
+        s.doc = doc_unused;
+        
+      ## Specific properties
+      case "color"
+        s.doc = "Color of the line object.  @xref{Colors, , \
+colorspec}.";
+        s.valid = valid_color;
+        
+      case "displayname"
+        s.doc = "The text of the legend entry corresponding to this \
+line.";
+        s.valid = valid_cellstring;
+        
+      case "erasemode"
+        s.doc = doc_unused;
+        
+      case "interpreter"
+      case "linestyle"
+        s.doc = "@xref{Line Styles}.";
+        
+      case "linewidth"
+        s.doc = "Width in points of the line object.";
+        
+      case "marker"
+        s.doc = "The shape of the marker to be used.  @xref{Marker \
+Styles}.";
+        
+      case "markeredgecolor"
+        s.doc = "Color of the edge of the markers.  If set \
+@qcode{\"auto\"}, the markers edges have the same color as the line.  If \
+set @qcode{\"none\"}, the markers edges are not displayed.  This property \
+can also be set to any color.  @xref{Colors, , colorspec}.";
+        
+      case "markerfacecolor"
+        s.doc = "Color of the face of the markers.  If set \
+@qcode{\"auto\"}, the markers faces have the same color as the line.  If \
+set @qcode{\"none\"}, the markers faces are not displayed.  This property \
+can also be set to any color.  @xref{Colors, , colorspec}.";
+        
+      case "markersize"
+        s.doc = "Size of the markers  in points.";
+        s.valid = "scalar";
+        
+      case "xdata"
+        s.doc = "Vector of x data to be plotted.";
+        s.valid = "vector";
+        
+      case "xdatasource"
+        s.valid = valid_string;
+        s.doc = "Name of the vector in the current base workspace \
+that should be used as x data.";
+        
+      case "ydata"
+        s.doc = "Vector of y data to be plotted.";
+        s.valid = "vector";
+        
+      case "ydatasource"
+        s.valid = valid_string;
+        s.doc = "Name of the vector in the current base workspace \
+that should be used as y data.";
+        
+      case "zdata"
+        s.doc = "Vector of z data to be plotted.";
+        s.valid = "vector";
+        
+      case "zdatasource"
+        s.valid = valid_string;
+        s.doc = "Name of the vector in the current base workspace \
+that should be used as z data.";
+        
+    endswitch
+
+  ## Text properties
+  elseif (strcmp (objname, "text"))
+    switch field
+      ## Overridden shared properties
+      case "children"
+        s.doc = doc_unused;
+
+      ## Specific properties
+      case "backgroundcolor"
+        s.doc = sprintf (doc_notimpl, "Background area");
+        s.valid = valid_color;
+        
+      case "color"
+        s.doc = "Color of the text.  @xref{Colors, ,colorspec}.  ";
+        s.valid = valid_color;
+        
+      case "displayname"
+      case "edgecolor"
+        s.doc = sprintf (doc_notimpl, "Background area");
+        s.valid = valid_color;
+        
+      case "editing"
+      case "erasemode"
+        s.doc = doc_unused;
+        
+      case "extent"
+      case "fontangle"
+        s.doc = "Flag whether the font is italic or normal.  \
+@code{fontangle} is currently unused.";
+        
+      case "fontname"
+        s.doc = "The font used for the text.";
+        s.valid = valid_string;
+        
+      case "fontsize"
+        s.doc = "The font size of the text.";
+        s.valid = "scalar";
+        
+      case "fontunits"
+        s.doc = "The units used to interpret @code{fontsize} \
+property.";
+        
+      case "fontweight"
+        s.doc = "Flag whether the font is bold, etc.";
+        
+      case "horizontalalignment"
+      case "interpreter"
+      case "linestyle"
+        s.doc = sprintf (doc_notimpl, "Background area");
+        
+      case "linewidth"
+        s.doc = sprintf (doc_notimpl, "Background area");
+        s.valid = "scalar";
+        
+      case "margin"
+        s.doc = sprintf (doc_notimpl, "Background area");
+        s.valid = "scalar";
+        
+      case "position"
+        s.doc = "Vector @qcode{[X0 Y0 Z0]} where X0, Y0 and Z0 \
+indicate the position of the text anchor as defined by \
+@code{verticalalignment} and @code{horizontalalignment}.";
+        s.valid = valid_4elvec;
+        
+      case "rotation"
+        s.doc = "The angle of rotation for the displayed text, \
+measured in degrees.";
+        s.valid = "scalar";
+        
+      case "string"
+        s.doc = "The text object string content.";
+        s.valid = valid_string;
+        
+      case "units"
+      case "verticalalignment"
+    endswitch
+
+  ## Image properties
+  elseif (strcmp (objname, "image"))
+    switch field
+      ## Overridden shared properties
+      case "children"
+        s.doc = doc_unused;
+
+      ## Specific properties
+      case "alphadata"
+        s.doc = sprintf (doc_notimpl, "Transparency");
+        s.valid = valid_scalmat;
+        
+      case "alphadatamapping"
+        s.doc = sprintf (doc_notimpl, "Transparency");
+        
+      case "cdata"
+        s.valid = "matrix";
+        
+      case "cdatamapping"
+      case "displayname"
+        s.doc = "The text of the legend entry corresponding to this \
+image.";
+        s.valid = valid_cellstring;
+        
+      case "erasemode"
+        s.doc = doc_unused;
+        
+      case "xdata"
+        s.doc = "Two element vector @qcode{[xmin xmax]} specifying the x \
+coordinates of the first and last columns of the image.  \
+\n\nSetting @code{xdata} empty matrix makes octave automatically \
+affect it the value @qcode{[1 columns(image)]}.";
+        s.valid = valid_2elvec;
+        
+      case "ydata"
+        s.doc = "Vector @qcode{[ymin ymax]} specifying the y \
+coordinates of the first and last columns of the image.  \
+\n\nSetting @code{ydata} empty matrix makes octave automatically \
+affect it the value @qcode{[1 rows(image)]}.";
+        s.valid = valid_2elvec;
+        
+    endswitch
+    
+  ## Surface properties
+  elseif (strcmp (objname, "surface"))
+    switch field
+      ## Overridden shared properties
+      case "children"
+        s.doc = doc_unused;
+
+      ## Specific properties
+      case "alphadata"
+        s.doc = sprintf (doc_notimpl, "Transparency");
+        s.valid = valid_scalmat;
+        
+      case "alphadatamapping"
+        s.doc = sprintf (doc_notimpl, "Transparency");
+        
+      case "ambientstrength"
+        s.doc = sprintf (doc_notimpl, "Light");
+        
+      case "backfacelighting"
+        s.doc = sprintf (doc_notimpl, "Light");
+        
+      case "cdata"
+        s.valid = "matrix";
+        
+      case "cdatamapping"
+      case "cdatasource"
+      case "diffusestrength"
+        s.doc = sprintf (doc_notimpl, "Light");
+        
+      case "displayname"
+        s.doc = "The text of the legend entry corresponding to this \
+surface.";
+        
+      case "edgealpha"
+        s.doc = sprintf (doc_notimpl, "Transparency");
+        s.valid = "scalar";
+        
+      case "edgecolor"
+      case "edgelighting"
+        s.doc = sprintf (doc_notimpl, "Light");
+        
+      case "erasemode"
+        s.doc = doc_unused;
+      case "facealpha"
+        s.doc = sprintf (doc_notimpl, "Transparency");
+        s.valid = valid_scalmat;
+        
+      case "facecolor"
+      case "facelighting"
+        s.doc = sprintf (doc_notimpl, "Light");
+        
+      case "interpreter"
+      case "linestyle"
+        s.doc = "@xref{Line Styles}.";
+        
+      case "linewidth"
+        s.doc = "@xref{XREFlinelinewidth, , line linewidth \
+property}.";
+        
+      case "marker"
+        s.doc = "@xref{Marker Styles}.";
+        
+      case "markeredgecolor"
+        s.doc = "@xref{XREFlinemarkeredgecolor, , line \
+markeredgecolor property}."; 
+        
+      case "markerfacecolor"
+        s.doc = "@xref{XREFlinemarkerfacecolor, , line \
+markerfacecolor property}."; 
+        
+      case "markersize"
+        s.doc = "@xref{XREFlinemarkersize, , line \
+markersize property}."; 
+        s.valid = "scalar";
+        
+      case "meshstyle"
+      case "normalmode"
+      case "specularcolorreflectance"
+        s.doc = sprintf (doc_notimpl, "Light");
+        
+      case "specularexponent"
+        s.doc = sprintf (doc_notimpl, "Light");
+        
+      case "specularstrength"
+        s.doc = sprintf (doc_notimpl, "Light");
+        
+      case "vertexnormals"
+      case "xdata"
+        s.valid = "matrix";
+        
+      case "xdatasource"
+      case "ydata"
+        s.valid = "matrix";
+        
+      case "ydatasource"
+      case "zdata"
+        s.valid = "matrix";
+        
+      case "zdatasource"
+    endswitch
+    
+  ## Patch properties
+  elseif (strcmp (objname, "patch"))
+    switch field
+      ## Overridden shared properties
+      case "children"
+        s.doc = doc_unused;
+
+      ## Specific properties
+      case "alphadatamapping"
+        s.doc = sprintf (doc_notimpl, "Transparency");
+        
+      case "ambientstrength"
+        s.doc = sprintf (doc_notimpl, "Light");
+        s.valid = "scalar";
+        
+      case "backfacelighting"
+        s.doc = sprintf (doc_notimpl, "Light");
+        
+      case "cdata"
+        s.doc = "Data defining the patch object color.\n\
+Patch color can be defined for faces or for vertices.  \n\n\
+If @code{cdata} is a scalar index into the current colormap or a RGB \
+triplet, it defines the color of all faces.  \n\n\
+If @code{cdata} is a N-by-1 vector of indices or a N-by-3 (RGB) \
+matrix, it defines the color of each one of the N faces.\n\n\
+If @code{cdata} is a N-by-M or a N-by-M-by-3 (RGB) \
+matrix, it defines the color all vertices.";
+        s.valid = valid_scalmat;
+        
+      case "diffusestrength"
+        s.doc = sprintf (doc_notimpl, "Light");
+        s.valid = "scalar";
+        
+      case "displayname"
+        s.doc = "The text of the legend entry corresponding to this \
+patch.";
+      case "edgealpha"
+        s.doc = sprintf (doc_notimpl, "Transparency");
+        s.valid = valid_scalmat;
+        
+      case "edgecolor"
+      case "edgelighting"
+        s.doc = sprintf (doc_notimpl, "Light");
+        
+      case "erasemode"
+        s.doc = doc_unused;
+        
+      case "facealpha"
+        s.doc = sprintf (doc_notimpl, "Transparency");
+        s.valid = valid_scalmat;
+        
+      case "facecolor"
+        ## Don't provide a default value, and mark colorspec with
+        ## braces, this forces the default rgb triplet to be displayed
+        s.valid = packopt ({markdef(valid_color), ...
+                            "@qcode{\"flat\"}", ...
+                            "@qcode{\"none\"}", ...
+                            "@qcode{\"interp\"}"});
+        
+      case "facelighting"
+        s.doc = sprintf (doc_notimpl, "Light");
+        
+      case "faces"
+      case "xdata"
+        s.valid = valid_vecmat;
+        
+      case "facevertexalphadata"
+        s.doc = sprintf (doc_notimpl, "Transparency");
+        s.valid = valid_scalmat;
+        
+      case "facevertexcdata"
+      case "interpreter"
+        s.doc = doc_unused;
+        
+      case "linestyle"
+      case "linewidth"
+      case "marker"
+        s.doc = "@xref{XREFlinemarker, , line marker property}.";
+        
+      case "markeredgecolor"
+        s.doc = "@xref{XREFlinemarkeredgecolor, , line \
+markeredgecolor property}."; 
+        
+      case "markerfacecolor"
+        s.doc = "@xref{XREFlinemarkerfacecolor, , line \
+markerfacecolor property}."; 
+        
+      case "markersize"
+        s.doc = "@xref{XREFlinemarkersize, , line \
+markersize property}."; 
+        s.valid = "scalar";
+        
+      case "normalmode"
+      case "specularcolorreflectance"
+        s.doc = sprintf (doc_notimpl, "Light");
+        s.valid = "scalar";
+        
+      case "specularexponent"
+        s.doc = sprintf (doc_notimpl, "Light");
+        s.valid = "scalar";
+        
+      case "specularstrength"
+        s.doc = sprintf (doc_notimpl, "Light");
+        s.valid = "scalar";
+        
+      case "vertexnormals"
+      case "vertices"
+        s.valid = valid_vecmat;
+        
+      case "xdata"
+        s.valid = valid_vecmat;
+        
+      case "ydata"
+        s.valid = valid_vecmat;
+        
+      case "zdata"
+        s.valid = valid_vecmat;
+        
+    endswitch
+  endif
+  
+  ## Replace keywords
+  if (! isempty (s.doc) && ! strcmp (objname, "base"))
+    s.doc = expand_doc (s.doc, field, objname);
+  endif
+  
+endfunction
+
+function strout = expand_doc (strin, field, objname)
+  strout = strrep (strin, "__objname__", objname);
+  strout = strrep (strout, "__prop__", ["@code{" field "}"]);
+
+  modemsg = "Setting @code{%s} also forces the @code{%smode} \
+property to be set to @qcode{\"manual\"}";
+  modemsg = sprintf (modemsg, field, field);
+  strout = strrep (strout, "__modemsg__", modemsg);
+endfunction
+
+function s = getstructure (objname, base = [])
+  hf = [];
+  if (! strcmp (objname, "root"))
+    ## Use an improbable figure number to avoid ishandle to return
+    ## true for 1 
+    hf = figure (2265465, "visible", "off");
+  endif
+
+  ## Build a default object to extract its properties list and default
+  ## values.
+  if (strcmp (objname, "base"))
+    ## Base properties are extracted from hggroup that only have 2
+    ## additional regular (non-hidden) properties, "displayname" and
+    ## "erasemode".
+    h = hggroup ();
+  elseif (strcmp (objname, "root"))
+    h = 0;
+  elseif (strcmp (objname, "figure"))
+    h = hf;
+  else
+    eval (["h = " objname " ();"]);
+  endif
+  
+  gprop = get (h);
+  sprop = set (h);
+
+  fields = fieldnames (gprop);
+  nf = numel (fields);
+  args = cell (2*nf, 1);
+  for ii = 1:nf
+    field = fields{ii};
+
+    ## Get hard coded documentation
+    val = getdoc (objname, field, base);
+    
+    ## Extract the default values that are not hard coded in getdoc
+    if (isempty (val.default) && val.printdefault)
+      val.default = getdefault (h, objname, field);
+    endif
+    
+    val.isreadonly = ! isfield (sprop, field);
+
+    ## Extract the valid values that are not hard coded in getdoc
+    if (! val.isreadonly && isempty (val.valid))
+      val.valid = sprop.(field);
+      if (! isempty (val.valid) &&
+          iscellstr (val.valid))
+        ## Add double quotes around string radio properties
+        val.valid = cellfun (@(s) ["@qcode{\"" s "\"}"], val.valid,
+                             "uniformoutput", false);
+        val.valid = strjoin (val.valid, ' | ');
+      endif
+    endif
+    
+    args{2*(ii-1)+1} = field;
+    args{2*ii} = val;
+  endfor
+
+  ## Build struct and remove unused fields in base properties
+  s = struct (args{:});
+
+  if (strcmp (objname, "base"))
+    s = rmfield (s, {"displayname", "erasemode"});
+  endif
+
+  if (isfigure (hf))
+    close (hf)
+  endif
+endfunction
+
+function def = getdefault (h, objname, field)         
+  ## This function is meant to be run without initialization file so
+  ## that the properties we get are the default.
+  def = get (h, field);
+  
+  ## Don't print default values for graphics handles
+  if (isscalar (def) && def != 0 && ishandle (def))
+    def = "";
+  else
+    if (ischar (def))
+      def = ["@qcode{\"" def "\"}"];
+    else
+      if ((isvector (def) && numel (def) < 5) ||
+          isempty (def))
+        ## Use disp to print the default value for short vectors and
+        ## empty values
+        str = disp (def);
+        str(end) = [];          # remove linefeed
+        str = strtrim (str);    # remove leading space
+
+        ## Add [] around vector values
+        if (ismatrix (def) && numel (def) > 1)
+          str = ["[" str "]"];
+          ## Add ";" between columns vector values
+          if (rows (def) != 1)
+            str = strrep (str, "\n", "; ");
+          endif
+        endif
+        
+        ## Replace texinfo reserved characters
+        def = strrep (str, "{", "@{");
+        def = strrep (def, "}", "@}");
+        def = strrep (def, "@", "@@");
+        
+        def = ["@code{" def "}"];
+      else
+        args = arrayfun (@(x) num2str (x), size (def),
+                         "uniformoutput", false); 
+        def = [strjoin(args, "-by-") " " class(def)];
+      endif
+    endif
+  endif
+endfunction
+
+function str = printdoc (objname, obj)
+  ## Sort fields so that they appear in alphabetic order in the manual
+  fields = sort (fieldnames (obj));
+  nf = numel (fields);
+
+  ## File header and begining of properties table
+  str = [warn_autogen() "\n\n@table @asis"];
+
+  
+  for ii = 1:nf 
+    field = fields{ii};
+    str = sprintf ("%s\n\n", str);
+
+    ## @anchor: cross reference using XREFobjnamefield label
+    ## Concept index: call info from octave with
+    ## 'doc ("objname field")' 
+    str = sprintf ("%s@anchor{XREF%s%s}\n@cindex %s %s\n",
+                   str, objname, field, objname, field);
+
+    ## Item
+    str = sprintf ("%s@item @code{%s}", str, field);
+
+    ## Mark item read-only if needed
+    if (obj.(field).isreadonly)
+      str = sprintf ("%s (read-only):", str);
+    else
+      str = sprintf ("%s:", str);
+    endif
+    
+    ## Print valid and default values
+    tmp = print_options (obj.(field).valid,
+                         obj.(field).default);
+    if (! isempty (tmp))
+      str = sprintf ("%s %s\n", str, tmp);
+    else
+      str = sprintf ("%s\n", str);
+    endif
+
+    ## Print documentation
+    str = sprintf ("%s%s\n", str, obj.(field).doc);
+  endfor
+  
+  ## End of properties table
+  str = sprintf ("%s\n@end table", str);
+endfunction
+
+function str = warn_autogen ()
+  str = "@c DO NOT EDIT!  Generated automatically by genpropdoc.m.\n\
+\n\
+@c Copyright (C) 2014 Pantxo Diribarne\n\
+@c\n\
+@c This file is part of Octave.\n\
+@c\n\
+@c Octave is free software; you can redistribute it and/or modify it\n\
+@c under the terms of the GNU General Public License as published by the\n\
+@c Free Software Foundation; either version 3 of the License, or (at\n\
+@c your option) any later version.\n\
+@c\n\
+@c Octave is distributed in the hope that it will be useful, but WITHOUT\n\
+@c ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n\
+@c FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n\
+@c for more details.\n\
+@c\n\
+@c You should have received a copy of the GNU General Public License\n\
+@c along with Octave; see the file COPYING.  If not, see\n\
+@c <http://www.gnu.org/licenses/>.";
+endfunction
+
+function str = print_options (val, default)
+  str = "";
+  if (! isempty (val))
+    tmp = strrep (val, default, ["@{" default "@}"]);
+    if (length (tmp) == length (val) && ! isempty (default))
+      str = [tmp ", def. " default];
+    else
+      str = tmp;
+    endif
+  elseif (! isempty (default))
+    str = ["def. " default];
+  endif
+endfunction
--- a/doc/interpreter/geometry.txi	Mon Jan 12 09:13:19 2015 -0800
+++ b/doc/interpreter/geometry.txi	Mon Jan 12 09:17:35 2015 -0800
@@ -20,7 +20,7 @@
 @chapter Geometry
 
 Much of the geometry code in Octave is based on the Qhull 
-library@footnote{Barber, C.B., Dobkin, D.P., and Huhdanpaa, H.T., 
+library@footnote{@nospell{Barber, C.B., Dobkin, D.P., and Huhdanpaa, H.T.}, 
 @cite{The Quickhull Algorithm for Convex Hulls}, ACM Trans. on Mathematical 
 Software, 22(4):469--483, Dec 1996, @url{http://www.qhull.org}}.  
 Some of the documentation for Qhull, particularly for the options that 
@@ -50,15 +50,11 @@
 
 @DOCSTRING(delaunay)
 
-The 3- and N-dimensional extension of the Delaunay triangulation are
-given by @code{delaunay3} and @code{delaunayn} respectively.  
-@code{delaunay3} returns a set of tetrahedra that satisfy the
+For 3-D inputs @code{delaunay} returns a set of tetrahedra that satisfy the
 Delaunay circum-circle criteria.  Similarly, @code{delaunayn} returns the
 N-dimensional simplex satisfying the Delaunay circum-circle criteria.  
 The N-dimensional extension of a triangulation is called a tessellation.
 
-@DOCSTRING(delaunay3)
-
 @DOCSTRING(delaunayn)
 
 An example of a Delaunay triangulation of a set of points is
@@ -417,12 +413,10 @@
 An important use of the Delaunay tessellation is that it can be used to
 interpolate from scattered data to an arbitrary set of points.  To do
 this the N-simplex of the known set of points is calculated with
-@code{delaunay}, @code{delaunay3} or @code{delaunayn}.  Then the
-simplices in to which the desired points are found are
-identified.  Finally the vertices of the simplices are used to
-interpolate to the desired points.  The functions that perform this
-interpolation are @code{griddata}, @code{griddata3} and
-@code{griddatan}.
+@code{delaunay} or @code{delaunayn}.  Then the simplices in to which the
+desired points are found are identified.  Finally the vertices of the simplices
+are used to interpolate to the desired points.  The functions that perform this
+interpolation are @code{griddata}, @code{griddata3} and @code{griddatan}.
 
 @DOCSTRING(griddata)
 
@@ -444,8 +438,7 @@
 @end example
 
 @noindent
-that interpolates from a random scattering of points, to a uniform
-grid. 
+that interpolates from a random scattering of points, to a uniform grid. 
 @ifnotinfo
 The output of the above can be seen in @ref{fig:griddata}.
 
--- a/doc/interpreter/grammar.txi	Mon Jan 12 09:13:19 2015 -0800
+++ b/doc/interpreter/grammar.txi	Mon Jan 12 09:17:35 2015 -0800
@@ -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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/interpreter/graphics_properties.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,34 @@
+GRAPH_PROP_TEXI_SRC= \
+  plot-axesproperties.texi \
+  plot-figureproperties.texi \
+  plot-imageproperties.texi \
+  plot-lineproperties.texi \
+  plot-patchproperties.texi \
+  plot-rootproperties.texi \
+  plot-surfaceproperties.texi \
+  plot-textproperties.texi
+
+
+plot-axesproperties.texi: genpropdoc.m
+	$(top_builddir)/run-octave -f -q -H -p $(srcdir) --eval "genpropdoc ('axes', '$@');" || { rm -f $@; exit 1; }
+
+plot-figureproperties.texi: genpropdoc.m
+	$(top_builddir)/run-octave -f -q -H -p $(srcdir) --eval "genpropdoc ('figure', '$@');" || { rm -f $@; exit 1; }
+
+plot-imageproperties.texi: genpropdoc.m
+	$(top_builddir)/run-octave -f -q -H -p $(srcdir) --eval "genpropdoc ('image', '$@');" || { rm -f $@; exit 1; }
+
+plot-lineproperties.texi: genpropdoc.m
+	$(top_builddir)/run-octave -f -q -H -p $(srcdir) --eval "genpropdoc ('line', '$@');" || { rm -f $@; exit 1; }
+
+plot-patchproperties.texi: genpropdoc.m
+	$(top_builddir)/run-octave -f -q -H -p $(srcdir) --eval "genpropdoc ('patch', '$@');" || { rm -f $@; exit 1; }
+
+plot-rootproperties.texi: genpropdoc.m
+	$(top_builddir)/run-octave -f -q -H -p $(srcdir) --eval "genpropdoc ('root', '$@');" || { rm -f $@; exit 1; }
+
+plot-surfaceproperties.texi: genpropdoc.m
+	$(top_builddir)/run-octave -f -q -H -p $(srcdir) --eval "genpropdoc ('surface', '$@');" || { rm -f $@; exit 1; }
+
+plot-textproperties.texi: genpropdoc.m
+	$(top_builddir)/run-octave -f -q -H -p $(srcdir) --eval "genpropdoc ('text', '$@');" || { rm -f $@; exit 1; }
--- a/doc/interpreter/gui.txi	Mon Jan 12 09:13:19 2015 -0800
+++ b/doc/interpreter/gui.txi	Mon Jan 12 09:17:35 2015 -0800
@@ -66,7 +66,7 @@
 
 These functions do not implement a GUI element but are useful when developing
 programs that do.  @strong{Warning:} The functions @code{uiwait},
-@code{uiresume}, and @code{waitfor} are only available for the FLTK tooolkit.
+@code{uiresume}, and @code{waitfor} are only available for the FLTK toolkit.
 
 @DOCSTRING(desktop)
 
--- a/doc/interpreter/image.txi	Mon Jan 12 09:13:19 2015 -0800
+++ b/doc/interpreter/image.txi	Mon Jan 12 09:17:35 2015 -0800
@@ -164,6 +164,8 @@
 
 @DOCSTRING(copper)
 
+@DOCSTRING(cubehelix)
+
 @DOCSTRING(flag)
 
 @DOCSTRING(gray)
--- a/doc/interpreter/install.txi	Mon Jan 12 09:13:19 2015 -0800
+++ b/doc/interpreter/install.txi	Mon Jan 12 09:17:35 2015 -0800
@@ -288,8 +288,7 @@
 @item Qhull
 Computational geometry library (@url{http://www.qhull.org}).  Qhull is
 required to provide the functions @code{convhull}, @code{convhulln}, 
-@code{delaunay}, @code{delaunay3}, @code{delaunayn}, @code{voronoi}, and
-@code{voronoin}.
+@code{delaunay}, @code{delaunayn}, @code{voronoi}, and @code{voronoin}.
 
 @item QRUPDATE
 QR factorization updating library
@@ -744,6 +743,7 @@
 Suggestions on how to compile ATLAS would be most welcome.
 
 @item @sc{glpk}
+
 @item Qhull (@url{http://www.qhull.org})
 
 Both @sc{glpk} and Qhull use @code{int} internally so maximum problem
@@ -856,7 +856,7 @@
 
 @noindent
 in the kernel configuration files (typically found in the directory
-@file{/sys/i386/conf}.  After making this change, you'll need to rebuild
+@file{/sys/i386/conf}).  After making this change, you'll need to rebuild
 the kernel, install it, and reboot.
 
 @item
@@ -1036,3 +1036,4 @@
 @env{FFLAGS} is set to @qcode{"-O"}.
 
 @end itemize
+
--- a/doc/interpreter/interp.txi	Mon Jan 12 09:13:19 2015 -0800
+++ b/doc/interpreter/interp.txi	Mon Jan 12 09:17:35 2015 -0800
@@ -176,7 +176,3 @@
 @end float
 @end ifnotinfo
 
-In additional the support function @code{bicubic} that underlies the
-cubic interpolation of @code{interp2} function can be called directly.
-
-@DOCSTRING(bicubic)
--- a/doc/interpreter/intro.txi	Mon Jan 12 09:13:19 2015 -0800
+++ b/doc/interpreter/intro.txi	Mon Jan 12 09:17:35 2015 -0800
@@ -334,9 +334,10 @@
 
 @noindent
 The function @code{lsode} uses the Livermore Solver for Ordinary
-Differential Equations, described in A. C. Hindmarsh, @cite{ODEPACK, a
-Systematized Collection of ODE Solvers}, in: Scientific Computing, R. S.
-Stepleman et al. (Eds.), North-Holland, Amsterdam, 1983, pages 55--64.
+Differential Equations, described in @nospell{A. C. Hindmarsh},
+@cite{ODEPACK, a Systematized Collection of ODE Solvers}, in: Scientific
+Computing, @nospell{R. S. Stepleman} et al. (Eds.), North-Holland, Amsterdam,
+1983, pages 55--64.
 
 @subsection Producing Graphical Output
 
--- a/doc/interpreter/io.txi	Mon Jan 12 09:13:19 2015 -0800
+++ b/doc/interpreter/io.txi	Mon Jan 12 09:17:35 2015 -0800
@@ -616,10 +616,26 @@
 @end table
 
 If the syntax of a conversion specification is invalid, unpredictable
-things will happen, so don't do this.  If there aren't enough function
-arguments provided to supply values for all the conversion
-specifications in the template string, or if the arguments are not of
-the correct types, the results are unpredictable.  If you supply more
+things will happen, so don't do this.  In particular, @sc{matlab} allows
+a bare percentage sign @samp{%} with no subsequent conversion character.
+Octave will emit an error and stop if it sees such code.  When the string
+variable to be processed cannot be guaranteed to be free of potential format
+codes it is better to use the two argument form of any of the @code{printf}
+functions and set the format string to @code{%s}.  Alternatively, for code
+which is not required to be backwards-compatible with @sc{matlab} the
+Octave function @code{puts} or @code{disp} can be used.
+
+@example
+@group
+printf (strvar);        # Unsafe if strvar contains format codes
+printf ("%s", strvar);  # Safe
+puts (strvar);          # Safe
+@end group
+@end example
+
+If there aren't enough function arguments provided to supply values for all
+the conversion specifications in the template string, or if the arguments are
+not of the correct types, the results are unpredictable.  If you supply more
 arguments than conversion specifications, the extra argument values are
 simply ignored; this is sometimes useful.
 
@@ -1006,7 +1022,11 @@
 
 @DOCSTRING(tmpfile)
 
-@DOCSTRING(tmpnam)
+@DOCSTRING(tempname)
+
+@DOCSTRING(tempdir)
+
+@DOCSTRING(P_tmpdir)
 
 @node EOF and Errors
 @subsection End of File and Errors
--- a/doc/interpreter/java.txi	Mon Jan 12 09:13:19 2015 -0800
+++ b/doc/interpreter/java.txi	Mon Jan 12 09:17:35 2015 -0800
@@ -163,9 +163,11 @@
 @cindex path, removing from classpath
 @DOCSTRING(javarmpath)
 
-The following four functions provide information and control over the interface
+The following functions provide information and control over the interface
 between Octave and the Java Virtual Machine.
 
+@DOCSTRING(javachk)
+
 @DOCSTRING(usejava)
 
 @cindex memory, displaying Java memory status
--- a/doc/interpreter/linalg.txi	Mon Jan 12 09:13:19 2015 -0800
+++ b/doc/interpreter/linalg.txi	Mon Jan 12 09:17:35 2015 -0800
@@ -21,18 +21,18 @@
 @cindex linear algebra
 
 This chapter documents the linear algebra functions provided in Octave.
-Reference material for many of these functions may be found in Golub and
-Van Loan, @cite{Matrix Computations, 2nd Ed.}, Johns Hopkins, 1989, and
-in the @cite{@sc{lapack} Users' Guide}, SIAM, 1992. The
-@cite{@sc{lapack} Users' Guide} is available at:
+Reference material for many of these functions may be found in
+@nospell{Golub and Van Loan}, @cite{Matrix Computations, 2nd Ed.},
+Johns Hopkins, 1989, and in the @cite{@sc{lapack} Users' Guide}, SIAM, 1992.
+The @cite{@sc{lapack} Users' Guide} is available at:
 @cite{http://www.netlib.org/lapack/lug/}
 
-A common text for engineering courses is G. Strang, @cite{Linear Algebra
-and Its Applications, 4th Edition}. It has become a widespread reference
-for linear algebra. An alternative is P. Lax @cite{Linear Algebra and
-Its Applications}, and also is a good choice. It claims to be suitable
-for high school students with substantial mathematical interests as well
-as first-year undergraduates.
+A common text for engineering courses is @nospell{G. Strang},
+@cite{Linear Algebra and Its Applications, 4th Edition}. It has become a
+widespread reference for linear algebra.  An alternative is P. Lax
+@cite{Linear Algebra and Its Applications}, and also is a good choice.  It
+claims to be suitable for high school students with substantial mathematical
+interests as well as first-year undergraduates.
 
 @menu
 * Techniques Used for Linear Algebra::
@@ -49,7 +49,7 @@
 Octave includes a polymorphic solver that selects an appropriate matrix
 factorization depending on the properties of the matrix itself.
 Generally, the cost of determining the matrix type is small relative to
-the cost of factorizing the matrix itself. In any case the matrix type
+the cost of factorizing the matrix itself.  In any case the matrix type
 is cached once it is calculated so that it is not re-determined each
 time it is used in a linear equation.
 
@@ -96,6 +96,8 @@
 
 @DOCSTRING(balance)
 
+@DOCSTRING(bandwidth)
+
 @DOCSTRING(cond)
 
 @DOCSTRING(det)
@@ -199,7 +201,7 @@
 
 @DOCSTRING(blkmm)
 
-@DOCSTRING(syl)
+@DOCSTRING(sylvester)
 
 @node Specialized Solvers
 @section Specialized Solvers
@@ -212,3 +214,4 @@
 @DOCSTRING(cgs)
 
 @DOCSTRING(gmres)
+
--- a/doc/interpreter/macros.texi	Mon Jan 12 09:13:19 2015 -0800
+++ b/doc/interpreter/macros.texi	Mon Jan 12 09:17:35 2015 -0800
@@ -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/matrix.txi	Mon Jan 12 09:13:19 2015 -0800
+++ b/doc/interpreter/matrix.txi	Mon Jan 12 09:17:35 2015 -0800
@@ -90,7 +90,7 @@
 
 @DOCSTRING(flipud)
 
-@DOCSTRING(flipdim)
+@DOCSTRING(flip)
 
 @DOCSTRING(rot90)
 
--- a/doc/interpreter/mk_doc_cache.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/doc/interpreter/mk_doc_cache.m	Mon Jan 12 09:17:35 2015 -0800
@@ -133,5 +133,5 @@
 
 cache(:,k:end) = [];    # delete unused pre-allocated entries
 
-save_header_format_string (["# doc-cache created by Octave " OCTAVE_VERSION ", %a %b %d %H:%M:%S %Y %Z"]);
+save_header_format_string (["# doc-cache created by Octave " OCTAVE_VERSION]);
 save ("-text", output_file, "cache");
--- a/doc/interpreter/munge-texi.pl	Mon Jan 12 09:13:19 2015 -0800
+++ b/doc/interpreter/munge-texi.pl	Mon Jan 12 09:17:35 2015 -0800
@@ -68,7 +68,7 @@
   }
   if (/^\s*\@EXAMPLEFILE\((\S+)\)/)
   {
-    $fname = "$top_srcdir/examples/$1";
+    $fname = "$top_srcdir/examples/code/$1";
     print '@verbatim',"\n";
     open (EXAMPFH, $fname) or die "unable to open example file $fname\n";
     while (<EXAMPFH>) 
--- a/doc/interpreter/numbers.txi	Mon Jan 12 09:13:19 2015 -0800
+++ b/doc/interpreter/numbers.txi	Mon Jan 12 09:17:35 2015 -0800
@@ -311,11 +311,11 @@
 @subsection Empty Matrices
 
 A matrix may have one or both dimensions zero, and operations on empty
-matrices are handled as described by Carl @nospell{de} Boor in @cite{An Empty
-Exercise}, SIGNUM, Volume 25, pages 2-6, 1990 and C. N. Nett and W. M.
-Haddad, in @cite{A System-Theoretic Appropriate Realization of the Empty
-Matrix Concept}, IEEE Transactions on Automatic Control, Volume 38,
-Number 5, May 1993.
+matrices are handled as described by @nospell{Carl de Boor} in
+@cite{An Empty Exercise}, SIGNUM, Volume 25, pages 2-6, 1990 and
+@nospell{C. N. Nett and W. M. Haddad}, in
+@cite{A System-Theoretic Appropriate Realization of the Empty Matrix Concept},
+IEEE Transactions on Automatic Control, Volume 38, Number 5, May 1993.
 @tex
 Briefly, given a scalar $s$, an $m\times n$ matrix $M_{m\times n}$,
 and an $m\times n$ empty matrix $[\,]_{m\times n}$ (with either one or
@@ -396,7 +396,7 @@
 defines the set of values @samp{[ 1, 4 ]}.
 
 Although a range constant specifies a row vector, Octave does @emph{not}
-convert range constants to vectors unless it is necessary to do so.
+normally convert range constants to vectors unless it is necessary to do so.
 This allows you to write a constant like @samp{1 : 10000} without using
 80,000 bytes of storage on a typical 32-bit workstation.
 
@@ -420,6 +420,11 @@
 defines @var{y} to be of type @code{matrix} and occupies 88 bytes of
 memory.
 
+This space saving optimization may be disabled using the function
+@dfn{disable_range}.
+
+@DOCSTRING(disable_range)
+
 Note that the upper (or lower, if the increment is negative) bound on
 the range is not always included in the set of values, and that ranges
 defined by floating point values can produce surprising results because
@@ -811,6 +816,8 @@
 
 @DOCSTRING(isnumeric)
 
+@DOCSTRING(islogical)
+
 @DOCSTRING(isfloat)
 
 @DOCSTRING(isreal)
@@ -835,7 +842,13 @@
 
 @DOCSTRING(isdefinite)
 
-@DOCSTRING(islogical)
+@DOCSTRING(isbanded)
+
+@DOCSTRING(isdiag)
+
+@DOCSTRING(istril)
+
+@DOCSTRING(istriu)
 
 @DOCSTRING(isprime)
 
--- a/doc/interpreter/optim.txi	Mon Jan 12 09:13:19 2015 -0800
+++ b/doc/interpreter/optim.txi	Mon Jan 12 09:17:35 2015 -0800
@@ -139,6 +139,8 @@
 
 @DOCSTRING(lsqnonneg)
 
+@DOCSTRING(lscov)
+
 @DOCSTRING(optimset)
 
 @DOCSTRING(optimget)
--- a/doc/interpreter/plot.txi	Mon Jan 12 09:13:19 2015 -0800
+++ b/doc/interpreter/plot.txi	Mon Jan 12 09:17:35 2015 -0800
@@ -63,6 +63,7 @@
 * Plot Annotations::
 * Multiple Plots on One Page::
 * Multiple Plot Windows::
+* Manipulation of Plot Objects::
 * Manipulation of Plot Windows::
 * Use of the @code{interpreter} Property::
 * Printing and Saving Plots::
@@ -232,10 +233,16 @@
 
 @DOCSTRING(area)
 
+@DOCSTRING(fill)
+
 @DOCSTRING(comet)
 
 @DOCSTRING(comet3)
 
+@DOCSTRING(frame2im)
+
+@DOCSTRING(im2frame)
+
 @node Axis Configuration
 @subsubsection Axis Configuration
 
@@ -530,6 +537,18 @@
 
 @DOCSTRING(figure)
 
+@node Manipulation of Plot Objects
+@subsection Manipulation of Plot Objects
+@cindex plotting, object manipulation
+
+@DOCSTRING(pan)
+
+@DOCSTRING(rotate)
+
+@DOCSTRING(rotate3d)
+
+@DOCSTRING(zoom)
+
 @node Manipulation of Plot Windows
 @subsection Manipulation of Plot Windows
 @cindex plotting, window manipulation
@@ -541,7 +560,7 @@
 @DOCSTRING(drawnow)
 
 Only figures that are modified will be updated.  The @code{refresh}
-function can also be used to force an update of the current figure, even if
+function can also be used to cause an update of the current figure, even if
 it is not modified.
 
 @DOCSTRING(refresh)
@@ -950,6 +969,17 @@
 
 @DOCSTRING(orient)
 
+@code{print} and @code{saveas} are used when work on a plot has finished
+and the output must be in a publication-ready format.  During intermediate
+stages it is often better to save the graphics object and all of its
+associated information so that changes---to colors, axis limits, marker styles,
+etc.---can be made easily from within Octave.  The @code{hgsave}/@code{hgload}
+commands can be used to save and re-create a graphics object.
+
+@DOCSTRING(hgsave)
+
+@DOCSTRING(hgload)
+
 @node Interacting with Plots
 @subsection Interacting with Plots
 
@@ -994,45 +1024,46 @@
 @anchor{XREFgraphics structures}
 
 The graphics functions use pointers, which are of class graphics_handle, in
-order to address the data structures which control graphical displays.  A
-graphics handle may point any one of a number of different object types.  The
-objects are the graphics data structures.  The types of objects are:
-@code{figure}, @code{axes}, @code{line}, @code{text}, @code{patch},
-@code{surface}, @code{text} and @code{image}.
-
-Each of these objects has a function by the same name. and, each of these
-functions returns a graphics handle pointing to an object of corresponding
+order to address the data structures which control visual display.  A
+graphics handle may point to any one of a number of different base object
+types and these objects are the graphics data structures themselves.  The
+primitive graphic object types are: @code{figure}, @code{axes}, @code{line},
+@code{text}, @code{patch}, @code{surface}, @code{text}, and @code{image}.
+
+Each of these objects has a function by the same name, and, each of these
+functions returns a graphics handle pointing to an object of the corresponding
 type.  In addition there are several functions which operate on properties of
-the graphics objects and which return handles: the functions @code{ plot} and
-@code{plot3} return a handle pointing to an object of type line, the function
-@code{subplot} returns a handle pointing to an object of type axes, the
-function @code{fill} returns a handle pointing to an object of type patch, the
-functions @code{area}, @code{bar}, @code{barh}, @code{contour},
+the graphics objects and which also return handles: the functions @code{plot}
+and @code{plot3} return a handle pointing to an object of type line, the
+function @code{subplot} returns a handle pointing to an object of type axes,
+the function @code{fill} returns a handle pointing to an object of type patch,
+the functions @code{area}, @code{bar}, @code{barh}, @code{contour},
 @code{contourf}, @code{contour3}, @code{surf}, @code{mesh}, @code{surfc},
 @code{meshc}, @code{errorbar}, @code{quiver}, @code{quiver3}, @code{scatter},
 @code{scatter3}, @code{stair}, @code{stem}, @code{stem3} each return a handle
-as documented in @ref{XREFdatasources,,Data Sources}.
-
+to a complex data structure as documented in
+@ref{XREFdatasources,,Data Sources}.
 
 The graphics objects are arranged in a hierarchy:
 
-1. The root is at 0.  i.e., @code{get (0)} returns the properties of the root
-   object.
+1. The root is at 0.  In other words, @code{get (0)} returns the properties of
+the root object.
 
 2. Below the root are @code{figure} objects.
 
-3. Below the @code{figure} objects are @code{axes}.
-
-4. Below the @code{axes} objects are
-@code{line}, @code{text}, @code{patch},
+3. Below the @code{figure} objects are @code{axes} objects.
+
+4. Below the @code{axes} objects are @code{line}, @code{text}, @code{patch},
 @code{surface}, and @code{image} objects.
 
 Graphics handles may be distinguished from function handles
 (@pxref{Function Handles}) by means of the function @code{ishandle}.
 @code{ishandle} returns true if its argument is a handle of a graphics object.
-In addition, the figure object may be tested using @code{isfigure}.
-@code{isfigure} returns true only if its argument is a handle of a figure.  The
-@code{whos} function can be used to show the object type of each currently
+In addition, a figure or axes object may be tested using @code{isfigure} or
+@code{isaxes} respectively.  The test functions return true only if the
+argument is both a handle and of the correct type (figure or axes).
+
+The @code{whos} function can be used to show the object type of each currently
 defined graphics handle.  (Note: this is not true today, but it is, I hope,
 considered an error in whos.  It may be better to have whos just show
 graphics_handle as the class, and provide a new function which, given a
@@ -1159,9 +1190,20 @@
 @subsubsection Creating Graphics Objects
 @cindex creating graphics objects
 
-You can create axes, line, patch, and surface objects directly using the
-@code{axes}, @code{line}, @code{patch}, @code{fill}, and @code{surface}
-functions.  These objects become children of the current axes object.
+You can create any graphics object primitive by calling the function of the
+same name as the object; In other words, @code{figure}, @code{axes},
+@code{line}, @code{text}, @code{image}, @code{patch}, and @code{surface}
+functions.  These fundamental graphic objects automatically become children
+of the current axes object as if @code{hold on} was in place.  Seperately, axes
+will automatically become children of the current figure object and figures
+will become children of the root object 0.
+
+If this auto-joining feature is not desired then it is important to call
+@code{newplot} first to prepare a new figure and axes for plotting.
+Alternatively, the easier way is to call a high-level graphics routine which
+will both create the plot and then populate it with low-level graphics objects.
+Instead of calling @code{line}, use @code{plot}.  Or use @code{surf} instead of
+@code{surface}.  Or use @code{fill} instead of @code{patch}.
 
 @DOCSTRING(axes)
 
@@ -1169,8 +1211,6 @@
 
 @DOCSTRING(patch)
 
-@DOCSTRING(fill)
-
 @DOCSTRING(surface)
 
 @subsubsection Handle Functions
@@ -1246,18 +1286,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)
 
@@ -1310,9 +1353,17 @@
 * Surface Properties::
 @end menu
 
-In this Section the object properties are discussed in detail, starting
-with the root figure properties and continuing through the graphics object
-hierarchy.
+In this Section the graphics object properties are discussed in detail, starting
+with the root figure properties and continuing through the objects
+hierarchy.  The documentation about a specific graphics object can be displayed 
+using @code{doc} function, e.g., @code{doc ("axes properties")} will show 
+@ref{Axes Properties}. 
+
+The allowed values for radio (string) properties can be retrieved 
+programmatically or displayed using the one or 
+two arguments call to @code{set} function.  @xref{XREFset, , set}.
+
+In the following documentation, default values are enclosed in @{ @}.
 
 @node Root Figure Properties
 @subsubsection Root Figure Properties
@@ -1320,72 +1371,8 @@
 
 The @code{root figure} properties are:
 
-@table @code
-@item __modified__
---- Values: @qcode{"on"}, @qcode{"off"}
-
-@item __myhandle__
-
-@item beingdeleted
---- Values: @qcode{"on"}, @qcode{"off"}
-
-@item busyaction
-
-@item buttondownfcn
-
-@item callbackobject
-
-@item children
-
-@item clipping
- --- Values: @qcode{"on"}, @qcode{"off"}
-
-@item createfcn
-
-@item currentfigure
-
-@item deletefcn
-
-@item handlevisibility
---- Values: @qcode{"on"}, @qcode{"off"}
-
-@item hittest
---- Values: @qcode{"on"}, @qcode{"off"}
-
-@item interruptible
---- Values: @qcode{"on"}, @qcode{"off"}
-
-@item parent
-
-@item screendepth
-
-@item screenpixelsperinch
-
-@item screensize
-
-@item selected
-
-@item selectionhighlight
-
-@item screendepth
-
-@item screenpixelsperinch
-
-@item showhiddenhandles
---- Values: @qcode{"on"}, @qcode{"off"}
-
-@item tag
-
-@item type
-
-@item uicontextmenu
-
-@item units
-
-@item userdata
-
-@item visible
-@end table
+@include plot-rootproperties.texi
+
 
 @node Figure Properties
 @subsubsection Figure Properties
@@ -1393,201 +1380,8 @@
 
 The @code{figure} properties are:
 
-@table @code
-@item __graphics_toolkit__
---- The graphics toolkit currently in use.
-
-@item __enhanced__
-
-@item __modified__
-
-@item __myhandle__
-
-@item __plot_stream__
-
-@item alphamap
-
-@item beingdeleted
---- Values: @qcode{"on"}, @qcode{"off"}
-
-@item busyaction
-
-@item buttondownfcn
-
-@item children
-Handle to children.
-
-@item clipping
---- Values: @qcode{"on"}, @qcode{"off"}
-
-@item closerequestfcn
---- Handle of function to call on close.
-
-@item color
-
-@item colormap
-An N-by-3 matrix containing the color map for the current axes.
-
-@item paperorientation
-
-@item createfcn
-
-@item currentaxes
-Handle to graphics object of current axes.
-
-@item currentcharacter
-
-@item currentobject
-
-@item currentpoint
-Holds the coordinates of the point over which the mouse pointer was when
-the mouse button was pressed.  If a mouse callback function is defined,
-@qcode{"currentpoint"} holds the coordinates of the point over which the
-mouse pointer is when the function gets called.
-
-@item deletefcn
-
-@item dockcontrols
---- Values: @qcode{"on"}, @qcode{"off"}
-
-@item doublebuffer
---- Values: @qcode{"on"}, @qcode{"off"}
-
-@item filename
-
-@item handlevisibility
---- Values: @qcode{"on"}, @qcode{"off"}
-
-@item hittest
-
-@item integerhandle
-
-@item interruptible
---- Values: @qcode{"on"}, @qcode{"off"}
-
-@item inverthardcopy
-
-@item keypressfcn
-see @qcode{"keypressfcn"}
-
-@item keyreleasefcn
-With @qcode{"keypressfcn"}, the keyboard callback functions.  These
-callback functions get called when a key is pressed/released
-respectively.  The functions are called with two input arguments.  The
-first argument holds the handle of the calling figure.  The second
-argument holds the event structure which has the following members:
-
-@table @code
-@item Character
-The ASCII value of the key
-
-@item Key
-lowercase value of the key
-
-@item Modifier
-A cell array containing strings representing the modifiers pressed with
-the key.  Possible values are @qcode{"shift"}, @qcode{"alt"}, and
-@qcode{"control"}.
-@end table
-
-@item menubar
-
-@item mincolormap
-
-@item name
-
-@item nextplot
-May be one of
-
-@table @asis
-@item @qcode{"new"}
-
-@item @qcode{"add"}
-
-@item @qcode{"replace"}
-
-@item @qcode{"replacechildren"}
-@end table
-
-@item numbertitle
-
-@item paperorientation
-Indicates the orientation for printing.  Either @qcode{"landscape"} or
-@qcode{"portrait"}.
-
-@item paperposition
-
-@item paperpositionmode
-
-@item papersize
-
-@item papertype
-
-@item paperunits
-
-@item pointer
-
-@item pointershapecdata
-
-@item pointershapehotspot
-
-@item position
-
-@item renderer
-
-@item renderermode
-
-@item resize
-
-@item resizefcn
-
-@item selected
-
-@item selectionhighlight
---- Values: @qcode{"on"}, @qcode{"off"}
-
-@item selectiontype
-
-@item tag
-
-@item toolbar
-
-@item type
-
-@item units
-
-@item userdata
-
-@item visible
-Either @qcode{"on"} or @qcode{"off"} to toggle display of the figure.
-
-@item windowbuttondownfcn
-See @qcode{"windowbuttonupfcn"}
-
-@item windowbuttonmotionfcn
-See @qcode{"windowbuttonupfcn"}
-
-@item windowbuttonupfcn
-With @qcode{"windowbuttondownfcn"} and @qcode{"windowbuttonmotionfcn"},
-the mouse callback functions.  These callback functions get called when
-the mouse button is pressed, dragged, and released respectively.  When
-these callback functions are called, the @qcode{"currentpoint"} property
-holds the current coordinates of the cursor.
-
-@item windowscrollwheelfcn
-
-@item windowstyle
-
-@item wvisual
-
-@item wvisualmode
-
-@item xdisplay
-
-@item xvisual
-
-@item xvisualmode
-@end table
+@include plot-figureproperties.texi
+
 
 @node Axes Properties
 @subsubsection Axes Properties
@@ -1595,324 +1389,8 @@
 
 The @code{axes} properties are:
 
-@table @code
-@item __modified__
-
-@item __myhandle__
-
-@item activepositionproperty
-
-@item alim
-
-@item alimmode
-
-@item ambientlightcolor
-
-@item beingdeleted
-
-@item box
-Box surrounding axes.
---- Values: @qcode{"on"}, @qcode{"off"}
-
-@item busyaction
-
-@item buttondownfcn
-
-@item cameraposition
-
-@item camerapositionmode
-
-@item cameratarget
-
-@item cameratargetmode
-
-@item cameraupvector
-
-@item cameraupvectormode
-
-@item cameraviewangle
-
-@item cameraviewanglemode
-
-@item children
-
-@item clim
-Two-element vector defining the limits for the c axis of
-an image.  See @code{pcolor} property.
-Setting this property also forces the corresponding mode
-property to be set to @qcode{"manual"}.
-
-@item climmode
-Either @qcode{"manual"} or @qcode{"auto"}.
-
-@item clipping
-
-@item color
-
-@item colororder
-
-@item createfcn
-
-@item currentpoint
-Holds the coordinates of the point over which the mouse pointer was when
-the mouse button was pressed.  If a mouse callback function is defined,
-@qcode{"currentpoint"} holds the coordinates of the point over which the
-mouse pointer is when the function gets called.
-
-@item dataaspectratio
-A two-element vector specifying the relative height and width of the
-data displayed in the axes.  Setting @code{dataaspectratio} to @samp{1,
-2]} causes the length of one unit as displayed on the y-axis to be the
-same as the length of 2 units on the x-axis.  Setting
-@code{dataaspectratio} also forces the @code{dataaspectratiomode}
-property to be set to @qcode{"manual"}.
-
-@item dataaspectratiomode
-Either @qcode{"manual"} or @qcode{"auto"}.
-
-@item deletefcn
-
-@item drawmode
-
-@item fontangle
-
-@item fontname
-
-@item fontsize
-
-@item fontunits
-
-@item fontweight
-
-@item gridlinestyle
-
-@item handlevisibility
-
-@item hittest
-
-@item interpreter
-
-@item interruptible
-
-@item layer
-
-@item linestyleorder
-
-@item linewidth
-
-@item minorgridlinestyle
-
-@item nextplot
-May be one of
-
-@table @asis
-@item @qcode{"add"}
-
-@item @qcode{"replace"}
-
-@item @qcode{"replacechildren"}
-@end table
-
-@item outerposition
-A vector specifying the position of the plot, including titles, axes and
-legend.  The four elements of the vector are the coordinates of the
-lower left corner and width and height of the plot, in units normalized
-to the width and height of the plot window.  For example, @code{[0.2,
-0.3, 0.4, 0.5]} sets the lower left corner of the axes at @math{(0.2,
-0.3)} and the width and height to be 0.4 and 0.5 respectively.  See also
-the @code{position} property.
-
-@item parent
-
-@item plotboxaspectratio
-
-@item plotboxaspectratiomode
-
-@item position
-A vector specifying the position of the plot, excluding titles, axes and
-legend.  The four elements of the vector are the coordinates of the
-lower left corner and width and height of the plot, in units normalized
-to the width and height of the plot window.  For example, @code{[0.2,
-0.3, 0.4, 0.5]} sets the lower left corner of the axes at @math{(0.2,
-0.3)} and the width and height to be 0.4 and 0.5 respectively.  See also
-the @code{outerposition} property.
-
-@item projection
-
-@item selected
-
-@item selectionhighlight
-
-@item tag
-
-@item tickdir
-
-@item tickdirmode
-
-@item ticklength
-
-@item tightinset
-
-@item title
-Index of text object for the axes title.
-
-@item type
-
-@item uicontextmenu
-
-@item units
-
-@item userdata
-
-@item view
-A three element vector specifying the view point for three-dimensional plots.
-
-@item visible
-Either @qcode{"on"} or @qcode{"off"} to toggle display of the axes.
-
-@item x_normrendertransform
-
-@item x_projectiontransform
-
-@item x_rendertransform
-
-@item x_viewporttransform
-
-@item x_viewtransform
-
-@item xaxislocation
-Either @qcode{"top"} or @qcode{"bottom"}.
-
-@item xcolor
-
-@item xdir
-Either @qcode{"forward"} or @qcode{"reverse"}.
-
-@item xgrid
-Either @qcode{"on"} or @qcode{"off"} to toggle display of grid lines.
-
-@item xlabel
-Indices to text objects for the axes labels.
-
-@item xlim
-Two-element vector defining the limits for the x-axis.
-Setting this property also forces the corresponding mode
-property to be set to @qcode{"manual"}.
-
-@item xlimmode
-Either @qcode{"manual"} or @qcode{"auto"}.
-
-@item xminorgrid
-Either @qcode{"on"} or @qcode{"off"} to toggle display of minor grid lines.
-
-@item xminortick
-
-@item xscale
-Either @qcode{"linear"} or @qcode{"log"}.
-
-@item xtick
-Set position of tick marks.
-Setting this property also forces the corresponding mode
-property to be set to @qcode{"manual"}.
-
-@item xticklabel
-Setting this property also forces the corresponding mode
-property to be set to @qcode{"manual"}.
-
-@item xticklabelmode
-Either @qcode{"manual"} or @qcode{"auto"}.
-
-@item xtickmode
-Either @qcode{"manual"} or @qcode{"auto"}.
-
-@item yaxislocation
-Either @qcode{"left"} or @qcode{"right"}
-
-@item ycolor
-
-@item ydir
-Either @qcode{"forward"} or @qcode{"reverse"}.
-
-@item ygrid
-Either @qcode{"on"} or @qcode{"off"} to toggle display of grid lines.
-
-@item ylabel
-Indices to text objects for the axes labels.
-
-@item ylim
-Two-element vectors defining the limits for the x, y, and z axes and the
-Setting one of these properties also forces the corresponding mode
-property to be set to @qcode{"manual"}.
-
-@item ylimmode
-Either @qcode{"manual"} or @qcode{"auto"}.
-
-@item yminorgrid
-Either @qcode{"on"} or @qcode{"off"} to toggle display of minor grid lines.
-
-@item yminortick
-
-@item yscale
-Either @qcode{"linear"} or @qcode{"log"}.
-
-@item ytick
-Set position of tick marks.
-Setting this property also forces the corresponding mode
-property to be set to @qcode{"manual"}.
-
-@item yticklabel
-Setting this property also forces the corresponding mode
-property to be set to @qcode{"manual"}.
-
-@item yticklabelmode
-Either @qcode{"manual"} or @qcode{"auto"}.
-
-@item ytickmode
-Either @qcode{"manual"} or @qcode{"auto"}.
-
-@item zcolor
-
-@item zdir
-Either @qcode{"forward"} or @qcode{"reverse"}.
-
-@item zgrid
-Either @qcode{"on"} or @qcode{"off"} to toggle display of grid lines.
-
-@item zlabel
-Indices to text objects for the axes labels.
-
-@item zlim
-Two-element vector defining the limits for z-axis.
-Setting this property also forces the corresponding mode
-property to be set to @qcode{"manual"}.
-
-@item zlimmode
-Either @qcode{"manual"} or @qcode{"auto"}.
-
-@item zminorgrid
-Either @qcode{"on"} or @qcode{"off"} to toggle display of minor grid lines.
-
-@item zminortick
-
-@item zscale
-Either @qcode{"linear"} or @qcode{"log"}.
-
-@item ztick
-Set position of tick marks.
-Setting this property also forces the corresponding mode
-property to be set to @qcode{"manual"}.
-
-@item zticklabel
-Setting this property also forces the corresponding mode
-property to be set to @qcode{"manual"}.
-
-@item zticklabelmode
-Either @qcode{"manual"} or @qcode{"auto"}.
-
-@item ztickmode
-Either @qcode{"manual"} or @qcode{"auto"}.
-
-@end table
+@include plot-axesproperties.texi
+
 
 @node Line Properties
 @subsubsection Line Properties
@@ -1920,111 +1398,8 @@
 
 The @code{line} properties are:
 
-@table @code
-@item __modified__
-
-@item __myhandle__
-
-@item beingdeleted
-
-@item busyaction
-
-@item buttondownfcn
-
-@item children
-
-@item clipping
-
-@item color
-The RGB color of the line, or a color name.  @xref{Colors}.
-
-@item createfcn
-
-@item deletefcn
-
-@item displayname
-The text of the legend entry corresponding to this line.
-
-@item erasemode
-
-@item handlevisibility
-
-@item hittest
-
-@item interpreter
-
-@item interruptible
-
-@item ldata
-The lower errorbar in the y direction to be plotted.
-
-@item  linestyle
-@itemx linewidth
-@xref{Line Styles}.
-
-@item linewidth
-
-@item marker
-
-@item markeredgecolor
-
-@item markerfacecolor
-
-@item markersize
-@xref{Marker Styles}.
-
-@item parent
-
-@item selected
-
-@item selectionhighlight
-
-@item tag
-
-@item type
-
-@item udata
-The upper errorbar in the y direction to be plotted.
-
-@item uicontextmenu
-
-@item userdata
-
-@item visible
-
-@item xdata
-The data to be plotted.
-
-@item xdatasource
-
-@item xldata
-The lower errorbar to be plotted.
-
-@item xlim
-
-@item xliminclude
-
-@item xudata
-The upper errorbar to be plotted.
-
-@item ydata
-The data to be plotted.
-
-@item ydatasource
-
-@item ylim
-
-@item yliminclude
-
-@item zdata
-The data to be plotted.
-
-@item zdatasource
-
-@item zlim
-
-@item zliminclude
-@end table
+@include plot-lineproperties.texi
+
 
 @node Text Properties
 @subsubsection Text Properties
@@ -2032,117 +1407,8 @@
 
 The @code{text} properties are:
 
-@table @code
-@item __modified__
-
-@item __myhandle__
-
-@item backgroundcolor
-
-@item beingdeleted
-
-@item busyaction
-
-@item buttondownfcn
-
-@item children
-
-@item clipping
-
-@item color
-The color of the text.  @xref{Colors}.
-
-@item createfcn
-
-@item deletefcn
-
-@item displayname
-The text of the legend entry corresponding to this line.
-
-@item edgecolor
-
-@item editing
-
-@item erasemode
-
-@item fontangle
-Flag whether the font is italic or normal.  Valid values are @qcode{"normal"},
-@qcode{"italic"}, and @qcode{"oblique"}.
-
-@item fontname
-The font used for the text.
-
-@item fontsize
-The size of the font, in points to use.
-
-@item fontunits
-
-@item fontweight
-Flag whether the font is bold, etc.  Valid values are @qcode{"normal"},
-@qcode{"bold"}, @qcode{"demi"}, or @qcode{"light"}.
-
-@item handlevisibility
-
-@item hittest
-
-@item horizontalalignment
-May be @qcode{"left"}, @qcode{"center"}, or @qcode{"right"}.
-
-@item interpreter
-Determines how the text is rendered.  Valid values are @qcode{"none"},
-@qcode{"tex"}, or @qcode{"latex"}.
-
-@item interruptible
-
-@item linestyle
-
-@item linewidth
-
-@item margin
-
-@item parent
-
-@item position
-The coordinates of the text object.
-
-@item rotation
-The angle of rotation for the displayed text, measured in degrees.
-
-@item selected
-
-@item selectionhighlight
-
-@item string
-The character string contained by the text object.
-
-@item tag
-
-@item type
-
-@item uicontextmenu
-
-@item units
-May be @qcode{"normalized"} or @qcode{"graph"}.
-
-@item userdata
-
-@item verticalalignment
-
-@item visible
-
-@item xlim
-
-@item xliminclude
-
-@item ylim
-
-@item yliminclude
-
-@item zlim
-
-@item zliminclude
-
-@end table
+@include plot-textproperties.texi
+
 
 @node Image Properties
 @subsubsection Image Properties
@@ -2150,76 +1416,8 @@
 
 The @code{image} properties are:
 
-@table @code
-@item __modified__
-
-@item __myhandle__
-
-@item beingdeleted
-
-@item busyaction
-
-@item buttondownfcn
-
-@item cdata
-The data for the image.  Each pixel of the image corresponds to an
-element of @code{cdata}.  The value of an element of @code{cdata}
-specifies the row-index into the colormap of the axes object containing
-the image.  The color value found in the color map for the given index
-determines the color of the pixel.
-
-@item cdatamapping
-
-@item children
-
-@item clim
-
-@item climinclude
-
-@item clipping
-
-@item createfcn
-
-@item deletefcn
-
-@item handlevisibility
-
-@item hittest
-
-@item interruptible
-
-@item parent
-
-@item selected
-
-@item selectionhighlight
-
-@item tag
-
-@item type
-
-@item uicontextmenu
-
-@item userdata
-
-@item visible
-
-@item xdata
-Two-element vector specifying the range of the x-coordinates for
-the image.
-
-@item xlim
-
-@item xliminclude
-
-@item ydata
-Two-element vector specifying the range of the y-coordinates for
-the image.
-
-@item ylim
-
-@item yliminclude
-@end table
+@include plot-imageproperties.texi
+
 
 @node Patch Properties
 @subsubsection Patch Properties
@@ -2227,148 +1425,8 @@
 
 The @code{patch} properties are:
 
-@table @code
-@item __modified__
-
-@item __myhandle__
-
-@item alim
-
-@item aliminclude
-
-@item alphadatamapping
-
-@item ambientstrength
-
-@item backfacelighting
-
-@item beingdeleted
-
-@item busyaction
-
-@item buttondownfcn
-
-@item cdata
-Data defining the patch object.
-
-@item cdatamapping
-
-@item children
-
-@item clim
-
-@item climinclude
-
-@item clipping
-
-@item createfcn
-
-@item deletefcn
-
-@item diffusestrength
-
-@item displayname
-The text of the legend entry corresponding to this line.
-
-@item edgealpha
-
-@item edgecolor
-The color of the line defining the patch.  @xref{Colors}.
-
-@item edgelighting
-
-@item erasemode
-
-@item facealpha
-A number in the range [0, 1] indicating the transparency of the patch.
-
-@item facecolor
-The fill color of the patch.  @xref{Colors}.
-
-@item facelighting
-
-@item faces
-
-@item facevertexalphadata
-
-@item facevertexcdata
-
-@item handlevisibility
-
-@item hittest
-
-@item interpreter
-
-@item interruptible
-
-@item linestyle
-@xref{Line Styles}.
-
-@item linewidth
-@xref{Line Styles}.
-
-@item marker
-@xref{Marker Styles}.
-
-@item markeredgecolor
-@xref{Marker Styles}.
-
-@item markerfacecolor
-@xref{Marker Styles}.
-
-@item markersize
-@xref{Marker Styles}.
-
-@item normalmode
-
-@item parent
-
-@item selected
-
-@item selectionhighlight
-
-@item specularcolorreflectance
-
-@item specularexponent
-
-@item specularstrength
-
-@item tag
-
-@item type
-
-@item uicontextmenu
-
-@item userdata
-
-@item vertexnormals
-
-@item vertices
-
-@item visible
-
-@item xdata
-Data defining the patch object.
-
-@item xlim
-
-@item xliminclude
-
-@item ydata
-Data defining the patch object.
-
-@item ylim
-
-@item yliminclude
-
-@item zdata
-Data defining the patch object.
-
-@item zlim
-
-@item zliminclude
-
-@end table
+@include plot-patchproperties.texi
+
 
 @node Surface Properties
 @subsubsection Surface Properties
@@ -2376,144 +1434,8 @@
 
 The @code{surface} properties are:
 
-@table @code
-@item __modified__
-
-@item __myhandle__
-
-@item alim
-
-@item aliminclude
-
-@item alphadata
-
-@item alphadatamapping
-
-@item ambientstrength
-
-@item backfacelighting
-
-@item beingdeleted
-
-@item busyaction
-
-@item buttondownfcn
-
-@item cdata
-
-@item cdatamapping
-
-@item cdatasource
-
-@item children
-
-@item clim
-
-@item climinclude
-
-@item clipping
-
-@item createfcn
-
-@item deletefcn
-
-@item diffusestrength
-
-@item displayname
-The text of the legend entry corresponding to this surface.
-
-@item edgealpha
-
-@item edgecolor
-
-@item edgelighting
-
-@item erasemode
-
-@item facealpha
-
-@item facecolor
-
-@item facelighting
-
-@item handlevisibility
-
-@item hittest
-
-@item interpreter
-
-@item interruptible
-
-@item linestyle
-
-@item linewidth
-
-@item marker
-
-@item markeredgecolor
-
-@item markerfacecolor
-
-@item markersize
-
-@item meshstyle
-
-@item normalmode
-
-@item parent
-
-@item selected
-
-@item selectionhighlight
-
-@item specularcolorreflectance
-
-@item specularexponent
-
-@item specularstrength
-
-@item tag
-
-@item type
-
-@item uicontextmenu
-
-@item userdata
-
-@item vertexnormals
-
-@item visible
-
-@item xdata
-The data determining the surface.  The @code{xdata} and @code{ydata}
-elements are vectors and @code{zdata} must be a matrix.
-
-@item xdatasource
-
-@item xlim
-
-@item xliminclude
-
-@item ydata
-The data determining the surface.  The @code{xdata} and @code{ydata}
-elements are vectors and @code{zdata} must be a matrix.
-
-@item ydatasource
-
-@item ylim
-
-@item yliminclude
-
-@item zdata
-The data determining the surface.  The @code{xdata} and @code{ydata}
-elements are vectors and @code{zdata} must be a matrix.
-
-@item zdatasource
-
-@item zlim
-
-@item zliminclude
-@end table
+@include plot-surfaceproperties.texi
+
 
 @node Searching Properties
 @subsection Searching Properties
@@ -2658,9 +1580,11 @@
 
 @c Special handling required to avoid '--' becoming single en-dash in Info
 @ifnottex
+
 @item @verb{|"--"|}
 @end ifnottex
 @iftex
+
 @item @code{"--"}
 @end iftex
 Dashed line.
@@ -2881,6 +1805,8 @@
 
 @DOCSTRING(linkprop)
 
+@DOCSTRING(linkaxes)
+
 These capabilities are used in a number of basic graphics objects.
 The @code{hggroup} objects created by the functions of Octave contain
 one or more graphics object and are used to:
--- a/doc/interpreter/preface.txi	Mon Jan 12 09:13:19 2015 -0800
+++ b/doc/interpreter/preface.txi	Mon Jan 12 09:17:35 2015 -0800
@@ -24,8 +24,8 @@
 
 Octave was originally intended to be companion software for an
 undergraduate-level textbook on chemical reactor design being written by
-James B. Rawlings of the University of Wisconsin-Madison and John
-G. Ekerdt of the University of Texas.
+@nospell{James B. Rawlings} of the University of Wisconsin-Madison and
+@nospell{John G. Ekerdt} of the University of Texas.
 
 Clearly, Octave is now much more than just another `courseware' package
 with limited utility beyond the classroom.  Although our initial goals
@@ -90,8 +90,8 @@
 @nospell{DE-FG02-04ER25635}.
 
 @item
-Ashok Krishnamurthy, David Hudak, Juan Carlos Chaves, and Stanley
-C. Ahalt of the Ohio Supercomputer Center.
+@nospell{Ashok Krishnamurthy, David Hudak, Juan Carlos Chaves}, and
+@nospell{Stanley C. Ahalt} of the Ohio Supercomputer Center.
 
 @item
 The National Science Foundation, through grant numbers CTS-0105360,
@@ -102,7 +102,7 @@
 Consortium (@url{http://www.che.utexas.edu/twmcc, TWMCC}).
 
 @item
-The Paul A. Elfers Endowed Chair in Chemical Engineering at the
+The @nospell{Paul A. Elfers} Endowed Chair in Chemical Engineering at the
 University of Wisconsin-Madison.
 
 @item
@@ -133,15 +133,16 @@
 Noel Bell, Senior Engineer, Texaco Chemical Company, Austin Texas.
 
 @item
-John A. Turner, Group Leader, Continuum Dynamics @nospell{(CCS-2)}, Los Alamos
-National Laboratory, for registering the @url{octave.org} domain name.
+John A. Turner, Group Leader, Continuum Dynamics @nospell{(CCS-2)},
+@nospell{Los Alamos} National Laboratory, for registering the
+@url{octave.org} domain name.
 
 @item
-James B. Rawlings, Professor, University of Wisconsin-Madison,
+@nospell{James B. Rawlings}, Professor, University of Wisconsin-Madison,
 Department of Chemical and Biological Engineering.
 
 @item
-Richard Stallman, for writing GNU.
+@nospell{Richard Stallman}, for writing GNU.
 @end itemize
 
 This project would not have been possible without the GNU software used
--- a/doc/interpreter/quad.txi	Mon Jan 12 09:13:19 2015 -0800
+++ b/doc/interpreter/quad.txi	Mon Jan 12 09:17:35 2015 -0800
@@ -55,7 +55,7 @@
 Numerical integration using an adaptive Gauss-Konrod rule.
 
 @item quadcc
-Numerical integration using adaptive Clenshaw-Curtis rules.
+Numerical integration using adaptive @nospell{Clenshaw-Curtis} rules.
 
 @item trapz, cumtrapz
 Numerical integration of data using the trapezoidal method.
--- a/doc/interpreter/set.txi	Mon Jan 12 09:13:19 2015 -0800
+++ b/doc/interpreter/set.txi	Mon Jan 12 09:17:35 2015 -0800
@@ -19,9 +19,12 @@
 @node Sets
 @chapter Sets
 
-Octave has a limited number of functions for managing sets of data, where a
-set is defined as a collection of unique elements.  In Octave a set is
-represented as a vector of numbers.
+Octave has a number of functions for managing sets of data.  A set is defined
+as a collection of unique elements and is typically represented by a vector of
+numbers sorted in ascending order.  Any vector or matrix can be converted to a
+set by removing duplicates through the use of the @code{unique} function.
+However, it isn't necessary to explicitly create a set as all of the functions
+which operate on sets will convert their input to a set before proceeding.
 
 @DOCSTRING(unique)
 
@@ -32,28 +35,34 @@
 @node Set Operations
 @section Set Operations
 
-Octave supports the basic set operations.  That is, Octave can compute
-the union, intersection, and difference of two sets.
-Octave also supports the @emph{Exclusive Or} set operation, and
-membership determination.  The functions for set operations all work in
-pretty much the same way.  As an example, assume that @code{x} and
-@code{y} contains two sets, then
+Octave supports several basic set operations.  Octave can compute the union,
+intersection, and difference of two sets.  Octave also supports the
+@emph{Exclusive Or} set operation.
+
+The functions for set operations all work in the same way by accepting two
+input sets and returning a third set.  As an example, assume that @code{a} and
+@code{b} contains two sets, then
 
 @example
-union (x, y)
+union (a, b)
 @end example
 
 @noindent
 computes the union of the two sets.
 
-@DOCSTRING(ismember)
+Finally, determining whether elements belong to a set can be done with the
+@code{ismember} function.  Because sets are ordered this operation is very
+efficient and is of order O(log2(n)) which is preferable to the @code{find}
+function which is of order O(n).
+
+@DOCSTRING(intersect)
 
 @DOCSTRING(union)
 
-@DOCSTRING(intersect)
-
 @DOCSTRING(setdiff)
 
 @DOCSTRING(setxor)
 
+@DOCSTRING(ismember)
+
 @DOCSTRING(powerset)
--- a/doc/interpreter/sparse.txi	Mon Jan 12 09:13:19 2015 -0800
+++ b/doc/interpreter/sparse.txi	Mon Jan 12 09:17:35 2015 -0800
@@ -44,13 +44,13 @@
 There are many classes of mathematical problems which give rise to
 matrices, where a large number of the elements are zero.  In this case
 it makes sense to have a special matrix type to handle this class of
-problems where only the non-zero elements of the matrix are
+problems where only the nonzero elements of the matrix are
 stored.  Not only does this reduce the amount of memory to store the
 matrix, but it also means that operations on this type of matrix can
 take advantage of the a priori knowledge of the positions of the
-non-zero elements to accelerate their calculations.
+nonzero elements to accelerate their calculations.
 
-A matrix type that stores only the non-zero elements is generally called
+A matrix type that stores only the nonzero elements is generally called
 sparse.  It is the purpose of this document to discuss the basics of the
 storage and creation of sparse matrices and the fundamental operations
 on them.
@@ -75,13 +75,13 @@
 of the methods have in common is that they attempt to reduce the complexity
 and storage given a priori knowledge of the particular class of problems
 that will be solved.  A good summary of the available techniques for storing
-sparse matrix is given by Saad @footnote{Y. Saad "SPARSKIT: A basic toolkit
-for sparse matrix computation", 1994,
+sparse matrix is given by @nospell{Saad} @footnote{Y. Saad "SPARSKIT: A basic
+toolkit for sparse matrix computation", 1994,
 @url{http://www-users.cs.umn.edu/~saad/software/SPARSKIT/paper.ps}}.
 With full matrices, knowledge of the point of an element of the matrix
 within the matrix is implied by its position in the computers memory. 
 However, this is not the case for sparse matrices, and so the positions
-of the non-zero elements of the matrix must equally be stored. 
+of the nonzero elements of the matrix must equally be stored. 
 
 An obvious way to do this is by storing the elements of the matrix as
 triplets, with two elements being their position in the array 
@@ -94,9 +94,9 @@
 In this format the position of each element in a row and the data are
 stored as previously.  However, if we assume that all elements in the
 same column are stored adjacent in the computers memory, then we only
-need to store information on the number of non-zero elements in each
+need to store information on the number of nonzero elements in each
 column, rather than their positions.  Thus assuming that the matrix has
-more non-zero elements than there are columns in the matrix, we win in
+more nonzero elements than there are columns in the matrix, we win in
 terms of the amount of memory used.
 
 In fact, the column index contains one more element than the number of
@@ -109,7 +109,7 @@
 @group
   for (j = 0; j < nc; j++)
     for (i = cidx(j); i < cidx(j+1); i++)
-       printf ("non-zero element (%i,%i) is %d\n", 
+       printf ("nonzero element (%i,%i) is %d\n", 
            ridx(i), j, data(i));
 @end group
 @end example
@@ -125,7 +125,7 @@
 @end group
 @end example
 
-The non-zero elements of this matrix are
+The nonzero elements of this matrix are
 
 @example
 @group
@@ -319,7 +319,7 @@
 in fact a sparse matrix.
 
 Another very basic function is @dfn{nnz} that returns the number of
-non-zero entries there are in a sparse matrix, while the function
+nonzero entries there are in a sparse matrix, while the function
 @dfn{nzmax} returns the amount of storage allocated to the sparse
 matrix.  Note that Octave tends to crop unused memory at the first
 opportunity for sparse objects.  There are some cases of user created
@@ -376,7 +376,7 @@
 
 There are several graphical means of finding out information about
 sparse matrices.  The first is the @dfn{spy} command, which displays
-the structure of the non-zero elements of the
+the structure of the nonzero elements of the
 matrix.  @xref{fig:spmatrix}, for an example of the use of
 @dfn{spy}.  More advanced graphical information can be obtained with the
 @dfn{treeplot}, @dfn{etreeplot} and @dfn{gplot} commands.
@@ -390,7 +390,7 @@
 interconnections between nodes are represented as an adjacency
 matrix.  That is, if the i-th node in a graph is connected to the j-th
 node.  Then the ij-th node (and in the case of undirected graphs the
-@nospell{ji-th} node) of the sparse adjacency matrix is non-zero.  If each node
+@nospell{ji-th} node) of the sparse adjacency matrix is nonzero.  If each node
 is then associated with a set of coordinates, then the @dfn{gplot}
 command can be used to graphically display the interconnections
 between nodes.
@@ -485,11 +485,11 @@
   @dfn{dmperm}, @dfn{symamd}, @dfn{randperm}, @dfn{symrcm}
 
 @item Linear algebra:
-  @dfn{condest}, @dfn{eigs}, @dfn{matrix_type}, @dfn{normest}, @dfn{sprank},
-  @dfn{spaugment}, @dfn{svds}
+  @dfn{condest}, @dfn{eigs}, @dfn{matrix_type},
+  @dfn{normest}, @dfn{sprank}, @dfn{spaugment}, @dfn{svds}
 
 @item Iterative techniques:
-  @dfn{luinc}, @dfn{pcg}, @dfn{pcr}
+  @dfn{ichol}, @dfn{ilu}, @dfn{pcg}, @dfn{pcr}
 @c @dfn{bicg}, @dfn{bicgstab}, @dfn{cholinc}, @dfn{cgs}, @dfn{gmres}, 
 @c @dfn{lsqr}, @dfn{minres}, @dfn{qmr}, @dfn{symmlq}
 
@@ -509,9 +509,9 @@
 The two basic reasons to use sparse matrices are to reduce the memory 
 usage and to not have to do calculations on zero elements.  The two are
 closely related in that the computation time on a sparse matrix operator
-or function is roughly linear with the number of non-zero elements.
+or function is roughly linear with the number of nonzero elements.
 
-Therefore, there is a certain density of non-zero elements of a matrix 
+Therefore, there is a certain density of nonzero elements of a matrix 
 where it no longer makes sense to store it as a sparse matrix, but rather
 as a full matrix.  For this reason operators and functions that have a 
 high probability of returning a full matrix will always return one.  For
@@ -630,7 +630,7 @@
 of zero is important must not be done using sparse matrices.
 
 In general any function or operator used on a sparse matrix will
-result in a sparse matrix with the same or a larger number of non-zero
+result in a sparse matrix with the same or a larger number of nonzero
 elements than the original matrix.  This is particularly true for the
 important case of sparse matrix factorizations.  The usual way to
 address this is to reorder the matrix, such that its factorization is
@@ -667,7 +667,7 @@
 @ifset htmltex
 598
 @end ifset
-non-zero terms, while this Cholesky@tie{}factorization has
+nonzero terms, while this Cholesky@tie{}factorization has
 @ifinfo
 @ifnothtml
 71,
@@ -693,7 +693,7 @@
 @ifset htmltex
 399
 @end ifset
-non-zero terms which is a significant improvement.
+nonzero terms which is a significant improvement.
 
 The Cholesky@tie{}factorization itself can be used to determine the
 appropriate sparsity preserving reordering of the matrix during the
@@ -793,17 +793,17 @@
 
 @item If the matrix is not square, or any of the previous solvers flags
 a singular or near singular matrix, find a minimum norm solution using
-@sc{cxsparse}@footnote{The @sc{cholmod}, @sc{umfpack} and @sc{cxsparse} packages were
-written by Tim Davis and are available at
+@sc{cxsparse}@footnote{The @sc{cholmod}, @sc{umfpack} and @sc{cxsparse}
+packages were written by Tim Davis and are available at
 @url{http://www.cise.ufl.edu/research/sparse/}}.
 @end enumerate
 
-The band density is defined as the number of non-zero values in the band
+The band density is defined as the number of nonzero values in the band
 divided by the total number of values in the full band.  The banded
 matrix solvers can be entirely disabled by using @dfn{spparms} to set
 @code{bandden} to 1 (i.e., @code{spparms ("bandden", 1)}).
 
-The QR@tie{}solver factorizes the problem with a Dulmage-Mendelsohn
+The QR@tie{}solver factorizes the problem with a @nospell{Dulmage-Mendelsohn}
 decomposition, to separate the problem into blocks that can be treated
 as over-determined, multiple well determined blocks, and a final
 over-determined block.  For matrices with blocks of strongly connected
@@ -860,7 +860,7 @@
 The left division @code{\} and right division @code{/} operators,
 discussed in the previous section, use direct solvers to resolve a
 linear equation of the form @code{@var{x} = @var{A} \ @var{b}} or
-@code{@var{x} = @var{b} / @var{A}}.  Octave equally includes a number of
+@code{@var{x} = @var{b} / @var{A}}.  Octave also includes a number of
 functions to solve sparse linear equations using iterative techniques.
 
 @DOCSTRING(pcg)
@@ -873,7 +873,9 @@
 @var{A} \ @var{b}} is solved instead.  Typical pre-conditioning matrices
 are partial factorizations of the original matrix.
 
-@DOCSTRING(luinc)
+@DOCSTRING(ichol)
+
+@DOCSTRING(ilu)
 
 @node Real Life Example
 @section Real Life Example using Sparse Matrices
@@ -997,7 +999,7 @@
 as constant on each simplex (represented by the vector @code{conductivity}).
 Based on the finite element geometry, we first calculate a system (or
 stiffness) matrix for each simplex (represented as 3-by-3 elements on the
-diagonal of the element-wise system matrix @code{SE}.  Based on @code{SE} 
+diagonal of the element-wise system matrix @code{SE}).  Based on @code{SE} 
 and a N-by-DE connectivity matrix @code{C}, representing the connections 
 between simplices and vertices, the global connectivity matrix @code{S} is
 calculated.
--- a/doc/interpreter/stmt.txi	Mon Jan 12 09:13:19 2015 -0800
+++ b/doc/interpreter/stmt.txi	Mon Jan 12 09:17:35 2015 -0800
@@ -83,10 +83,10 @@
 @var{condition} is true.
 
 The condition in an @code{if} statement is considered true if its value
-is non-zero, and false if its value is zero.  If the value of the
+is nonzero, and false if its value is zero.  If the value of the
 conditional expression in an @code{if} statement is a vector or a
 matrix, it is considered true only if it is non-empty and @emph{all}
-of the elements are non-zero.
+of the elements are nonzero.
 
 The second form of an if statement looks like this:
 
@@ -398,10 +398,10 @@
 The @code{while} statement is the simplest looping statement in Octave.
 It repeatedly executes a statement as long as a condition is true.  As
 with the condition in an @code{if} statement, the condition in a
-@code{while} statement is considered true if its value is non-zero, and
+@code{while} statement is considered true if its value is nonzero, and
 false if its value is zero.  If the value of the conditional expression
 in a @code{while} statement is a vector or a matrix, it is considered
-true only if it is non-empty and @emph{all} of the elements are non-zero.
+true only if it is non-empty and @emph{all} of the elements are nonzero.
 
 Octave's @code{while} statement looks like this:
 
@@ -463,10 +463,10 @@
 true, and the test of the condition is at the end of the loop, so the
 body of the loop is always executed at least once.  As with the
 condition in an @code{if} statement, the condition in a @code{do-until}
-statement is considered true if its value is non-zero, and false if its
+statement is considered true if its value is nonzero, and false if its
 value is zero.  If the value of the conditional expression in a
 @code{do-until} statement is a vector or a matrix, it is considered 
-true only if it is non-empty and @emph{all} of the elements are non-zero.
+true only if it is non-empty and @emph{all} of the elements are nonzero.
 
 Octave's @code{do-until} statement looks like this:
 
--- a/doc/interpreter/strings.txi	Mon Jan 12 09:13:19 2015 -0800
+++ b/doc/interpreter/strings.txi	Mon Jan 12 09:17:35 2015 -0800
@@ -401,8 +401,6 @@
 
 @DOCSTRING(strncmpi)
 
-@DOCSTRING(validatestring)
-
 @node Manipulating Strings
 @section Manipulating Strings
 
@@ -442,8 +440,6 @@
 
 @DOCSTRING(strjoin)
 
-@DOCSTRING(strmatch)
-
 @DOCSTRING(strtok)
 
 @DOCSTRING(strsplit)
--- a/doc/interpreter/system.txi	Mon Jan 12 09:13:19 2015 -0800
+++ b/doc/interpreter/system.txi	Mon Jan 12 09:17:35 2015 -0800
@@ -202,8 +202,6 @@
 
 @DOCSTRING(glob)
 
-@DOCSTRING(fnmatch)
-
 @DOCSTRING(file_in_path)
 
 @DOCSTRING(filesep)
@@ -224,12 +222,6 @@
 
 @DOCSTRING(is_rooted_relative_filename)
 
-@DOCSTRING(P_tmpdir)
-
-@DOCSTRING(tempdir)
-
-@DOCSTRING(tempname)
-
 @DOCSTRING(recycle)
 
 @node File Archiving Utilities
@@ -332,6 +324,8 @@
 
 @DOCSTRING(dos)
 
+@DOCSTRING(open)
+
 @DOCSTRING(perl)
 
 @DOCSTRING(python)
@@ -408,7 +402,9 @@
 
 @DOCSTRING(getenv)
 
-@DOCSTRING(putenv)
+@DOCSTRING(setenv)
+
+@DOCSTRING(unsetenv)
 
 @node Current Working Directory
 @section Current Working Directory
@@ -517,6 +513,8 @@
 
 @DOCSTRING(isdeployed)
 
+@DOCSTRING(isstudent)
+
 @DOCSTRING(OCTAVE_HOME)
 
 @DOCSTRING(matlabroot)
--- a/doc/interpreter/testfun.txi	Mon Jan 12 09:13:19 2015 -0800
+++ b/doc/interpreter/testfun.txi	Mon Jan 12 09:17:35 2015 -0800
@@ -297,14 +297,14 @@
 @group
 function output = must_be_zero (@var{input})
   if (@var{input} != 0)
-    error ("Non-zero input!")
+    error ("Nonzero input!")
   endif
   output = input;
 endfunction
 
 %!fail ("must_be_zero (1)");
 %!assert (must_be_zero (0), 0);
-%!error <Non-zero> must_be_zero (1);
+%!error <Nonzero> must_be_zero (1);
 %!xtest error ("This code generates an error");
 @end group
 @end example
@@ -320,7 +320,7 @@
 >>>>> /path/to/must_be_zero.m
   ***** fail ("must_be_zero (1)");
   ***** assert (must_be_zero (0), 0);
-  ***** error <Non-zero> must_be_zero (1);
+  ***** error <Nonzero> must_be_zero (1);
   ***** xtest error ("This code generates an error");
 !!!!! known failure
 This code generates an error
--- a/doc/interpreter/tips.txi	Mon Jan 12 09:13:19 2015 -0800
+++ b/doc/interpreter/tips.txi	Mon Jan 12 09:17:35 2015 -0800
@@ -500,7 +500,8 @@
 @@deftypefn  @{Function File@} @{@@var@{c@} =@} nchoosek (@@var@{n@}, @@var@{k@})
 @@deftypefnx @{Function File@} @{@@var@{c@} =@} nchoosek (@@var@{set@}, @@var@{k@})
 
-Compute the binomial coefficient or all combinations of a set of items.
+Compute the binomial coefficient of @@var@{n@} or list all possible
+combinations of a @@var@{set@} of items.
 
 If @@var@{n@} is a scalar then calculate the binomial coefficient
 of @@var@{n@} and @@var@{k@} which is defined as
@@ -554,10 +555,10 @@
 @@end group
 @@end example
 
-@@code@{nchoosek@} works only for non-negative, integer arguments.  Use
-@@code@{bincoeff@} for non-integer and negative scalar arguments, or for
-computing many binomial coefficients at once with vector inputs
-for @@var@{n@} or @@var@{k@}.
+Programming Note: When calculating the binomial coefficient @@code@{nchoosek@}
+works only for non-negative, integer arguments.  Use @@code@{bincoeff@} for
+non-integer and negative scalar arguments, or for computing many binomial
+coefficients at once with vector inputs for @@var@{n@} or @@var@{k@}.
 
 @@seealso@{bincoeff, perms@}
 @@end deftypefn
@@ -566,7 +567,7 @@
 @noindent
 which demonstrates most of the concepts discussed above.
 @iftex
-This documentation string renders as
+This documentation string renders in Info format as
 @c Note: use the actual output of info below, rather than try and 
 @c reproduce it here to prevent it looking different from how it would
 @c appear with info.
@@ -574,8 +575,8 @@
 @example
  -- Function File: C = nchoosek (N, K)
  -- Function File: C = nchoosek (SET, K)
-     Compute the binomial coefficient or all combinations of a set of
-     items.
+     Compute the binomial coefficient of N or list all possible
+     combinations of a SET of items.
 
      If N is a scalar then calculate the binomial coefficient of N and
      K which is defined as
@@ -608,32 +609,31 @@
                  1   3
                  2   3
 
+     Programming Note: When calculating the binomial coefficient
      `nchoosek' works only for non-negative, integer arguments.  Use
      `bincoeff' for non-integer and negative scalar arguments, or for
      computing many binomial coefficients at once with vector inputs
      for N or K.
 
-     See also: bincoeff, perms
+     See also: bincoeff, perms.
 @end example
 @noindent
-using info, whereas in a printed documentation using @TeX{} it will
-appear as
+whereas in printed documentation using @TeX{} it will appear as
 
 @deftypefn  {Function File} {@var{c} =} nchoosek (@var{n}, @var{k})
 @deftypefnx {Function File} {@var{c} =} nchoosek (@var{set}, @var{k})
 
-Compute the binomial coefficient or all combinations of a set of items.
+Compute the binomial coefficient of @var{n} or list all possible
+combinations of a @var{set} of items.
 
 If @var{n} is a scalar then calculate the binomial coefficient
 of @var{n} and @var{k} which is defined as
-
 @tex
 $$
  {n \choose k} = {n (n-1) (n-2) \cdots (n-k+1) \over k!}
                = {n! \over k! (n-k)!}
 $$
 @end tex
-
 @noindent
 This is the number of combinations of @var{n} items taken in groups of
 size @var{k}.
@@ -665,10 +665,10 @@
 @end group
 @end example
 
-@code{nchoosek} works only for non-negative, integer arguments.  Use
-@code{bincoeff} for non-integer and negative scalar arguments, or for
-computing many binomial coefficients at once with vector inputs for @var{n}
-or @var{k}.
+Programming Note: When calculating the binomial coefficient @code{nchoosek}
+works only for non-negative, integer arguments.  Use @code{bincoeff} for
+non-integer and negative scalar arguments, or for computing many binomial
+coefficients at once with vector inputs for @var{n} or @var{k}.
 
 @seealso{bincoeff, perms}
 @end deftypefn
--- a/doc/interpreter/var.txi	Mon Jan 12 09:13:19 2015 -0800
+++ b/doc/interpreter/var.txi	Mon Jan 12 09:17:35 2015 -0800
@@ -221,8 +221,7 @@
 @end example
 
 The behavior of persistent variables is equivalent to the behavior of
-static variables in C@.  The command @code{static} in Octave is also
-recognized and is equivalent to @code{persistent}.
+static variables in C@.
 
 Like global variables, a persistent variable may only be initialized once.
 For example, after executing the following code
--- a/doc/interpreter/vectorize.txi	Mon Jan 12 09:13:19 2015 -0800
+++ b/doc/interpreter/vectorize.txi	Mon Jan 12 09:17:35 2015 -0800
@@ -496,6 +496,15 @@
 
 @DOCSTRING(structfun)
 
+Consistent with earlier advice, seek to use Octave built-in functions whenever
+possible for the best performance.  This advice applies especially to the four
+functions above.  For example, when adding two arrays together
+element-by-element one could use a handle to the built-in addition function
+@code{@@plus} or define an anonymous function @code{@@(x,y) x + y}.  But, the
+anonymous function is 60% slower than the first method.
+@xref{Operator Overloading}, for a list of basic functions which might be used
+in place of anonymous ones.
+
 @node Accumulation
 @section Accumulation
 
@@ -697,7 +706,7 @@
 for i = 1:length (A)
   ## this will be two columns, the first is the difference and
   ## the second the mean of the two elements used for the diff.
-  B(i,:) = [A(i+1)-A(i), (A(i+1) + A(i))/2)];
+  B(i,:) = [A(i+1)-A(i), (A(i+1) + A(i))/2];
 endfor
 @end group
 @end example
@@ -713,3 +722,4 @@
 a column vector.  This is a common vectorization trick.
 
 @end itemize
+
--- a/doc/refcard/refcard.tex	Mon Jan 12 09:13:19 2015 -0800
+++ b/doc/refcard/refcard.tex	Mon Jan 12 09:17:35 2015 -0800
@@ -536,7 +536,7 @@
 speye ({\it n)}&create sparse identity matrix.\cr
 sprand ({\it n}, {\it m}, {\it d})&sparse rand matrix of density {\it d}.\cr
 spdiags (...)&sparse generalization of {\it diag}.\cr
-nnz ({\it s})&No. non-zero elements in sparse matrix.\cr
+nnz ({\it s})&No. nonzero elements in sparse matrix.\cr
 \endsec
 
 \sec Ranges;
--- a/examples/@FIRfilter/FIRfilter.m	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,20 +0,0 @@
-## -*- texinfo -*-
-## @deftypefn  {Function File} {} FIRfilter ()
-## @deftypefnx {Function File} {} FIRfilter (@var{p})
-## Create a FIR filter with polynomial @var{p} as coefficient vector.
-## @end deftypefn
-
-function f = FIRfilter (p)
-
-  f.polynomial = [];
-  if (nargin == 0)
-    p = @polynomial ([1]);
-  elseif (nargin == 1)
-    if (!isa (p, "polynomial"))
-      error ("FIRfilter: expecting polynomial as input argument");
-    endif
-  else
-    print_usage ();
-  endif
-  f = class (f, "FIRfilter", p);
-endfunction
--- a/examples/@FIRfilter/FIRfilter_aggregation.m	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-## -*- texinfo -*-
-## @deftypefn  {Function File} {} FIRfilter ()
-## @deftypefnx {Function File} {} FIRfilter (@var{p})
-## Create a FIR filter with polynomial @var{p} as coefficient vector.
-## @end deftypefn
-
-function f = FIRfilter (p)
-
-  if (nargin == 0)
-    f.polynomial = @polynomial ([1]);
-  elseif (nargin == 1)
-    if (isa (p, "polynomial"))
-      f.polynomial = p;
-    else
-      error ("FIRfilter: expecting polynomial as input argument");
-    endif
-  else
-    print_usage ();
-  endif
-  f = class (f, "FIRfilter");
-endfunction
--- a/examples/@FIRfilter/display.m	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,6 +0,0 @@
-function display (f)
-
-  display (f.polynomial);
-
-endfunction
-
--- a/examples/@FIRfilter/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-FCN_FILE_DIRS += @FIRfilter
-
-EXTRA_DIST += @FIRfilter/module.mk
-
-at_FIRfilter_FCN_FILES = \
-  @FIRfilter/display.m \
-  @FIRfilter/FIRfilter_aggregation.m \
-  @FIRfilter/FIRfilter.m \
-  @FIRfilter/subsasgn.m \
-  @FIRfilter/subsref.m
-
-FCN_FILES += $(at_FIRfilter_FCN_FILES)
--- a/examples/@FIRfilter/subsasgn.m	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-function out = subsasgn (f, index, val)
-  switch (index.type)
-    case "."
-      fld = index.subs;
-      if (strcmp (fld, "polynomial"))
-        out = f;
-        out.polynomial = val;
-      else
-        error ("@FIRfilter/subsref: invalid property \"%s\"", fld);
-      endif
-    otherwise
-      error ("FIRfilter/subsagn: Invalid index type")
-  endswitch
-endfunction
--- a/examples/@FIRfilter/subsref.m	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,16 +0,0 @@
-function out = subsref (f, x)
-  switch (x.type)
-    case "()"
-      n = f.polynomial;
-      out = filter (n.poly, 1, x.subs{1});
-    case "."
-      fld = x.subs;
-      if (strcmp (fld, "polynomial"))
-        out = f.polynomial;
-      else
-        error ("@FIRfilter/subsref: invalid property \"%s\"", fld);
-      endif
-    otherwise
-      error ("@FIRfilter/subsref: invalid subscript type for FIR filter");
-  endswitch
-endfunction
--- a/examples/@polynomial/display.m	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-function display (p)
-  a = p.poly;
-  first = true;
-  fprintf ("%s =", inputname (1));
-  for i = 1 : length (a);
-    if (a(i) != 0)
-      if (first)
-        first = false;
-      elseif (a(i) > 0)
-        fprintf (" +");
-      endif
-      if (a(i) < 0)
-        fprintf (" -");
-      endif
-      if (i == 1)
-        fprintf (" %g", abs (a(i)));
-      elseif (abs(a(i)) != 1)
-        fprintf (" %g *", abs (a(i)));
-      endif
-      if (i > 1)
-        fprintf (" X");
-      endif
-      if (i > 2)
-        fprintf (" ^ %d", i - 1);
-      endif
-    endif
-  endfor
-  if (first)
-    fprintf (" 0");
-  endif
-  fprintf ("\n");
-endfunction
--- a/examples/@polynomial/double.m	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-function b = double (a)
-  b = a.poly;
-endfunction
--- a/examples/@polynomial/end.m	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-function r = end (obj, index_pos, num_indices)
-
-  if (num_indices != 1)
-    error ("polynomial object may only have one index")
-  endif
-  
-  r = length (obj.poly) - 1;
-
-endfunction
--- a/examples/@polynomial/get.m	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-function s = get (p, f)
-  if (nargin == 1)
-    s.poly = p.poly;
-  elseif (nargin == 2)
-    if (ischar (f))
-      switch (f)
-        case "poly"
-          s = p.poly;
-        otherwise
-          error ("get: invalid property %s", f);
-      endswitch
-    else
-      error ("get: expecting the property to be a string");
-    endif
-  else
-    print_usage ();
-  endif
-endfunction
--- a/examples/@polynomial/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-FCN_FILE_DIRS += @polynomial
-
-EXTRA_DIST += @polynomial/module.mk
-
-at_polynomial_FCN_FILES = \
-  @polynomial/display.m \
-  @polynomial/double.m \
-  @polynomial/end.m \
-  @polynomial/get.m \
-  @polynomial/mtimes.m \
-  @polynomial/numel.m \
-  @polynomial/plot.m \
-  @polynomial/polynomial.m \
-  @polynomial/polynomial_superiorto.m \
-  @polynomial/polyval.m \
-  @polynomial/roots.m \
-  @polynomial/set.m \
-  @polynomial/subsasgn.m \
-  @polynomial/subsref.m
-
-FCN_FILES += $(at_polynomial_FCN_FILES)
--- a/examples/@polynomial/mtimes.m	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-function y = mtimes (a, b)
-  y = polynomial (conv (double (a), double (b)));
-endfunction
--- a/examples/@polynomial/numel.m	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-function n = numel (obj, idx)
-
-  # always produce an array.
-  n = 1;
-
-endfunction
-
--- a/examples/@polynomial/plot.m	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-function h = plot (p, varargin)
-  n = 128;
-  rmax = max (abs (roots (p.poly)));
-  x = [0 : (n - 1)] / (n - 1) * 2.2 * rmax - 1.1 * rmax;
-  if (nargout > 0)
-    h = plot (x, p(x), varargin{:});
-  else
-    plot (x, p(x), varargin{:});
-  endif
-endfunction
--- a/examples/@polynomial/polynomial.m	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-## -*- texinfo -*-
-## @deftypefn  {Function File} {} polynomial ()
-## @deftypefnx {Function File} {} polynomial (@var{a})
-## Create a polynomial object representing the polynomial
-##
-## @example
-## a0 + a1 * x + a2 * x^2 + @dots{} + an * x^n
-## @end example
-##
-## @noindent
-## from a vector of coefficients [a0 a1 a2 @dots{} an].
-## @end deftypefn
-
-function p = polynomial (a)
-  if (nargin == 0)
-    p.poly = [0];
-    p = class (p, "polynomial");
-  elseif (nargin == 1)
-    if (strcmp (class (a), "polynomial"))
-      p = a;
-    elseif (isvector (a) && isreal (a))
-      p.poly = a(:).';
-      p = class (p, "polynomial");
-    else
-      error ("polynomial: expecting real vector");
-    endif
-  else
-    print_usage ();
-  endif
-endfunction
--- a/examples/@polynomial/polynomial_superiorto.m	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-## -*- texinfo -*-
-## @deftypefn  {Function File} {} polynomial ()
-## @deftypefnx {Function File} {} polynomial (@var{a})
-## Create a polynomial object representing the polynomial
-##
-## @example
-## a0 + a1 * x + a2 * x^2 + @dots{} + an * x^n
-## @end example
-##
-## @noindent
-## from a vector of coefficients [a0 a1 a2 @dots{} an].
-## @end deftypefn
-
-function p = polynomial (a)
-  if (nargin == 0)
-    p.poly = [0];
-    p = class (p, "polynomial");
-  elseif (nargin == 1)
-    if (strcmp (class (a), "polynomial"))
-      p = a;
-    elseif (isvector (a) && isreal (a))
-      p.poly = a(:).';
-      p = class (p, "polynomial");
-    else
-      error ("polynomial: expecting real vector");
-    endif
-  else
-    print_usage ();
-  endif
-  superiorto ("double");
-endfunction
--- a/examples/@polynomial/polyval.m	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-function [y, dy] = polyval (p, varargin)
-  if (nargout == 2)
-    [y, dy] = polyval (fliplr (p.poly), varargin{:});
-  else
-    y = polyval (fliplr (p.poly), varargin{:});
-  endif
-endfunction
--- a/examples/@polynomial/roots.m	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-function y = roots (p)
-  y = roots(fliplr(p.poly));
-endfunction
\ No newline at end of file
--- a/examples/@polynomial/set.m	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,20 +0,0 @@
-function s = set (p, varargin)
-  s = p;
-  if (length (varargin) < 2 || rem (length (varargin), 2) != 0)
-    error ("set: expecting property/value pairs");
-  endif
-  while (length (varargin) > 1)
-    prop = varargin{1};
-    val = varargin{2};
-    varargin(1:2) = [];
-    if (ischar (prop) && strcmp (prop, "poly"))
-      if (isvector (val) && isreal (val))
-        s.poly = val(:).';
-      else
-        error ("set: expecting the value to be a real vector");
-      endif
-    else
-      error ("set: invalid property of polynomial class");
-    endif
-  endwhile
-endfunction
--- a/examples/@polynomial/subsasgn.m	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-function p = subsasgn (p, s, val)
-  if (length (s) < 1)
-    error ("polynomial: needs index");
-  endif
-  switch (s(1).type)
-    case "{}"
-      ind = s(1).subs;
-      if (numel (ind) != 1)
-        error ("polynomial: need exactly one index");
-      else
-        if (length (s) == 1)
-          if (isnumeric (ind{1}))
-            p.poly(ind{1}+1) = val; 
-          else
-            p.poly(ind{1}) = val;
-          endif
-        else
-          error ("polynomial: chained subscripts not allowed for {}");
-        endif
-      endif
-    case "."
-      fld = s(1).subs;
-      if (strcmp (fld, "poly"))
-        if (length (s) == 1)
-          p.poly = val;
-        else
-          p.poly = subsasgn (p.poly, s(2:end), val);
-        endif
-      else
-        error ("@polynomial/subsref: invalid property \"%s\"", fld);
-      endif
-    otherwise
-      error ("invalid subscript type");
-  endswitch
-endfunction
--- a/examples/@polynomial/subsref.m	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-function b = subsref (a, s)
-  if (isempty (s))
-    error ("polynomial: missing index");
-  endif
-  switch (s(1).type)
-    case "()"
-      ind = s(1).subs;
-      if (numel (ind) != 1)
-        error ("polynomial: need exactly one index");
-      else
-        b = polyval (fliplr (a.poly), ind{1});
-      endif
-    case "{}"
-      ind = s(1).subs;
-      if (numel (ind) != 1)
-        error ("polynomial: need exactly one index");
-      else
-        if (isnumeric (ind{1}))
-          b = a.poly(ind{1}+1);
-        else
-          b = a.poly(ind{1});
-        endif
-      endif
-    case "."
-      fld = s.subs;
-      if (strcmp (fld, "poly"))
-        b = a.poly;
-      else
-        error ("@polynomial/subsref: invalid property \"%s\"", fld);
-      endif
-    otherwise
-      error ("invalid subscript type");
-  endswitch
-  if (numel (s) > 1)
-    b = subsref (b, s(2:end));
-  endif
-endfunction
--- a/examples/COPYING	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-Copyright notices are intentionally omitted from the files in the
-examples directory.  We don't want copyright notices cluttering the
-manual.
--- a/examples/Makefile.am	Mon Jan 12 09:13:19 2015 -0800
+++ b/examples/Makefile.am	Mon Jan 12 09:17:35 2015 -0800
@@ -1,6 +1,6 @@
-# Makefile for Octave's examples directory
+# Makefile for Octave's example directory
 #
-# Copyright (C) 1996-2013 John W. Eaton
+# Copyright (C) 1993-2013 John W. Eaton
 #
 # This file is part of Octave.
 # 
@@ -18,47 +18,12 @@
 # along with Octave; see the file COPYING.  If not, see
 # <http://www.gnu.org/licenses/>.
 
+## Pass-through layer.  Simply pass make commands down to SUBDIRS.
+
 include $(top_srcdir)/build-aux/common.mk
 
-EXTRA_DIST = 
-
-FCN_FILE_DIRS =
-
-FCN_FILES =
-
-include @polynomial/module.mk
-include @FIRfilter/module.mk
+EXTRA_DIST = \
+  Makefile.am
 
-EXTRA_DIST += \
-  $(FCN_FILES) \
-  addtwomatrices.cc \
-  celldemo.cc \
-  embedded.cc \
-  fortrandemo.cc \
-  fortransub.f \
-  funcdemo.cc \
-  globaldemo.cc \
-  helloworld.cc \
-  make_int.cc \
-  mex_demo.c \
-  mycell.c \
-  myfeval.c \
-  myfevalf.f \
-  myfunc.c \
-  myhello.c \
-  mypow2.c \
-  myprop.c \
-  myset.c \
-  mysparse.c \
-  mystring.c \
-  mystruct.c \
-  oct_demo.cc \
-  oregonator.cc \
-  oregonator.m \
-  paramdemo.cc \
-  standalone.cc \
-  standalonebuiltin.cc \
-  stringdemo.cc \
-  structdemo.cc \
-  unwinddemo.cc
+SUBDIRS = code data
 
--- a/examples/addtwomatrices.cc	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-#include <octave/oct.h>
-
-DEFUN_DLD (addtwomatrices, args, , "Add A to B")
-{
-  int nargin = args.length ();
-
-  if (nargin != 2)
-    print_usage ();
-  else
-    {
-      NDArray A = args(0).array_value ();
-      NDArray B = args(1).array_value ();
-      if (! error_state)
-        return octave_value (A + B);
-    }
-
-  return octave_value_list ();
-}
--- a/examples/celldemo.cc	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-#include <octave/oct.h>
-#include <octave/Cell.h>
-
-DEFUN_DLD (celldemo, args, , "Cell Demo")
-{
-  octave_value_list retval;
-  int nargin = args.length ();
-
-  if (nargin != 1)
-    print_usage ();
-  else
-    {
-      Cell c = args(0).cell_value ();
-      if (! error_state)
-        for (octave_idx_type i = 0; i < c.numel (); i++)
-          {
-            retval(i) = c(i);          // using operator syntax
-            //retval(i) = c.elem (i);  // using method syntax
-          }
-    }
-
-  return retval;
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/@FIRfilter/FIRfilter.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,20 @@
+## -*- texinfo -*-
+## @deftypefn  {Function File} {} FIRfilter ()
+## @deftypefnx {Function File} {} FIRfilter (@var{p})
+## Create a FIR filter with polynomial @var{p} as coefficient vector.
+## @end deftypefn
+
+function f = FIRfilter (p)
+
+  f.polynomial = [];
+  if (nargin == 0)
+    p = @polynomial ([1]);
+  elseif (nargin == 1)
+    if (!isa (p, "polynomial"))
+      error ("FIRfilter: expecting polynomial as input argument");
+    endif
+  else
+    print_usage ();
+  endif
+  f = class (f, "FIRfilter", p);
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/@FIRfilter/FIRfilter_aggregation.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,21 @@
+## -*- texinfo -*-
+## @deftypefn  {Function File} {} FIRfilter ()
+## @deftypefnx {Function File} {} FIRfilter (@var{p})
+## Create a FIR filter with polynomial @var{p} as coefficient vector.
+## @end deftypefn
+
+function f = FIRfilter (p)
+
+  if (nargin == 0)
+    f.polynomial = @polynomial ([1]);
+  elseif (nargin == 1)
+    if (isa (p, "polynomial"))
+      f.polynomial = p;
+    else
+      error ("FIRfilter: expecting polynomial as input argument");
+    endif
+  else
+    print_usage ();
+  endif
+  f = class (f, "FIRfilter");
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/@FIRfilter/display.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,6 @@
+function display (f)
+
+  display (f.polynomial);
+
+endfunction
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/@FIRfilter/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,12 @@
+FCN_FILE_DIRS += @FIRfilter
+
+EXTRA_DIST += @FIRfilter/module.mk
+
+at_FIRfilter_FCN_FILES = \
+  @FIRfilter/display.m \
+  @FIRfilter/FIRfilter_aggregation.m \
+  @FIRfilter/FIRfilter.m \
+  @FIRfilter/subsasgn.m \
+  @FIRfilter/subsref.m
+
+FCN_FILES += $(at_FIRfilter_FCN_FILES)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/@FIRfilter/subsasgn.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,14 @@
+function out = subsasgn (f, index, val)
+  switch (index.type)
+    case "."
+      fld = index.subs;
+      if (strcmp (fld, "polynomial"))
+        out = f;
+        out.polynomial = val;
+      else
+        error ("@FIRfilter/subsref: invalid property \"%s\"", fld);
+      endif
+    otherwise
+      error ("FIRfilter/subsagn: Invalid index type")
+  endswitch
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/@FIRfilter/subsref.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,16 @@
+function out = subsref (f, x)
+  switch (x.type)
+    case "()"
+      n = f.polynomial;
+      out = filter (n.poly, 1, x.subs{1});
+    case "."
+      fld = x.subs;
+      if (strcmp (fld, "polynomial"))
+        out = f.polynomial;
+      else
+        error ("@FIRfilter/subsref: invalid property \"%s\"", fld);
+      endif
+    otherwise
+      error ("@FIRfilter/subsref: invalid subscript type for FIR filter");
+  endswitch
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/@polynomial/display.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,32 @@
+function display (p)
+  a = p.poly;
+  first = true;
+  fprintf ("%s =", inputname (1));
+  for i = 1 : length (a);
+    if (a(i) != 0)
+      if (first)
+        first = false;
+      elseif (a(i) > 0)
+        fprintf (" +");
+      endif
+      if (a(i) < 0)
+        fprintf (" -");
+      endif
+      if (i == 1)
+        fprintf (" %g", abs (a(i)));
+      elseif (abs(a(i)) != 1)
+        fprintf (" %g *", abs (a(i)));
+      endif
+      if (i > 1)
+        fprintf (" X");
+      endif
+      if (i > 2)
+        fprintf (" ^ %d", i - 1);
+      endif
+    endif
+  endfor
+  if (first)
+    fprintf (" 0");
+  endif
+  fprintf ("\n");
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/@polynomial/double.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,3 @@
+function b = double (a)
+  b = a.poly;
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/@polynomial/end.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,9 @@
+function r = end (obj, index_pos, num_indices)
+
+  if (num_indices != 1)
+    error ("polynomial object may only have one index")
+  endif
+  
+  r = length (obj.poly) - 1;
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/@polynomial/get.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,18 @@
+function s = get (p, f)
+  if (nargin == 1)
+    s.poly = p.poly;
+  elseif (nargin == 2)
+    if (ischar (f))
+      switch (f)
+        case "poly"
+          s = p.poly;
+        otherwise
+          error ("get: invalid property %s", f);
+      endswitch
+    else
+      error ("get: expecting the property to be a string");
+    endif
+  else
+    print_usage ();
+  endif
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/@polynomial/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,21 @@
+FCN_FILE_DIRS += @polynomial
+
+EXTRA_DIST += @polynomial/module.mk
+
+at_polynomial_FCN_FILES = \
+  @polynomial/display.m \
+  @polynomial/double.m \
+  @polynomial/end.m \
+  @polynomial/get.m \
+  @polynomial/mtimes.m \
+  @polynomial/numel.m \
+  @polynomial/plot.m \
+  @polynomial/polynomial.m \
+  @polynomial/polynomial_superiorto.m \
+  @polynomial/polyval.m \
+  @polynomial/roots.m \
+  @polynomial/set.m \
+  @polynomial/subsasgn.m \
+  @polynomial/subsref.m
+
+FCN_FILES += $(at_polynomial_FCN_FILES)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/@polynomial/mtimes.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,3 @@
+function y = mtimes (a, b)
+  y = polynomial (conv (double (a), double (b)));
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/@polynomial/numel.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,7 @@
+function n = numel (obj, idx)
+
+  # always produce an array.
+  n = 1;
+
+endfunction
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/@polynomial/plot.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,10 @@
+function h = plot (p, varargin)
+  n = 128;
+  rmax = max (abs (roots (p.poly)));
+  x = [0 : (n - 1)] / (n - 1) * 2.2 * rmax - 1.1 * rmax;
+  if (nargout > 0)
+    h = plot (x, p(x), varargin{:});
+  else
+    plot (x, p(x), varargin{:});
+  endif
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/@polynomial/polynomial.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,30 @@
+## -*- texinfo -*-
+## @deftypefn  {Function File} {} polynomial ()
+## @deftypefnx {Function File} {} polynomial (@var{a})
+## Create a polynomial object representing the polynomial
+##
+## @example
+## a0 + a1 * x + a2 * x^2 + @dots{} + an * x^n
+## @end example
+##
+## @noindent
+## from a vector of coefficients [a0 a1 a2 @dots{} an].
+## @end deftypefn
+
+function p = polynomial (a)
+  if (nargin == 0)
+    p.poly = [0];
+    p = class (p, "polynomial");
+  elseif (nargin == 1)
+    if (strcmp (class (a), "polynomial"))
+      p = a;
+    elseif (isvector (a) && isreal (a))
+      p.poly = a(:).';
+      p = class (p, "polynomial");
+    else
+      error ("polynomial: expecting real vector");
+    endif
+  else
+    print_usage ();
+  endif
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/@polynomial/polynomial_superiorto.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,31 @@
+## -*- texinfo -*-
+## @deftypefn  {Function File} {} polynomial ()
+## @deftypefnx {Function File} {} polynomial (@var{a})
+## Create a polynomial object representing the polynomial
+##
+## @example
+## a0 + a1 * x + a2 * x^2 + @dots{} + an * x^n
+## @end example
+##
+## @noindent
+## from a vector of coefficients [a0 a1 a2 @dots{} an].
+## @end deftypefn
+
+function p = polynomial (a)
+  if (nargin == 0)
+    p.poly = [0];
+    p = class (p, "polynomial");
+  elseif (nargin == 1)
+    if (strcmp (class (a), "polynomial"))
+      p = a;
+    elseif (isvector (a) && isreal (a))
+      p.poly = a(:).';
+      p = class (p, "polynomial");
+    else
+      error ("polynomial: expecting real vector");
+    endif
+  else
+    print_usage ();
+  endif
+  superiorto ("double");
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/@polynomial/polyval.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,7 @@
+function [y, dy] = polyval (p, varargin)
+  if (nargout == 2)
+    [y, dy] = polyval (fliplr (p.poly), varargin{:});
+  else
+    y = polyval (fliplr (p.poly), varargin{:});
+  endif
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/@polynomial/roots.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,3 @@
+function y = roots (p)
+  y = roots(fliplr(p.poly));
+endfunction
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/@polynomial/set.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,20 @@
+function s = set (p, varargin)
+  s = p;
+  if (length (varargin) < 2 || rem (length (varargin), 2) != 0)
+    error ("set: expecting property/value pairs");
+  endif
+  while (length (varargin) > 1)
+    prop = varargin{1};
+    val = varargin{2};
+    varargin(1:2) = [];
+    if (ischar (prop) && strcmp (prop, "poly"))
+      if (isvector (val) && isreal (val))
+        s.poly = val(:).';
+      else
+        error ("set: expecting the value to be a real vector");
+      endif
+    else
+      error ("set: invalid property of polynomial class");
+    endif
+  endwhile
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/@polynomial/subsasgn.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,35 @@
+function p = subsasgn (p, s, val)
+  if (length (s) < 1)
+    error ("polynomial: needs index");
+  endif
+  switch (s(1).type)
+    case "{}"
+      ind = s(1).subs;
+      if (numel (ind) != 1)
+        error ("polynomial: need exactly one index");
+      else
+        if (length (s) == 1)
+          if (isnumeric (ind{1}))
+            p.poly(ind{1}+1) = val; 
+          else
+            p.poly(ind{1}) = val;
+          endif
+        else
+          error ("polynomial: chained subscripts not allowed for {}");
+        endif
+      endif
+    case "."
+      fld = s(1).subs;
+      if (strcmp (fld, "poly"))
+        if (length (s) == 1)
+          p.poly = val;
+        else
+          p.poly = subsasgn (p.poly, s(2:end), val);
+        endif
+      else
+        error ("@polynomial/subsref: invalid property \"%s\"", fld);
+      endif
+    otherwise
+      error ("invalid subscript type");
+  endswitch
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/@polynomial/subsref.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,37 @@
+function b = subsref (a, s)
+  if (isempty (s))
+    error ("polynomial: missing index");
+  endif
+  switch (s(1).type)
+    case "()"
+      ind = s(1).subs;
+      if (numel (ind) != 1)
+        error ("polynomial: need exactly one index");
+      else
+        b = polyval (fliplr (a.poly), ind{1});
+      endif
+    case "{}"
+      ind = s(1).subs;
+      if (numel (ind) != 1)
+        error ("polynomial: need exactly one index");
+      else
+        if (isnumeric (ind{1}))
+          b = a.poly(ind{1}+1);
+        else
+          b = a.poly(ind{1});
+        endif
+      endif
+    case "."
+      fld = s.subs;
+      if (strcmp (fld, "poly"))
+        b = a.poly;
+      else
+        error ("@polynomial/subsref: invalid property \"%s\"", fld);
+      endif
+    otherwise
+      error ("invalid subscript type");
+  endswitch
+  if (numel (s) > 1)
+    b = subsref (b, s(2:end));
+  endif
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/COPYING	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,3 @@
+Copyright notices are intentionally omitted from the files in the
+examples directory.  We don't want copyright notices cluttering the
+manual.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/Makefile.am	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,64 @@
+# Makefile for Octave's examples directory
+#
+# Copyright (C) 1996-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/>.
+
+include $(top_srcdir)/build-aux/common.mk
+
+EXTRA_DIST = 
+
+FCN_FILE_DIRS =
+
+FCN_FILES =
+
+include @polynomial/module.mk
+include @FIRfilter/module.mk
+
+EXTRA_DIST += \
+  $(FCN_FILES) \
+  addtwomatrices.cc \
+  celldemo.cc \
+  embedded.cc \
+  fortrandemo.cc \
+  fortransub.f \
+  funcdemo.cc \
+  globaldemo.cc \
+  helloworld.cc \
+  make_int.cc \
+  mex_demo.c \
+  mycell.c \
+  myfeval.c \
+  myfevalf.f \
+  myfunc.c \
+  myhello.c \
+  mypow2.c \
+  myprop.c \
+  myset.c \
+  mysparse.c \
+  mystring.c \
+  mystruct.c \
+  oct_demo.cc \
+  oregonator.cc \
+  oregonator.m \
+  paramdemo.cc \
+  standalone.cc \
+  standalonebuiltin.cc \
+  stringdemo.cc \
+  structdemo.cc \
+  unwinddemo.cc
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/addtwomatrices.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,18 @@
+#include <octave/oct.h>
+
+DEFUN_DLD (addtwomatrices, args, , "Add A to B")
+{
+  int nargin = args.length ();
+
+  if (nargin != 2)
+    print_usage ();
+  else
+    {
+      NDArray A = args(0).array_value ();
+      NDArray B = args(1).array_value ();
+      if (! error_state)
+        return octave_value (A + B);
+    }
+
+  return octave_value_list ();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/celldemo.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,23 @@
+#include <octave/oct.h>
+#include <octave/Cell.h>
+
+DEFUN_DLD (celldemo, args, , "Cell Demo")
+{
+  octave_value_list retval;
+  int nargin = args.length ();
+
+  if (nargin != 1)
+    print_usage ();
+  else
+    {
+      Cell c = args(0).cell_value ();
+      if (! error_state)
+        for (octave_idx_type i = 0; i < c.numel (); i++)
+          {
+            retval(i) = c(i);          // using operator syntax
+            //retval(i) = c.elem (i);  // using method syntax
+          }
+    }
+
+  return retval;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/embedded.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,35 @@
+#include <iostream>
+#include <octave/oct.h>
+#include <octave/octave.h>
+#include <octave/parse.h>
+#include <octave/toplev.h>
+
+int
+main (void)
+{
+  string_vector argv (2);
+  argv(0) = "embedded";
+  argv(1) = "-q";
+
+  octave_main (2, argv.c_str_vec (), 1);
+
+  octave_idx_type n = 2;
+  octave_value_list in;
+
+  for (octave_idx_type i = 0; i < n; i++)
+    in(i) = octave_value (5 * (i + 2));
+
+  octave_value_list out = feval ("gcd", in, 1);
+
+  if (! error_state && out.length () > 0)
+    std::cout << "GCD of ["
+              << in(0).int_value ()
+              << ", "
+              << in(1).int_value ()
+              << "] is " << out(0).int_value ()
+              << std::endl;
+  else
+    std::cout << "invalid\n";
+
+  clean_up_and_exit (0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/fortrandemo.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,35 @@
+#include <octave/oct.h>
+#include <octave/f77-fcn.h>
+
+extern "C"
+{
+  F77_RET_T
+  F77_FUNC (fortransub, FORTSUB)
+    (const int&, double*, F77_CHAR_ARG_DECL F77_CHAR_ARG_LEN_DECL);
+}
+
+DEFUN_DLD (fortrandemo, args, , "Fortran Demo")
+{
+  octave_value_list retval;
+  int nargin = args.length ();
+
+  if (nargin != 1)
+    print_usage ();
+  else
+    {
+      NDArray a = args(0).array_value ();
+      if (! error_state)
+        {
+          double *av = a.fortran_vec ();
+          octave_idx_type na = a.numel ();
+          OCTAVE_LOCAL_BUFFER (char, ctmp, 128);
+
+          F77_XFCN (fortransub, FORTSUB,
+                    (na, av, ctmp F77_CHAR_ARG_LEN (128)));
+
+          retval(1) = std::string (ctmp);
+          retval(0) = a;
+        }
+    }
+  return retval;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/fortransub.f	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,21 @@
+      subroutine fortransub (n, a, s)
+      implicit none
+      character*(*) s
+      real*8 a(*)
+      integer*4 i, n, ioerr
+      do i = 1, n
+        if (a(i) .eq. 0d0) then
+          call xstopx ('fortransub: divide by zero')
+        else
+          a(i) = 1d0 / a(i)
+        endif
+      enddo
+      write (unit = s, fmt = '(a,i3,a,a)', iostat = ioerr)
+     $       'There are ', n,
+     $       ' values in the input vector', char(0)
+      if (ioerr .ne. 0) then
+        call xstopx ('fortransub: error writing string')
+      endif
+      return
+      end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/funcdemo.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,32 @@
+#include <octave/oct.h>
+#include <octave/parse.h>
+
+DEFUN_DLD (funcdemo, args, nargout, "Function Demo")
+{
+  octave_value_list retval;
+  int nargin = args.length ();
+
+  if (nargin < 2)
+    print_usage ();
+  else
+    {
+      octave_value_list newargs;
+      for (octave_idx_type i = nargin - 1; i > 0; i--)
+        newargs(i-1) = args(i);
+      if (args(0).is_function_handle () || args(0).is_inline_function ())
+        {
+          octave_function *fcn = args(0).function_value ();
+          if (! error_state)
+            retval = feval (fcn, newargs, nargout);
+        }
+      else if (args(0).is_string ())
+        {
+          std::string fcn = args(0).string_value ();
+          if (! error_state)
+            retval = feval (fcn, newargs, nargout);
+        }
+      else
+        error ("funcdemo: INPUT must be string, inline, or function handle");
+    }
+  return retval;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/globaldemo.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,25 @@
+#include <octave/oct.h>
+
+DEFUN_DLD (globaldemo, args, , "Global Demo")
+{
+  octave_value retval;
+  int nargin = args.length ();
+
+  if (nargin != 1)
+    print_usage ();
+  else
+    {
+      std::string s = args(0).string_value ();
+      if (! error_state)
+        {
+          octave_value tmp = get_global_value (s, true);
+          if (tmp.is_defined ())
+            retval = tmp;
+          else
+            retval = "Global variable not found";
+
+          set_global_value ("a", 42.0);
+        }
+    }
+  return retval;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/helloworld.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,13 @@
+#include <octave/oct.h>
+
+DEFUN_DLD (helloworld, args, nargout,
+           "Hello World Help String")
+{
+  int nargin = args.length ();
+
+  octave_stdout << "Hello World has "
+                << nargin << " input arguments and "
+                << nargout << " output arguments.\n";
+
+  return octave_value_list ();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/make_int.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,316 @@
+#include <octave/config.h>
+
+#include <cstdlib>
+
+#include <string>
+
+#include <ostream>
+
+#include <octave/lo-mappers.h>
+#include <octave/lo-utils.h>
+#include <octave/mx-base.h>
+#include <octave/str-vec.h>
+
+#include <octave/defun-dld.h>
+#include <octave/error.h>
+#include <octave/gripes.h>
+#include <octave/oct-obj.h>
+#include <octave/ops.h>
+#include <octave/ov-base.h>
+#include <octave/ov-typeinfo.h>
+#include <octave/ov.h>
+#include <octave/ov-scalar.h>
+#include <octave/pager.h>
+#include <octave/pr-output.h>
+#include <octave/symtab.h>
+#include <octave/variables.h>
+
+class octave_value_list;
+
+class tree_walker;
+
+// Integer values.
+
+class
+octave_integer : public octave_base_value
+{
+public:
+
+  octave_integer (void)
+    : octave_base_value (), scalar (0) { }
+
+  octave_integer (int i)
+    : octave_base_value (), scalar (i) { }
+
+  octave_integer (const octave_integer& s)
+    : octave_base_value (), scalar (s.scalar) { }
+
+  ~octave_integer (void) { }
+
+  octave_base_value *clone (void) { return new octave_integer (*this); }
+
+#if 0
+  void *operator new (size_t size);
+  void operator delete (void *p, size_t size);
+#endif
+
+  idx_vector index_vector (void) const { return idx_vector ((double) scalar); }
+
+  int rows (void) const { return 1; }
+  int columns (void) const { return 1; }
+
+  bool is_constant (void) const { return true; }
+
+  bool is_defined (void) const { return true; }
+  bool is_real_scalar (void) const { return true; }
+
+  octave_value all (void) const { return (double) (scalar != 0); }
+  octave_value any (void) const { return (double) (scalar != 0); }
+
+  bool is_real_type (void) const { return true; }
+  bool is_scalar_type (void) const { return true; }
+  bool is_numeric_type (void) const { return true; }
+
+  bool valid_as_scalar_index (void) const
+  { return scalar == 1; }
+
+  bool valid_as_zero_index (void) const
+  { return scalar == 0; }
+
+  bool is_true (void) const { return (scalar != 0); }
+
+  double double_value (bool = false) const { return (double) scalar; }
+
+  int integer_value (bool = false) const { return scalar; }
+
+  Matrix matrix_value (bool = false) const { return Matrix (1, 1, scalar); }
+
+  Complex complex_value (bool = false) const { return scalar; }
+
+  ComplexMatrix complex_matrix_value (bool = false) const
+  { return  ComplexMatrix (1, 1, Complex (scalar)); }
+
+  octave_value gnot (void) const { return octave_value ((double) ! scalar); }
+
+  octave_value uminus (void) const { return new octave_integer (- scalar); }
+
+  octave_value transpose (void) const { return new octave_integer (scalar); }
+
+  octave_value hermitian (void) const { return new octave_integer (scalar); }
+
+  void increment (void) { ++scalar; }
+
+  void decrement (void) { --scalar; }
+
+  void print (std::ostream& os, bool pr_as_read_syntax = false) const;
+
+private:
+
+  int scalar;
+
+  DECLARE_OCTAVE_ALLOCATOR
+
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+};
+
+void
+octave_integer::print (std::ostream& os, bool pr_as_read_syntax) const
+{
+  os << scalar;
+  // octave_print_internal (os, scalar, pr_as_read_syntax);
+}
+
+#ifdef DEFUNOP_OP
+#undef DEFUNOP_OP
+#endif
+
+#define DEFUNOP_OP(name, t, op) \
+  UNOPDECL (name, a) \
+  { \
+    CAST_UNOP_ARG (const octave_ ## t&); \
+    return octave_value (new octave_integer (op v.t ## _value ())); \
+  }
+
+DEFUNOP_OP (gnot, integer, !)
+DEFUNOP_OP (uminus, integer, -)
+DEFUNOP_OP (transpose, integer, /* no-op */)
+DEFUNOP_OP (hermitian, integer, /* no-op */)
+
+DEFNCUNOP_METHOD (incr, integer, increment)
+DEFNCUNOP_METHOD (decr, integer, decrement)
+
+#ifdef DEFBINOP_OP
+#undef DEFBINOP_OP
+#endif
+
+#define DEFBINOP_OP(name, t1, t2, op) \
+  BINOPDECL (name, a1, a2) \
+  { \
+    CAST_BINOP_ARGS (const octave_ ## t1&, const octave_ ## t2&); \
+    return octave_value \
+      (new octave_integer (v1.t1 ## _value () op v2.t2 ## _value ())); \
+  }
+
+// integer by integer ops.
+
+DEFBINOP_OP (add, integer, integer, +)
+DEFBINOP_OP (sub, integer, integer, -)
+DEFBINOP_OP (mul, integer, integer, *)
+
+DEFBINOP (div, integer, integer)
+{
+  CAST_BINOP_ARGS (const octave_integer&, const octave_integer&);
+
+  int d = v2.integer_value ();
+
+  if (d == 0)
+    gripe_divide_by_zero ();
+
+  return new octave_integer (v1.integer_value () / d);
+}
+
+
+DEFBINOP (i_s_div, integer, scalar)
+{
+  CAST_BINOP_ARGS (const octave_integer&, const octave_scalar&);
+
+  double d = v2.double_value ();
+
+  if (d == 0.0)
+    gripe_divide_by_zero ();
+
+  return new octave_scalar (v1.double_value () / d);
+}
+
+DEFBINOP (ldiv, integer, integer)
+{
+  CAST_BINOP_ARGS (const octave_integer&, const octave_integer&);
+
+  int d = v1.integer_value ();
+
+  if (d == 0)
+    gripe_divide_by_zero ();
+
+  return new octave_integer (v2.integer_value () / d);
+}
+
+DEFBINOP_OP (lt, integer, integer, <)
+DEFBINOP_OP (le, integer, integer, <=)
+DEFBINOP_OP (eq, integer, integer, ==)
+DEFBINOP_OP (ge, integer, integer, >=)
+DEFBINOP_OP (gt, integer, integer, >)
+DEFBINOP_OP (ne, integer, integer, !=)
+
+DEFBINOP_OP (el_mul, integer, integer, !=)
+
+DEFBINOP (el_div, integer, integer)
+{
+  CAST_BINOP_ARGS (const octave_integer&, const octave_integer&);
+
+  int d = v2.integer_value ();
+
+  if (d == 0)
+    gripe_divide_by_zero ();
+
+  return new octave_integer (v1.integer_value () / d);
+}
+
+DEFBINOP (el_ldiv, integer, integer)
+{
+  CAST_BINOP_ARGS (const octave_integer&, const octave_integer&);
+
+  int d = v1.integer_value ();
+
+  if (d == 0)
+    gripe_divide_by_zero ();
+
+  return new octave_integer (v2.integer_value () / d);
+}
+
+DEFBINOP_OP (el_and, integer, integer, &&)
+DEFBINOP_OP (el_or, integer, integer, ||)
+
+DEFUN_DLD (make_int, args, ,
+           "int_val = make_int (val)\n\
+\n\
+Creates an integer variable from VAL.")
+{
+  static bool type_loaded = false;
+
+  if (! type_loaded)
+    {
+      octave_integer::register_type ();
+      mlock ();
+
+      octave_stdout << "installing integer type at type-id = "
+                    << octave_integer::static_type_id () << "\n";
+
+      INSTALL_UNOP (op_not, octave_integer, gnot);
+      INSTALL_UNOP (op_uminus, octave_integer, uminus);
+      INSTALL_UNOP (op_transpose, octave_integer, transpose);
+      INSTALL_UNOP (op_hermitian, octave_integer, hermitian);
+
+      INSTALL_NCUNOP (op_incr, octave_integer, incr);
+      INSTALL_NCUNOP (op_decr, octave_integer, decr);
+
+      INSTALL_BINOP (op_add, octave_integer, octave_integer, add);
+      INSTALL_BINOP (op_sub, octave_integer, octave_integer, sub);
+      INSTALL_BINOP (op_mul, octave_integer, octave_integer, mul);
+      INSTALL_BINOP (op_div, octave_integer, octave_integer, div);
+      INSTALL_BINOP (op_ldiv, octave_integer, octave_integer, ldiv);
+      INSTALL_BINOP (op_lt, octave_integer, octave_integer, lt);
+      INSTALL_BINOP (op_le, octave_integer, octave_integer, le);
+      INSTALL_BINOP (op_eq, octave_integer, octave_integer, eq);
+      INSTALL_BINOP (op_ge, octave_integer, octave_integer, ge);
+      INSTALL_BINOP (op_gt, octave_integer, octave_integer, gt);
+      INSTALL_BINOP (op_ne, octave_integer, octave_integer, ne);
+      INSTALL_BINOP (op_el_mul, octave_integer, octave_integer, el_mul);
+      INSTALL_BINOP (op_el_div, octave_integer, octave_integer, el_div);
+      INSTALL_BINOP (op_el_ldiv, octave_integer, octave_integer, el_ldiv);
+      INSTALL_BINOP (op_el_and, octave_integer, octave_integer, el_and);
+      INSTALL_BINOP (op_el_or, octave_integer, octave_integer, el_or);
+
+      INSTALL_BINOP (op_div, octave_integer, octave_scalar, i_s_div);
+    }
+
+  octave_value retval;
+
+  if (args.length () == 1)
+    {
+      double d = args(0).double_value ();
+
+      if (! error_state)
+        retval = octave_value (new octave_integer (NINT (d)));
+    }
+  else
+    usage ("make_int");
+
+  return retval;
+}
+
+DEFUN_DLD (doit, args, ,
+           "doit (I)")
+{
+  octave_value_list retval;
+
+  if (args(0).type_id () == octave_integer::static_type_id ())
+    {
+      // At this point, we know we have a handle for an octave_integer
+      // object, so we can peek at the representation and extract the
+      // data.
+
+      const octave_base_value& rep = args(0).get_rep ();
+
+      int my_value = ((const octave_integer&) rep) . integer_value ();
+
+      message ("doit", "your lucky number is: %d", my_value);
+    }
+  else
+    gripe_wrong_type_arg ("doit", args(0));
+
+  return retval;
+}
+
+DEFINE_OCTAVE_ALLOCATOR (octave_integer);
+
+DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_integer, "integer", "integer");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/mex_demo.c	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,58 @@
+// mex_demo.c -- example of a dynamically linked function for Octave.
+
+// To use this file, your version of Octave must support dynamic
+// linking.  To find out if it does, type the command
+//
+//   octave_config_info ("ENABLE_DYNAMIC_LINKING")
+//
+// at the Octave prompt.  Support for dynamic linking is included if
+// this expression returns the string "yes".
+//
+// To compile this file, type the command
+//
+//   mkoctfile --mex mex_demo.c
+//
+// from within Octave or from the shell prompt.  This will create a file
+// called mex_demo.mex that can be loaded by Octave.  To test the mex_demo.mex
+// file, start Octave and type the command
+//
+// d = mex_demo ("easy as", 1, 2, 3)
+//
+// at the Octave prompt.  Octave should respond by printing
+//
+//   Hello, world!
+//   I have 4 inputs and 1 output
+//   d =  1.2346
+
+// Additional samples of code are in the examples directory of the Octave
+// distribution.  See also the chapter External Code Interface in the
+// documentation.
+
+#include "mex.h"
+
+// Every user function should include "mex.h" which imports the basic set of
+// function prototypes necessary for dynamically linked functions.  In
+// particular, it will declare mexFunction which is used by every function
+// which will be visible to Octave.  A mexFunction is visible in Octave under
+// the name of the source code file without the extension.
+
+// The four arguments to mexFunction are:
+// 1) The number of return arguments (# of left-hand side args).
+// 2) An array of pointers to return arguments.
+// 3) The number of input arguments (# of right-hand side args).
+// 4) An array of pointers to input arguments.
+
+void
+mexFunction (int nlhs, mxArray *plhs[],
+             int nrhs, const mxArray *prhs[])
+{
+  mexPrintf ("Hello, World!\n");
+
+  mexPrintf ("I have %d inputs and %d outputs\n", nrhs, nlhs);
+
+  mxArray *v = mxCreateDoubleMatrix (1, 1, mxREAL);
+  double *data = mxGetPr (v);
+  *data = 1.23456789;
+
+  plhs[0] = v;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/mycell.c	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,18 @@
+#include "mex.h"
+
+void
+mexFunction (int nlhs, mxArray* plhs[],
+             int nrhs, const mxArray* prhs[])
+{
+  mwSize n;
+  mwIndex i;
+
+  if (nrhs != 1 || ! mxIsCell (prhs[0]))
+    mexErrMsgTxt ("ARG1 must be a cell");
+
+  n = mxGetNumberOfElements (prhs[0]);
+  n = (n > nlhs ? nlhs : n);
+
+  for (i = 0; i < n; i++)
+    plhs[i] = mxDuplicateArray (mxGetCell (prhs[0], i));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/myfeval.c	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,27 @@
+#include "mex.h"
+
+void
+mexFunction (int nlhs, mxArray* plhs[],
+             int nrhs, const mxArray* prhs[])
+{
+  char *str;
+
+  mexPrintf ("Starting file myfeval.mex\n");
+
+  mexPrintf ("I have %d inputs and %d outputs\n", nrhs, nlhs);
+
+  if (nrhs < 1 || ! mxIsString (prhs[0]))
+    mexErrMsgTxt ("ARG1 must be a function name");
+
+  str = mxArrayToString (prhs[0]);
+
+  mexPrintf ("I'm going to call the function %s\n", str);
+
+  if (nlhs == 0)
+    nlhs = 1;  // Octave's automatic 'ans' variable
+
+  /* Cast prhs just to get rid of 'const' qualifier and stop compile warning */
+  mexCallMATLAB (nlhs, plhs, nrhs-1, (mxArray**)prhs+1, str);
+
+  mxFree (str);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/myfevalf.f	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,30 @@
+      subroutine mexFunction (nlhs, plhs, nrhs, prhs)
+
+      implicit none
+
+      integer*4 nlhs, nrhs
+
+* The following will need to be integer*8 on 64-bit systems, otherwise
+* these variables won't be large enough to hold pointers...
+      integer*4 plhs(*), prhs(*)
+
+      integer*4 mxIsString, mxGetString, mxGetN, mexCallMATLAB
+      integer*4 status, len
+      character*100 str
+
+      call mexPrintf ('Hello, World!')
+
+      if (nrhs .lt. 1 .or. mxIsString (prhs(1)) .ne. 1) then
+        call mexErrMsgTxt ('function name expected')
+      endif
+
+      len = mxGetN (prhs(1))
+
+      status = mxGetString (prhs(1), str, 100)
+
+      call mexPrintf ('FORTRAN will call the interpreter now')
+
+      status = mexCallMATLAB (nlhs, plhs, nrhs-1, prhs(2), str(1:len))
+
+      return
+      end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/myfunc.c	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,15 @@
+#include "mex.h"
+
+void
+mexFunction (int nlhs, mxArray *plhs[],
+             int nrhs, const mxArray *prhs[])
+{
+  const char *nm;
+
+  nm = mexFunctionName ();
+  mexPrintf ("You called function: %s\n", nm);
+  if (strcmp (nm, "myfunc") == 0)
+    mexPrintf ("This is the principal function\n", nm);
+
+  return;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/myhello.c	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,10 @@
+#include "mex.h"
+
+void
+mexFunction (int nlhs, mxArray *plhs[],
+             int nrhs, const mxArray *prhs[])
+{
+  mexPrintf ("Hello, World!\n");
+
+  mexPrintf ("I have %d inputs and %d outputs\n", nrhs, nlhs);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/mypow2.c	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,39 @@
+#include "mex.h"
+
+void
+mexFunction (int nlhs, mxArray* plhs[],
+             int nrhs, const mxArray* prhs[])
+{
+  mwSize n;
+  mwIndex i;
+  double *vri, *vro;
+
+  if (nrhs != 1 || ! mxIsNumeric (prhs[0]))
+    mexErrMsgTxt ("ARG1 must be a matrix");
+
+  n = mxGetNumberOfElements (prhs[0]);
+  plhs[0] = mxCreateNumericArray (mxGetNumberOfDimensions (prhs[0]),
+                                  mxGetDimensions (prhs[0]),
+                                  mxGetClassID (prhs[0]),
+                                  mxIsComplex (prhs[0]));
+  vri = mxGetPr (prhs[0]);
+  vro = mxGetPr (plhs[0]);
+
+  if (mxIsComplex (prhs[0]))
+    {
+      double *vii, *vio;
+      vii = mxGetPi (prhs[0]);
+      vio = mxGetPi (plhs[0]);
+
+      for (i = 0; i < n; i++)
+        {
+          vro[i] = vri[i] * vri[i] - vii[i] * vii[i];
+          vio[i] = 2 * vri[i] * vii[i];
+        }
+    }
+  else
+    {
+      for (i = 0; i < n; i++)
+        vro[i] = vri[i] * vri[i];
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/myprop.c	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,24 @@
+#include "mex.h"
+
+void
+mexFunction (int nlhs, mxArray* plhs[],
+             int nrhs, const mxArray* prhs[])
+{
+  double handle;
+  char property[256];
+
+  if (nrhs < 2 || nrhs > 3)
+    mexErrMsgTxt ("incorrect number of arguments");
+  if (!mxIsDouble (prhs[0]))
+    mexErrMsgTxt ("handle expected to be a double scalar");
+  if (!mxIsChar (prhs[1]))
+    mexErrMsgTxt ("expected property to be a string");
+
+  handle = mxGetScalar (prhs[0]);
+  mxGetString (prhs[1], property, 256);
+  plhs[0] = mxDuplicateArray (mexGet (handle, property));
+
+  if (nrhs == 3)
+    if (mexSet (handle, property, mxDuplicateArray (prhs[2])))
+      mexErrMsgTxt ("failed to set property");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/myset.c	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,34 @@
+#include "mex.h"
+
+void
+mexFunction (int nlhs, mxArray* plhs[],
+             int nrhs, const mxArray* prhs[])
+{
+  char *str;
+  mxArray *v;
+
+  if (nrhs != 2 || ! mxIsString (prhs[0]))
+    mexErrMsgTxt ("expects symbol name and value");
+
+  str = mxArrayToString (prhs[0]);
+
+  v = mexGetArray (str, "global");
+
+  if (v)
+    {
+      mexPrintf ("%s is a global variable with the following value:\n", str);
+      mexCallMATLAB (0, NULL, 1, &v, "disp");
+    }
+
+  v = mexGetArray (str, "caller");
+
+  if (v)
+    {
+      mexPrintf ("%s is a caller variable with the following value:\n", str);
+      mexCallMATLAB (0, NULL, 1, &v, "disp");
+    }
+
+  // WARNING!! Can't do this in MATLAB!  Must copy variable first.
+  mxSetName (prhs[1], str);
+  mexPutArray (prhs[1], "caller");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/mysparse.c	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,117 @@
+#include "mex.h"
+
+void
+mexFunction (int nlhs, mxArray *plhs[],
+             int nrhs, const mxArray *prhs[])
+{
+  mwSize m, n, nz;
+  mxArray *v;
+  mwIndex i;
+  double *pr, *pi;
+  double *pr2, *pi2;
+  mwIndex *ir, *jc;
+  mwIndex *ir2, *jc2;
+
+  if (nrhs != 1 || ! mxIsSparse (prhs[0]))
+    mexErrMsgTxt ("ARG1 must be a sparse matrix");
+
+  m = mxGetM (prhs[0]);
+  n = mxGetN (prhs[0]);
+  nz = mxGetNzmax (prhs[0]);
+
+  if (mxIsComplex (prhs[0]))
+    {
+      mexPrintf ("Matrix is %d-by-%d complex sparse matrix", m, n);
+      mexPrintf (" with %d elements\n", nz);
+
+      pr = mxGetPr (prhs[0]);
+      pi = mxGetPi (prhs[0]);
+      ir = mxGetIr (prhs[0]);
+      jc = mxGetJc (prhs[0]);
+
+      i = n;
+      while (jc[i] == jc[i-1] && i != 0) i--;
+
+      mexPrintf ("last nonzero element (%d, %d) = (%g, %g)\n",
+                 ir[nz-1]+ 1, i, pr[nz-1], pi[nz-1]);
+
+      v = mxCreateSparse (m, n, nz, mxCOMPLEX);
+      pr2 = mxGetPr (v);
+      pi2 = mxGetPi (v);
+      ir2 = mxGetIr (v);
+      jc2 = mxGetJc (v);
+
+      for (i = 0; i < nz; i++)
+        {
+          pr2[i] = 2 * pr[i];
+          pi2[i] = 2 * pi[i];
+          ir2[i] = ir[i];
+        }
+      for (i = 0; i < n + 1; i++)
+        jc2[i] = jc[i];
+
+      if (nlhs > 0)
+        plhs[0] = v;
+    }
+  else if (mxIsLogical (prhs[0]))
+    {
+      mxLogical *pbr, *pbr2;
+      mexPrintf ("Matrix is %d-by-%d logical sparse matrix", m, n);
+      mexPrintf (" with %d elements\n", nz);
+
+      pbr = mxGetLogicals (prhs[0]);
+      ir = mxGetIr (prhs[0]);
+      jc = mxGetJc (prhs[0]);
+
+      i = n;
+      while (jc[i] == jc[i-1] && i != 0) i--;
+      mexPrintf ("last nonzero element (%d, %d) = %d\n",
+                 ir[nz-1]+ 1, i, pbr[nz-1]);
+
+      v = mxCreateSparseLogicalMatrix (m, n, nz);
+      pbr2 = mxGetLogicals (v);
+      ir2 = mxGetIr (v);
+      jc2 = mxGetJc (v);
+
+      for (i = 0; i < nz; i++)
+        {
+          pbr2[i] = pbr[i];
+          ir2[i] = ir[i];
+        }
+      for (i = 0; i < n + 1; i++)
+        jc2[i] = jc[i];
+
+      if (nlhs > 0)
+        plhs[0] = v;
+    }
+  else
+    {
+      mexPrintf ("Matrix is %d-by-%d real sparse matrix", m, n);
+      mexPrintf (" with %d elements\n", nz);
+
+      pr = mxGetPr (prhs[0]);
+      ir = mxGetIr (prhs[0]);
+      jc = mxGetJc (prhs[0]);
+
+      i = n;
+      while (jc[i] == jc[i-1] && i != 0) i--;
+      mexPrintf ("last nonzero element (%d, %d) = %g\n",
+                 ir[nz-1]+ 1, i, pr[nz-1]);
+
+      v = mxCreateSparse (m, n, nz, mxREAL);
+      pr2 = mxGetPr (v);
+      ir2 = mxGetIr (v);
+      jc2 = mxGetJc (v);
+
+      for (i = 0; i < nz; i++)
+        {
+          pr2[i] = 2 * pr[i];
+          ir2[i] = ir[i];
+        }
+      for (i = 0; i < n + 1; i++)
+        jc2[i] = jc[i];
+
+      if (nlhs > 0)
+        plhs[0] = v;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/mystring.c	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,25 @@
+#include <string.h>
+#include "mex.h"
+
+void
+mexFunction (int nlhs, mxArray *plhs[],
+             int nrhs, const mxArray *prhs[])
+{
+  mwSize m, n;
+  mwIndex i, j;
+  mxChar *pi, *po;
+
+  if (nrhs != 1 || ! mxIsChar (prhs[0])
+      || mxGetNumberOfDimensions (prhs[0]) > 2)
+    mexErrMsgTxt ("ARG1 must be a char matrix");
+
+  m = mxGetM (prhs[0]);
+  n = mxGetN (prhs[0]);
+  pi = mxGetChars (prhs[0]);
+  plhs[0] = mxCreateNumericMatrix (m, n, mxCHAR_CLASS, mxREAL);
+  po = mxGetChars (plhs[0]);
+
+  for (j = 0; j < n; j++)
+    for (i = 0; i < m; i++)
+      po[j*m + m - 1 - i] = pi[j*m + i];
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/mystruct.c	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,36 @@
+#include "mex.h"
+
+void
+mexFunction (int nlhs, mxArray* plhs[],
+             int nrhs, const mxArray* prhs[])
+{
+  int i;
+  mwIndex j;
+  mxArray *v;
+  const char *keys[] = { "this", "that" };
+
+  if (nrhs != 1 || ! mxIsStruct (prhs[0]))
+    mexErrMsgTxt ("expects struct");
+
+  for (i = 0; i < mxGetNumberOfFields (prhs[0]); i++)
+    for (j = 0; j < mxGetNumberOfElements (prhs[0]); j++)
+      {
+        mexPrintf ("field %s(%d) = ", mxGetFieldNameByNumber (prhs[0], i), j);
+        v = mxGetFieldByNumber (prhs[0], j, i);
+        mexCallMATLAB (0, NULL, 1, &v, "disp");
+      }
+
+  v = mxCreateStructMatrix (2, 2, 2, keys);
+
+  mxSetFieldByNumber (v, 0, 0, mxCreateString ("this1"));
+  mxSetFieldByNumber (v, 0, 1, mxCreateString ("that1"));
+  mxSetFieldByNumber (v, 1, 0, mxCreateString ("this2"));
+  mxSetFieldByNumber (v, 1, 1, mxCreateString ("that2"));
+  mxSetFieldByNumber (v, 2, 0, mxCreateString ("this3"));
+  mxSetFieldByNumber (v, 2, 1, mxCreateString ("that3"));
+  mxSetFieldByNumber (v, 3, 0, mxCreateString ("this4"));
+  mxSetFieldByNumber (v, 3, 1, mxCreateString ("that4"));
+
+  if (nlhs)
+    plhs[0] = v;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/oct_demo.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,84 @@
+// oct_demo.cc -- example of a dynamically linked function for Octave.
+
+// To use this file, your version of Octave must support dynamic
+// linking.  To find out if it does, type the command
+//
+//   octave_config_info ("ENABLE_DYNAMIC_LINKING")
+//
+// at the Octave prompt.  Support for dynamic linking is included if
+// this expression returns the string "yes".
+//
+// To compile this file, type the command
+//
+//   mkoctfile oct_demo.cc
+//
+// from within Octave or from the shell prompt.  This will create a file
+// called oct_demo.oct that can be loaded by Octave.  To test the
+// oct_demo.oct file, start Octave and type the command
+//
+//   oct_demo ("easy as", 1, 2, 3)
+//
+// at the Octave prompt.  Octave should respond by printing
+//
+//   Hello, world!
+//   easy as
+//   1
+//   2
+//   3
+//   ans = 3
+
+// Additional samples of real dynamically loaded functions are available in
+// the files of the libinterp/dldfcn directory of the Octave distribution.
+// See also the chapter External Code Interface in the documentation.
+
+#include <iostream>
+
+#include <octave/oct.h>
+
+// Every user function should include <octave/oct.h> which imports the
+// basic set of Octave header files required.  In particular this will define
+// the DEFUN_DLD macro (defun-dld.h) which is used for every user function
+// that is visible to Octave.
+
+// The four arguments to the DEFUN_DLD macro are:
+// 1) The function name as seen in Octave.
+// 2) The variable to hold any inputs (of type octave_value_list)
+// 3) The number of output arguments
+// 4) A string to use as help text if 'help <function_name>' is entered.
+//
+// Note below that the third parameter (nargout) of DEFUN_DLD is not used,
+// so it is omitted from the list of arguments in order to avoid a warning
+// from gcc about an unused function parameter.
+
+DEFUN_DLD (oct_demo, args, ,
+           "[...] = oct_demo (...)\n\
+\n\
+Print a greeting followed by the values of all the arguments passed.\n\
+Return all arguments in reverse order.")
+{
+  // The list of values to return.  See the declaration in oct-obj.h
+
+  octave_value_list retval;
+
+  // This stream is normally connected to the pager.
+
+  octave_stdout << "Hello, world!\n";
+
+  // The inputs to this function are available in args.
+
+  int nargin = args.length ();
+
+  // The octave_value_list class is a zero-based array of octave_value objects.
+  // The declaration for the octave_value class is in the file ov.h.
+  // The print() method will send its output to octave_stdout,
+  // so it will also end up going through the pager.
+
+  for (int i = 0; i < nargin; i++)
+    {
+      octave_value tmp = args(i);
+      tmp.print (octave_stdout);
+      retval(nargin-i-1) = tmp;
+    }
+
+  return retval;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/oregonator.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,22 @@
+#include <octave/oct.h>
+
+DEFUN_DLD (oregonator, args, ,
+           "The `oregonator'.\n\
+\n\
+Reference:\n\
+\n\
+  Oscillations in chemical systems.  IV.  Limit cycle behavior in a\n\
+  model of a real chemical reaction. Richard J. Field and Richard\n\
+  M. Noyes, The Journal of Chemical Physics, Volume 60 Number 5,\n\
+  March 1974.")
+{
+  ColumnVector dx (3);
+
+  ColumnVector x (args(0).vector_value ());
+
+  dx(0) = 77.27 * (x(1) - x(0)*x(1) + x(0) - 8.375e-06*pow (x(0), 2.0));
+  dx(1) = (x(2) - x(0)*x(1) - x(1)) / 77.27;
+  dx(2) = 0.161*(x(0) - x(2));
+
+  return octave_value (dx);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/oregonator.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,18 @@
+## The `oregonator'.
+##
+## Reference:
+##
+##   Oscillations in chemical systems.  IV.  Limit cycle behavior in a
+##   model of a real chemical reaction. Richard J. Field and Richard
+##   M. Noyes, The Journal of Chemical Physics, Volume 60 Number 5,
+##   March 1974.
+
+function dx = oregonator (x, t)
+
+  dx = zeros (3, 1);
+
+  dx(1) = 77.27*(x(2) - x(1)*x(2) + x(1) - 8.375e-06*x(1)^2);
+  dx(2) = (x(3) - x(1)*x(2) - x(2)) / 77.27;
+  dx(3) = 0.161*(x(1) - x(3));
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/paramdemo.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,30 @@
+#include <octave/oct.h>
+
+DEFUN_DLD (paramdemo, args, nargout, "Parameter Check Demo")
+{
+  octave_value retval;
+  int nargin = args.length ();
+
+  if (nargin != 1)
+    print_usage ();
+  else if (nargout != 0)
+    error ("paramdemo: OUTPUT argument required");
+  else
+    {
+      NDArray m = args(0).array_value ();
+      double min_val = -10.0;
+      double max_val = 10.0;
+      octave_stdout << "Properties of input array:\n";
+      if (m.any_element_is_negative ())
+        octave_stdout << "  includes negative values\n";
+      if (m.any_element_is_inf_or_nan ())
+        octave_stdout << "  includes Inf or NaN values\n";
+      if (m.any_element_not_one_or_zero ())
+        octave_stdout << "  includes other values than 1 and 0\n";
+      if (m.all_elements_are_int_or_inf_or_nan ())
+        octave_stdout << "  includes only int, Inf or NaN values\n";
+      if (m.all_integers (min_val, max_val))
+        octave_stdout << "  includes only integers in [-10,10]\n";
+    }
+  return retval;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/standalone.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,19 @@
+#include <iostream>
+#include <octave/oct.h>
+
+int
+main (void)
+{
+  std::cout << "Hello Octave world!\n";
+
+  int n = 2;
+  Matrix a_matrix = Matrix (n, n);
+
+  for (octave_idx_type i = 0; i < n; i++)
+    for (octave_idx_type j = 0; j < n; j++)
+      a_matrix(i,j) = (i + 1) * 10 + (j + 1);
+
+  std::cout << a_matrix;
+
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/standalonebuiltin.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,28 @@
+#include <iostream>
+#include <octave/oct.h>
+#include <octave/builtin-defun-decls.h>
+
+int
+main (void)
+{
+  int n = 2;
+  Matrix a_matrix = Matrix (n, n);
+
+  for (octave_idx_type i = 0; i < n; i++)
+    for (octave_idx_type j = 0; j < n; j++)
+      a_matrix(i,j) = (i + 1) * 10 + (j + 1);
+
+  std::cout << "This is a matrix:" << std::endl 
+            << a_matrix            << std::endl;
+
+  octave_value_list in;
+  in(0) = a_matrix;
+
+  octave_value_list out = Fnorm (in, 1);
+  double norm_of_the_matrix = out(0).double_value ();
+
+  std::cout << "This is the norm of the matrix:" << std::endl 
+            << norm_of_the_matrix                << std::endl;
+  
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/stringdemo.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,29 @@
+#include <octave/oct.h>
+
+DEFUN_DLD (stringdemo, args, , "String Demo")
+{
+  octave_value_list retval;
+  int nargin = args.length ();
+
+  if (nargin != 1)
+    print_usage ();
+  else
+    {
+      charMatrix ch = args(0).char_matrix_value ();
+
+      if (! error_state)
+        {
+          retval(1) = octave_value (ch, '\'');  // Single Quote String
+
+          octave_idx_type nr = ch.rows ();
+          for (octave_idx_type i = 0; i < nr / 2; i++)
+            {
+              std::string tmp = ch.row_as_string (i);
+              ch.insert (ch.row_as_string (nr-i-1).c_str (), i, 0);
+              ch.insert (tmp.c_str (), nr-i-1, 0);
+            }
+          retval(0) = octave_value (ch, '"');  // Double Quote String
+        }
+    }
+  return retval;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/structdemo.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,45 @@
+#include <octave/oct.h>
+#include <octave/ov-struct.h>
+
+DEFUN_DLD (structdemo, args, , "Struct Demo")
+{
+  octave_value retval;
+  int nargin = args.length ();
+
+  if (args.length () == 2)
+    {
+      octave_scalar_map arg0 = args(0).scalar_map_value ();
+      //octave_map arg0 = args(0).map_value ();
+
+      if (! error_state)
+        {
+          std::string arg1 = args(1).string_value ();
+
+          if (! error_state)
+            {
+              octave_value tmp = arg0.contents (arg1);
+              //octave_value tmp = arg0.contents (arg1)(0);
+
+              if (tmp.is_defined ())
+                {
+                  octave_scalar_map st;
+
+                  st.assign ("selected", tmp);
+
+                  retval = octave_value (st);
+                }
+              else
+                error ("structdemo: struct does not have a field named '%s'\n",
+                       arg1.c_str ());
+            }
+          else
+            error ("structdemo: ARG2 must be a character string");
+        }
+      else
+        error ("structdemo: ARG1 must be a struct");
+    }
+  else
+    print_usage ();
+
+  return retval;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/code/unwinddemo.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,47 @@
+#include <octave/oct.h>
+#include <octave/unwind-prot.h>
+
+void
+my_err_handler (const char *fmt, ...)
+{
+  // Do nothing!!
+}
+
+void
+my_err_with_id_handler (const char *id, const char *fmt, ...)
+{
+  // Do nothing!!
+}
+
+DEFUN_DLD (unwinddemo, args, nargout, "Unwind Demo")
+{
+  octave_value retval;
+  int nargin = args.length ();
+
+  if (nargin < 2)
+    print_usage ();
+  else
+    {
+      NDArray a = args(0).array_value ();
+      NDArray b = args(1).array_value ();
+
+      if (! error_state)
+        {
+          // Declare unwind_protect frame which lasts as long as
+          // the variable frame has scope.
+          unwind_protect frame;
+          frame.add_fcn (set_liboctave_warning_handler,
+                         current_liboctave_warning_handler);
+
+          frame.add_fcn (set_liboctave_warning_with_id_handler,
+                         current_liboctave_warning_with_id_handler);
+
+          set_liboctave_warning_handler (my_err_handler);
+          set_liboctave_warning_with_id_handler (my_err_with_id_handler);
+
+          retval = octave_value (quotient (a, b));
+        }
+    }
+
+  return retval;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/data/Makefile.am	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,29 @@
+# Makefile for Octave's examples/data directory
+#
+# 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/>.
+
+include $(top_srcdir)/build-aux/common.mk
+
+DATA_FILES = \
+   penny.mat
+
+octdata_DATA = $(DATA_FILES)
+
+EXTRA_DIST = $(DATA_FILES)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/data/penny.mat	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,135 @@
+# Created by Octave 3.8.1, Sun Jun 01 16:28:53 2014 CEST <weber@t61>
+# name: P
+# type: matrix
+# rows: 128
+# columns: 128
+ 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 18 43 68 89 107 120 135 149 162 172 180 192 196 203 207 211 210 212 213 214 212 210 209 204 201 194 183 177 163 148 130 116 98 81 60 35 6 4 3 3 3 3 3 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
+ 2 2 2 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 6 33 63 90 111 132 152 172 190 199 209 215 219 222 224 225 226 228 228 229 228 229 230 228 229 230 229 228 227 226 225 221 216 216 207 197 189 171 151 128 107 81 52 21 4 3 3 3 2 3 3 3 2 2 2 2 3 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
+ 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 9 44 78 104 130 159 183 200 214 222 225 227 230 230 233 235 235 235 235 235 235 235 235 234 233 233 234 234 233 233 232 232 232 231 232 231 230 228 227 226 223 220 213 203 183 157 130 100 70 34 5 3 3 3 3 2 3 2 3 2 2 2 2 2 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
+ 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 1 2 2 2 2 2 27 64 99 129 160 186 206 218 226 229 231 234 235 236 236 235 235 232 229 226 221 219 218 216 216 214 214 215 216 218 220 221 223 226 228 229 230 231 231 231 230 230 229 228 227 226 222 218 209 188 159 128 96 58 15 4 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
+ 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 35 75 110 140 174 202 217 227 232 234 235 236 236 234 228 221 214 208 203 199 196 195 193 192 190 190 189 188 188 189 190 191 191 193 192 193 194 197 201 206 213 218 223 227 229 230 230 229 227 226 226 223 220 213 196 164 127 91 49 5 4 3 3 2 2 2 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2
+ 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 10 52 92 129 164 196 217 226 232 235 236 237 234 224 214 205 198 193 191 187 186 187 183 183 182 181 179 178 178 181 179 179 179 179 180 180 180 179 178 179 180 182 184 186 190 195 200 209 217 223 227 228 229 228 227 225 224 222 217 204 173 135 96 52 5 3 3 3 3 3 2 3 2 2 2 2 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
+ 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 1 8 52 93 131 165 200 221 229 234 236 237 234 225 212 201 193 188 185 183 180 178 176 175 174 173 173 182 174 171 177 180 170 175 184 170 169 176 180 179 177 172 169 169 171 174 176 178 179 182 185 188 194 203 212 221 226 228 227 227 226 224 223 219 208 184 144 103 54 5 3 3 3 3 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 2
+ 2 2 2 2 2 2 2 2 2 1 2 1 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 13 49 90 131 167 203 222 230 232 235 236 225 214 202 194 189 186 181 178 175 172 170 168 167 167 164 163 164 188 177 163 185 188 163 176 175 159 159 172 182 175 170 161 159 159 161 163 166 168 170 171 173 176 178 182 185 193 202 213 221 225 227 226 225 224 223 220 211 188 145 101 48 5 3 3 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
+ 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 4 45 88 128 166 201 222 231 234 234 232 219 204 193 189 186 183 179 175 171 167 164 163 160 158 156 155 155 154 154 171 178 158 184 185 160 175 159 148 148 165 170 153 150 147 148 150 151 153 156 157 159 161 163 165 169 173 175 177 180 185 192 204 216 223 225 226 224 224 223 221 212 188 141 91 34 4 3 2 2 2 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 2 2 2
+ 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 2 2 2 2 2 1 2 3 41 82 125 163 199 220 228 229 235 229 216 201 191 185 181 180 180 184 186 174 163 158 155 152 150 148 145 145 144 144 145 154 173 159 174 174 169 168 142 136 137 159 166 161 141 138 138 141 142 144 146 148 149 151 154 157 160 170 170 169 172 174 176 179 186 198 210 222 226 225 224 224 222 220 212 181 130 80 15 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
+ 2 2 2 2 1 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 20 71 114 154 194 220 230 230 235 231 215 200 193 187 180 177 173 181 198 188 183 188 162 150 146 143 141 139 136 135 135 135 135 138 162 167 159 156 166 155 129 126 127 151 143 137 129 129 130 132 133 136 137 140 141 144 145 148 151 165 177 183 174 167 168 170 173 176 182 195 211 222 225 225 223 222 221 219 206 166 114 53 4 3 2 3 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
+ 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 33 85 132 172 211 231 236 233 233 220 206 196 191 184 179 174 169 165 164 188 174 156 162 176 146 139 135 132 130 128 126 125 125 125 125 139 156 146 130 154 147 119 116 117 139 139 122 122 120 121 122 126 127 128 130 132 135 137 139 141 146 150 173 177 176 173 162 163 167 171 175 181 193 208 220 224 223 223 222 220 217 197 159 102 36 4 3 2 3 2 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2
+ 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 14 72 124 166 210 235 244 239 235 221 203 195 191 187 187 181 169 162 158 156 154 174 166 143 145 166 136 129 126 122 120 118 116 115 114 114 115 127 139 118 114 133 118 106 106 110 134 136 135 128 114 114 115 117 118 120 122 124 127 128 131 134 138 145 165 147 150 153 153 155 159 163 169 173 176 183 198 214 222 224 223 222 220 219 209 177 118 53 4 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
+ 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 38 96 144 187 227 246 247 240 228 207 198 191 186 186 200 195 194 180 156 151 147 144 158 166 137 136 155 129 120 116 113 111 109 106 105 104 104 104 106 109 101 100 102 99 97 97 99 105 109 112 110 105 105 107 108 110 112 114 116 119 120 124 126 131 148 151 138 140 142 146 148 151 166 175 168 169 172 175 185 202 217 223 223 222 220 219 218 201 142 79 4 3 3 3 3 2 2 2 2 2 2 3 2 2 2 2 2 2 2
+ 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 56 114 161 204 242 249 245 236 216 203 195 188 182 178 192 187 168 170 182 157 143 138 136 140 160 137 134 143 117 111 108 105 102 98 98 96 95 93 93 92 92 90 89 89 88 88 87 89 89 91 91 94 95 98 98 100 102 105 106 108 111 113 115 118 123 146 133 130 132 135 138 141 147 174 179 183 172 164 167 171 176 193 210 221 223 223 221 220 220 212 164 102 27 4 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2
+ 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 67 126 172 217 248 248 245 228 210 201 193 186 181 174 171 193 173 156 150 163 164 135 130 126 126 149 148 141 120 107 102 99 96 94 91 89 87 87 85 83 82 82 82 82 82 82 80 81 81 82 82 82 84 87 89 91 93 94 97 99 101 103 105 107 112 122 137 121 122 125 128 131 135 147 168 154 161 179 160 159 163 166 172 180 201 216 222 222 222 218 219 216 182 121 52 4 3 3 2 2 2 3 2 2 2 2 2 2 2 2 2
+ 2 2 1 2 2 2 2 2 2 2 2 1 2 2 2 7 83 137 185 230 249 247 238 217 204 198 193 187 179 172 166 162 182 173 148 142 146 163 128 122 117 116 126 126 111 100 96 93 91 88 86 83 81 79 78 76 75 76 78 80 85 89 89 81 78 76 76 76 77 78 80 81 83 85 87 89 91 92 95 97 100 104 116 118 113 115 118 121 125 131 156 163 143 147 170 153 153 156 159 164 168 175 192 211 221 223 222 220 219 219 189 133 65 4 3 2 2 3 2 2 2 2 2 2 2 2 2 2
+ 2 2 2 2 2 2 2 2 2 2 2 2 2 2 20 91 147 197 240 248 248 232 209 200 196 193 198 196 175 165 158 154 163 172 142 135 139 155 121 113 110 106 103 99 93 90 86 84 82 80 78 75 73 72 73 72 72 86 90 93 97 100 100 93 95 93 93 91 83 78 81 85 82 80 81 82 84 86 88 90 93 95 99 102 104 107 110 114 120 130 150 154 162 162 152 143 144 149 153 158 162 165 172 184 205 219 223 222 220 219 220 205 151 80 4 3 3 3 3 3 3 2 3 3 2 2 2 2
+ 2 1 2 2 2 2 1 2 2 2 2 2 2 3 80 141 192 233 249 250 232 210 200 194 190 198 197 183 170 159 153 148 143 153 160 140 143 145 115 106 102 97 93 89 85 81 78 75 74 72 71 68 69 72 83 90 91 95 97 94 101 106 111 108 103 98 97 104 107 108 104 99 98 89 75 76 77 78 80 82 85 88 91 94 96 99 102 106 112 128 138 127 141 153 134 134 138 142 146 151 170 162 163 168 175 193 213 222 222 221 219 219 220 180 111 30 3 3 2 3 2 2 2 1 2 2 2 2
+ 2 1 2 1 2 2 2 1 2 2 2 2 35 97 156 207 245 251 246 220 205 196 190 184 190 196 170 163 158 157 145 139 133 132 142 143 133 112 101 96 91 88 84 78 77 72 69 68 65 66 66 68 83 89 93 101 106 111 114 115 114 116 122 119 111 107 115 121 122 114 107 102 101 98 82 71 72 72 74 76 79 81 84 87 90 93 96 101 107 119 116 118 138 141 126 129 133 137 142 162 167 155 158 163 167 175 193 214 222 222 221 219 219 219 169 97 9 3 2 3 2 2 2 2 2 2 2 2
+ 2 2 2 2 2 1 2 1 2 2 1 31 102 158 210 247 253 243 217 205 196 188 181 176 188 189 161 155 168 176 142 132 125 120 117 113 106 99 93 88 83 80 76 72 69 65 62 60 61 70 85 88 88 90 101 114 121 126 131 133 131 131 137 132 131 136 135 135 130 125 121 118 114 105 96 90 76 69 70 72 73 76 77 82 84 87 90 93 99 103 106 111 131 134 120 125 127 132 143 161 148 148 153 158 163 166 172 189 212 221 221 220 219 221 219 171 96 8 3 3 2 2 2 2 2 2 2 2
+ 1 1 2 2 1 2 2 2 2 2 6 81 143 197 241 253 247 222 206 197 190 182 175 169 168 187 162 150 154 166 163 130 120 114 109 105 98 92 87 82 78 72 69 65 62 59 57 57 65 88 96 100 101 103 110 122 134 140 144 147 146 148 150 146 145 144 142 139 134 131 133 133 131 120 108 107 102 92 80 78 74 72 74 75 78 81 83 87 91 95 98 102 110 119 115 116 120 126 148 150 137 141 146 166 168 159 164 169 181 205 219 222 221 220 218 221 187 112 16 3 3 2 2 2 2 2 2 2
+ 1 2 2 2 2 2 2 2 2 2 80 140 194 241 254 244 220 205 197 190 183 175 168 163 158 169 173 148 142 152 148 123 112 106 102 96 92 86 81 76 70 67 63 60 56 53 55 68 86 91 97 106 111 114 118 128 146 153 154 153 157 156 153 149 147 146 141 135 129 130 142 144 145 138 125 118 117 124 124 117 108 94 79 71 73 75 78 82 85 89 92 97 100 103 108 111 115 126 148 134 131 135 148 166 151 152 157 162 168 179 204 220 222 221 220 218 222 182 105 11 3 2 2 2 2 2 2 2
+ 2 2 2 2 2 2 2 1 1 66 135 189 237 253 248 220 205 198 190 183 175 168 162 157 151 150 158 160 156 147 126 113 106 101 96 90 85 80 75 71 64 60 57 54 51 51 71 79 90 94 110 118 124 131 138 143 155 162 161 156 161 161 155 146 143 139 135 129 127 136 150 151 149 140 129 127 131 139 136 131 118 98 85 74 70 70 73 76 79 82 86 90 94 98 102 106 109 125 141 124 126 134 157 146 142 148 152 157 163 169 182 204 220 222 220 219 217 223 175 93 4 3 2 2 3 3 2 2
+ 2 1 2 1 1 2 2 1 54 125 182 235 252 249 224 206 198 191 185 176 169 161 155 150 145 140 137 134 131 120 110 104 99 95 89 84 79 75 70 64 59 54 52 49 56 76 89 97 101 114 124 133 147 154 152 152 165 168 168 163 165 165 157 140 130 130 129 129 135 149 153 153 151 137 127 133 139 148 151 142 122 108 94 87 69 66 69 71 74 77 81 85 88 92 95 100 104 115 136 124 128 148 140 133 137 141 146 152 158 165 171 182 205 220 222 220 219 219 223 170 88 4 3 3 2 2 2 2
+ 2 2 1 1 2 2 1 58 128 186 235 252 244 219 205 197 195 187 176 168 161 154 148 143 137 132 126 121 113 108 103 98 93 86 81 76 73 67 61 57 53 51 53 70 95 108 114 120 127 138 148 160 167 164 162 169 175 176 173 173 169 168 156 139 131 132 136 142 146 149 151 155 147 134 138 146 150 158 157 145 131 115 99 89 84 70 65 68 70 74 76 80 84 87 91 94 99 105 122 133 135 126 123 128 133 137 144 157 172 168 169 174 188 211 221 221 220 218 226 214 142 45 3 3 2 2 3 3
+ 1 2 2 2 2 2 43 114 173 225 248 245 220 207 198 192 200 202 172 164 155 148 142 136 131 125 120 113 107 101 97 91 86 79 74 69 66 60 57 53 55 73 95 112 126 132 135 142 149 160 169 177 179 178 179 181 181 181 180 178 176 170 163 144 136 134 137 141 145 144 151 156 149 148 150 153 159 160 159 154 146 131 114 101 89 83 64 62 65 68 71 74 78 81 85 88 92 96 101 107 111 114 117 121 127 132 140 171 170 181 169 168 174 187 212 221 221 219 219 228 208 129 30 3 3 2 2 2
+ 2 2 2 1 2 23 96 161 217 245 245 225 209 202 194 189 182 193 190 161 150 143 137 131 125 119 113 106 101 96 91 85 79 74 68 64 60 56 53 53 68 86 111 131 141 145 148 155 165 176 181 185 187 186 185 186 185 185 184 183 178 169 165 148 136 133 134 141 147 148 152 155 146 143 143 149 159 158 156 158 152 143 121 107 96 83 63 59 60 63 67 69 72 76 79 82 86 90 94 98 103 107 113 118 122 128 137 166 149 162 170 162 167 173 191 214 221 221 219 218 227 197 109 4 3 3 2 3
+ 2 2 2 1 2 64 130 189 235 248 236 214 205 198 195 187 179 173 186 184 151 141 133 126 121 116 109 103 98 93 87 81 75 69 64 60 56 53 50 59 73 90 113 139 146 150 151 153 171 180 183 188 188 187 188 189 189 187 185 184 177 168 165 156 143 142 142 142 151 149 145 150 138 133 136 146 151 151 154 154 151 146 139 111 91 85 69 55 56 58 61 63 66 69 73 76 79 84 88 91 96 100 106 111 125 132 128 156 153 144 150 154 159 164 171 190 213 222 221 220 218 229 198 113 4 2 3 3
+ 2 2 2 2 60 128 188 235 249 234 213 204 198 211 216 208 195 184 182 181 160 135 125 120 115 108 102 97 91 86 80 74 69 63 58 55 52 51 58 77 92 109 134 146 152 156 153 172 179 181 186 191 186 184 189 191 191 190 190 185 179 178 171 155 150 150 150 153 154 147 151 148 141 140 141 144 143 142 142 139 131 128 122 98 83 75 61 51 52 54 56 61 62 66 69 72 76 79 82 87 91 96 102 108 131 132 125 156 147 138 143 149 154 160 168 175 200 220 222 220 218 225 227 159 62 4 2 3
+ 1 2 2 35 108 172 224 248 240 216 208 199 192 191 205 200 184 174 168 163 148 127 120 114 108 103 97 92 87 80 75 70 64 60 55 51 50 63 81 92 107 125 143 152 160 163 169 182 180 180 187 192 188 186 188 191 194 194 193 192 190 187 176 162 157 157 159 160 158 154 156 155 152 147 148 146 142 136 130 126 118 110 106 90 75 68 53 45 48 50 52 55 58 61 64 67 71 74 77 82 86 91 96 102 117 137 137 151 138 133 139 144 150 156 163 170 180 207 220 222 220 218 231 216 134 24 3 3
+ 2 2 2 67 138 197 236 249 226 214 205 197 188 181 177 189 186 157 146 138 130 121 116 110 104 99 93 88 82 77 72 66 61 57 53 48 49 73 90 103 119 133 151 159 166 175 180 187 183 177 182 190 192 189 186 191 194 195 195 194 192 189 184 173 165 163 164 167 165 161 162 162 154 156 157 157 153 145 134 122 114 105 91 76 66 60 45 41 43 45 48 51 53 56 58 62 65 68 72 76 80 85 90 94 101 113 128 132 125 127 132 138 144 153 169 163 170 180 207 222 222 220 219 231 211 129 15 3
+ 2 2 43 116 179 232 251 233 216 207 205 203 183 175 169 164 175 168 139 130 122 114 108 104 98 92 88 82 77 72 67 62 57 52 48 45 53 85 103 114 127 141 158 172 178 186 190 192 188 179 178 184 192 193 190 190 191 193 194 193 193 189 185 179 174 174 173 173 173 170 166 164 167 167 166 166 164 159 148 133 118 100 72 58 54 41 35 36 38 41 43 47 49 52 55 57 60 64 68 71 75 78 84 89 94 100 106 112 116 121 127 133 140 153 181 172 166 172 186 214 222 221 219 217 233 190 97 3
+ 2 12 89 159 217 251 243 220 209 201 202 210 192 171 163 155 150 152 135 122 115 108 102 98 92 87 82 77 72 67 63 57 53 47 44 43 67 94 108 119 134 142 161 177 185 190 194 195 192 185 180 182 193 194 190 187 187 191 191 194 195 193 188 184 183 182 181 180 179 173 175 176 175 174 173 172 172 170 163 149 130 106 73 50 34 31 30 32 35 37 40 42 44 48 51 54 56 60 63 66 70 74 80 84 89 94 100 106 110 116 122 128 135 144 169 187 166 168 176 195 218 222 221 219 224 230 157 49
+ 2 81 152 210 249 246 222 210 201 193 187 191 195 173 154 146 138 131 122 114 106 101 95 90 85 79 75 71 65 61 56 51 47 43 40 56 82 103 114 133 139 150 166 180 186 189 194 195 192 184 181 193 196 194 190 188 189 191 193 195 191 186 188 189 187 187 185 183 183 183 183 181 181 181 180 178 179 178 172 160 140 114 81 36 26 26 26 29 31 33 36 39 41 44 47 50 52 55 60 63 67 71 75 80 85 90 96 102 108 114 121 126 134 153 174 182 181 166 172 182 211 222 221 220 218 233 190 91
+ 53 126 188 244 247 228 215 205 195 188 180 174 178 181 159 140 131 123 115 108 100 95 89 84 79 74 70 65 60 56 51 47 42 37 37 63 86 109 122 138 146 157 167 179 187 191 192 188 186 189 191 197 197 194 192 189 189 194 195 191 183 185 189 188 189 188 188 186 186 185 186 186 185 186 184 183 183 181 178 172 156 134 102 51 23 24 24 26 28 30 33 34 37 40 43 46 49 51 55 59 62 66 71 75 80 86 91 97 103 109 117 124 147 160 155 161 178 171 167 174 193 217 223 221 220 224 229 150
+ 98 167 227 247 239 221 209 199 189 181 173 167 160 162 160 137 125 117 109 102 95 89 83 78 73 69 65 59 54 51 47 42 37 33 36 67 88 116 131 141 156 164 169 180 187 191 190 180 174 186 196 198 197 196 195 193 190 192 192 185 180 185 191 192 191 190 189 189 188 189 189 189 190 190 188 186 186 184 182 176 165 147 122 79 24 20 21 23 25 26 28 29 34 35 38 41 44 47 51 55 57 62 66 70 76 81 87 93 99 106 117 141 148 138 136 142 152 156 162 168 177 201 221 222 221 220 232 205
+ 141 204 247 249 226 214 203 194 184 175 167 160 153 146 139 127 118 110 103 96 89 84 78 72 68 64 59 55 50 45 41 38 33 30 34 69 91 122 136 147 161 167 170 179 183 188 189 180 173 180 196 196 193 190 188 189 186 186 185 180 180 185 188 190 191 192 191 191 190 190 190 191 192 192 190 190 188 186 183 179 169 154 134 102 43 18 18 19 22 23 24 27 28 32 35 37 41 44 47 49 54 57 62 66 71 77 83 88 94 102 115 128 124 125 130 136 143 149 157 164 172 185 213 221 222 220 218 231
+ 163 224 250 242 222 211 200 191 181 172 163 156 149 141 132 123 114 107 99 92 85 79 74 68 64 59 55 51 46 41 38 33 30 28 34 67 92 118 137 148 159 165 169 178 183 185 188 186 183 183 192 190 184 181 182 179 175 177 180 178 180 182 182 187 191 191 190 191 190 190 191 191 192 192 192 192 191 189 186 180 173 161 145 122 82 23 16 18 18 20 20 22 24 27 30 33 35 38 43 45 49 52 56 61 66 71 77 81 88 95 102 110 114 119 124 131 136 143 150 157 166 175 190 216 223 221 220 224
+ 211 252 245 224 213 202 192 182 174 165 156 149 140 132 123 115 107 99 92 85 78 73 68 63 58 54 50 44 40 36 32 29 25 25 50 76 103 123 139 151 158 165 175 179 180 186 187 187 188 187 183 180 178 176 173 171 172 175 173 174 180 180 183 187 190 189 189 189 190 189 190 191 192 192 192 193 192 189 185 178 168 158 142 119 83 23 14 14 15 17 17 19 22 24 27 30 33 36 39 41 45 49 54 59 62 68 73 79 85 91 99 105 111 117 122 128 134 141 147 155 164 172 182 208 222 222 221 218
+ 242 255 231 218 207 196 187 177 169 160 152 143 135 126 117 109 101 94 87 81 74 69 63 58 54 47 44 39 36 31 28 26 22 22 51 76 100 121 133 148 157 165 175 177 179 185 187 188 189 184 176 174 174 172 171 175 176 173 168 171 179 184 185 187 189 189 189 189 188 187 188 190 190 191 191 192 192 188 184 178 168 157 143 122 91 31 13 12 13 14 15 16 18 21 24 27 30 32 36 39 42 47 51 55 60 64 69 75 81 87 94 101 106 112 118 125 130 137 144 151 159 167 176 192 218 223 221 220
+ 250 251 227 214 204 194 183 175 165 156 148 140 131 122 113 105 97 90 83 77 71 65 59 54 48 45 40 36 31 29 26 22 20 20 33 70 91 112 128 143 156 163 172 177 179 183 185 181 183 183 181 173 171 173 179 183 180 173 172 175 178 182 188 187 189 189 189 188 185 184 185 186 187 189 190 191 190 188 185 179 169 159 147 132 107 57 13 10 10 11 12 14 15 17 20 22 25 28 32 35 38 42 45 50 54 59 64 70 76 82 88 94 102 107 113 119 125 131 138 145 153 161 169 178 198 220 223 221
+ 255 231 218 205 196 185 177 167 158 150 140 132 123 114 106 98 90 84 77 71 64 59 53 49 43 38 34 31 27 25 21 18 16 16 32 73 97 114 132 149 158 164 170 176 178 180 180 176 176 181 182 180 177 184 187 187 179 176 177 181 184 182 187 187 186 187 187 184 181 180 182 183 185 187 188 189 188 187 183 177 168 157 148 133 104 48 10 9 8 9 10 11 12 15 17 20 23 26 29 33 36 40 44 47 52 57 61 67 73 79 85 92 99 106 111 117 123 129 136 143 151 158 166 176 190 218 224 222
+ 245 224 211 201 191 181 172 162 153 144 136 126 117 108 100 93 85 78 73 66 59 54 49 45 39 34 30 27 24 21 18 16 14 13 28 65 94 116 134 149 157 160 167 176 178 177 175 174 173 174 174 178 183 188 186 183 177 173 172 180 185 184 183 183 181 184 184 182 179 176 177 180 181 182 184 186 187 186 182 177 170 162 152 138 112 62 10 8 7 7 8 8 10 12 15 17 20 23 27 30 33 37 41 45 49 53 58 63 69 76 81 87 94 101 107 113 119 125 132 139 147 154 163 171 181 206 223 223
+ 231 218 207 196 185 176 167 157 149 139 131 121 112 103 96 88 80 74 68 62 55 50 45 40 35 30 27 23 21 18 15 13 11 11 29 60 82 111 133 148 157 162 164 176 179 175 169 170 169 171 174 178 184 185 177 171 168 166 170 177 181 181 177 179 178 179 180 179 174 170 171 174 175 177 181 183 183 183 181 179 175 166 158 145 121 75 14 6 5 5 5 6 7 9 13 14 18 20 24 27 31 34 38 41 46 50 55 61 66 72 77 84 90 97 103 109 116 122 129 135 143 150 158 167 176 191 219 224
+ 224 212 201 191 181 172 162 153 143 134 125 115 107 99 91 83 77 70 64 57 51 46 41 36 32 27 24 20 19 15 13 11 10 10 28 65 83 108 130 145 155 163 164 173 179 173 164 168 169 172 180 184 183 177 169 160 158 164 168 168 172 171 169 174 175 175 176 174 168 166 166 168 169 171 174 177 178 179 181 181 178 171 162 149 130 91 31 6 4 4 3 4 5 7 9 11 14 18 20 25 28 31 35 39 44 48 52 57 62 68 74 80 87 93 100 106 112 118 125 132 139 147 155 163 172 180 208 224
+ 219 207 196 187 177 167 158 148 138 130 120 111 103 94 85 79 72 66 59 54 48 42 37 32 28 24 22 18 15 13 11 10 8 7 25 66 88 109 129 140 151 159 163 168 177 173 162 166 173 182 184 182 174 165 161 152 154 163 161 158 161 160 163 165 166 170 174 170 165 162 161 160 162 164 166 169 172 175 180 181 178 171 161 152 133 98 42 6 4 3 2 3 3 5 7 9 12 15 18 22 25 29 32 36 40 44 49 53 58 64 70 76 83 89 96 103 109 116 121 129 135 143 150 159 167 176 194 220
+ 213 203 193 182 172 163 154 144 135 125 116 106 98 89 82 74 67 61 56 49 44 38 34 30 26 22 18 16 13 11 9 7 5 6 20 62 85 107 125 133 145 154 158 163 171 173 162 162 173 182 179 172 157 148 152 146 150 154 149 149 150 152 155 156 159 166 170 166 160 157 155 154 155 158 160 163 168 176 180 178 170 156 146 139 126 96 48 6 4 3 3 2 2 2 4 7 9 12 16 19 23 26 30 33 38 41 45 51 55 61 68 73 80 86 92 99 106 112 118 126 133 140 147 155 163 172 181 212
+ 212 201 192 181 171 161 152 143 132 123 113 104 96 87 80 72 65 59 53 47 42 36 32 28 24 21 17 15 11 10 8 6 4 4 10 53 71 97 118 127 133 147 155 156 165 170 165 161 170 176 168 163 145 132 136 147 143 140 140 139 142 148 150 152 156 163 163 160 156 151 150 150 151 152 155 158 164 174 178 173 160 137 118 114 110 92 57 10 4 3 2 2 2 2 2 4 6 10 13 16 20 23 27 30 34 37 41 46 51 57 63 69 75 81 88 94 101 108 114 120 127 135 142 151 158 166 174 190
+ 205 195 184 174 164 155 146 136 125 116 106 98 90 81 73 67 60 54 48 41 37 32 28 23 20 17 14 11 8 7 6 5 3 3 29 58 77 98 117 127 130 142 153 153 158 167 163 161 172 162 156 147 126 120 138 141 129 123 129 131 140 147 148 152 156 163 159 156 149 146 146 145 147 150 155 160 168 174 171 158 136 101 84 84 86 69 36 4 3 2 2 2 2 2 2 2 5 7 11 15 18 22 25 28 31 35 40 44 49 55 60 66 73 79 87 93 100 107 113 120 126 134 141 148 156 164 172 185
+ 203 194 182 173 163 153 143 134 124 114 104 96 87 80 72 64 58 52 46 40 34 30 26 22 18 15 13 10 8 6 4 3 3 3 20 53 75 89 108 120 130 136 147 154 158 165 168 164 170 159 156 145 127 121 127 135 122 112 115 126 137 147 146 149 155 161 160 158 151 148 147 146 144 147 153 159 165 166 160 145 135 116 76 68 71 64 35 4 3 3 2 3 2 2 2 2 3 5 9 11 15 19 22 24 28 31 35 40 45 51 56 62 69 75 82 89 95 102 109 115 122 129 135 143 151 159 167 176
+ 197 188 177 167 157 147 137 124 117 107 98 90 82 74 67 60 53 47 41 36 31 27 22 19 16 12 9 7 5 3 3 2 2 3 31 60 74 90 106 119 131 139 144 147 155 164 172 175 173 158 156 138 121 113 124 123 111 104 109 125 141 149 149 150 159 162 160 158 155 154 152 148 146 147 153 155 155 149 135 131 121 92 60 59 64 57 20 4 3 2 3 2 2 2 2 2 2 3 7 10 13 17 19 23 25 29 34 39 44 49 55 61 68 74 81 87 95 102 108 115 121 127 135 142 150 158 167 175
+ 194 184 173 163 153 143 133 123 113 104 95 87 79 71 64 57 51 45 39 33 28 25 20 17 13 11 9 6 3 2 2 2 2 2 33 58 71 85 101 114 126 137 142 141 147 158 166 172 172 161 156 136 112 107 116 113 109 111 117 127 141 147 154 153 158 163 164 161 159 158 156 153 149 149 150 149 141 130 123 119 112 78 51 49 58 58 30 4 3 2 2 2 2 2 2 3 3 2 5 8 11 13 16 20 23 27 32 36 42 47 53 58 65 72 78 85 92 99 106 112 119 125 132 139 147 155 163 173
+ 191 181 170 160 149 139 130 119 110 101 92 83 75 67 61 54 48 42 36 31 26 22 18 14 12 9 7 4 3 3 2 2 2 2 31 54 69 84 97 109 122 132 138 141 144 148 154 162 167 162 155 134 107 109 108 109 113 119 125 132 142 149 153 158 160 162 162 164 162 161 160 158 154 151 149 145 133 127 124 123 112 76 49 45 51 55 45 7 3 3 2 2 2 2 2 2 2 2 3 6 9 12 13 18 21 25 29 34 39 44 50 56 63 70 76 83 91 97 104 110 117 123 129 137 144 153 161 169
+ 190 179 169 158 149 139 129 118 108 99 90 82 75 67 60 53 47 41 35 30 25 22 18 15 11 8 6 4 3 3 2 3 3 2 16 42 60 79 93 105 116 126 133 141 145 144 143 143 156 163 157 141 110 107 107 119 122 124 128 132 139 147 155 159 161 162 163 163 163 163 164 163 160 157 153 150 138 131 129 128 118 92 53 49 49 53 52 36 5 2 3 2 2 3 2 2 2 2 2 3 6 9 12 15 19 22 26 31 35 40 47 53 59 66 73 79 87 93 100 106 113 119 126 132 140 148 156 164
+ 184 173 163 152 143 132 122 112 103 94 86 78 71 63 56 50 43 37 32 28 23 20 16 12 10 6 4 3 3 3 3 3 2 2 13 37 59 76 91 106 116 123 131 139 145 140 136 140 147 158 153 136 110 100 110 132 131 128 129 130 135 144 151 156 158 160 162 162 163 163 164 163 161 158 156 151 141 136 133 128 116 81 55 54 54 55 53 41 6 3 3 3 2 2 2 2 2 2 2 2 5 8 11 14 18 21 25 30 35 40 46 52 59 65 72 78 86 92 99 105 112 119 125 131 139 148 156 165
+ 180 170 160 150 139 129 119 109 99 93 83 75 67 60 54 47 41 36 30 26 22 18 14 11 8 5 4 3 3 2 3 2 3 2 2 28 53 67 81 101 111 116 127 130 137 137 128 136 139 155 151 140 112 100 107 131 131 127 125 124 126 133 141 146 149 153 158 159 158 158 160 159 160 158 157 155 150 144 139 131 116 84 62 57 56 56 54 48 27 4 3 2 3 2 2 2 2 2 2 2 3 7 9 13 16 21 24 28 33 38 44 50 57 64 70 77 84 90 97 104 110 117 123 130 137 145 153 162
+ 178 167 157 147 136 126 116 106 97 88 80 73 65 58 51 45 39 34 29 25 21 17 13 10 8 5 3 3 3 2 2 2 2 2 2 19 46 62 67 89 103 108 122 124 127 131 126 129 136 148 151 143 121 104 106 121 126 121 118 117 119 123 130 135 139 146 152 152 151 150 151 154 156 156 156 156 155 152 145 133 114 84 69 60 57 57 55 52 41 6 3 3 3 2 2 2 2 2 2 2 2 4 8 11 14 19 23 27 32 37 42 49 55 61 68 75 82 89 95 102 108 115 121 128 136 143 151 159
+ 175 164 154 144 133 123 113 104 94 86 78 71 64 57 50 43 38 33 28 24 20 16 13 10 7 4 3 2 3 2 2 2 2 2 2 12 38 55 59 71 88 103 120 124 125 130 131 132 132 138 148 141 131 116 109 108 116 112 110 112 115 120 124 128 133 139 144 142 140 138 142 147 151 153 153 154 153 152 147 135 116 87 73 62 58 58 56 54 49 28 3 3 2 2 2 2 2 2 2 2 2 3 7 10 13 17 21 26 30 35 41 47 53 60 66 73 80 88 94 100 106 113 120 126 134 141 149 158
+ 172 162 152 141 131 121 110 101 92 84 77 69 62 55 48 42 36 31 27 23 20 15 12 10 6 4 3 3 3 3 2 2 2 2 3 2 27 45 59 67 79 101 117 124 126 128 127 130 129 129 142 139 131 132 128 113 112 107 105 107 111 117 120 125 129 133 135 133 130 127 131 139 146 150 151 151 151 149 144 133 115 94 77 66 60 58 57 56 53 43 5 3 3 3 2 3 2 2 2 2 2 2 5 9 12 16 19 24 28 34 40 45 52 58 65 72 78 85 91 99 105 112 118 125 132 140 147 155
+ 170 160 149 139 128 118 108 100 91 82 75 67 60 54 47 41 35 31 26 22 18 15 12 9 6 4 3 3 3 3 3 3 2 2 2 1 12 39 57 68 82 101 113 120 121 123 119 116 119 122 132 140 132 133 134 122 111 106 103 104 110 115 119 121 126 128 127 127 122 120 121 128 138 146 147 148 149 148 140 129 113 96 84 70 60 58 56 55 55 50 27 4 3 2 3 3 2 2 2 2 2 2 4 7 11 15 19 23 27 32 37 44 51 56 63 70 77 83 91 97 103 110 117 123 131 139 146 154
+ 168 158 147 136 126 116 106 97 88 80 73 65 59 52 46 40 35 30 26 22 19 15 12 9 6 4 3 3 3 2 2 2 2 2 2 2 2 34 57 63 78 96 104 112 118 117 119 111 115 120 122 131 135 139 137 126 115 105 104 105 110 116 117 117 123 126 124 124 123 118 116 120 128 138 142 144 145 143 135 124 111 101 87 68 64 62 57 53 53 52 38 5 3 3 2 3 2 2 2 2 2 2 4 6 10 14 17 21 26 31 36 43 48 56 62 69 75 82 89 96 102 109 115 122 129 137 144 152
+ 166 156 145 134 124 114 105 95 87 79 71 64 57 50 45 39 34 30 26 22 19 15 12 9 6 4 3 3 2 2 3 2 3 3 2 2 2 27 53 60 71 89 96 101 113 116 116 118 117 115 114 112 124 138 141 132 119 102 105 106 112 114 115 115 118 124 124 120 122 120 118 115 119 128 132 135 137 135 128 120 111 103 82 70 75 76 68 60 56 51 38 5 3 3 3 2 2 2 2 2 2 3 2 6 10 13 17 20 24 30 35 41 47 53 60 68 75 81 88 94 101 107 114 121 128 136 142 151
+ 165 154 143 133 122 112 103 94 85 78 70 62 56 50 44 39 33 28 25 21 18 15 12 9 7 4 3 3 3 2 2 2 2 2 2 2 2 15 47 59 65 83 92 98 108 115 116 117 113 108 107 104 102 122 136 134 115 96 106 109 112 115 115 116 117 122 124 122 122 121 117 113 113 118 123 125 126 124 121 116 111 100 72 67 74 73 67 58 49 39 21 4 3 3 2 3 2 2 2 2 2 2 2 4 8 12 15 19 24 28 33 39 46 53 59 66 73 80 87 94 100 106 114 119 127 134 141 149
+ 163 153 141 131 121 111 101 92 84 76 69 61 56 49 43 38 33 30 25 21 18 15 12 10 7 4 3 2 2 2 2 2 2 2 2 2 2 3 33 55 68 79 90 100 107 110 110 113 109 102 95 97 89 92 112 113 100 95 104 112 114 116 117 118 119 121 123 122 120 119 117 113 109 110 113 116 114 113 111 110 106 92 64 60 59 55 44 29 18 6 4 3 2 2 2 3 2 2 2 2 2 2 2 4 7 11 14 18 22 28 32 38 45 51 58 65 71 78 86 92 99 105 112 118 125 132 140 148
+ 161 151 140 130 119 109 100 91 83 75 68 61 55 49 43 37 33 29 25 21 19 15 12 9 7 4 3 3 2 2 2 1 2 2 2 2 2 2 14 40 57 72 85 97 105 106 101 103 106 97 95 91 84 79 79 90 95 98 105 112 116 118 121 123 121 121 122 122 121 119 116 111 104 101 105 101 99 98 99 100 93 78 65 58 54 47 12 3 3 2 2 2 2 3 2 2 2 2 2 2 2 3 2 3 6 10 13 17 21 26 31 37 43 50 57 63 70 77 84 91 97 104 111 117 124 131 139 146
+ 160 149 138 129 117 108 98 89 82 74 67 60 55 48 42 37 32 28 25 21 18 15 12 10 8 5 4 3 2 3 2 2 2 2 2 2 2 2 7 33 47 65 76 90 99 103 101 97 104 102 95 92 86 83 77 85 96 102 108 113 118 120 121 124 125 123 124 123 121 119 115 109 101 99 99 94 90 91 94 94 86 77 70 63 57 44 6 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 6 9 12 16 20 25 31 36 42 49 55 63 70 76 83 90 97 103 110 116 123 130 137 145
+ 158 147 137 127 116 107 97 89 81 73 67 60 53 47 42 37 32 28 25 21 19 16 13 11 8 6 4 3 3 2 2 2 2 2 2 2 2 2 6 33 40 63 71 80 87 92 100 99 100 102 97 92 89 86 83 84 95 104 110 114 119 121 122 126 126 127 125 123 121 118 114 107 99 97 95 85 84 88 92 89 81 78 74 66 57 42 5 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 5 8 11 16 20 24 30 35 42 48 54 62 68 75 83 90 96 103 109 115 122 129 136 144
+ 157 147 137 126 116 107 97 88 80 73 66 59 53 46 41 37 33 29 25 22 20 16 14 11 9 7 5 3 3 3 3 3 3 2 2 2 2 2 3 29 38 60 66 76 79 83 93 94 90 98 96 93 91 90 88 87 92 101 109 115 118 122 123 127 127 127 126 121 117 117 112 105 100 98 93 81 85 89 85 84 81 75 70 63 53 38 5 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 5 8 11 15 19 24 28 35 40 47 54 61 68 75 82 89 96 103 108 115 122 128 136 143
+ 159 148 138 128 117 108 99 90 82 74 67 61 54 48 43 37 33 29 26 23 20 17 14 13 10 8 6 5 4 3 2 3 2 2 2 2 2 2 2 8 34 51 59 72 80 79 85 93 94 93 93 94 93 93 94 92 91 94 103 111 117 121 122 126 127 127 125 120 114 112 111 106 101 99 94 84 90 91 89 86 72 61 58 53 45 29 5 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 6 10 14 17 22 27 33 39 45 51 58 66 73 80 87 93 100 106 113 120 126 133 141
+ 156 145 135 124 114 105 96 88 80 72 66 58 53 47 42 37 33 29 25 23 20 18 15 13 11 8 7 5 4 3 3 2 2 3 2 2 2 1 2 6 32 47 57 73 82 81 84 86 90 90 92 93 94 94 95 94 91 92 102 110 116 121 122 126 127 126 123 118 115 112 109 104 100 100 91 89 94 93 91 77 58 53 51 43 29 7 3 2 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 4 7 11 15 19 24 29 34 40 46 52 60 67 74 81 88 95 102 108 114 121 128 136 142
+ 157 147 137 127 117 107 98 89 82 74 67 61 54 48 43 38 34 31 27 25 21 19 16 14 12 10 8 7 5 4 3 3 2 2 2 2 2 2 2 2 13 34 40 59 74 77 77 82 82 86 90 93 95 97 97 97 95 91 93 103 111 115 119 124 125 124 123 122 118 114 110 108 104 102 94 91 96 96 91 74 63 63 61 53 39 6 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 7 10 14 18 22 27 32 38 44 51 58 64 72 80 86 93 100 106 112 119 126 132 140
+ 155 145 134 124 114 105 96 88 80 73 66 60 53 47 42 38 34 30 27 24 22 19 16 14 13 11 9 7 5 4 4 3 2 3 2 2 2 2 2 2 4 23 33 44 56 68 77 78 80 86 90 93 98 100 100 98 96 93 90 98 108 113 115 121 123 121 123 123 119 115 114 111 107 103 93 93 94 94 84 67 64 61 55 44 23 4 3 2 2 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 5 8 11 15 19 24 28 34 39 45 52 59 66 73 81 88 94 101 108 114 121 127 135 142
+ 154 144 134 124 114 105 95 88 80 73 67 60 54 48 43 39 35 31 28 26 22 20 17 15 13 11 9 7 6 5 4 4 3 3 2 2 2 2 2 2 2 3 15 29 47 61 72 76 80 86 90 95 98 101 102 101 98 95 90 93 104 110 113 118 120 120 122 122 121 119 117 114 110 104 94 91 91 90 84 70 66 60 48 23 4 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 4 8 11 15 19 24 29 34 40 46 53 60 66 73 80 87 94 101 108 114 121 128 135 142
+ 157 146 136 126 116 107 98 90 82 76 69 62 57 51 45 41 37 33 30 27 24 21 19 17 15 13 11 8 7 7 6 4 3 4 3 2 2 2 2 2 2 2 2 6 37 55 66 74 80 85 90 95 99 101 103 103 101 97 95 91 96 104 110 114 118 118 120 121 122 123 121 116 114 108 98 94 90 91 90 80 69 61 48 21 4 3 3 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 4 8 10 14 18 22 28 33 39 45 52 58 65 72 79 86 92 99 106 113 119 127 133 141
+ 154 144 134 124 114 105 96 89 80 75 68 62 56 50 45 41 38 34 30 28 25 22 19 18 16 13 11 10 8 7 6 5 5 4 3 2 2 2 2 2 2 2 2 18 46 59 69 77 83 88 93 97 100 102 104 105 103 98 95 92 93 100 105 111 115 115 115 120 122 123 121 119 114 107 97 96 96 94 93 86 75 63 50 33 5 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 5 8 11 16 19 24 29 35 41 47 53 60 67 74 81 88 94 101 108 115 121 128 135 143
+ 155 145 134 124 114 106 97 88 82 75 69 63 57 52 47 43 39 36 32 29 26 23 21 19 17 15 13 11 9 8 7 6 5 4 3 3 2 2 2 2 2 2 4 36 55 68 74 79 85 90 94 97 100 103 105 106 106 102 96 93 92 94 98 104 110 114 114 118 120 121 123 120 115 110 102 99 103 102 100 96 86 75 62 51 30 4 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 5 9 13 16 20 25 30 35 41 48 55 60 68 74 82 89 95 102 109 115 122 129 136 143
+ 155 144 134 123 114 105 97 89 82 76 69 64 59 53 49 45 41 37 34 31 27 25 23 20 19 16 14 12 11 10 7 7 6 5 3 3 3 2 2 2 2 2 20 41 57 70 81 86 88 91 94 98 101 103 105 107 106 104 98 94 91 90 90 97 101 109 114 117 118 118 121 121 117 113 106 103 106 106 106 102 93 86 78 65 50 31 6 3 3 2 2 2 2 2 1 2 2 2 2 2 2 2 2 3 6 9 13 17 21 26 31 36 42 49 55 61 68 75 82 89 95 102 109 116 123 130 137 144
+ 154 144 134 124 114 106 98 90 83 77 71 65 60 55 50 45 42 39 36 33 30 27 24 22 19 17 15 15 13 11 9 8 7 6 5 4 3 2 2 2 2 11 38 49 59 70 81 90 95 97 97 98 100 103 104 106 107 105 101 96 92 88 88 91 95 103 107 109 113 114 118 121 118 117 111 106 109 110 109 104 96 92 87 78 66 49 26 4 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 4 6 10 14 18 22 27 32 38 43 49 55 62 69 76 83 90 97 103 110 117 124 130 137 145
+ 154 145 135 124 115 107 98 90 84 77 72 67 61 56 51 48 44 41 38 34 31 29 26 24 22 20 17 16 15 12 12 10 9 7 5 5 3 3 2 2 2 23 48 63 72 75 82 88 94 100 102 102 101 102 103 105 105 104 102 98 93 90 87 88 91 95 101 104 105 109 113 118 119 117 114 106 110 110 106 102 96 92 88 80 68 51 28 4 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 4 7 11 15 19 23 28 34 38 45 50 57 63 70 77 84 91 98 105 111 118 125 131 138 146
+ 158 149 142 128 119 113 104 96 87 80 75 70 66 60 55 51 47 44 41 38 34 31 29 26 25 23 21 18 16 15 14 13 11 10 8 6 5 3 2 2 3 29 51 67 77 86 90 90 92 96 100 104 106 104 103 103 103 103 102 99 95 90 87 86 88 91 95 100 99 100 103 108 114 113 114 109 107 107 101 98 94 89 84 77 67 51 30 5 3 3 2 1 2 2 2 2 2 2 2 2 2 2 2 5 8 11 14 18 24 28 33 39 45 50 57 63 70 77 84 90 97 104 111 118 124 130 137 145
+ 156 157 164 130 127 142 132 123 95 81 77 96 92 84 62 53 70 70 65 52 36 33 44 45 42 39 35 24 27 20 17 16 16 15 9 6 4 3 2 3 18 46 64 76 84 91 98 99 96 96 99 103 107 109 107 104 102 101 100 97 93 87 85 84 86 88 91 93 92 91 93 99 105 106 102 99 98 97 93 91 88 81 73 69 57 40 16 4 3 3 2 2 2 2 2 2 2 2 2 2 1 2 4 7 9 13 17 22 26 31 36 42 47 54 60 67 74 80 87 93 100 107 114 121 127 133 140 147
+ 158 158 170 132 128 145 119 123 114 83 80 105 90 79 63 55 79 70 64 73 47 35 52 62 53 57 48 26 33 44 20 22 42 22 9 6 4 3 2 3 32 55 70 80 88 94 100 104 105 100 99 101 105 108 109 108 106 101 99 96 92 87 83 79 81 84 86 87 87 85 84 88 91 93 85 81 81 82 82 82 81 77 66 58 49 31 6 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 5 8 10 14 18 23 28 32 37 43 49 56 61 68 74 81 88 94 102 108 115 121 128 135 141 149
+ 159 159 171 133 130 150 120 126 114 85 83 108 83 71 60 57 82 67 51 74 54 36 36 42 56 44 27 23 23 46 43 46 37 14 9 6 4 3 3 13 45 64 76 85 92 97 102 105 108 109 105 102 102 105 107 109 109 107 102 98 93 88 83 79 79 80 81 82 82 82 83 80 76 77 73 66 64 65 65 65 66 64 56 44 34 17 4 3 2 2 2 2 2 2 2 2 2 2 2 2 2 3 6 9 12 15 20 24 29 34 39 44 51 58 63 69 76 83 89 96 104 110 117 123 129 136 142 150
+ 160 160 173 136 132 152 142 138 111 87 85 111 104 87 62 58 85 82 78 76 47 38 35 36 63 40 26 22 23 31 53 45 18 13 9 7 4 3 3 33 57 72 82 90 96 101 104 108 109 111 112 111 105 103 104 106 108 109 107 102 97 91 84 78 76 79 79 79 78 79 82 78 68 62 58 53 49 47 46 47 47 45 39 26 15 5 3 3 2 2 2 2 2 2 2 2 2 1 2 2 2 4 7 10 14 18 22 26 31 36 42 47 52 59 65 72 78 84 91 98 104 111 118 124 130 138 144 151
+ 166 158 178 144 130 154 126 120 130 95 87 107 92 77 64 61 78 83 73 78 49 39 36 36 59 51 27 23 22 24 39 43 17 13 10 7 5 4 10 43 64 78 88 93 100 103 106 108 109 111 112 114 114 111 105 104 105 107 108 107 105 99 91 82 76 76 76 76 77 77 78 76 69 58 49 39 34 29 26 26 25 24 21 10 4 3 3 2 2 2 2 2 2 2 2 1 2 2 2 2 3 5 8 11 14 18 23 27 32 36 42 47 53 60 66 72 79 85 92 98 105 112 118 124 130 137 143 150
+ 172 161 177 145 133 156 135 123 127 96 90 109 90 76 69 63 79 75 54 71 61 41 37 37 59 52 28 23 21 23 39 41 17 12 11 7 5 7 35 58 76 87 94 99 103 107 109 109 111 111 111 113 115 116 114 107 104 106 107 107 107 105 101 91 79 74 75 76 76 74 73 71 65 57 46 30 14 7 5 4 3 3 3 2 2 2 2 2 2 2 3 2 2 2 2 2 2 2 2 2 4 7 10 13 16 20 25 30 34 39 44 50 56 62 68 74 81 88 94 101 107 113 120 126 132 139 145 152
+ 167 162 159 140 138 144 138 126 104 94 93 107 104 96 74 64 81 64 52 64 63 42 37 38 61 42 26 23 21 24 45 31 16 11 8 7 8 34 59 76 88 96 102 106 108 110 111 110 110 110 112 112 114 116 117 115 109 106 106 107 107 106 104 99 86 76 74 77 75 73 68 64 59 53 38 14 4 3 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 4 6 9 12 16 20 23 28 33 38 44 48 53 60 66 72 79 85 91 98 105 111 117 123 130 135 142 149 156
+ 171 161 153 144 135 128 122 114 106 99 93 90 83 77 72 66 63 60 55 52 48 45 41 37 40 35 27 24 21 21 28 27 15 10 9 8 16 49 72 87 97 104 108 112 113 113 113 112 110 110 109 111 113 114 115 117 118 115 109 107 106 107 106 105 101 94 84 79 77 74 72 64 57 49 39 9 5 4 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 6 8 10 14 17 21 25 30 34 39 44 50 55 61 67 73 80 87 93 100 106 112 119 125 130 136 142 149 156
+ 170 161 152 143 135 128 122 114 107 100 94 88 82 77 71 66 63 60 55 52 48 43 40 36 35 30 26 23 21 20 19 17 14 11 10 19 46 65 85 97 106 111 114 117 117 117 115 113 111 110 109 111 112 114 115 116 117 118 116 110 107 107 107 106 104 101 96 89 80 77 73 64 53 38 21 8 7 7 5 5 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 6 8 10 14 16 20 24 29 33 38 43 48 53 59 65 72 78 84 91 97 104 110 116 122 128 134 140 147 153 160
+ 172 163 154 146 138 131 124 116 109 103 96 90 84 78 73 68 64 60 56 52 48 44 40 37 33 31 27 24 21 19 17 14 13 11 15 41 61 76 89 100 109 114 119 120 121 119 117 115 113 111 110 110 111 113 114 115 116 118 119 117 112 108 107 106 106 105 103 100 92 82 75 63 40 20 11 10 9 9 8 7 6 5 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 5 7 10 13 15 19 22 26 31 35 40 46 50 55 62 67 74 80 86 93 100 106 112 119 124 130 136 142 148 155 162
+ 175 166 157 149 141 133 127 119 111 105 99 92 86 80 75 70 66 62 58 53 49 45 41 38 34 32 27 24 21 19 16 14 11 14 34 57 72 85 95 103 110 115 120 122 124 123 121 120 116 114 112 110 110 111 113 113 115 116 119 120 118 112 109 107 107 106 107 105 103 94 77 63 34 15 12 11 13 12 10 9 8 6 4 3 3 3 3 3 2 3 2 2 2 2 2 2 4 6 9 12 15 18 22 25 29 33 37 42 48 53 58 64 69 77 83 90 96 102 108 114 121 126 132 138 144 151 157 163
+ 177 168 160 151 143 136 128 121 114 107 101 94 89 82 77 73 68 64 59 55 50 47 44 39 35 32 29 26 22 19 16 15 14 24 48 66 79 90 98 105 109 113 117 122 125 125 124 123 120 117 114 112 111 110 111 111 113 115 118 120 120 120 113 109 109 108 108 108 107 105 95 72 51 22 15 14 14 13 13 12 10 7 4 4 3 3 2 3 2 2 2 2 2 2 2 3 5 8 11 14 18 20 23 27 32 36 41 45 49 56 61 67 73 79 86 91 98 105 111 117 123 129 135 140 146 153 159 166
+ 182 173 164 156 147 140 132 125 118 111 104 98 92 87 81 76 71 67 62 57 53 50 45 41 39 34 31 28 24 21 18 16 16 31 54 70 82 91 99 105 109 112 114 117 122 125 127 127 126 122 119 116 114 111 112 111 110 113 116 118 121 123 122 116 110 109 110 111 111 108 106 96 69 44 20 16 16 16 15 13 12 9 7 5 3 3 2 3 2 2 2 2 2 2 4 5 7 10 12 16 18 22 26 29 34 38 42 46 51 57 61 67 73 79 86 92 99 106 112 118 124 130 135 142 148 155 160 166
+ 184 175 166 158 151 142 135 127 120 113 107 101 94 89 84 78 73 68 64 60 55 51 47 43 39 35 32 29 25 22 19 18 21 45 63 76 86 94 100 105 109 112 114 116 119 123 126 129 129 127 123 120 117 114 112 111 110 111 114 117 119 122 123 124 118 111 111 114 115 113 109 97 79 56 36 19 18 18 16 14 12 10 8 6 3 3 3 3 3 3 3 2 3 3 5 6 9 12 14 17 20 25 28 32 35 40 44 48 53 59 64 70 76 82 88 95 101 108 114 121 126 132 137 143 149 156 162 169
+ 186 176 170 160 153 145 137 130 123 116 110 104 97 91 87 81 75 70 65 61 56 54 48 45 40 38 33 30 27 22 20 18 31 55 70 81 90 97 102 106 111 113 115 116 118 121 122 126 130 131 129 124 121 118 114 112 110 111 112 115 118 122 125 126 125 120 116 116 120 122 121 104 89 82 69 42 31 29 18 15 13 11 9 7 4 4 2 2 2 2 2 3 4 5 7 9 11 14 17 20 23 27 30 33 39 41 47 50 56 61 67 72 79 85 91 98 103 111 117 123 129 135 140 145 152 158 165 171
+ 187 178 169 161 153 145 138 131 123 117 110 104 98 93 87 81 76 72 66 61 57 52 48 44 41 37 33 30 26 22 20 26 51 70 80 91 97 102 108 111 115 117 118 119 120 122 121 123 127 133 132 128 125 121 117 113 112 111 112 114 118 122 125 127 128 127 122 120 123 137 135 118 97 90 82 56 31 30 19 16 14 12 9 7 6 5 4 4 4 4 4 5 7 7 9 12 14 17 19 23 26 29 34 37 41 45 50 54 60 65 71 77 83 90 96 102 108 115 121 127 133 138 144 150 156 161 169 176
+ 193 183 174 166 157 150 143 135 128 121 114 108 102 96 91 85 79 75 69 65 60 56 52 47 44 39 35 31 27 23 21 32 58 74 86 95 102 108 112 115 119 121 122 124 124 123 122 122 121 126 133 133 130 127 123 119 115 112 112 113 116 120 124 127 129 129 130 130 134 137 141 127 104 96 91 73 43 30 29 19 16 13 12 9 8 7 6 5 5 5 6 7 9 10 12 13 15 19 21 25 28 32 35 38 42 47 51 55 61 66 72 78 85 91 97 104 110 116 122 128 134 139 145 150 157 163 170 178
+ 193 184 175 166 159 150 142 136 129 122 115 109 103 97 92 86 80 75 71 65 61 56 52 48 44 40 35 32 28 25 29 57 75 87 97 106 112 116 119 123 125 127 128 128 128 127 126 124 122 122 128 134 134 131 127 122 117 114 114 114 116 121 125 128 131 131 131 138 140 137 143 127 109 97 88 67 39 31 35 20 16 15 13 11 10 8 7 8 8 8 9 10 11 12 14 17 19 22 24 27 31 35 39 42 45 50 54 59 64 70 76 83 90 96 102 108 114 120 127 132 138 143 148 154 160 167 174 182
+ 196 187 178 170 161 154 146 138 131 125 118 111 106 101 95 89 84 77 72 67 63 59 54 50 45 41 36 32 29 28 50 72 87 98 107 114 120 123 127 130 132 134 133 132 132 131 128 125 123 121 121 126 132 134 131 126 120 116 115 116 117 121 125 128 133 132 132 142 143 135 143 135 111 93 86 62 31 28 27 19 18 17 15 13 11 11 9 10 10 10 12 13 13 15 17 19 22 25 27 30 34 38 41 45 48 52 57 62 67 73 80 86 92 98 105 111 118 124 130 135 141 146 151 157 163 170 177 185
+ 199 190 181 172 164 156 148 140 134 127 120 115 108 103 97 92 86 80 74 70 65 60 55 51 47 43 37 34 31 41 70 87 99 110 118 124 130 132 135 136 139 139 139 138 136 134 132 128 125 122 121 121 125 134 134 129 123 120 118 118 119 120 127 131 135 135 136 145 147 147 143 132 98 82 70 43 31 36 25 21 20 18 16 14 13 13 12 12 13 14 14 15 16 18 19 22 24 27 30 34 37 40 43 47 51 58 59 65 71 77 83 89 96 101 108 115 121 128 134 138 143 148 153 159 166 173 181 187
+ 203 194 184 175 167 159 151 144 137 130 123 118 112 106 100 94 89 83 77 72 67 62 57 53 48 44 39 36 40 67 87 101 112 121 127 132 136 140 141 142 144 144 143 142 141 139 136 133 129 125 123 122 122 128 136 134 129 123 120 119 119 120 125 132 136 137 138 146 149 149 143 130 100 84 67 48 44 37 27 22 22 20 19 17 16 15 15 15 15 16 18 19 20 26 23 26 28 31 35 38 41 44 47 51 54 58 64 70 78 82 87 93 99 105 112 118 124 132 138 142 146 151 157 162 168 176 183 190
+ 206 198 190 181 172 164 156 149 142 135 128 123 116 110 104 99 92 86 81 75 71 65 61 55 51 46 43 42 59 81 98 112 122 130 135 140 142 144 146 147 147 147 147 146 144 143 142 139 136 132 128 127 125 125 129 137 135 129 123 121 119 119 123 129 136 140 138 142 144 142 142 132 113 98 82 63 52 50 31 27 24 23 21 20 18 17 16 17 18 19 20 22 24 45 47 29 30 35 56 68 72 65 51 53 57 61 72 99 110 112 94 94 100 107 113 119 128 154 169 154 149 152 157 164 170 177 185 192
+ 207 200 190 182 173 165 158 150 143 136 130 123 118 111 106 100 94 88 82 76 71 66 61 56 51 48 47 64 86 103 117 127 134 139 144 147 148 150 150 149 148 148 147 146 144 144 143 143 141 137 133 131 128 127 127 135 135 130 124 121 119 119 122 130 138 143 145 147 148 147 140 130 119 104 88 72 58 53 47 30 27 25 23 21 22 20 19 20 21 21 24 26 30 58 42 32 35 66 68 58 66 85 69 59 62 69 105 104 101 125 109 100 105 112 118 126 154 173 176 150 152 156 162 168 175 184 189 196
+ 211 202 194 186 177 169 161 154 147 140 134 127 121 115 108 102 96 91 85 79 74 68 63 59 55 52 65 86 105 119 130 137 143 145 150 152 153 153 152 150 149 148 146 142 139 138 139 141 142 140 138 136 133 130 127 129 136 134 127 121 118 118 121 128 138 145 148 151 151 152 147 136 126 114 99 83 67 56 53 46 30 28 26 24 24 22 22 23 24 25 27 29 32 62 45 35 43 74 50 47 52 78 90 64 66 75 111 96 94 125 117 104 109 115 122 149 164 167 179 151 155 159 165 172 179 187 193 199
+ 214 205 198 188 180 172 165 158 151 145 137 130 124 118 112 106 100 94 88 82 77 71 66 61 57 65 86 105 121 131 140 145 149 151 154 155 156 155 153 152 150 149 147 143 139 134 130 130 134 139 140 140 136 132 128 127 132 136 130 122 118 117 119 125 137 145 151 155 156 155 152 144 132 123 111 95 78 64 55 53 45 32 29 27 26 25 26 26 26 28 30 31 37 65 47 38 44 75 55 50 53 71 98 68 70 77 107 121 120 135 110 108 113 121 146 161 145 163 181 154 157 162 168 175 182 190 195 203
+ 217 209 201 193 185 176 169 162 154 147 141 134 127 122 115 109 102 96 90 83 79 73 68 64 63 85 104 121 133 142 149 152 155 156 157 158 158 158 156 154 152 151 149 147 143 139 133 126 125 128 133 139 139 135 131 129 128 136 133 126 120 118 118 123 134 146 154 156 158 159 157 152 138 129 121 109 94 76 63 54 54 45 33 30 29 28 29 29 30 32 33 35 40 69 50 41 45 70 80 57 57 72 102 72 74 91 119 120 121 135 122 112 118 144 164 146 146 169 185 160 161 166 171 178 185 192 199 209
+ 222 213 204 196 189 180 173 165 158 151 144 137 131 125 118 112 106 99 93 87 82 76 70 67 80 104 121 135 145 152 157 159 160 161 161 160 159 159 157 156 154 152 149 149 148 144 140 132 124 121 122 127 135 137 134 130 128 132 136 130 125 121 121 123 132 145 155 159 161 162 160 157 148 132 127 121 110 92 77 63 54 54 45 35 32 32 31 33 33 34 36 39 44 72 52 45 47 52 66 58 62 83 104 75 78 108 117 96 100 120 145 117 128 160 171 172 176 185 192 191 190 170 174 181 188 195 203 219
+ 225 217 208 200 192 185 176 169 162 155 148 141 135 129 122 116 108 103 96 91 85 79 73 74 99 120 135 147 156 162 165 166 167 165 164 162 160 158 157 155 152 151 151 150 151 149 145 139 131 123 119 119 124 133 136 131 128 130 138 133 127 124 123 126 131 144 156 161 163 164 163 161 155 141 130 126 121 110 94 77 62 54 55 45 36 34 35 35 37 38 39 42 48 75 55 49 52 54 57 60 65 97 102 77 83 113 118 98 104 125 154 124 128 142 149 156 165 183 195 185 184 174 177 184 192 199 207 231
+ 232 223 215 206 199 191 183 176 167 161 154 147 141 134 127 121 114 108 102 96 89 84 77 81 111 129 145 157 166 172 175 175 173 173 170 167 163 158 156 153 151 148 149 150 151 151 150 147 141 132 124 118 118 122 132 135 133 129 136 139 132 128 126 126 132 140 154 162 164 165 166 164 160 154 139 131 127 123 114 98 81 63 54 56 47 39 38 39 39 40 43 45 49 74 70 53 55 58 60 64 70 103 96 80 84 96 127 125 122 142 155 129 127 131 136 142 149 168 193 169 171 175 180 187 194 201 212 234
+ 238 227 219 211 203 195 187 180 172 164 158 151 144 138 131 125 118 112 107 99 92 86 82 101 126 145 160 172 179 182 184 184 183 181 179 177 173 167 161 156 151 147 144 147 150 152 152 150 147 139 131 122 118 118 123 134 141 145 144 143 138 132 129 129 131 140 152 162 166 167 167 168 165 161 152 136 132 128 123 112 97 79 61 56 59 46 42 42 43 43 46 49 52 59 59 56 59 62 64 69 92 106 83 83 88 93 109 132 143 145 135 127 131 134 138 145 151 164 183 170 173 179 185 191 198 206 224 236
+ 245 229 220 212 205 198 190 182 175 167 160 153 147 140 134 127 121 114 107 102 94 88 99 130 150 164 175 182 187 188 189 189 188 186 184 181 179 175 170 165 157 151 145 143 146 149 151 150 149 143 135 125 119 117 121 130 143 154 153 149 142 137 133 133 135 142 154 165 168 169 170 170 168 165 159 142 135 132 127 119 104 89 71 60 60 59 47 46 46 48 49 52 55 57 58 62 64 67 71 96 105 85 84 87 93 99 105 112 120 124 127 132 136 139 143 150 156 163 168 171 177 184 191 197 204 217 236 236
+ 241 238 227 219 211 204 196 189 181 174 166 159 152 147 140 134 127 120 113 106 99 96 116 143 161 173 181 186 191 192 191 192 191 190 187 185 182 180 177 172 168 162 156 147 142 143 147 149 150 148 143 136 127 122 117 122 134 149 156 152 148 142 138 137 136 142 150 162 169 171 172 172 172 171 168 160 143 138 134 126 114 102 89 74 64 64 63 52 50 51 52 56 58 59 62 65 67 71 88 106 93 85 87 91 97 101 107 112 118 123 128 133 138 142 147 152 158 164 169 175 180 186 193 199 207 224 237 235
+ 219 247 232 224 217 208 201 193 185 177 171 164 158 151 145 138 132 125 118 111 104 110 138 159 173 181 186 190 191 194 193 193 192 192 190 187 185 182 178 175 172 168 164 158 149 139 140 145 147 149 146 143 136 127 121 119 128 142 157 155 150 146 142 141 140 143 150 160 169 171 173 173 175 175 174 169 155 143 139 133 120 110 100 87 74 66 68 64 55 54 55 58 61 64 66 68 72 76 86 89 86 88 92 96 100 106 112 116 121 126 131 137 142 146 152 157 162 168 173 179 185 191 197 204 214 234 236 234
+ 197 244 235 228 219 211 203 195 188 181 174 168 161 155 148 141 135 128 120 114 111 137 158 174 183 188 191 192 193 195 195 193 193 191 190 188 184 181 178 175 172 169 166 162 153 143 136 139 145 147 147 145 142 135 126 120 125 140 156 156 151 146 145 143 144 146 152 161 169 173 175 176 179 180 178 174 163 147 143 138 125 115 106 97 85 74 71 73 62 60 61 62 65 69 71 74 76 80 84 88 91 94 97 101 106 112 117 121 127 131 136 141 147 152 157 163 168 173 179 185 192 197 204 212 232 237 235 230
+ 165 227 246 231 224 216 207 201 193 186 179 172 166 159 153 146 139 132 126 120 127 153 168 181 188 193 196 196 196 194 195 195 193 193 190 187 184 181 178 175 172 170 167 164 157 149 138 133 140 145 146 146 146 141 133 125 124 133 154 158 153 149 148 147 148 148 152 159 168 174 176 178 181 183 182 180 172 155 149 145 136 124 116 108 98 86 78 77 77 66 65 67 68 71 75 79 81 84 88 92 95 98 101 106 111 116 120 125 129 135 140 145 150 156 161 167 172 178 184 190 196 202 209 221 236 235 233 231
+ 129 191 241 238 229 222 213 206 199 192 184 177 171 165 158 151 144 137 130 125 141 162 176 186 193 197 199 198 197 196 196 195 194 192 190 187 183 179 176 174 171 170 168 164 158 152 144 134 134 140 143 144 146 144 140 132 128 132 149 161 158 153 150 150 150 152 152 156 165 175 178 181 183 185 186 184 178 166 156 152 146 137 125 117 109 99 89 81 82 82 72 72 73 77 79 82 85 90 92 95 101 103 107 111 116 120 125 130 135 139 144 149 155 159 165 171 176 182 189 195 200 206 215 234 237 235 232 225
+ 85 155 212 246 234 226 219 211 203 197 190 182 175 169 162 156 149 141 136 132 152 169 181 191 198 201 202 201 199 197 196 195 194 192 190 186 183 178 175 172 171 168 167 164 160 153 146 139 132 134 139 141 143 144 142 136 134 134 144 162 162 158 153 148 149 150 150 153 160 170 179 182 185 188 189 187 182 176 164 159 154 147 138 128 118 109 101 91 83 88 87 77 78 81 83 87 90 92 97 101 104 107 111 115 120 125 129 133 139 143 148 153 159 164 169 175 181 187 194 199 204 211 226 237 236 233 230 186
+ 19 94 163 220 244 233 226 218 210 202 197 189 182 175 168 161 155 147 140 137 154 172 184 192 199 203 205 205 203 200 196 194 193 192 190 187 183 179 175 173 170 169 168 167 163 157 151 145 138 129 132 135 137 142 144 140 138 137 140 154 167 165 160 154 152 152 150 148 152 160 176 184 186 190 191 190 188 183 175 167 163 155 148 139 128 119 111 103 94 88 94 93 83 85 87 90 93 96 101 104 108 111 115 119 123 128 132 137 141 146 151 156 162 167 174 178 184 190 196 201 207 215 234 237 235 232 226 162
+ 1 68 139 197 244 238 229 222 214 206 200 193 185 178 172 165 157 150 145 142 166 182 190 197 202 205 207 207 205 201 197 193 192 191 190 185 182 177 174 172 171 169 167 169 167 159 152 148 142 132 127 130 131 139 144 141 139 140 142 153 170 170 166 163 163 162 160 156 159 165 178 187 191 194 194 193 191 187 181 173 166 158 152 143 132 123 114 109 101 92 96 102 93 89 92 95 98 102 106 109 113 117 120 125 129 133 137 142 147 152 156 162 166 173 178 185 191 196 202 207 214 232 238 236 232 228 169 84
+ 1 3 73 143 200 243 237 230 222 215 206 200 193 185 178 171 164 157 150 147 166 184 192 198 203 206 208 208 207 204 199 194 191 190 189 186 183 178 175 172 171 171 172 171 171 167 161 153 148 142 128 121 124 129 140 143 140 140 142 145 164 174 173 169 167 166 166 161 157 160 172 187 192 196 197 196 195 192 189 182 175 166 157 151 143 131 122 115 110 102 96 102 109 103 97 99 102 105 109 113 116 120 124 128 133 136 140 145 150 155 160 165 170 175 181 187 193 199 203 210 220 237 236 235 231 211 138 37
+ 2 2 27 97 162 221 243 234 228 220 212 205 198 191 183 176 168 162 154 152 171 187 195 200 205 207 208 209 209 205 201 195 191 190 188 185 183 180 176 173 171 170 171 170 173 171 167 161 153 148 136 117 117 120 133 142 140 140 144 144 158 176 178 175 172 171 169 165 160 160 169 186 196 200 200 199 197 196 194 189 181 175 166 156 149 139 129 121 117 112 102 104 112 116 105 104 106 109 112 117 120 124 128 132 136 141 145 149 154 159 164 169 174 180 186 193 197 202 208 215 234 238 234 233 224 160 74 4
+ 2 1 1 49 117 180 229 242 233 226 219 210 204 196 188 182 173 166 159 157 177 191 198 203 206 208 209 209 209 208 203 197 191 189 187 184 183 181 178 175 172 172 169 168 171 173 169 163 159 154 145 124 111 114 124 139 140 142 143 142 152 174 182 181 177 174 173 169 164 161 167 185 199 204 204 201 200 199 199 195 188 183 175 164 154 146 137 129 122 118 110 109 114 122 122 111 111 113 117 121 125 129 133 137 141 145 149 154 159 163 167 173 179 185 191 196 201 206 214 229 237 237 233 228 180 103 4 4
+ 1 1 1 17 84 149 207 243 238 230 222 214 207 200 192 185 177 168 162 168 186 196 202 205 208 210 210 210 210 208 205 198 190 186 184 183 182 181 180 178 175 173 166 166 168 172 170 163 158 156 150 131 110 111 119 137 140 141 142 142 152 174 187 186 182 178 175 172 165 162 167 185 203 207 207 203 203 203 202 197 192 187 183 172 158 147 141 133 127 123 117 116 119 127 131 123 118 120 123 127 130 134 137 142 146 151 154 159 164 169 173 179 185 191 196 201 206 213 228 237 236 233 229 189 111 12 3 3
+ 1 1 1 1 34 100 162 218 243 236 229 221 212 204 197 189 181 173 167 176 192 200 205 208 210 212 211 211 210 210 208 205 197 189 184 182 182 182 182 180 178 176 168 168 166 168 171 168 160 153 152 143 120 107 112 134 139 141 142 140 148 169 187 191 188 184 180 176 170 164 166 179 201 209 210 207 205 206 206 202 196 190 188 181 169 153 145 141 135 129 123 123 121 130 138 139 128 125 128 131 135 138 143 146 151 155 159 164 168 173 179 185 191 196 200 206 211 224 237 237 234 230 200 129 37 3 4 3
+ 1 1 1 1 1 37 101 162 215 241 238 229 221 212 203 196 188 180 173 177 194 203 207 211 212 213 213 213 212 211 211 209 206 199 192 185 185 182 182 182 180 179 175 173 169 168 168 171 167 157 149 149 138 113 107 123 138 141 142 140 143 162 182 195 196 192 186 181 177 170 166 171 191 210 212 210 207 208 208 207 201 196 191 190 183 171 154 145 142 138 130 125 127 127 139 146 147 133 132 135 138 141 145 149 153 157 162 167 172 177 182 188 195 199 203 209 217 234 238 235 231 224 166 89 6 4 4 3
+ 1 1 1 1 1 4 68 132 186 230 242 233 226 215 207 199 191 183 177 189 202 208 212 213 215 215 215 215 214 214 212 211 208 204 199 194 188 184 183 182 180 180 175 175 172 169 168 170 170 162 148 144 141 117 109 124 139 143 143 140 146 167 185 198 202 197 193 187 182 174 169 172 191 212 215 211 208 210 212 210 204 200 193 193 190 181 165 150 145 142 133 128 133 133 144 151 154 143 138 140 143 147 151 155 159 163 168 173 178 184 189 195 200 204 210 217 235 238 236 231 221 164 90 5 4 3 3 3
+ 1 2 1 1 1 1 14 79 140 193 235 240 232 222 213 204 196 187 181 193 205 211 215 217 218 219 219 218 217 216 215 213 210 206 203 200 196 191 188 184 183 180 180 178 176 173 170 169 171 169 156 144 141 128 112 120 140 143 143 143 146 165 186 198 206 205 199 194 187 179 172 173 187 213 217 215 211 212 214 215 211 205 198 195 193 190 181 163 149 145 139 133 139 137 146 156 160 159 145 145 147 151 155 159 163 168 173 178 184 189 196 200 204 210 216 233 238 237 232 225 176 106 10 3 3 3 3 3
+
+
--- a/examples/embedded.cc	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-#include <iostream>
-#include <octave/oct.h>
-#include <octave/octave.h>
-#include <octave/parse.h>
-#include <octave/toplev.h>
-
-int
-main (void)
-{
-  string_vector argv (2);
-  argv(0) = "embedded";
-  argv(1) = "-q";
-
-  octave_main (2, argv.c_str_vec (), 1);
-
-  octave_idx_type n = 2;
-  octave_value_list in;
-
-  for (octave_idx_type i = 0; i < n; i++)
-    in(i) = octave_value (5 * (i + 2));
-
-  octave_value_list out = feval ("gcd", in, 1);
-
-  if (! error_state && out.length () > 0)
-    std::cout << "GCD of ["
-              << in(0).int_value ()
-              << ", "
-              << in(1).int_value ()
-              << "] is " << out(0).int_value ()
-              << std::endl;
-  else
-    std::cout << "invalid\n";
-
-  clean_up_and_exit (0);
-}
--- a/examples/fortrandemo.cc	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-#include <octave/oct.h>
-#include <octave/f77-fcn.h>
-
-extern "C"
-{
-  F77_RET_T
-  F77_FUNC (fortransub, FORTSUB)
-    (const int&, double*, F77_CHAR_ARG_DECL F77_CHAR_ARG_LEN_DECL);
-}
-
-DEFUN_DLD (fortrandemo, args, , "Fortran Demo")
-{
-  octave_value_list retval;
-  int nargin = args.length ();
-
-  if (nargin != 1)
-    print_usage ();
-  else
-    {
-      NDArray a = args(0).array_value ();
-      if (! error_state)
-        {
-          double *av = a.fortran_vec ();
-          octave_idx_type na = a.numel ();
-          OCTAVE_LOCAL_BUFFER (char, ctmp, 128);
-
-          F77_XFCN (fortransub, FORTSUB,
-                    (na, av, ctmp F77_CHAR_ARG_LEN (128)));
-
-          retval(1) = std::string (ctmp);
-          retval(0) = a;
-        }
-    }
-  return retval;
-}
--- a/examples/fortransub.f	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-      subroutine fortransub (n, a, s)
-      implicit none
-      character*(*) s
-      real*8 a(*)
-      integer*4 i, n, ioerr
-      do i = 1, n
-        if (a(i) .eq. 0d0) then
-          call xstopx ('fortransub: divide by zero')
-        else
-          a(i) = 1d0 / a(i)
-        endif
-      enddo
-      write (unit = s, fmt = '(a,i3,a,a)', iostat = ioerr)
-     $       'There are ', n,
-     $       ' values in the input vector', char(0)
-      if (ioerr .ne. 0) then
-        call xstopx ('fortransub: error writing string')
-      endif
-      return
-      end
-
--- a/examples/funcdemo.cc	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-#include <octave/oct.h>
-#include <octave/parse.h>
-
-DEFUN_DLD (funcdemo, args, nargout, "Function Demo")
-{
-  octave_value_list retval;
-  int nargin = args.length ();
-
-  if (nargin < 2)
-    print_usage ();
-  else
-    {
-      octave_value_list newargs;
-      for (octave_idx_type i = nargin - 1; i > 0; i--)
-        newargs(i-1) = args(i);
-      if (args(0).is_function_handle () || args(0).is_inline_function ())
-        {
-          octave_function *fcn = args(0).function_value ();
-          if (! error_state)
-            retval = feval (fcn, newargs, nargout);
-        }
-      else if (args(0).is_string ())
-        {
-          std::string fcn = args(0).string_value ();
-          if (! error_state)
-            retval = feval (fcn, newargs, nargout);
-        }
-      else
-        error ("funcdemo: INPUT must be string, inline, or function handle");
-    }
-  return retval;
-}
--- a/examples/globaldemo.cc	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-#include <octave/oct.h>
-
-DEFUN_DLD (globaldemo, args, , "Global Demo")
-{
-  octave_value retval;
-  int nargin = args.length ();
-
-  if (nargin != 1)
-    print_usage ();
-  else
-    {
-      std::string s = args(0).string_value ();
-      if (! error_state)
-        {
-          octave_value tmp = get_global_value (s, true);
-          if (tmp.is_defined ())
-            retval = tmp;
-          else
-            retval = "Global variable not found";
-
-          set_global_value ("a", 42.0);
-        }
-    }
-  return retval;
-}
--- a/examples/helloworld.cc	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-#include <octave/oct.h>
-
-DEFUN_DLD (helloworld, args, nargout,
-           "Hello World Help String")
-{
-  int nargin = args.length ();
-
-  octave_stdout << "Hello World has "
-                << nargin << " input arguments and "
-                << nargout << " output arguments.\n";
-
-  return octave_value_list ();
-}
--- a/examples/make_int.cc	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,316 +0,0 @@
-#include <octave/config.h>
-
-#include <cstdlib>
-
-#include <string>
-
-#include <ostream>
-
-#include <octave/lo-mappers.h>
-#include <octave/lo-utils.h>
-#include <octave/mx-base.h>
-#include <octave/str-vec.h>
-
-#include <octave/defun-dld.h>
-#include <octave/error.h>
-#include <octave/gripes.h>
-#include <octave/oct-obj.h>
-#include <octave/ops.h>
-#include <octave/ov-base.h>
-#include <octave/ov-typeinfo.h>
-#include <octave/ov.h>
-#include <octave/ov-scalar.h>
-#include <octave/pager.h>
-#include <octave/pr-output.h>
-#include <octave/symtab.h>
-#include <octave/variables.h>
-
-class octave_value_list;
-
-class tree_walker;
-
-// Integer values.
-
-class
-octave_integer : public octave_base_value
-{
-public:
-
-  octave_integer (void)
-    : octave_base_value (), scalar (0) { }
-
-  octave_integer (int i)
-    : octave_base_value (), scalar (i) { }
-
-  octave_integer (const octave_integer& s)
-    : octave_base_value (), scalar (s.scalar) { }
-
-  ~octave_integer (void) { }
-
-  octave_base_value *clone (void) { return new octave_integer (*this); }
-
-#if 0
-  void *operator new (size_t size);
-  void operator delete (void *p, size_t size);
-#endif
-
-  idx_vector index_vector (void) const { return idx_vector ((double) scalar); }
-
-  int rows (void) const { return 1; }
-  int columns (void) const { return 1; }
-
-  bool is_constant (void) const { return true; }
-
-  bool is_defined (void) const { return true; }
-  bool is_real_scalar (void) const { return true; }
-
-  octave_value all (void) const { return (double) (scalar != 0); }
-  octave_value any (void) const { return (double) (scalar != 0); }
-
-  bool is_real_type (void) const { return true; }
-  bool is_scalar_type (void) const { return true; }
-  bool is_numeric_type (void) const { return true; }
-
-  bool valid_as_scalar_index (void) const
-  { return scalar == 1; }
-
-  bool valid_as_zero_index (void) const
-  { return scalar == 0; }
-
-  bool is_true (void) const { return (scalar != 0); }
-
-  double double_value (bool = false) const { return (double) scalar; }
-
-  int integer_value (bool = false) const { return scalar; }
-
-  Matrix matrix_value (bool = false) const { return Matrix (1, 1, scalar); }
-
-  Complex complex_value (bool = false) const { return scalar; }
-
-  ComplexMatrix complex_matrix_value (bool = false) const
-  { return  ComplexMatrix (1, 1, Complex (scalar)); }
-
-  octave_value gnot (void) const { return octave_value ((double) ! scalar); }
-
-  octave_value uminus (void) const { return new octave_integer (- scalar); }
-
-  octave_value transpose (void) const { return new octave_integer (scalar); }
-
-  octave_value hermitian (void) const { return new octave_integer (scalar); }
-
-  void increment (void) { ++scalar; }
-
-  void decrement (void) { --scalar; }
-
-  void print (std::ostream& os, bool pr_as_read_syntax = false) const;
-
-private:
-
-  int scalar;
-
-  DECLARE_OCTAVE_ALLOCATOR
-
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
-};
-
-void
-octave_integer::print (std::ostream& os, bool pr_as_read_syntax) const
-{
-  os << scalar;
-  // octave_print_internal (os, scalar, pr_as_read_syntax);
-}
-
-#ifdef DEFUNOP_OP
-#undef DEFUNOP_OP
-#endif
-
-#define DEFUNOP_OP(name, t, op) \
-  UNOPDECL (name, a) \
-  { \
-    CAST_UNOP_ARG (const octave_ ## t&); \
-    return octave_value (new octave_integer (op v.t ## _value ())); \
-  }
-
-DEFUNOP_OP (gnot, integer, !)
-DEFUNOP_OP (uminus, integer, -)
-DEFUNOP_OP (transpose, integer, /* no-op */)
-DEFUNOP_OP (hermitian, integer, /* no-op */)
-
-DEFNCUNOP_METHOD (incr, integer, increment)
-DEFNCUNOP_METHOD (decr, integer, decrement)
-
-#ifdef DEFBINOP_OP
-#undef DEFBINOP_OP
-#endif
-
-#define DEFBINOP_OP(name, t1, t2, op) \
-  BINOPDECL (name, a1, a2) \
-  { \
-    CAST_BINOP_ARGS (const octave_ ## t1&, const octave_ ## t2&); \
-    return octave_value \
-      (new octave_integer (v1.t1 ## _value () op v2.t2 ## _value ())); \
-  }
-
-// integer by integer ops.
-
-DEFBINOP_OP (add, integer, integer, +)
-DEFBINOP_OP (sub, integer, integer, -)
-DEFBINOP_OP (mul, integer, integer, *)
-
-DEFBINOP (div, integer, integer)
-{
-  CAST_BINOP_ARGS (const octave_integer&, const octave_integer&);
-
-  int d = v2.integer_value ();
-
-  if (d == 0)
-    gripe_divide_by_zero ();
-
-  return new octave_integer (v1.integer_value () / d);
-}
-
-
-DEFBINOP (i_s_div, integer, scalar)
-{
-  CAST_BINOP_ARGS (const octave_integer&, const octave_scalar&);
-
-  double d = v2.double_value ();
-
-  if (d == 0.0)
-    gripe_divide_by_zero ();
-
-  return new octave_scalar (v1.double_value () / d);
-}
-
-DEFBINOP (ldiv, integer, integer)
-{
-  CAST_BINOP_ARGS (const octave_integer&, const octave_integer&);
-
-  int d = v1.integer_value ();
-
-  if (d == 0)
-    gripe_divide_by_zero ();
-
-  return new octave_integer (v2.integer_value () / d);
-}
-
-DEFBINOP_OP (lt, integer, integer, <)
-DEFBINOP_OP (le, integer, integer, <=)
-DEFBINOP_OP (eq, integer, integer, ==)
-DEFBINOP_OP (ge, integer, integer, >=)
-DEFBINOP_OP (gt, integer, integer, >)
-DEFBINOP_OP (ne, integer, integer, !=)
-
-DEFBINOP_OP (el_mul, integer, integer, !=)
-
-DEFBINOP (el_div, integer, integer)
-{
-  CAST_BINOP_ARGS (const octave_integer&, const octave_integer&);
-
-  int d = v2.integer_value ();
-
-  if (d == 0)
-    gripe_divide_by_zero ();
-
-  return new octave_integer (v1.integer_value () / d);
-}
-
-DEFBINOP (el_ldiv, integer, integer)
-{
-  CAST_BINOP_ARGS (const octave_integer&, const octave_integer&);
-
-  int d = v1.integer_value ();
-
-  if (d == 0)
-    gripe_divide_by_zero ();
-
-  return new octave_integer (v2.integer_value () / d);
-}
-
-DEFBINOP_OP (el_and, integer, integer, &&)
-DEFBINOP_OP (el_or, integer, integer, ||)
-
-DEFUN_DLD (make_int, args, ,
-           "int_val = make_int (val)\n\
-\n\
-Creates an integer variable from VAL.")
-{
-  static bool type_loaded = false;
-
-  if (! type_loaded)
-    {
-      octave_integer::register_type ();
-      mlock ();
-
-      octave_stdout << "installing integer type at type-id = "
-                    << octave_integer::static_type_id () << "\n";
-
-      INSTALL_UNOP (op_not, octave_integer, gnot);
-      INSTALL_UNOP (op_uminus, octave_integer, uminus);
-      INSTALL_UNOP (op_transpose, octave_integer, transpose);
-      INSTALL_UNOP (op_hermitian, octave_integer, hermitian);
-
-      INSTALL_NCUNOP (op_incr, octave_integer, incr);
-      INSTALL_NCUNOP (op_decr, octave_integer, decr);
-
-      INSTALL_BINOP (op_add, octave_integer, octave_integer, add);
-      INSTALL_BINOP (op_sub, octave_integer, octave_integer, sub);
-      INSTALL_BINOP (op_mul, octave_integer, octave_integer, mul);
-      INSTALL_BINOP (op_div, octave_integer, octave_integer, div);
-      INSTALL_BINOP (op_ldiv, octave_integer, octave_integer, ldiv);
-      INSTALL_BINOP (op_lt, octave_integer, octave_integer, lt);
-      INSTALL_BINOP (op_le, octave_integer, octave_integer, le);
-      INSTALL_BINOP (op_eq, octave_integer, octave_integer, eq);
-      INSTALL_BINOP (op_ge, octave_integer, octave_integer, ge);
-      INSTALL_BINOP (op_gt, octave_integer, octave_integer, gt);
-      INSTALL_BINOP (op_ne, octave_integer, octave_integer, ne);
-      INSTALL_BINOP (op_el_mul, octave_integer, octave_integer, el_mul);
-      INSTALL_BINOP (op_el_div, octave_integer, octave_integer, el_div);
-      INSTALL_BINOP (op_el_ldiv, octave_integer, octave_integer, el_ldiv);
-      INSTALL_BINOP (op_el_and, octave_integer, octave_integer, el_and);
-      INSTALL_BINOP (op_el_or, octave_integer, octave_integer, el_or);
-
-      INSTALL_BINOP (op_div, octave_integer, octave_scalar, i_s_div);
-    }
-
-  octave_value retval;
-
-  if (args.length () == 1)
-    {
-      double d = args(0).double_value ();
-
-      if (! error_state)
-        retval = octave_value (new octave_integer (NINT (d)));
-    }
-  else
-    usage ("make_int");
-
-  return retval;
-}
-
-DEFUN_DLD (doit, args, ,
-           "doit (I)")
-{
-  octave_value_list retval;
-
-  if (args(0).type_id () == octave_integer::static_type_id ())
-    {
-      // At this point, we know we have a handle for an octave_integer
-      // object, so we can peek at the representation and extract the
-      // data.
-
-      const octave_base_value& rep = args(0).get_rep ();
-
-      int my_value = ((const octave_integer&) rep) . integer_value ();
-
-      message ("doit", "your lucky number is: %d", my_value);
-    }
-  else
-    gripe_wrong_type_arg ("doit", args(0));
-
-  return retval;
-}
-
-DEFINE_OCTAVE_ALLOCATOR (octave_integer);
-
-DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_integer, "integer", "integer");
--- a/examples/mex_demo.c	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-// mex_demo.c -- example of a dynamically linked function for Octave.
-
-// To use this file, your version of Octave must support dynamic
-// linking.  To find out if it does, type the command
-//
-//   octave_config_info ("ENABLE_DYNAMIC_LINKING")
-//
-// at the Octave prompt.  Support for dynamic linking is included if
-// this expression returns the string "yes".
-//
-// To compile this file, type the command
-//
-//   mkoctfile --mex mex_demo.c
-//
-// from within Octave or from the shell prompt.  This will create a file
-// called mex_demo.mex that can be loaded by Octave.  To test the mex_demo.mex
-// file, start Octave and type the command
-//
-// d = mex_demo ("easy as", 1, 2, 3)
-//
-// at the Octave prompt.  Octave should respond by printing
-//
-//   Hello, world!
-//   I have 4 inputs and 1 output
-//   d =  1.2346
-
-// Additional samples of code are in the examples directory of the Octave
-// distribution.  See also the chapter External Code Interface in the
-// documentation.
-
-#include "mex.h"
-
-// Every user function should include "mex.h" which imports the basic set of
-// function prototypes necessary for dynamically linked functions.  In
-// particular, it will declare mexFunction which is used by every function
-// which will be visible to Octave.  A mexFunction is visible in Octave under
-// the name of the source code file without the extension.
-
-// The four arguments to mexFunction are:
-// 1) The number of return arguments (# of left-hand side args).
-// 2) An array of pointers to return arguments.
-// 3) The number of input arguments (# of right-hand side args).
-// 4) An array of pointers to input arguments.
-
-void
-mexFunction (int nlhs, mxArray *plhs[],
-             int nrhs, const mxArray *prhs[])
-{
-  mexPrintf ("Hello, World!\n");
-
-  mexPrintf ("I have %d inputs and %d outputs\n", nrhs, nlhs);
-
-  mxArray *v = mxCreateDoubleMatrix (1, 1, mxREAL);
-  double *data = mxGetPr (v);
-  *data = 1.23456789;
-
-  plhs[0] = v;
-}
--- a/examples/mycell.c	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-#include "mex.h"
-
-void
-mexFunction (int nlhs, mxArray* plhs[],
-             int nrhs, const mxArray* prhs[])
-{
-  mwSize n;
-  mwIndex i;
-
-  if (nrhs != 1 || ! mxIsCell (prhs[0]))
-    mexErrMsgTxt ("ARG1 must be a cell");
-
-  n = mxGetNumberOfElements (prhs[0]);
-  n = (n > nlhs ? nlhs : n);
-
-  for (i = 0; i < n; i++)
-    plhs[i] = mxDuplicateArray (mxGetCell (prhs[0], i));
-}
--- a/examples/myfeval.c	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-#include "mex.h"
-
-void
-mexFunction (int nlhs, mxArray* plhs[],
-             int nrhs, const mxArray* prhs[])
-{
-  char *str;
-
-  mexPrintf ("Starting file myfeval.mex\n");
-
-  mexPrintf ("I have %d inputs and %d outputs\n", nrhs, nlhs);
-
-  if (nrhs < 1 || ! mxIsString (prhs[0]))
-    mexErrMsgTxt ("ARG1 must be a function name");
-
-  str = mxArrayToString (prhs[0]);
-
-  mexPrintf ("I'm going to call the function %s\n", str);
-
-  if (nlhs == 0)
-    nlhs = 1;  // Octave's automatic 'ans' variable
-
-  /* Cast prhs just to get rid of 'const' qualifier and stop compile warning */
-  mexCallMATLAB (nlhs, plhs, nrhs-1, (mxArray**)prhs+1, str);
-
-  mxFree (str);
-}
--- a/examples/myfevalf.f	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-      subroutine mexFunction (nlhs, plhs, nrhs, prhs)
-
-      implicit none
-
-      integer*4 nlhs, nrhs
-
-* The following will need to be integer*8 on 64-bit systems, otherwise
-* these variables won't be large enough to hold pointers...
-      integer*4 plhs(*), prhs(*)
-
-      integer*4 mxIsString, mxGetString, mxGetN, mexCallMATLAB
-      integer*4 status, len
-      character*100 str
-
-      call mexPrintf ('Hello, World!')
-
-      if (nrhs .lt. 1 .or. mxIsString (prhs(1)) .ne. 1) then
-        call mexErrMsgTxt ('function name expected')
-      endif
-
-      len = mxGetN (prhs(1))
-
-      status = mxGetString (prhs(1), str, 100)
-
-      call mexPrintf ('FORTRAN will call the interpreter now')
-
-      status = mexCallMATLAB (nlhs, plhs, nrhs-1, prhs(2), str(1:len))
-
-      return
-      end
--- a/examples/myfunc.c	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-#include "mex.h"
-
-void
-mexFunction (int nlhs, mxArray *plhs[],
-             int nrhs, const mxArray *prhs[])
-{
-  const char *nm;
-
-  nm = mexFunctionName ();
-  mexPrintf ("You called function: %s\n", nm);
-  if (strcmp (nm, "myfunc") == 0)
-    mexPrintf ("This is the principal function\n", nm);
-
-  return;
-}
--- a/examples/myhello.c	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-#include "mex.h"
-
-void
-mexFunction (int nlhs, mxArray *plhs[],
-             int nrhs, const mxArray *prhs[])
-{
-  mexPrintf ("Hello, World!\n");
-
-  mexPrintf ("I have %d inputs and %d outputs\n", nrhs, nlhs);
-}
--- a/examples/mypow2.c	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-#include "mex.h"
-
-void
-mexFunction (int nlhs, mxArray* plhs[],
-             int nrhs, const mxArray* prhs[])
-{
-  mwSize n;
-  mwIndex i;
-  double *vri, *vro;
-
-  if (nrhs != 1 || ! mxIsNumeric (prhs[0]))
-    mexErrMsgTxt ("ARG1 must be a matrix");
-
-  n = mxGetNumberOfElements (prhs[0]);
-  plhs[0] = mxCreateNumericArray (mxGetNumberOfDimensions (prhs[0]),
-                                  mxGetDimensions (prhs[0]),
-                                  mxGetClassID (prhs[0]),
-                                  mxIsComplex (prhs[0]));
-  vri = mxGetPr (prhs[0]);
-  vro = mxGetPr (plhs[0]);
-
-  if (mxIsComplex (prhs[0]))
-    {
-      double *vii, *vio;
-      vii = mxGetPi (prhs[0]);
-      vio = mxGetPi (plhs[0]);
-
-      for (i = 0; i < n; i++)
-        {
-          vro[i] = vri[i] * vri[i] - vii[i] * vii[i];
-          vio[i] = 2 * vri[i] * vii[i];
-        }
-    }
-  else
-    {
-      for (i = 0; i < n; i++)
-        vro[i] = vri[i] * vri[i];
-    }
-}
--- a/examples/myprop.c	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,24 +0,0 @@
-#include "mex.h"
-
-void
-mexFunction (int nlhs, mxArray* plhs[],
-             int nrhs, const mxArray* prhs[])
-{
-  double handle;
-  char property[256];
-
-  if (nrhs < 2 || nrhs > 3)
-    mexErrMsgTxt ("incorrect number of arguments");
-  if (!mxIsDouble (prhs[0]))
-    mexErrMsgTxt ("handle expected to be a double scalar");
-  if (!mxIsChar (prhs[1]))
-    mexErrMsgTxt ("expected property to be a string");
-
-  handle = mxGetScalar (prhs[0]);
-  mxGetString (prhs[1], property, 256);
-  plhs[0] = mxDuplicateArray (mexGet (handle, property));
-
-  if (nrhs == 3)
-    if (mexSet (handle, property, mxDuplicateArray (prhs[2])))
-      mexErrMsgTxt ("failed to set property");
-}
--- a/examples/myset.c	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-#include "mex.h"
-
-void
-mexFunction (int nlhs, mxArray* plhs[],
-             int nrhs, const mxArray* prhs[])
-{
-  char *str;
-  mxArray *v;
-
-  if (nrhs != 2 || ! mxIsString (prhs[0]))
-    mexErrMsgTxt ("expects symbol name and value");
-
-  str = mxArrayToString (prhs[0]);
-
-  v = mexGetArray (str, "global");
-
-  if (v)
-    {
-      mexPrintf ("%s is a global variable with the following value:\n", str);
-      mexCallMATLAB (0, NULL, 1, &v, "disp");
-    }
-
-  v = mexGetArray (str, "caller");
-
-  if (v)
-    {
-      mexPrintf ("%s is a caller variable with the following value:\n", str);
-      mexCallMATLAB (0, NULL, 1, &v, "disp");
-    }
-
-  // WARNING!! Can't do this in MATLAB!  Must copy variable first.
-  mxSetName (prhs[1], str);
-  mexPutArray (prhs[1], "caller");
-}
--- a/examples/mysparse.c	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-#include "mex.h"
-
-void
-mexFunction (int nlhs, mxArray *plhs[],
-             int nrhs, const mxArray *prhs[])
-{
-  mwSize m, n, nz;
-  mxArray *v;
-  mwIndex i;
-  double *pr, *pi;
-  double *pr2, *pi2;
-  mwIndex *ir, *jc;
-  mwIndex *ir2, *jc2;
-
-  if (nrhs != 1 || ! mxIsSparse (prhs[0]))
-    mexErrMsgTxt ("ARG1 must be a sparse matrix");
-
-  m = mxGetM (prhs[0]);
-  n = mxGetN (prhs[0]);
-  nz = mxGetNzmax (prhs[0]);
-
-  if (mxIsComplex (prhs[0]))
-    {
-      mexPrintf ("Matrix is %d-by-%d complex sparse matrix", m, n);
-      mexPrintf (" with %d elements\n", nz);
-
-      pr = mxGetPr (prhs[0]);
-      pi = mxGetPi (prhs[0]);
-      ir = mxGetIr (prhs[0]);
-      jc = mxGetJc (prhs[0]);
-
-      i = n;
-      while (jc[i] == jc[i-1] && i != 0) i--;
-
-      mexPrintf ("last non-zero element (%d, %d) = (%g, %g)\n",
-                 ir[nz-1]+ 1, i, pr[nz-1], pi[nz-1]);
-
-      v = mxCreateSparse (m, n, nz, mxCOMPLEX);
-      pr2 = mxGetPr (v);
-      pi2 = mxGetPi (v);
-      ir2 = mxGetIr (v);
-      jc2 = mxGetJc (v);
-
-      for (i = 0; i < nz; i++)
-        {
-          pr2[i] = 2 * pr[i];
-          pi2[i] = 2 * pi[i];
-          ir2[i] = ir[i];
-        }
-      for (i = 0; i < n + 1; i++)
-        jc2[i] = jc[i];
-
-      if (nlhs > 0)
-        plhs[0] = v;
-    }
-  else if (mxIsLogical (prhs[0]))
-    {
-      mxLogical *pbr, *pbr2;
-      mexPrintf ("Matrix is %d-by-%d logical sparse matrix", m, n);
-      mexPrintf (" with %d elements\n", nz);
-
-      pbr = mxGetLogicals (prhs[0]);
-      ir = mxGetIr (prhs[0]);
-      jc = mxGetJc (prhs[0]);
-
-      i = n;
-      while (jc[i] == jc[i-1] && i != 0) i--;
-      mexPrintf ("last non-zero element (%d, %d) = %d\n",
-                 ir[nz-1]+ 1, i, pbr[nz-1]);
-
-      v = mxCreateSparseLogicalMatrix (m, n, nz);
-      pbr2 = mxGetLogicals (v);
-      ir2 = mxGetIr (v);
-      jc2 = mxGetJc (v);
-
-      for (i = 0; i < nz; i++)
-        {
-          pbr2[i] = pbr[i];
-          ir2[i] = ir[i];
-        }
-      for (i = 0; i < n + 1; i++)
-        jc2[i] = jc[i];
-
-      if (nlhs > 0)
-        plhs[0] = v;
-    }
-  else
-    {
-      mexPrintf ("Matrix is %d-by-%d real sparse matrix", m, n);
-      mexPrintf (" with %d elements\n", nz);
-
-      pr = mxGetPr (prhs[0]);
-      ir = mxGetIr (prhs[0]);
-      jc = mxGetJc (prhs[0]);
-
-      i = n;
-      while (jc[i] == jc[i-1] && i != 0) i--;
-      mexPrintf ("last non-zero element (%d, %d) = %g\n",
-                 ir[nz-1]+ 1, i, pr[nz-1]);
-
-      v = mxCreateSparse (m, n, nz, mxREAL);
-      pr2 = mxGetPr (v);
-      ir2 = mxGetIr (v);
-      jc2 = mxGetJc (v);
-
-      for (i = 0; i < nz; i++)
-        {
-          pr2[i] = 2 * pr[i];
-          ir2[i] = ir[i];
-        }
-      for (i = 0; i < n + 1; i++)
-        jc2[i] = jc[i];
-
-      if (nlhs > 0)
-        plhs[0] = v;
-    }
-}
--- a/examples/mystring.c	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-#include <string.h>
-#include "mex.h"
-
-void
-mexFunction (int nlhs, mxArray *plhs[],
-             int nrhs, const mxArray *prhs[])
-{
-  mwSize m, n;
-  mwIndex i, j;
-  mxChar *pi, *po;
-
-  if (nrhs != 1 || ! mxIsChar (prhs[0])
-      || mxGetNumberOfDimensions (prhs[0]) > 2)
-    mexErrMsgTxt ("ARG1 must be a char matrix");
-
-  m = mxGetM (prhs[0]);
-  n = mxGetN (prhs[0]);
-  pi = mxGetChars (prhs[0]);
-  plhs[0] = mxCreateNumericMatrix (m, n, mxCHAR_CLASS, mxREAL);
-  po = mxGetChars (plhs[0]);
-
-  for (j = 0; j < n; j++)
-    for (i = 0; i < m; i++)
-      po[j*m + m - 1 - i] = pi[j*m + i];
-}
--- a/examples/mystruct.c	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-#include "mex.h"
-
-void
-mexFunction (int nlhs, mxArray* plhs[],
-             int nrhs, const mxArray* prhs[])
-{
-  int i;
-  mwIndex j;
-  mxArray *v;
-  const char *keys[] = { "this", "that" };
-
-  if (nrhs != 1 || ! mxIsStruct (prhs[0]))
-    mexErrMsgTxt ("expects struct");
-
-  for (i = 0; i < mxGetNumberOfFields (prhs[0]); i++)
-    for (j = 0; j < mxGetNumberOfElements (prhs[0]); j++)
-      {
-        mexPrintf ("field %s(%d) = ", mxGetFieldNameByNumber (prhs[0], i), j);
-        v = mxGetFieldByNumber (prhs[0], j, i);
-        mexCallMATLAB (0, NULL, 1, &v, "disp");
-      }
-
-  v = mxCreateStructMatrix (2, 2, 2, keys);
-
-  mxSetFieldByNumber (v, 0, 0, mxCreateString ("this1"));
-  mxSetFieldByNumber (v, 0, 1, mxCreateString ("that1"));
-  mxSetFieldByNumber (v, 1, 0, mxCreateString ("this2"));
-  mxSetFieldByNumber (v, 1, 1, mxCreateString ("that2"));
-  mxSetFieldByNumber (v, 2, 0, mxCreateString ("this3"));
-  mxSetFieldByNumber (v, 2, 1, mxCreateString ("that3"));
-  mxSetFieldByNumber (v, 3, 0, mxCreateString ("this4"));
-  mxSetFieldByNumber (v, 3, 1, mxCreateString ("that4"));
-
-  if (nlhs)
-    plhs[0] = v;
-}
--- a/examples/oct_demo.cc	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-// oct_demo.cc -- example of a dynamically linked function for Octave.
-
-// To use this file, your version of Octave must support dynamic
-// linking.  To find out if it does, type the command
-//
-//   octave_config_info ("ENABLE_DYNAMIC_LINKING")
-//
-// at the Octave prompt.  Support for dynamic linking is included if
-// this expression returns the string "yes".
-//
-// To compile this file, type the command
-//
-//   mkoctfile oct_demo.cc
-//
-// from within Octave or from the shell prompt.  This will create a file
-// called oct_demo.oct that can be loaded by Octave.  To test the
-// oct_demo.oct file, start Octave and type the command
-//
-//   oct_demo ("easy as", 1, 2, 3)
-//
-// at the Octave prompt.  Octave should respond by printing
-//
-//   Hello, world!
-//   easy as
-//   1
-//   2
-//   3
-//   ans = 3
-
-// Additional samples of real dynamically loaded functions are available in
-// the files of the libinterp/dldfcn directory of the Octave distribution.
-// See also the chapter External Code Interface in the documentation.
-
-#include <iostream>
-
-#include <octave/oct.h>
-
-// Every user function should include <octave/oct.h> which imports the
-// basic set of Octave header files required.  In particular this will define
-// the DEFUN_DLD macro (defun-dld.h) which is used for every user function
-// that is visible to Octave.
-
-// The four arguments to the DEFUN_DLD macro are:
-// 1) The function name as seen in Octave.
-// 2) The variable to hold any inputs (of type octave_value_list)
-// 3) The number of output arguments
-// 4) A string to use as help text if 'help <function_name>' is entered.
-//
-// Note below that the third parameter (nargout) of DEFUN_DLD is not used,
-// so it is omitted from the list of arguments in order to avoid a warning
-// from gcc about an unused function parameter.
-
-DEFUN_DLD (oct_demo, args, ,
-           "[...] = oct_demo (...)\n\
-\n\
-Print a greeting followed by the values of all the arguments passed.\n\
-Return all arguments in reverse order.")
-{
-  // The list of values to return.  See the declaration in oct-obj.h
-
-  octave_value_list retval;
-
-  // This stream is normally connected to the pager.
-
-  octave_stdout << "Hello, world!\n";
-
-  // The inputs to this function are available in args.
-
-  int nargin = args.length ();
-
-  // The octave_value_list class is a zero-based array of octave_value objects.
-  // The declaration for the octave_value class is in the file ov.h.
-  // The print() method will send its output to octave_stdout,
-  // so it will also end up going through the pager.
-
-  for (int i = 0; i < nargin; i++)
-    {
-      octave_value tmp = args(i);
-      tmp.print (octave_stdout);
-      retval(nargin-i-1) = tmp;
-    }
-
-  return retval;
-}
--- a/examples/oregonator.cc	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-#include <octave/oct.h>
-
-DEFUN_DLD (oregonator, args, ,
-           "The `oregonator'.\n\
-\n\
-Reference:\n\
-\n\
-  Oscillations in chemical systems.  IV.  Limit cycle behavior in a\n\
-  model of a real chemical reaction. Richard J. Field and Richard\n\
-  M. Noyes, The Journal of Chemical Physics, Volume 60 Number 5,\n\
-  March 1974.")
-{
-  ColumnVector dx (3);
-
-  ColumnVector x (args(0).vector_value ());
-
-  dx(0) = 77.27 * (x(1) - x(0)*x(1) + x(0) - 8.375e-06*pow (x(0), 2.0));
-  dx(1) = (x(2) - x(0)*x(1) - x(1)) / 77.27;
-  dx(2) = 0.161*(x(0) - x(2));
-
-  return octave_value (dx);
-}
--- a/examples/oregonator.m	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-## The `oregonator'.
-##
-## Reference:
-##
-##   Oscillations in chemical systems.  IV.  Limit cycle behavior in a
-##   model of a real chemical reaction. Richard J. Field and Richard
-##   M. Noyes, The Journal of Chemical Physics, Volume 60 Number 5,
-##   March 1974.
-
-function dx = oregonator (x, t)
-
-  dx = zeros (3, 1);
-
-  dx(1) = 77.27*(x(2) - x(1)*x(2) + x(1) - 8.375e-06*x(1)^2);
-  dx(2) = (x(3) - x(1)*x(2) - x(2)) / 77.27;
-  dx(3) = 0.161*(x(1) - x(3));
-
-end
--- a/examples/paramdemo.cc	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-#include <octave/oct.h>
-
-DEFUN_DLD (paramdemo, args, nargout, "Parameter Check Demo")
-{
-  octave_value retval;
-  int nargin = args.length ();
-
-  if (nargin != 1)
-    print_usage ();
-  else if (nargout != 0)
-    error ("paramdemo: OUTPUT argument required");
-  else
-    {
-      NDArray m = args(0).array_value ();
-      double min_val = -10.0;
-      double max_val = 10.0;
-      octave_stdout << "Properties of input array:\n";
-      if (m.any_element_is_negative ())
-        octave_stdout << "  includes negative values\n";
-      if (m.any_element_is_inf_or_nan ())
-        octave_stdout << "  includes Inf or NaN values\n";
-      if (m.any_element_not_one_or_zero ())
-        octave_stdout << "  includes other values than 1 and 0\n";
-      if (m.all_elements_are_int_or_inf_or_nan ())
-        octave_stdout << "  includes only int, Inf or NaN values\n";
-      if (m.all_integers (min_val, max_val))
-        octave_stdout << "  includes only integers in [-10,10]\n";
-    }
-  return retval;
-}
--- a/examples/standalone.cc	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-#include <iostream>
-#include <octave/oct.h>
-
-int
-main (void)
-{
-  std::cout << "Hello Octave world!\n";
-
-  int n = 2;
-  Matrix a_matrix = Matrix (n, n);
-
-  for (octave_idx_type i = 0; i < n; i++)
-    for (octave_idx_type j = 0; j < n; j++)
-      a_matrix(i,j) = (i + 1) * 10 + (j + 1);
-
-  std::cout << a_matrix;
-
-  return 0;
-}
--- a/examples/standalonebuiltin.cc	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-#include <iostream>
-#include <octave/oct.h>
-#include <octave/builtin-defun-decls.h>
-
-int
-main (void)
-{
-  int n = 2;
-  Matrix a_matrix = Matrix (n, n);
-
-  for (octave_idx_type i = 0; i < n; i++)
-    for (octave_idx_type j = 0; j < n; j++)
-      a_matrix(i,j) = (i + 1) * 10 + (j + 1);
-
-  std::cout << "This is a matrix:" << std::endl 
-            << a_matrix            << std::endl;
-
-  octave_value_list in;
-  in(0) = a_matrix;
-
-  octave_value_list out = Fnorm (in, 1);
-  double norm_of_the_matrix = out(0).double_value ();
-
-  std::cout << "This is the norm of the matrix:" << std::endl 
-            << norm_of_the_matrix                << std::endl;
-  
-  return 0;
-}
--- a/examples/stringdemo.cc	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-#include <octave/oct.h>
-
-DEFUN_DLD (stringdemo, args, , "String Demo")
-{
-  octave_value_list retval;
-  int nargin = args.length ();
-
-  if (nargin != 1)
-    print_usage ();
-  else
-    {
-      charMatrix ch = args(0).char_matrix_value ();
-
-      if (! error_state)
-        {
-          retval(1) = octave_value (ch, '\'');  // Single Quote String
-
-          octave_idx_type nr = ch.rows ();
-          for (octave_idx_type i = 0; i < nr / 2; i++)
-            {
-              std::string tmp = ch.row_as_string (i);
-              ch.insert (ch.row_as_string (nr-i-1).c_str (), i, 0);
-              ch.insert (tmp.c_str (), nr-i-1, 0);
-            }
-          retval(0) = octave_value (ch, '"');  // Double Quote String
-        }
-    }
-  return retval;
-}
--- a/examples/structdemo.cc	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-#include <octave/oct.h>
-#include <octave/ov-struct.h>
-
-DEFUN_DLD (structdemo, args, , "Struct Demo")
-{
-  octave_value retval;
-  int nargin = args.length ();
-
-  if (args.length () == 2)
-    {
-      octave_scalar_map arg0 = args(0).scalar_map_value ();
-      //octave_map arg0 = args(0).map_value ();
-
-      if (! error_state)
-        {
-          std::string arg1 = args(1).string_value ();
-
-          if (! error_state)
-            {
-              octave_value tmp = arg0.contents (arg1);
-              //octave_value tmp = arg0.contents (arg1)(0);
-
-              if (tmp.is_defined ())
-                {
-                  octave_scalar_map st;
-
-                  st.assign ("selected", tmp);
-
-                  retval = octave_value (st);
-                }
-              else
-                error ("structdemo: struct does not have a field named '%s'\n",
-                       arg1.c_str ());
-            }
-          else
-            error ("structdemo: ARG2 must be a character string");
-        }
-      else
-        error ("structdemo: ARG1 must be a struct");
-    }
-  else
-    print_usage ();
-
-  return retval;
-}
--- a/examples/unwinddemo.cc	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-#include <octave/oct.h>
-#include <octave/unwind-prot.h>
-
-void
-my_err_handler (const char *fmt, ...)
-{
-  // Do nothing!!
-}
-
-DEFUN_DLD (unwinddemo, args, nargout, "Unwind Demo")
-{
-  octave_value retval;
-  int nargin = args.length ();
-
-  if (nargin < 2)
-    print_usage ();
-  else
-    {
-      NDArray a = args(0).array_value ();
-      NDArray b = args(1).array_value ();
-
-      if (! error_state)
-        {
-          // Declare unwind_protect frame which lasts as long as
-          // the variable frame has scope.
-          unwind_protect frame;
-          frame.protect_var (current_liboctave_warning_handler);
-
-          set_liboctave_warning_handler (my_err_handler);
-          retval = octave_value (quotient (a, b));
-        }
-    }
-  return retval;
-}
--- a/libgui/graphics/Backend.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/graphics/Backend.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -53,16 +53,16 @@
   if (go.isa ("figure"))
     return std::string ("__plot_stream__");
   else if (go.isa ("uicontrol")
-	   || go.isa ("uipanel")
-	   || go.isa ("uimenu")
-	   || go.isa ("uicontextmenu")
-	   || go.isa ("uitoolbar")
-	   || go.isa ("uipushtool")
-	   || go.isa ("uitoggletool"))
+           || go.isa ("uipanel")
+           || go.isa ("uimenu")
+           || go.isa ("uicontextmenu")
+           || go.isa ("uitoolbar")
+           || go.isa ("uipushtool")
+           || go.isa ("uitoggletool"))
     return std::string ("__object__");
   else
     qCritical ("QtHandles::Backend: no __object__ property known for object "
-	       "of type %s", go.type ().c_str ());
+               "of type %s", go.type ().c_str ());
 
   return std::string ();
 }
@@ -73,7 +73,7 @@
   ObjectFactory* factory = ObjectFactory::instance ();
 
   connect (this, SIGNAL (createObject (double)),
-	   factory, SLOT (createObject (double)));
+           factory, SLOT (createObject (double)));
 }
 
 Backend::~Backend (void)
@@ -92,13 +92,13 @@
       || go.isa ("uitoggletool"))
     {
       Logger::debug ("Backend::initialize %s from thread %08x",
-		     go.type ().c_str (), QThread::currentThreadId ());
+                     go.type ().c_str (), QThread::currentThreadId ());
 
       ObjectProxy* proxy = new ObjectProxy ();
       graphics_object gObj (go);
 
-      gObj.get_properties ().set(toolkitObjectProperty (go),
-				 OCTAVE_PTR_TYPE ((OCTAVE_INTPTR_TYPE) proxy));
+      OCTAVE_PTR_TYPE tmp (reinterpret_cast <OCTAVE_INTPTR_TYPE> (proxy));
+      gObj.get_properties ().set(toolkitObjectProperty (go), tmp);
 
       emit createObject (go.get_handle ().value ());
 
@@ -123,30 +123,30 @@
     return;
 
   Logger::debug ("Backend::update %s(%d) from thread %08x",
-		 go.type ().c_str (), pId, QThread::currentThreadId ());
+                 go.type ().c_str (), pId, QThread::currentThreadId ());
 
   ObjectProxy* proxy = toolkitObjectProxy (go);
 
   if (proxy)
     {
       if (go.isa ("uicontrol")
-	  && pId == uicontrol::properties::ID_STYLE)
-	{
-	  // Special case: we need to recreate the control widget
-	  // associated with the octave graphics_object
+          && pId == uicontrol::properties::ID_STYLE)
+        {
+          // Special case: we need to recreate the control widget
+          // associated with the octave graphics_object
 
-	  finalize (go);
-	  initialize (go);
-	}
+          finalize (go);
+          initialize (go);
+        }
       else
-	proxy->update (pId);
+        proxy->update (pId);
     }
 }
 
 void Backend::finalize (const graphics_object& go)
 {
   Logger::debug ("Backend::finalize %s from thread %08x",
-		 go.type ().c_str (), QThread::currentThreadId ());
+                 go.type ().c_str (), QThread::currentThreadId ());
 
   ObjectProxy* proxy = toolkitObjectProxy (go);
 
@@ -168,7 +168,7 @@
       ObjectProxy* proxy = toolkitObjectProxy (go);
 
       if (proxy)
-	proxy->redraw ();
+        proxy->redraw ();
     }
 }
 
@@ -189,12 +189,12 @@
       octave_value ov = go.get (toolkitObjectProperty (go));
 
       if (ov.is_defined () && ! ov.is_empty ())
-	{
-	  OCTAVE_INTPTR_TYPE ptr = ov.OCTAVE_PTR_SCALAR ().value ();
+        {
+          OCTAVE_INTPTR_TYPE ptr = ov.OCTAVE_PTR_SCALAR ().value ();
 
-	  if (! error_state)
-	    return reinterpret_cast<ObjectProxy*> (ptr);
-	}
+          if (! error_state)
+            return reinterpret_cast<ObjectProxy*> (ptr);
+        }
     }
 
   return 0;
--- a/libgui/graphics/BaseControl.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/graphics/BaseControl.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -45,24 +45,24 @@
       || props.style_is ("popupmenu"))
     {
       p.setColor (QPalette::Base,
-		  Utils::fromRgb (props.get_backgroundcolor_rgb ()));
+                  Utils::fromRgb (props.get_backgroundcolor_rgb ()));
       p.setColor (QPalette::Text,
-		  Utils::fromRgb (props.get_foregroundcolor_rgb ()));
+                  Utils::fromRgb (props.get_foregroundcolor_rgb ()));
     }
   else if (props.style_is ("pushbutton")
-	   || props.style_is ("togglebutton"))
+           || props.style_is ("togglebutton"))
     {
       p.setColor (QPalette::Button,
-		  Utils::fromRgb (props.get_backgroundcolor_rgb ()));
+                  Utils::fromRgb (props.get_backgroundcolor_rgb ()));
       p.setColor (QPalette::ButtonText,
-		  Utils::fromRgb (props.get_foregroundcolor_rgb ()));
+                  Utils::fromRgb (props.get_foregroundcolor_rgb ()));
     }
   else
     {
       p.setColor (QPalette::Window,
-		  Utils::fromRgb (props.get_backgroundcolor_rgb ()));
+                  Utils::fromRgb (props.get_backgroundcolor_rgb ()));
       p.setColor (QPalette::WindowText,
-		  Utils::fromRgb (props.get_foregroundcolor_rgb ()));
+                  Utils::fromRgb (props.get_foregroundcolor_rgb ()));
     }
 
   w->setPalette (p);
@@ -83,7 +83,7 @@
 
   Matrix bb = up.get_boundingbox (false);
   w->setGeometry (xround (bb(0)), xround (bb(1)),
-		  xround (bb(2)), xround (bb(3)));
+                  xround (bb(2)), xround (bb(3)));
   w->setFont (Utils::computeFont<uicontrol> (up, bb(3)));
   updatePalette (up, w);
   w->setEnabled (up.enable_is ("on"));
@@ -108,11 +108,11 @@
    switch (pId)
     {
     case uicontrol::properties::ID_POSITION:
-	{
-	  Matrix bb = up.get_boundingbox (false);
-	  w->setGeometry (xround (bb(0)), xround (bb(1)),
-			  xround (bb(2)), xround (bb(3)));
-	}
+        {
+          Matrix bb = up.get_boundingbox (false);
+          w->setGeometry (xround (bb(0)), xround (bb(1)),
+                          xround (bb(2)), xround (bb(3)));
+        }
       break;
     case uicontrol::properties::ID_FONTNAME:
     case uicontrol::properties::ID_FONTSIZE:
@@ -147,62 +147,62 @@
     }
 }
 
-bool BaseControl::eventFilter (QObject* watched, QEvent* event)
+bool BaseControl::eventFilter (QObject* watched, QEvent* xevent)
 {
-  switch (event->type ())
+  switch (xevent->type ())
     {
     case QEvent::Resize:
       if (m_normalizedFont)
-	{
-	  gh_manager::auto_lock lock;
+        {
+          gh_manager::auto_lock lock;
 
-	  qWidget<QWidget> ()->setFont (Utils::computeFont<uicontrol>
-					(properties<uicontrol> ()));
-	}
+          qWidget<QWidget> ()->setFont (Utils::computeFont<uicontrol>
+                                        (properties<uicontrol> ()));
+        }
       break;
     case QEvent::MouseButtonPress:
-	{
-	  gh_manager::auto_lock lock;
+        {
+          gh_manager::auto_lock lock;
 
-	  QMouseEvent* m = dynamic_cast<QMouseEvent*> (event);
-	  graphics_object go = object ();
-	  uicontrol::properties& up = Utils::properties<uicontrol> (go);
-	  graphics_object fig = go.get_ancestor ("figure");
+          QMouseEvent* m = dynamic_cast<QMouseEvent*> (xevent);
+          graphics_object go = object ();
+          uicontrol::properties& up = Utils::properties<uicontrol> (go);
+          graphics_object fig = go.get_ancestor ("figure");
 
-	  if (m->button () != Qt::LeftButton
-	      || ! up.enable_is ("on"))
-	    {
-	      gh_manager::post_set (fig.get_handle (), "selectiontype",
-				    Utils::figureSelectionType (m), false);
-	      gh_manager::post_set (fig.get_handle (), "currentpoint",
-				    Utils::figureCurrentPoint (fig, m),
-				    false);
-	      gh_manager::post_callback (fig.get_handle (),
-					 "windowbuttondownfcn");
-	      gh_manager::post_callback (m_handle, "buttondownfcn");
+          if (m->button () != Qt::LeftButton
+              || ! up.enable_is ("on"))
+            {
+              gh_manager::post_set (fig.get_handle (), "selectiontype",
+                                    Utils::figureSelectionType (m), false);
+              gh_manager::post_set (fig.get_handle (), "currentpoint",
+                                    Utils::figureCurrentPoint (fig, m),
+                                    false);
+              gh_manager::post_callback (fig.get_handle (),
+                                         "windowbuttondownfcn");
+              gh_manager::post_callback (m_handle, "buttondownfcn");
 
-	      if (m->button () == Qt::RightButton)
-		ContextMenu::executeAt (up, m->globalPos ());
-	    }
-	  else
-	    {
-	      if (up.style_is ("listbox"))
-		gh_manager::post_set (fig.get_handle (), "selectiontype",
-				      Utils::figureSelectionType (m), false);
-	      else
-		gh_manager::post_set (fig.get_handle (), "selectiontype",
-				      octave_value ("normal"), false);
-	    }
-	}
+              if (m->button () == Qt::RightButton)
+                ContextMenu::executeAt (up, m->globalPos ());
+            }
+          else
+            {
+              if (up.style_is ("listbox"))
+                gh_manager::post_set (fig.get_handle (), "selectiontype",
+                                      Utils::figureSelectionType (m), false);
+              else
+                gh_manager::post_set (fig.get_handle (), "selectiontype",
+                                      octave_value ("normal"), false);
+            }
+        }
       break;
     case QEvent::MouseMove:
       if (qWidget<QWidget> ()->hasMouseTracking ())
         {
-	  gh_manager::auto_lock lock;
+          gh_manager::auto_lock lock;
 
-	  QMouseEvent* m = dynamic_cast<QMouseEvent*> (event);
-	  graphics_object go = object ();
-	  graphics_object fig = go.get_ancestor ("figure");
+          QMouseEvent* m = dynamic_cast<QMouseEvent*> (xevent);
+          graphics_object go = object ();
+          graphics_object fig = go.get_ancestor ("figure");
 
           gh_manager::post_set (fig.get_handle (), "currentpoint",
                                 Utils::figureCurrentPoint (fig, m), false);
@@ -215,7 +215,7 @@
           gh_manager::auto_lock lock;
 
           octave_scalar_map keyData =
-            Utils::makeKeyEventStruct (dynamic_cast<QKeyEvent*> (event));
+            Utils::makeKeyEventStruct (dynamic_cast<QKeyEvent*> (xevent));
           graphics_object fig = object ().get_ancestor ("figure");
 
           gh_manager::post_set (fig.get_handle (), "currentcharacter",
@@ -226,7 +226,7 @@
     default: break;
     }
 
-  return Object::eventFilter (watched, event);
+  return Object::eventFilter (watched, xevent);
 }
 
 }; // namespace QtHandles
--- a/libgui/graphics/ButtonControl.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/graphics/ButtonControl.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -46,7 +46,7 @@
       Matrix value = up.get_value ().matrix_value ();
 
       if (value.numel () > 0 && value(0) == up.get_max ())
-	btn->setChecked (true);
+        btn->setChecked (true);
     }
 
   connect (btn, SIGNAL (clicked (void)), SLOT (clicked (void)));
@@ -70,19 +70,19 @@
     case uicontrol::properties::ID_VALUE:
       m_blockCallback = true;
       if (btn->isCheckable ())
-	{
-	  Matrix value = up.get_value ().matrix_value ();
+        {
+          Matrix value = up.get_value ().matrix_value ();
 
-	  if (value.numel () > 0)
-	    {
-	      double dValue = value(0);
+          if (value.numel () > 0)
+            {
+              double dValue = value(0);
 
-	      if (dValue == up.get_min () && btn->isChecked ())
-		btn->setChecked (false);
-	      else if (dValue == up.get_max () && ! btn->isChecked ())
-		btn->setChecked (true);
-	    }
-	}
+              if (dValue == up.get_min () && btn->isChecked ())
+                btn->setChecked (false);
+              else if (dValue == up.get_max () && ! btn->isChecked ())
+                btn->setChecked (true);
+            }
+        }
       m_blockCallback = false;
       break;
     default:
@@ -105,8 +105,8 @@
       double newValue = (checked ? up.get_max () : up.get_min ());
 
       if (oldValue.numel() != 1
-	  || (newValue != oldValue(0)))
-	gh_manager::post_set (m_handle, "value", newValue, false);
+          || (newValue != oldValue(0)))
+        gh_manager::post_set (m_handle, "value", newValue, false);
       gh_manager::post_callback (m_handle, "callback");
     }
 }
--- a/libgui/graphics/Canvas.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/graphics/Canvas.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -95,7 +95,7 @@
       draw (m_handle);
 
       if (m_mouseMode == ZoomMode && m_mouseAxes.ok ())
-	drawZoomBox (m_mouseAnchor, m_mouseCurrent);
+        drawZoomBox (m_mouseAnchor, m_mouseCurrent);
     }
 }
 
@@ -109,65 +109,65 @@
       axes::properties& ap = Utils::properties<axes> (ax);
 
       switch (m_mouseMode)
-	{
-	case RotateMode:
-	    {
-	      Matrix bb = ap.get_boundingbox (true);
-	      Matrix view = ap.get_view ().matrix_value ();
+        {
+        case RotateMode:
+            {
+              Matrix bb = ap.get_boundingbox (true);
+              Matrix view = ap.get_view ().matrix_value ();
 
-	      // Compute new view angles
-	      view(0) += ((m_mouseCurrent.x () - event->x ())
-			  * (180.0 / bb(2)));
-	      view(1) += ((event->y () - m_mouseCurrent.y ())
-			  * (180.0 / bb(3)));
+              // Compute new view angles
+              view(0) += ((m_mouseCurrent.x () - event->x ())
+                          * (180.0 / bb(2)));
+              view(1) += ((event->y () - m_mouseCurrent.y ())
+                          * (180.0 / bb(3)));
 
-	      // Clipping
-	      view(1) = std::min (view(1), 90.0);
-	      view(1) = std::max (view(1), -90.0);
-	      if (view(0) > 180.0)
-		view(0) -= 360.0;
-	      else if (view(0) < -180.0)
-		view(0) += 360.0;
+              // Clipping
+              view(1) = std::min (view(1), 90.0);
+              view(1) = std::max (view(1), -90.0);
+              if (view(0) > 180.0)
+                view(0) -= 360.0;
+              else if (view(0) < -180.0)
+                view(0) += 360.0;
 
-	      // Snapping
-	      double snapMargin = 1.0;
-	      for (int a = -90; a <= 90; a += 90)
-		if ((a - snapMargin) < view(1)
-		    && view(1) < (a + snapMargin))
-		  {
-		    view(1) = a;
-		    break;
-		  }
-	      for (int a = -180; a <= 180; a += 180)
-		if ((a - snapMargin) < view(0)
-		    && view(0) < (a + snapMargin))
-		  {
-		    if (a == 180)
-		      view(0) = -180;
-		    else
-		      view(0) = a;
-		    break;
-		  }
+              // Snapping
+              double snapMargin = 1.0;
+              for (int a = -90; a <= 90; a += 90)
+                if ((a - snapMargin) < view(1)
+                    && view(1) < (a + snapMargin))
+                  {
+                    view(1) = a;
+                    break;
+                  }
+              for (int a = -180; a <= 180; a += 180)
+                if ((a - snapMargin) < view(0)
+                    && view(0) < (a + snapMargin))
+                  {
+                    if (a == 180)
+                      view(0) = -180;
+                    else
+                      view(0) = a;
+                    break;
+                  }
 
-	      // Update axes properties
-	      ap.set_view (view);
+              // Update axes properties
+              ap.set_view (view);
 
-	      // Update current mouse position
-	      m_mouseCurrent = event->pos ();
+              // Update current mouse position
+              m_mouseCurrent = event->pos ();
 
-	      // Force immediate redraw
-	      redraw (true);
-	    }
-	  break;
-	case ZoomMode:
-	  m_mouseCurrent = event->pos();
-	  redraw (true);
-	  break;
-	case PanMode:
-	  break;
-	default:
-	  break;
-	}
+              // Force immediate redraw
+              redraw (true);
+            }
+          break;
+        case ZoomMode:
+          m_mouseCurrent = event->pos();
+          redraw (true);
+          break;
+        case PanMode:
+          break;
+        default:
+          break;
+        }
     }
   else if (m_mouseMode == NoMode)
     {
@@ -178,8 +178,8 @@
           graphics_object figObj (obj.get_ancestor ("figure"));
 
           updateCurrentPoint (figObj, obj, event);
-	  gh_manager::post_callback (figObj.get_handle (),
-				     "windowbuttonmotionfcn");
+          gh_manager::post_callback (figObj.get_handle (),
+                                     "windowbuttonmotionfcn");
         }
     }
 }
@@ -199,24 +199,24 @@
       octave_idx_type num_children = children.numel ();
 
       for (int i = 0; i < num_children; i++)
-	{
-	  graphics_object childObj (gh_manager::get_object (children(i)));
+        {
+          graphics_object childObj (gh_manager::get_object (children(i)));
 
           if (childObj.isa ("axes"))
             axesList.append (childObj);
-	  else if (childObj.isa ("uicontrol") || childObj.isa ("uipanel"))
-	    {
-	      Matrix bb = childObj.get_properties ().get_boundingbox (false);
-	      QRectF r (bb(0), bb(1), bb(2), bb(3));
+          else if (childObj.isa ("uicontrol") || childObj.isa ("uipanel"))
+            {
+              Matrix bb = childObj.get_properties ().get_boundingbox (false);
+              QRectF r (bb(0), bb(1), bb(2), bb(3));
 
-	      r.adjust (-5, -5, 5, 5);
-	      if (r.contains (event->posF ()))
-		{
-		  currentObj = childObj;
-		  break;
-		}
-	    }
-	}
+              r.adjust (-5, -5, 5, 5);
+              if (r.contains (event->posF ()))
+                {
+                  currentObj = childObj;
+                  break;
+                }
+            }
+        }
 
       if (! currentObj)
         {
@@ -269,61 +269,61 @@
       MouseMode newMouseMode = NoMode;
 
       if (fig)
-	newMouseMode = fig->mouseMode ();
+        newMouseMode = fig->mouseMode ();
 
       switch (newMouseMode)
-	{
-	case NoMode:
-	  gh_manager::post_set (figObj.get_handle (), "selectiontype",
-				Utils::figureSelectionType (event), false);
+        {
+        case NoMode:
+          gh_manager::post_set (figObj.get_handle (), "selectiontype",
+                                Utils::figureSelectionType (event), false);
           updateCurrentPoint (figObj, obj, event);
-	  gh_manager::post_callback (figObj.get_handle (),
-				     "windowbuttondownfcn");
+          gh_manager::post_callback (figObj.get_handle (),
+                                     "windowbuttondownfcn");
           gh_manager::post_callback (currentObj.get_handle (),
                                      "buttondownfcn");
-	  if (event->button () == Qt::RightButton)
-	    ContextMenu::executeAt (currentObj.get_properties (),
-				    event->globalPos ());
-	  break;
-	case RotateMode:
-	case ZoomMode:
-	case PanMode:
-	  if (axesObj)
-	    {
-	      if (event->buttons () == Qt::LeftButton
-		  && event->modifiers () == Qt::NoModifier)
-		{
-		  m_mouseAnchor = m_mouseCurrent = event->pos ();
-		  m_mouseAxes = axesObj.get_handle ();
-		  m_mouseMode = newMouseMode;
-		}
-	      else if (newMouseMode == ZoomMode
-		       && event->modifiers () == Qt::NoModifier)
-		{
-		  switch (event->buttons ())
-		    {
-		    case Qt::RightButton:
-		      Utils::properties<axes> (axesObj).unzoom ();
-		      break;
-		    case Qt::MidButton:
-			{
-			  axes::properties& ap =
-			    Utils::properties<axes> (axesObj);
+          if (event->button () == Qt::RightButton)
+            ContextMenu::executeAt (currentObj.get_properties (),
+                                    event->globalPos ());
+          break;
+        case RotateMode:
+        case ZoomMode:
+        case PanMode:
+          if (axesObj)
+            {
+              if (event->buttons () == Qt::LeftButton
+                  && event->modifiers () == Qt::NoModifier)
+                {
+                  m_mouseAnchor = m_mouseCurrent = event->pos ();
+                  m_mouseAxes = axesObj.get_handle ();
+                  m_mouseMode = newMouseMode;
+                }
+              else if (newMouseMode == ZoomMode
+                       && event->modifiers () == Qt::NoModifier)
+                {
+                  switch (event->buttons ())
+                    {
+                    case Qt::RightButton:
+                      Utils::properties<axes> (axesObj).unzoom ();
+                      break;
+                    case Qt::MidButton:
+                        {
+                          axes::properties& ap =
+                            Utils::properties<axes> (axesObj);
 
-			  ap.clear_zoom_stack ();
-			  ap.set_xlimmode ("auto");
-			  ap.set_ylimmode ("auto");
-			  ap.set_zlimmode ("auto");
-			}
-		      break;
-		    }
-		  redraw (false);
-		}
-	    }
-	  break;
-	default:
-	  break;
-	}
+                          ap.clear_zoom_stack ();
+                          ap.set_xlimmode ("auto");
+                          ap.set_ylimmode ("auto");
+                          ap.set_zlimmode ("auto");
+                        }
+                      break;
+                    }
+                  redraw (false);
+                }
+            }
+          break;
+        default:
+          break;
+        }
     }
 }
 
@@ -337,26 +337,26 @@
       graphics_object ax = gh_manager::get_object (m_mouseAxes);
 
       if (ax.valid_object ())
-	{
-	  axes::properties& ap = Utils::properties<axes> (ax);
+        {
+          axes::properties& ap = Utils::properties<axes> (ax);
 
-	  ColumnVector p0 = ap.pixel2coord (m_mouseAnchor.x (),
-					    m_mouseAnchor.y ());
-	  ColumnVector p1 = ap.pixel2coord (event->x (),
-					    event->y ());
+          ColumnVector p0 = ap.pixel2coord (m_mouseAnchor.x (),
+                                            m_mouseAnchor.y ());
+          ColumnVector p1 = ap.pixel2coord (event->x (),
+                                            event->y ());
 
-	  Matrix xl (1, 2, 0.0);
-	  Matrix yl (1, 2, 0.0);
+          Matrix xl (1, 2, 0.0);
+          Matrix yl (1, 2, 0.0);
 
-	  xl(0) = std::min (p0(0), p1(0));
-	  xl(1) = std::max (p0(0), p1(0));
-	  yl(0) = std::min (p0(1), p1(1));
-	  yl(1) = std::max (p0(1), p1(1));
+          xl(0) = std::min (p0(0), p1(0));
+          xl(1) = std::max (p0(0), p1(0));
+          yl(0) = std::min (p0(1), p1(1));
+          yl(1) = std::max (p0(1), p1(1));
 
-	  ap.zoom (xl, yl);
+          ap.zoom (xl, yl);
 
-	  redraw (false);
-	}
+          redraw (false);
+        }
     }
   else if (m_mouseMode == NoMode)
     {
@@ -407,7 +407,7 @@
 }
 
 Canvas* Canvas::create (const std::string& /* name */, QWidget* parent,
-			const graphics_handle& handle)
+                        const graphics_handle& handle)
 {
   // Only OpenGL
   return new GLCanvas (parent, handle);
--- a/libgui/graphics/Canvas.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/graphics/Canvas.h	Mon Jan 12 09:17:35 2015 -0800
@@ -58,7 +58,7 @@
   virtual QWidget* qWidget (void) = 0;
 
   static Canvas* create (const std::string& name, QWidget* parent,
-			 const graphics_handle& handle);
+                         const graphics_handle& handle);
 
 protected:
   virtual void draw (const graphics_handle& handle) = 0;
--- a/libgui/graphics/CheckBoxControl.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/graphics/CheckBoxControl.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -41,7 +41,7 @@
       Container* container = parent->innerContainer ();
 
       if (container)
-	return new CheckBoxControl (go, new QCheckBox (container));
+        return new CheckBoxControl (go, new QCheckBox (container));
     }
 
   return 0;
--- a/libgui/graphics/Container.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/graphics/Container.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -37,8 +37,8 @@
 namespace QtHandles
 {
 
-Container::Container (QWidget* parent)
-  : ContainerBase (parent), m_canvas (0)
+Container::Container (QWidget* xparent)
+  : ContainerBase (xparent), m_canvas (0)
 {
   setFocusPolicy (Qt::ClickFocus);
 }
@@ -47,25 +47,25 @@
 {
 }
 
-Canvas* Container::canvas (const graphics_handle& handle, bool create)
+Canvas* Container::canvas (const graphics_handle& xhandle, bool xcreate)
 {
-  if (! m_canvas && create)
+  if (! m_canvas && xcreate)
     {
-      graphics_object go = gh_manager::get_object (handle);
+      graphics_object go = gh_manager::get_object (xhandle);
 
       if (go)
-	{
-	  graphics_object fig = go.get_ancestor ("figure");
+        {
+          graphics_object fig = go.get_ancestor ("figure");
 
-	  m_canvas = Canvas::create (fig.get("renderer").string_value (),
-				     this, handle);
+          m_canvas = Canvas::create (fig.get("renderer").string_value (),
+                                     this, xhandle);
 
-	  QWidget* canvasWidget = m_canvas->qWidget ();
+          QWidget* canvasWidget = m_canvas->qWidget ();
 
-	  canvasWidget->lower ();
-	  canvasWidget->show ();
-	  canvasWidget->setGeometry (0, 0, width (), height ());
-	}
+          canvasWidget->lower ();
+          canvasWidget->show ();
+          canvasWidget->setGeometry (0, 0, width (), height ());
+        }
     }
 
   return m_canvas;
@@ -81,26 +81,26 @@
   foreach (QObject* qObj, children ())
     {
       if (qObj->isWidgetType ())
-	{
-	  Object* obj = Object::fromQObject (qObj);
+        {
+          Object* obj = Object::fromQObject (qObj);
 
-	  if (obj)
-	    {
-	      Matrix bb = obj->properties ().get_boundingbox (false);
+          if (obj)
+            {
+              Matrix bb = obj->properties ().get_boundingbox (false);
 
-	      obj->qWidget<QWidget> ()
-		->setGeometry (xround (bb(0)), xround (bb(1)),
-			       xround (bb(2)), xround (bb(3)));
-	    }
-	}
+              obj->qWidget<QWidget> ()
+                ->setGeometry (xround (bb(0)), xround (bb(1)),
+                               xround (bb(2)), xround (bb(3)));
+            }
+        }
     }
 }
 
-void Container::childEvent (QChildEvent* event)
+void Container::childEvent (QChildEvent* xevent)
 {
-  if (event->child ()->isWidgetType ())
+  if (xevent->child ()->isWidgetType ())
     {
-      qobject_cast<QWidget*> (event->child ())->setMouseTracking (hasMouseTracking ());
+      qobject_cast<QWidget*> (xevent->child ())->setMouseTracking (hasMouseTracking ());
     }
 }
 
--- a/libgui/graphics/ContextMenu.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/graphics/ContextMenu.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -35,11 +35,11 @@
 
 ContextMenu* ContextMenu::create (const graphics_object& go)
 {
-  Object* parent = Object::parentObject (go);
+  Object* xparent = Object::parentObject (go);
 
-  if (parent)
+  if (xparent)
     {
-      QWidget* w = parent->qWidget<QWidget> ();
+      QWidget* w = xparent->qWidget<QWidget> ();
 
       return new ContextMenu (go, new QMenu (w));
     }
@@ -47,13 +47,13 @@
   return 0;
 }
 
-ContextMenu::ContextMenu (const graphics_object& go, QMenu* menu)
-    : Object (go, menu)
+ContextMenu::ContextMenu (const graphics_object& go, QMenu* xmenu)
+    : Object (go, xmenu)
 {
-  menu->setAutoFillBackground (true);
+  xmenu->setAutoFillBackground (true);
 
-  connect (menu, SIGNAL (aboutToShow (void)), SLOT (aboutToShow (void)));
-  connect (menu, SIGNAL (aboutToHide (void)), SLOT (aboutToHide (void)));
+  connect (xmenu, SIGNAL (aboutToShow (void)), SLOT (aboutToShow (void)));
+  connect (xmenu, SIGNAL (aboutToHide (void)), SLOT (aboutToHide (void)));
 }
 
 ContextMenu::~ContextMenu (void)
@@ -63,25 +63,25 @@
 void ContextMenu::update (int pId)
 {
   uicontextmenu::properties& up = properties<uicontextmenu> ();
-  QMenu* menu = qWidget<QMenu> ();
+  QMenu* xmenu = qWidget<QMenu> ();
 
   switch (pId)
     {
     case base_properties::ID_VISIBLE:
       if (up.is_visible ())
-	{
-	  Matrix pos = up.get_position ().matrix_value ();
-	  QWidget* parentW = menu->parentWidget ();
-	  QPoint pt;
+        {
+          Matrix pos = up.get_position ().matrix_value ();
+          QWidget* parentW = xmenu->parentWidget ();
+          QPoint pt;
 
-	  pt.rx () = xround (pos(0));
-	  pt.ry () = parentW->height () - xround (pos(1));
-	  pt = parentW->mapToGlobal (pt);
+          pt.rx () = xround (pos(0));
+          pt.ry () = parentW->height () - xround (pos(1));
+          pt = parentW->mapToGlobal (pt);
 
-	  menu->popup (pt);
-	}
+          xmenu->popup (pt);
+        }
       else
-	menu->hide ();
+        xmenu->hide ();
       break;
     default:
       Object::update (pId);
@@ -114,18 +114,18 @@
       graphics_object go = gh_manager::get_object (h);
 
       if (go.valid_object ())
-	{
-	  ContextMenu* cMenu =
-	    dynamic_cast<ContextMenu*> (Backend::toolkitObject (go));
+        {
+          ContextMenu* cMenu =
+            dynamic_cast<ContextMenu*> (Backend::toolkitObject (go));
 
-	  if (cMenu)
-	    {
-	      QMenu* menu = cMenu->qWidget<QMenu> ();
+          if (cMenu)
+            {
+              QMenu* menu = cMenu->qWidget<QMenu> ();
 
-	      if (menu)
-		menu->popup (pt);
-	    }
-	}
+              if (menu)
+                menu->popup (pt);
+            }
+        }
     }
 }
 
--- a/libgui/graphics/EditControl.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/graphics/EditControl.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -43,14 +43,14 @@
       Container* container = parent->innerContainer ();
 
       if (container)
-	{
-	  uicontrol::properties& up = Utils::properties<uicontrol> (go);
+        {
+          uicontrol::properties& up = Utils::properties<uicontrol> (go);
 
-	  if ((up.get_max () - up.get_min ()) > 1)
-	    return new EditControl (go, new TextEdit (container));
-	  else
-	    return new EditControl (go, new QLineEdit (container));
-	}
+          if ((up.get_max () - up.get_min ()) > 1)
+            return new EditControl (go, new TextEdit (container));
+          else
+            return new EditControl (go, new QLineEdit (container));
+        }
     }
 
   return 0;
@@ -74,12 +74,12 @@
 
   edit->setText (Utils::fromStdString (up.get_string_string ()));
   edit->setAlignment (Utils::fromHVAlign (up.get_horizontalalignment (),
-					  up.get_verticalalignment ()));
+                                          up.get_verticalalignment ()));
 
   connect (edit, SIGNAL (textEdited (const QString&)),
-	   SLOT (textChanged (void)));
+           SLOT (textChanged (void)));
   connect (edit, SIGNAL (editingFinished (void)),
-	   SLOT (editingFinished (void)));
+           SLOT (editingFinished (void)));
 }
 
 EditControl::EditControl (const graphics_object& go, TextEdit* edit)
@@ -103,9 +103,9 @@
   edit->setPlainText (Utils::fromStdString (up.get_string_string ()));
   
   connect (edit, SIGNAL (textChanged (void)),
-	   SLOT (textChanged (void)));
+           SLOT (textChanged (void)));
   connect (edit, SIGNAL (editingFinished (void)),
-	   SLOT (editingFinished (void)));
+           SLOT (editingFinished (void)));
 }
 
 EditControl::~EditControl (void)
@@ -129,11 +129,11 @@
   if (! handled)
     {
       switch (pId)
-	{
-	default:
-	  BaseControl::update (pId);
-	  break;
-	}
+        {
+        default:
+          BaseControl::update (pId);
+          break;
+        }
     }
 }
 
@@ -150,17 +150,17 @@
     case uicontrol::properties::ID_HORIZONTALALIGNMENT:
     case uicontrol::properties::ID_VERTICALALIGNMENT:
       edit->setAlignment (Utils::fromHVAlign (up.get_horizontalalignment (),
-					      up.get_verticalalignment ()));
+                                              up.get_verticalalignment ()));
       return true;
     case uicontrol::properties::ID_MIN:
     case uicontrol::properties::ID_MAX:
       if ((up.get_max () - up.get_min ()) > 1)
-	{
-	  QWidget* container = edit->parentWidget ();
+        {
+          QWidget* container = edit->parentWidget ();
 
-	  delete edit;
-	  init (new TextEdit (container), true);
-	}
+          delete edit;
+          init (new TextEdit (container), true);
+        }
       return true;
     default:
       break;
@@ -182,12 +182,12 @@
     case uicontrol::properties::ID_MIN:
     case uicontrol::properties::ID_MAX:
       if ((up.get_max () - up.get_min ()) <= 1)
-	{
-	  QWidget* container = edit->parentWidget ();
+        {
+          QWidget* container = edit->parentWidget ();
 
-	  delete edit;
-	  init (new QLineEdit (container), true);
-	}
+          delete edit;
+          init (new QLineEdit (container), true);
+        }
       return true;
     default:
       break;
@@ -206,8 +206,8 @@
   if (m_textChanged)
     {
       QString txt = (m_multiLine
-		     ? qWidget<TextEdit> ()->toPlainText ()
-		     : qWidget<QLineEdit> ()->text ());
+                     ? qWidget<TextEdit> ()->toPlainText ()
+                     : qWidget<QLineEdit> ()->text ());
 
       gh_manager::post_set (m_handle, "string", Utils::toStdString (txt), false);
       gh_manager::post_callback (m_handle, "callback");
--- a/libgui/graphics/Figure.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/graphics/Figure.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -61,8 +61,8 @@
       graphics_object go (gh_manager::get_object (kids(i)));
 
       if (go && (go.isa ("uicontrol") || go.isa ("uipanel")
-		 || go.isa ("uibuttongroup")))
-	return true;
+                 || go.isa ("uibuttongroup")))
+        return true;
     }
 
   return false;
@@ -77,7 +77,7 @@
       graphics_object go (gh_manager::get_object (kids(i)));
 
       if (go && go.isa ("uimenu"))
-	return true;
+        return true;
     }
 
   return false;
@@ -173,7 +173,7 @@
 
   MouseModeActionGroup* mouseModeGroup = new MouseModeActionGroup (win);
   connect (mouseModeGroup, SIGNAL (modeChanged (MouseMode)),
-	   SLOT (setMouseMode (MouseMode)));
+           SLOT (setMouseMode (MouseMode)));
   m_figureToolBar->addActions (mouseModeGroup->actions ());
 
   m_menuBar = new MenuBar (win);
@@ -188,23 +188,23 @@
   fileMenu->addAction (tr ("Save &As"))->setEnabled (false);
   fileMenu->addSeparator ();
   fileMenu->addAction (tr ("&Close Figure"), this,
-		       SLOT (fileCloseFigure (void)), Qt::CTRL|Qt::Key_W);
+                       SLOT (fileCloseFigure (void)), Qt::CTRL|Qt::Key_W);
 
   QMenu* editMenu = m_menuBar->addMenu (tr ("&Edit"));
   editMenu->menuAction ()->setObjectName ("builtinMenu");
   editMenu->addAction (tr ("Cop&y"), this, SLOT (editCopy (void)),
-		       Qt::CTRL|Qt::Key_C)->setEnabled (false);
+                       Qt::CTRL|Qt::Key_C)->setEnabled (false);
   editMenu->addAction (tr ("Cu&t"), this, SLOT (editCut (void)),
-		       Qt::CTRL|Qt::Key_X)->setEnabled (false);
+                       Qt::CTRL|Qt::Key_X)->setEnabled (false);
   editMenu->addAction (tr ("&Paste"), this, SLOT (editPaste(void)),
-		       Qt::CTRL|Qt::Key_V)->setEnabled (false);
+                       Qt::CTRL|Qt::Key_V)->setEnabled (false);
   editMenu->addSeparator ();
   editMenu->addActions (mouseModeGroup->actions ());
 
   QMenu* helpMenu = m_menuBar->addMenu (tr ("&Help"));
   helpMenu->menuAction ()->setObjectName ("builtinMenu");
   helpMenu->addAction (tr ("&About QtHandles"), this,
-		       SLOT (helpAboutQtHandles (void)));
+                       SLOT (helpAboutQtHandles (void)));
   helpMenu->addAction (tr ("About &Qt"), qApp, SLOT (aboutQt (void)));
 
   m_menuBar->addReceiver (this);
@@ -226,12 +226,12 @@
     }
 
   foreach (QFrame* frame,
-	   qWidget<QWidget> ()->findChildren<QFrame*> ("UIPanel"))
+           qWidget<QWidget> ()->findChildren<QFrame*> ("UIPanel"))
     {
       Object* obj = Object::fromQObject (frame);
 
       if (obj)
-	obj->slotRedraw ();
+        obj->slotRedraw ();
     }
 }
 
@@ -260,20 +260,20 @@
   switch (pId)
     {
     case figure::properties::ID_POSITION:
-	{
+        {
           m_innerRect = boundingBoxToRect (fp.get_boundingbox (true));
           //qDebug () << "Figure::update(position):" << m_innerRect;
-	  int offset = 0;
+          int offset = 0;
 
           foreach (QToolBar* tb, win->findChildren<QToolBar*> ())
             if (! tb->isHidden ())
               offset += tb->sizeHint ().height ();
-	  if (! m_menuBar->isHidden ())
-	    offset += m_menuBar->sizeHint ().height () + 1;
+          if (! m_menuBar->isHidden ())
+            offset += m_menuBar->sizeHint ().height () + 1;
           //qDebug () << "Figure::update(position)(adjusted):" << m_innerRect.adjusted (0, -offset, 0, 0);
-	  win->setGeometry (m_innerRect.adjusted (0, -offset, 0, 0));
+          win->setGeometry (m_innerRect.adjusted (0, -offset, 0, 0));
           //qDebug () << "Figure::update(position): done";
-	}
+        }
       break;
     case figure::properties::ID_NAME:
     case figure::properties::ID_NUMBERTITLE:
@@ -281,17 +281,17 @@
       break;
     case figure::properties::ID_VISIBLE:
       if (fp.is_visible ())
-	QTimer::singleShot (0, win, SLOT (show ()));
+        QTimer::singleShot (0, win, SLOT (show ()));
       else
-	win->hide ();
+        win->hide ();
       break;
     case figure::properties::ID_TOOLBAR:
       if (fp.toolbar_is ("none"))
-	showFigureToolBar (false);
+        showFigureToolBar (false);
       else if (fp.toolbar_is ("figure"))
-	showFigureToolBar (true);
+        showFigureToolBar (true);
       else // "auto"
-	showFigureToolBar (! hasUiControlChildren (fp));
+        showFigureToolBar (! hasUiControlChildren (fp));
       break;
     case figure::properties::ID_MENUBAR:
       showMenuBar (fp.menubar_is ("figure"));
@@ -332,9 +332,9 @@
       QRect r = qWidget<QWidget> ()->geometry ();
 
       if (! visible)
-	r.adjust (0, dy, 0, 0);
+        r.adjust (0, dy, 0, 0);
       else
-	r.adjust (0, -dy, 0, 0);
+        r.adjust (0, -dy, 0, 0);
 
       m_blockUpdates = true;
       qWidget<QWidget> ()->setGeometry (r);
@@ -344,12 +344,12 @@
       updateBoundingBox (false);
 
       if (visible)
-	m_mouseMode = m_lastMouseMode;
+        m_mouseMode = m_lastMouseMode;
       else
-	{
-	  m_lastMouseMode = m_mouseMode;
-	  m_mouseMode = NoMode;
-	}
+        {
+          m_lastMouseMode = m_mouseMode;
+          m_mouseMode = NoMode;
+        }
     }
 }
 
@@ -373,9 +373,9 @@
 
       //qDebug () << "Figure::showMenuBar:" << r;
       if (! visible)
-	r.adjust (0, dy, 0, 0);
+        r.adjust (0, dy, 0, 0);
       else
-	r.adjust (0, -dy, 0, 0);
+        r.adjust (0, -dy, 0, 0);
       //qDebug () << "Figure::showMenuBar(adjusted):" << r;
 
       m_blockUpdates = true;
@@ -467,7 +467,7 @@
       if (flags & UpdateBoundingBoxSize)
         r.setSize (win->frameGeometry ().size ());
 
-      if (r.isValid () && r != m_outerRect )
+      if (r.isValid () && r != m_outerRect)
         {
           //qDebug() << "outer rect changed:" << m_outerRect << "->>" << r;
           m_outerRect = r;
@@ -493,103 +493,103 @@
   gh_manager::post_function (Figure::updateBoundingBoxHelper, d);
 }
 
-bool Figure::eventNotifyBefore (QObject* obj, QEvent* event)
+bool Figure::eventNotifyBefore (QObject* obj, QEvent* xevent)
 {
   if (! m_blockUpdates)
     {
       if (obj == m_container)
-	{
+        {
           // Do nothing...
-	}
+        }
       else if (obj == m_menuBar)
-	{
-	  switch (event->type ())
-	    {
-	    case QEvent::ActionRemoved:
-		{
-		  QAction* a = dynamic_cast<QActionEvent*> (event)->action ();
+        {
+          switch (xevent->type ())
+            {
+            case QEvent::ActionRemoved:
+                {
+                  QAction* a = dynamic_cast<QActionEvent*> (xevent)->action ();
 
-		  if (! a->isSeparator ()
-		      && a->objectName () != "builtinMenu")
+                  if (! a->isSeparator ()
+                      && a->objectName () != "builtinMenu")
                     updateMenuBar ();
-		}
-	      break;
-	    default:
-	      break;
-	    }
-	}
+                }
+              break;
+            default:
+              break;
+            }
+        }
       else
-	{
-	  switch (event->type ())
-	    {
-	    case QEvent::Close:
-	      event->ignore ();
-	      gh_manager::post_callback (m_handle, "closerequestfcn");
-	      return true;
-	    default:
-	      break;
-	    }
-	}
+        {
+          switch (xevent->type ())
+            {
+            case QEvent::Close:
+              xevent->ignore ();
+              gh_manager::post_callback (m_handle, "closerequestfcn");
+              return true;
+            default:
+              break;
+            }
+        }
     }
 
   return false;
 }
 
-void Figure::eventNotifyAfter (QObject* watched, QEvent* event)
+void Figure::eventNotifyAfter (QObject* watched, QEvent* xevent)
 {
   if (! m_blockUpdates)
     {
       if (watched == m_container)
         {
-	  switch (event->type ())
-	    {
-	    case QEvent::Resize:
-	      updateBoundingBox (true, UpdateBoundingBoxSize);
-	      break;
-	    case QEvent::ChildAdded:
-	      if (dynamic_cast<QChildEvent*> (event)->child
-		  ()->isWidgetType())
-		{
-		  gh_manager::auto_lock lock;
-		  const figure::properties& fp = properties<figure> ();
+          switch (xevent->type ())
+            {
+            case QEvent::Resize:
+              updateBoundingBox (true, UpdateBoundingBoxSize);
+              break;
+            case QEvent::ChildAdded:
+              if (dynamic_cast<QChildEvent*> (xevent)->child
+                  ()->isWidgetType())
+                {
+                  gh_manager::auto_lock lock;
+                  const figure::properties& fp = properties<figure> ();
 
-		  showFigureToolBar (! hasUiControlChildren (fp));
-		}
-	    default:
-	      break;
-	    }
+                  showFigureToolBar (! hasUiControlChildren (fp));
+                }
+            default:
+              break;
+            }
         }
       else if (watched == m_menuBar)
         {
-	  switch (event->type ())
-	    {
-	    case QEvent::ActionAdded:
-		{
-		  QAction* a = dynamic_cast<QActionEvent*> (event)->action ();
+          switch (xevent->type ())
+            {
+            case QEvent::ActionAdded:
+                {
+                  QAction* a = dynamic_cast<QActionEvent*> (xevent)->action ();
 
-		  if (! a->isSeparator ()
+                  if (! a->isSeparator ()
                       && a->objectName () != "builtinMenu")
                     updateMenuBar ();
-		}
-	      break;
-	    default:
-	      break;
-	    }
+                }
+              break;
+            default:
+              break;
+            }
         }
       else
         {
-	  switch (event->type ())
-	    {
-	    case QEvent::Move:
-	      updateBoundingBox (false, UpdateBoundingBoxPosition);
-	      updateBoundingBox (true, UpdateBoundingBoxPosition);
-	      break;
-	    case QEvent::Resize:
-	      updateBoundingBox (false, UpdateBoundingBoxSize);
-	      break;
-	    default:
-	      break;
-	    }
+          switch (xevent->type ())
+            {
+            case QEvent::Move:
+              updateBoundingBox (false, UpdateBoundingBoxPosition);
+              updateBoundingBox (true, UpdateBoundingBoxPosition);
+              break;
+            case QEvent::Resize:
+              updateBoundingBox (false, UpdateBoundingBoxSize);
+              break;
+            default:
+              break;
+            }
         }
     }
 }
@@ -597,7 +597,7 @@
 void Figure::helpAboutQtHandles (void)
 {
   QMessageBox::about (qWidget<QMainWindow> (), tr ("About QtHandles"),
-		      ABOUT_TEXT);
+                      ABOUT_TEXT);
 }
 
 void Figure::fileNewFigure (void)
@@ -656,9 +656,9 @@
       QRect r = win->geometry ();
 
       if (visible)
-	r.adjust (0, -sz.height (), 0, 0);
+        r.adjust (0, -sz.height (), 0, 0);
       else
-	r.adjust (0, sz.height (), 0, 0);
+        r.adjust (0, sz.height (), 0, 0);
 
       m_blockUpdates = true;
       win->setGeometry (r);
--- a/libgui/graphics/Figure.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/graphics/Figure.h	Mon Jan 12 09:17:35 2015 -0800
@@ -37,11 +37,11 @@
 
 enum MouseMode
 {
-  NoMode	= 0,
-  RotateMode	= 1,
-  ZoomMode	= 2,
-  PanMode	= 3,
-  SelectMode	= 4
+  NoMode        = 0,
+  RotateMode    = 1,
+  ZoomMode      = 2,
+  PanMode       = 3,
+  SelectMode    = 4
 };
 
 class Container;
--- a/libgui/graphics/FigureWindow.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/graphics/FigureWindow.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -31,8 +31,8 @@
 namespace QtHandles
 {
 
-FigureWindow::FigureWindow (QWidget* parent)
-  : FigureWindowBase (parent)
+FigureWindow::FigureWindow (QWidget* xparent)
+  : FigureWindowBase (xparent)
 {
 }
 
--- a/libgui/graphics/GLCanvas.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/graphics/GLCanvas.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -37,8 +37,8 @@
 namespace QtHandles
 {
 
-GLCanvas::GLCanvas (QWidget* parent, const graphics_handle& handle)
-  : QGLWidget (parent), Canvas (handle)
+GLCanvas::GLCanvas (QWidget* xparent, const graphics_handle& xhandle)
+  : QGLWidget (xparent), Canvas (xhandle)
 {
   setFocusPolicy (Qt::ClickFocus);
 }
@@ -47,9 +47,9 @@
 {
 }
 
-void GLCanvas::draw (const graphics_handle& handle)
+void GLCanvas::draw (const graphics_handle& xhandle)
 {
-  graphics_object go = gh_manager::get_object (handle);
+  graphics_object go = gh_manager::get_object (xhandle);
 
   if (go)
     {
@@ -119,31 +119,31 @@
   canvasPaintEvent ();
 }
 
-void GLCanvas::mouseMoveEvent (QMouseEvent* event)
+void GLCanvas::mouseMoveEvent (QMouseEvent* xevent)
 {
-  canvasMouseMoveEvent (event);
+  canvasMouseMoveEvent (xevent);
 }
 
-void GLCanvas::mousePressEvent (QMouseEvent* event)
+void GLCanvas::mousePressEvent (QMouseEvent* xevent)
 {
-  canvasMousePressEvent (event);
+  canvasMousePressEvent (xevent);
 }
 
-void GLCanvas::mouseReleaseEvent (QMouseEvent* event)
+void GLCanvas::mouseReleaseEvent (QMouseEvent* xevent)
 {
-  canvasMouseReleaseEvent (event);
+  canvasMouseReleaseEvent (xevent);
 }
 
-void GLCanvas::keyPressEvent (QKeyEvent* event)
+void GLCanvas::keyPressEvent (QKeyEvent* xevent)
 {
-  if (! canvasKeyPressEvent (event))
-    QGLWidget::keyPressEvent (event);
+  if (! canvasKeyPressEvent (xevent))
+    QGLWidget::keyPressEvent (xevent);
 }
 
-void GLCanvas::keyReleaseEvent (QKeyEvent* event)
+void GLCanvas::keyReleaseEvent (QKeyEvent* xevent)
 {
-  if (! canvasKeyReleaseEvent (event))
-    QGLWidget::keyReleaseEvent (event);
+  if (! canvasKeyReleaseEvent (xevent))
+    QGLWidget::keyReleaseEvent (xevent);
 }
 
 }; // namespace QtHandles
--- a/libgui/graphics/GLCanvas.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/graphics/GLCanvas.h	Mon Jan 12 09:17:35 2015 -0800
@@ -39,7 +39,7 @@
   void draw (const graphics_handle& handle);
   void drawZoomBox (const QPoint& p1, const QPoint& p2);
   void resize (int /* x */, int /* y */,
-	       int /* width */, int /* height */) { }
+               int /* width */, int /* height */) { }
   graphics_object selectFromAxes (const graphics_object& ax,
                                   const QPoint& pt);
   QWidget* qWidget (void) { return this; }
--- a/libgui/graphics/GenericEventNotify.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/graphics/GenericEventNotify.h	Mon Jan 12 09:17:35 2015 -0800
@@ -86,7 +86,7 @@
 class T : public B, public GenericEventNotifySender \
 { \
 public: \
-  T (QWidget* parent) : B (parent), GenericEventNotifySender () { } \
+  T (QWidget* xparent) : B (xparent), GenericEventNotifySender () { } \
   ~ T (void) { } \
 \
   bool event (QEvent* evt) \
--- a/libgui/graphics/ListBoxControl.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/graphics/ListBoxControl.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -69,7 +69,7 @@
       Container* container = parent->innerContainer ();
 
       if (container)
-	return new ListBoxControl (go, new QListWidget (container));
+        return new ListBoxControl (go, new QListWidget (container));
     }
 
   return 0;
@@ -92,25 +92,25 @@
       int lc = list->count ();
 
       for (octave_idx_type i = 0; i < n; i++)
-	{
-	  int idx = xround (value(i));
+        {
+          int idx = xround (value(i));
 
-	  if (1 <= idx && idx <= lc)
-	    {
-	      list->item (idx-1)->setSelected (true);
-	      if (i == 0
-		  && list->selectionMode () ==
-		  	QAbstractItemView::SingleSelection)
-		break;
-	    }
-	}
+          if (1 <= idx && idx <= lc)
+            {
+              list->item (idx-1)->setSelected (true);
+              if (i == 0
+                  && list->selectionMode () ==
+                        QAbstractItemView::SingleSelection)
+                break;
+            }
+        }
     }
 
   list->removeEventFilter (this);
   list->viewport ()->installEventFilter (this);
 
   connect (list, SIGNAL (itemSelectionChanged (void)),
-	   SLOT (itemSelectionChanged (void)));
+           SLOT (itemSelectionChanged (void)));
 }
 
 ListBoxControl::~ListBoxControl (void)
@@ -134,9 +134,9 @@
     case uicontrol::properties::ID_MIN:
     case uicontrol::properties::ID_MAX:
       if ((up.get_max () - up.get_min ()) > 1)
-	list->setSelectionMode (QAbstractItemView::ExtendedSelection);
+        list->setSelectionMode (QAbstractItemView::ExtendedSelection);
       else
-	list->setSelectionMode (QAbstractItemView::SingleSelection);
+        list->setSelectionMode (QAbstractItemView::SingleSelection);
       break;
     case uicontrol::properties::ID_VALUE:
       m_blockCallback = true;
--- a/libgui/graphics/Menu.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/graphics/Menu.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -46,11 +46,11 @@
       int keyMod = Qt::CTRL;
 
       if (c >= 'A' && c <= 'Z')
-	keyMod |= Qt::SHIFT;
+        keyMod |= Qt::SHIFT;
       if (c >= 'a' && c <= 'z')
-	c -= ('a' - 'A');
+        c -= ('a' - 'A');
       if (c >= 'A' && c <= 'Z')
-	return QKeySequence (keyMod | static_cast<int> (c));
+        return QKeySequence (keyMod | static_cast<int> (c));
     }
 
   return QKeySequence ();
@@ -65,13 +65,13 @@
       QObject* qObj = parent->qObject ();
 
       if (qObj)
-	return new Menu (go, new QAction (qObj), parent);
+        return new Menu (go, new QAction (qObj), parent);
     }
 
   return 0;
 }
 
-Menu::Menu (const graphics_object& go, QAction* action, Object* parent)
+Menu::Menu (const graphics_object& go, QAction* action, Object* xparent)
     : Object (go, action), m_parent (0), m_separator (0)
 {
   uimenu::properties& up = properties<uimenu> ();
@@ -92,7 +92,7 @@
       m_separator->setVisible (up.is_visible ());
     }
 
-  MenuContainer* menuContainer = dynamic_cast<MenuContainer*> (parent);
+  MenuContainer* menuContainer = dynamic_cast<MenuContainer*> (xparent);
 
   if (menuContainer)
     m_parent = menuContainer->menu ();
@@ -102,46 +102,46 @@
       int pos = static_cast<int> (up.get_position ());
 
       if (pos <= 0)
-	{
-	  if (m_separator)
-	    m_parent->insertAction (0, m_separator);
-	  m_parent->insertAction (0, action);
+        {
+          if (m_separator)
+            m_parent->insertAction (0, m_separator);
+          m_parent->insertAction (0, action);
 
-	  int count = 0;
+          int count = 0;
 
-	  foreach (QAction* a, m_parent->actions ())
-	    if (! a->isSeparator () && a->objectName () != "builtinMenu")
-	      count++;
-	  up.get_property ("position").set
-	    (octave_value (static_cast<double> (count)), true, false);
-	}
+          foreach (QAction* a, m_parent->actions ())
+            if (! a->isSeparator () && a->objectName () != "builtinMenu")
+              count++;
+          up.get_property ("position").set
+            (octave_value (static_cast<double> (count)), true, false);
+        }
       else
-	{
+        {
 
-	  int count = 0;
-	  QAction* before = 0;
+          int count = 0;
+          QAction* before = 0;
 
-	  foreach (QAction* a, m_parent->actions ())
-	    if (! a->isSeparator () && a->objectName () != "builtinMenu")
-	      {
-		count++;
-		if (pos <= count)
-		  {
-		    before = a;
-		    break;
-		  }
-	      }
+          foreach (QAction* a, m_parent->actions ())
+            if (! a->isSeparator () && a->objectName () != "builtinMenu")
+              {
+                count++;
+                if (pos <= count)
+                  {
+                    before = a;
+                    break;
+                  }
+              }
 
-	  if (m_separator)
-	    m_parent->insertAction (before, m_separator);
-	  m_parent->insertAction (before, action);
+          if (m_separator)
+            m_parent->insertAction (before, m_separator);
+          m_parent->insertAction (before, action);
 
-	  if (before)
-	    updateSiblingPositions ();
-	  else
-	    up.get_property ("position").set
-	      (octave_value (static_cast<double> (count+1)), true, false);
-	}
+          if (before)
+            updateSiblingPositions ();
+          else
+            up.get_property ("position").set
+              (octave_value (static_cast<double> (count+1)), true, false);
+        }
     }
 
   connect (action, SIGNAL (triggered (bool)), SLOT (actionTriggered (void)));
@@ -163,76 +163,76 @@
       break;
     case uimenu::properties::ID_CHECKED:
       if (up.is_checked ())
-	{
-	  action->setCheckable (true);
-	  action->setChecked (up.is_checked ());
-	}
+        {
+          action->setCheckable (true);
+          action->setChecked (up.is_checked ());
+        }
       else
-	{
-	  action->setChecked (false);
-	  action->setCheckable (false);
-	}
+        {
+          action->setChecked (false);
+          action->setCheckable (false);
+        }
       break;
     case uimenu::properties::ID_ENABLE:
       action->setEnabled (up.is_enable ());
       break;
     case uimenu::properties::ID_ACCELERATOR:
       if (! action->menu ())
-	action->setShortcut (accelSequence (up));
+        action->setShortcut (accelSequence (up));
       break;
     case uimenu::properties::ID_SEPARATOR:
       if (up.is_separator ())
-	{
-	  if (! m_separator)
-	    {
-	      m_separator = new QAction (action);
-	      m_separator->setSeparator (true);
-	      m_separator->setVisible (up.is_visible ());
-	      if (m_parent)
-		m_parent->insertAction (action, m_separator);
-	    }
-	}
+        {
+          if (! m_separator)
+            {
+              m_separator = new QAction (action);
+              m_separator->setSeparator (true);
+              m_separator->setVisible (up.is_visible ());
+              if (m_parent)
+                m_parent->insertAction (action, m_separator);
+            }
+        }
       else
-	{
-	  if (m_separator)
-	    delete m_separator;
-	  m_separator = 0;
-	}
+        {
+          if (m_separator)
+            delete m_separator;
+          m_separator = 0;
+        }
       break;
     case uimenu::properties::ID_VISIBLE:
       action->setVisible (up.is_visible ());
       if (m_separator)
-	m_separator->setVisible (up.is_visible ());
+        m_separator->setVisible (up.is_visible ());
       break;
     case uimenu::properties::ID_POSITION:
       if (m_separator)
-	m_parent->removeAction (m_separator);
+        m_parent->removeAction (m_separator);
       m_parent->removeAction (action);
-	{
-	  int pos = static_cast<int> (up.get_position ());
-	  QAction* before = 0;
+        {
+          int pos = static_cast<int> (up.get_position ());
+          QAction* before = 0;
 
-	  if (pos > 0)
-	    {
-	      int count = 0;
+          if (pos > 0)
+            {
+              int count = 0;
 
-	      foreach (QAction* a, m_parent->actions ())
-		if (! a->isSeparator () && a->objectName () != "builtinMenu")
-		  {
-		    count++;
-		    if (pos <= count)
-		      {
-			before = a;
-			break;
-		      }
-		  }
-	    }
+              foreach (QAction* a, m_parent->actions ())
+                if (! a->isSeparator () && a->objectName () != "builtinMenu")
+                  {
+                    count++;
+                    if (pos <= count)
+                      {
+                        before = a;
+                        break;
+                      }
+                  }
+            }
 
-	  if (m_separator)
-	    m_parent->insertAction (before, m_separator);
-	  m_parent->insertAction (before, action);
-	  updateSiblingPositions ();
-	}
+          if (m_separator)
+            m_parent->insertAction (before, m_separator);
+          m_parent->insertAction (before, action);
+          updateSiblingPositions ();
+        }
       break;
     default:
       Object::update (pId);
@@ -251,7 +251,7 @@
       action->setMenu (_menu);
       action->setShortcut (QKeySequence ());
       connect (_menu, SIGNAL (aboutToShow (void)),
-	       this, SLOT (actionHovered (void)));
+               this, SLOT (actionHovered (void)));
     }
 
   return _menu;
@@ -278,29 +278,29 @@
       double count = 1.0;
 
       foreach (QAction* a, m_parent->actions ())
-	{
-	  if (! a->isSeparator () && a->objectName () != "builtinMenu")
-	    {
-	      Object* aObj = Object::fromQObject (a);
+        {
+          if (! a->isSeparator () && a->objectName () != "builtinMenu")
+            {
+              Object* aObj = Object::fromQObject (a);
 
-	      if (aObj)
-		{
-		  graphics_object go = aObj->object ();
+              if (aObj)
+                {
+                  graphics_object go = aObj->object ();
 
-		  // Probably overkill as a uimenu child can only be another
-		  // uimenu object.
-		  if (go.isa ("uimenu"))
-		    {
-		      uimenu::properties& up = Utils::properties<uimenu> (go);
+                  // Probably overkill as a uimenu child can only be another
+                  // uimenu object.
+                  if (go.isa ("uimenu"))
+                    {
+                      uimenu::properties& up = Utils::properties<uimenu> (go);
 
-		      up.get_property ("position").set
-			(octave_value (count), true, false);
-		    }
-		}
+                      up.get_property ("position").set
+                        (octave_value (count), true, false);
+                    }
+                }
 
-	      count++;
-	    }
-	}
+              count++;
+            }
+        }
     }
 }
 
--- a/libgui/graphics/MouseModeActionGroup.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/graphics/MouseModeActionGroup.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -33,17 +33,17 @@
 namespace QtHandles
 {
 
-MouseModeActionGroup::MouseModeActionGroup (QObject* parent)
-  : QObject (parent), m_current (0)
+MouseModeActionGroup::MouseModeActionGroup (QObject* xparent)
+  : QObject (xparent), m_current (0)
 {
   m_actions.append (new QAction (QIcon (":/images/rotate.png"),
-				 tr ("Rotate"), this));
+                                 tr ("Rotate"), this));
   m_actions.append (new QAction (QIcon (":/images/zoom.png"),
-				 tr ("Zoom"), this));
+                                 tr ("Zoom"), this));
   m_actions.append (new QAction (QIcon (":/images/pan.png"),
-				 tr ("Pan"), this));
+                                 tr ("Pan"), this));
   m_actions.append (new QAction (QIcon (":/images/select.png"),
-				 tr ("Select"), this));
+                                 tr ("Select"), this));
   m_actions[2]->setEnabled (false);
   m_actions[3]->setEnabled (false);
 
@@ -63,23 +63,23 @@
   if (! checked)
     {
       if (sender () == m_current)
-	{
-	  m_current = 0;
-	  emit modeChanged (NoMode);
-	}
+        {
+          m_current = 0;
+          emit modeChanged (NoMode);
+        }
     }
   else
     {
       int i = m_actions.indexOf (qobject_cast<QAction*> (sender ()));
 
       if (i >= 0)
-	{
-	  m_current = m_actions[i];
-	  for (int j = 0; j < m_actions.size (); j++)
-	    if (j != i)
-	      m_actions[j]->setChecked (false);
-	  emit modeChanged (static_cast<MouseMode> (i+1));
-	}
+        {
+          m_current = m_actions[i];
+          for (int j = 0; j < m_actions.size (); j++)
+            if (j != i)
+              m_actions[j]->setChecked (false);
+          emit modeChanged (static_cast<MouseMode> (i+1));
+        }
     }
 }
 
--- a/libgui/graphics/Object.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/graphics/Object.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -40,8 +40,8 @@
 
   if (! lock)
     qCritical ("QtHandles::Object::Object: "
-	       "creating Object (h=%g) without a valid lock!!!",
-	       m_handle.value ());
+               "creating Object (h=%g) without a valid lock!!!",
+               m_handle.value ());
 
   init (obj);
 }
@@ -50,16 +50,16 @@
 {
   if (m_qobject)
     qCritical ("QtHandles::Object::init: "
-	       "resetting QObject while in invalid state");
+               "resetting QObject while in invalid state");
 
   m_qobject = obj;
 
   if (m_qobject)
     {
       m_qobject->setProperty ("QtHandles::Object",
-			      qVariantFromValue<void*> (this));
+                              qVariantFromValue<void*> (this));
       connect (m_qobject, SIGNAL (destroyed (QObject*)),
-	       SLOT (objectDestroyed (QObject*)));
+               SLOT (objectDestroyed (QObject*)));
     }
 }
 
@@ -73,8 +73,8 @@
 
   if (! lock)
     qCritical ("QtHandles::Object::object: "
-	       "accessing graphics object (h=%g) without a valid lock!!!",
-	       m_handle.value ());
+               "accessing graphics object (h=%g) without a valid lock!!!",
+               m_handle.value ());
 
   return gh_manager::get_object (m_handle);
 }
@@ -93,7 +93,7 @@
       break;
     default:
       if (object ().valid_object ())
-	update (pId);
+        update (pId);
       break;
     }
 }
--- a/libgui/graphics/Object.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/graphics/Object.h	Mon Jan 12 09:17:35 2015 -0800
@@ -55,14 +55,14 @@
   typename T::properties& properties (void)
     {
       return dynamic_cast<typename T::properties&>
-	(object ().get_properties ());
+        (object ().get_properties ());
     }
   
   template <class T>
   const typename T::properties& properties (void) const
     {
       return dynamic_cast<const typename T::properties&>
-	(object ().get_properties ());
+        (object ().get_properties ());
     }
 
   graphics_object object (void) const;
--- a/libgui/graphics/ObjectFactory.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/graphics/ObjectFactory.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -62,7 +62,7 @@
   if (! s_instanceCreated)
     {
       if (QThread::currentThread () != QApplication::instance ()->thread ())
-	s_instance.moveToThread (QApplication::instance ()->thread ());
+        s_instance.moveToThread (QApplication::instance ()->thread ());
       s_instanceCreated = true;
     }
 
@@ -78,72 +78,72 @@
   if (go.valid_object ())
     {
       if (go.get_properties ().is_beingdeleted ())
-	qWarning ("ObjectFactory::createObject: object is being deleted");
+        qWarning ("ObjectFactory::createObject: object is being deleted");
       else
-	{
-	  ObjectProxy* proxy = Backend::toolkitObjectProxy (go);
+        {
+          ObjectProxy* proxy = Backend::toolkitObjectProxy (go);
 
-	  if (proxy)
-	    {
-	      Logger::debug ("ObjectFactory::createObject: "
-			     "create %s from thread %08x",
-			     go.type ().c_str (), QThread::currentThreadId ());
+          if (proxy)
+            {
+              Logger::debug ("ObjectFactory::createObject: "
+                             "create %s from thread %08x",
+                             go.type ().c_str (), QThread::currentThreadId ());
 
-	      Object* obj = 0;
+              Object* obj = 0;
 
-	      if (go.isa ("figure"))
-		obj = Figure::create (go);
-	      else if (go.isa ("uicontrol"))
-		{
-		  uicontrol::properties& up =
-		   Utils::properties<uicontrol> (go);
+              if (go.isa ("figure"))
+                obj = Figure::create (go);
+              else if (go.isa ("uicontrol"))
+                {
+                  uicontrol::properties& up =
+                   Utils::properties<uicontrol> (go);
 
-		  if (up.style_is ("pushbutton"))
-		    obj = PushButtonControl::create (go);
-		  else if (up.style_is ("edit"))
-		    obj = EditControl::create (go);
-		  else if (up.style_is ("checkbox"))
-		    obj = CheckBoxControl::create (go);
-		  else if (up.style_is ("radiobutton"))
-		    obj = RadioButtonControl::create (go);
-		  else if (up.style_is ("togglebutton"))
-		    obj = ToggleButtonControl::create (go);
-		  else if (up.style_is ("text"))
-		    obj = TextControl::create (go);
-		  else if (up.style_is ("popupmenu"))
-		    obj = PopupMenuControl::create (go);
-		  else if (up.style_is ("slider"))
-		    obj = SliderControl::create (go);
-		  else if (up.style_is ("listbox"))
-		    obj = ListBoxControl::create (go);
-		}
-	      else if (go.isa ("uipanel"))
-		obj = Panel::create (go);
-	      else if (go.isa ("uimenu"))
-		obj = Menu::create (go);
-	      else if (go.isa ("uicontextmenu"))
-		obj = ContextMenu::create (go);
-	      else if (go.isa ("uitoolbar"))
-		obj = ToolBar::create (go);
-	      else if (go.isa ("uipushtool"))
-		obj = PushTool::create (go);
-	      else if (go.isa ("uitoggletool"))
-		obj = ToggleTool::create (go);
-	      else
-		qWarning ("ObjectFactory::createObject: unsupported type `%s'",
-			  go.type ().c_str ());
+                  if (up.style_is ("pushbutton"))
+                    obj = PushButtonControl::create (go);
+                  else if (up.style_is ("edit"))
+                    obj = EditControl::create (go);
+                  else if (up.style_is ("checkbox"))
+                    obj = CheckBoxControl::create (go);
+                  else if (up.style_is ("radiobutton"))
+                    obj = RadioButtonControl::create (go);
+                  else if (up.style_is ("togglebutton"))
+                    obj = ToggleButtonControl::create (go);
+                  else if (up.style_is ("text"))
+                    obj = TextControl::create (go);
+                  else if (up.style_is ("popupmenu"))
+                    obj = PopupMenuControl::create (go);
+                  else if (up.style_is ("slider"))
+                    obj = SliderControl::create (go);
+                  else if (up.style_is ("listbox"))
+                    obj = ListBoxControl::create (go);
+                }
+              else if (go.isa ("uipanel"))
+                obj = Panel::create (go);
+              else if (go.isa ("uimenu"))
+                obj = Menu::create (go);
+              else if (go.isa ("uicontextmenu"))
+                obj = ContextMenu::create (go);
+              else if (go.isa ("uitoolbar"))
+                obj = ToolBar::create (go);
+              else if (go.isa ("uipushtool"))
+                obj = PushTool::create (go);
+              else if (go.isa ("uitoggletool"))
+                obj = ToggleTool::create (go);
+              else
+                qWarning ("ObjectFactory::createObject: unsupported type `%s'",
+                          go.type ().c_str ());
 
-	      if (obj)
-		proxy->setObject (obj);
-	    }
-	  else
-	    qWarning ("ObjectFactory::createObject: no proxy for handle %g",
-		      handle);
-	}
+              if (obj)
+                proxy->setObject (obj);
+            }
+          else
+            qWarning ("ObjectFactory::createObject: no proxy for handle %g",
+                      handle);
+        }
     }
   else
     qWarning ("ObjectFactory::createObject: invalid object for handle %g",
-	      handle);
+              handle);
 }
 
 };
--- a/libgui/graphics/ObjectProxy.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/graphics/ObjectProxy.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -43,26 +43,26 @@
   if (obj != m_object)
     {
       if (m_object)
-	{
-	  disconnect (this, SIGNAL (sendUpdate (int)),
-		      m_object, SLOT (slotUpdate (int)));
-	  disconnect (this, SIGNAL (sendFinalize (void)),
-		      m_object, SLOT (slotFinalize (void)));
-	  disconnect (this, SIGNAL (sendRedraw (void)),
-		      m_object, SLOT (slotRedraw (void)));
-	}
+        {
+          disconnect (this, SIGNAL (sendUpdate (int)),
+                      m_object, SLOT (slotUpdate (int)));
+          disconnect (this, SIGNAL (sendFinalize (void)),
+                      m_object, SLOT (slotFinalize (void)));
+          disconnect (this, SIGNAL (sendRedraw (void)),
+                      m_object, SLOT (slotRedraw (void)));
+        }
 
       m_object = obj;
 
       if (m_object)
-	{
-	  connect (this, SIGNAL (sendUpdate (int)),
-		   m_object, SLOT (slotUpdate (int)));
-	  connect (this, SIGNAL (sendFinalize (void)),
-		   m_object, SLOT (slotFinalize (void)));
-	  connect (this, SIGNAL (sendRedraw (void)),
-		   m_object, SLOT (slotRedraw (void)));
-	}
+        {
+          connect (this, SIGNAL (sendUpdate (int)),
+                   m_object, SLOT (slotUpdate (int)));
+          connect (this, SIGNAL (sendFinalize (void)),
+                   m_object, SLOT (slotFinalize (void)));
+          connect (this, SIGNAL (sendRedraw (void)),
+                   m_object, SLOT (slotRedraw (void)));
+        }
     }
 }
 
--- a/libgui/graphics/Panel.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/graphics/Panel.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -58,13 +58,13 @@
 static void setupPalette (const uipanel::properties& pp, QPalette& p)
 {
   p.setColor (QPalette::Window,
-	      Utils::fromRgb (pp.get_backgroundcolor_rgb ()));
+              Utils::fromRgb (pp.get_backgroundcolor_rgb ()));
   p.setColor (QPalette::WindowText,
-	      Utils::fromRgb (pp.get_foregroundcolor_rgb ()));
+              Utils::fromRgb (pp.get_foregroundcolor_rgb ()));
   p.setColor (QPalette::Light,
-	      Utils::fromRgb (pp.get_highlightcolor_rgb ()));
+              Utils::fromRgb (pp.get_highlightcolor_rgb ()));
   p.setColor (QPalette::Dark,
-	      Utils::fromRgb (pp.get_shadowcolor_rgb ()));
+              Utils::fromRgb (pp.get_shadowcolor_rgb ()));
 }
 
 static int borderWidthFromProperties (const uipanel::properties& pp)
@@ -75,7 +75,7 @@
     {
       bw = xround (pp.get_borderwidth ());
       if (pp.bordertype_is ("etchedin") || pp.bordertype_is ("etchedout"))
-	bw *= 2;
+        bw *= 2;
     }
 
   return bw;
@@ -90,7 +90,7 @@
       Container* container = parent->innerContainer ();
 
       if (container)
-	return new Panel (go, new QFrame (container));
+        return new Panel (go, new QFrame (container));
     }
 
   return 0;
@@ -105,7 +105,7 @@
   frame->setAutoFillBackground (true);
   Matrix bb = pp.get_boundingbox (false);
   frame->setGeometry (xround (bb(0)), xround (bb(1)),
-		      xround (bb(2)), xround (bb(3)));
+                      xround (bb(2)), xround (bb(3)));
   frame->setFrameStyle (frameStyleFromProperties (pp));
   frame->setLineWidth (xround (pp.get_borderwidth ()));
   QPalette pal = frame->palette ();
@@ -144,71 +144,71 @@
 {
 }
 
-bool Panel::eventFilter (QObject* watched, QEvent* event)
+bool Panel::eventFilter (QObject* watched, QEvent* xevent)
 {
   if (! m_blockUpdates)
     {
       if (watched == qObject ())
-	{
-	  switch (event->type ())
-	    {
-	    case QEvent::Resize:
-		{
-		  gh_manager::auto_lock lock;
-		  graphics_object go = object ();
+        {
+          switch (xevent->type ())
+            {
+            case QEvent::Resize:
+                {
+                  gh_manager::auto_lock lock;
+                  graphics_object go = object ();
 
-		  if (go.valid_object ())
-		    {
-		      if (m_title)
-			{
-			  const uipanel::properties& pp =
-			    Utils::properties<uipanel> (go);
+                  if (go.valid_object ())
+                    {
+                      if (m_title)
+                        {
+                          const uipanel::properties& pp =
+                            Utils::properties<uipanel> (go);
 
-			  if (pp.fontunits_is ("normalized"))
-			    {
-			      QFrame* frame = qWidget<QFrame> ();
+                          if (pp.fontunits_is ("normalized"))
+                            {
+                              QFrame* frame = qWidget<QFrame> ();
 
-			      m_title->setFont (Utils::computeFont<uipanel>
-						(pp, frame->height ()));
-			      m_title->resize (m_title->sizeHint ());
-			    }
-			}
-		      updateLayout ();
-		    }
-		}
-	      break;
-	    case QEvent::MouseButtonPress:
-		{
-		  QMouseEvent* m = dynamic_cast<QMouseEvent*> (event);
+                              m_title->setFont (Utils::computeFont<uipanel>
+                                                (pp, frame->height ()));
+                              m_title->resize (m_title->sizeHint ());
+                            }
+                        }
+                      updateLayout ();
+                    }
+                }
+              break;
+            case QEvent::MouseButtonPress:
+                {
+                  QMouseEvent* m = dynamic_cast<QMouseEvent*> (xevent);
 
-		  if (m->button () == Qt::RightButton)
-		    {
-		      gh_manager::auto_lock lock;
+                  if (m->button () == Qt::RightButton)
+                    {
+                      gh_manager::auto_lock lock;
 
-		      ContextMenu::executeAt (properties (), m->globalPos ());
-		    }
-		}
-	      break;
-	    default:
-	      break;
-	    }
-	}
+                      ContextMenu::executeAt (properties (), m->globalPos ());
+                    }
+                }
+              break;
+            default:
+              break;
+            }
+        }
       else if (watched == m_container)
-	{
-	  switch (event->type ())
-	    {
-	    case QEvent::Resize:
-	      if (qWidget<QWidget> ()->isVisible ())
-		{
-		  gh_manager::auto_lock lock;
+        {
+          switch (xevent->type ())
+            {
+            case QEvent::Resize:
+              if (qWidget<QWidget> ()->isVisible ())
+                {
+                  gh_manager::auto_lock lock;
 
-		  properties ().update_boundingbox ();
-		}
-	      break;
-	    default:
-	      break;
-	    }
-	}
+                  properties ().update_boundingbox ();
+                }
+              break;
+            default:
+              break;
+            }
+        }
     }
 
   return false;
@@ -224,13 +224,13 @@
   switch (pId)
     {
     case uipanel::properties::ID_POSITION:
-	{
-	  Matrix bb = pp.get_boundingbox (false);
+        {
+          Matrix bb = pp.get_boundingbox (false);
 
-	  frame->setGeometry (xround (bb(0)), xround (bb(1)),
-			      xround (bb(2)), xround (bb(3)));
-	  updateLayout ();
-	}
+          frame->setGeometry (xround (bb(0)), xround (bb(1)),
+                              xround (bb(2)), xround (bb(3)));
+          updateLayout ();
+        }
       break;
     case uipanel::properties::ID_BORDERWIDTH:
       frame->setLineWidth (xround (pp.get_borderwidth ()));
@@ -240,46 +240,46 @@
     case uipanel::properties::ID_FOREGROUNDCOLOR:
     case uipanel::properties::ID_HIGHLIGHTCOLOR:
     case uipanel::properties::ID_SHADOWCOLOR:
-	{
-	  QPalette pal = frame->palette ();
+        {
+          QPalette pal = frame->palette ();
 
-	  setupPalette (pp, pal);
-	  frame->setPalette (pal);
-	  if (m_title)
-	    m_title->setPalette (pal);
-	}
+          setupPalette (pp, pal);
+          frame->setPalette (pal);
+          if (m_title)
+            m_title->setPalette (pal);
+        }
       break;
     case uipanel::properties::ID_TITLE:
-	{
-	  QString title = Utils::fromStdString (pp.get_title ());
+        {
+          QString title = Utils::fromStdString (pp.get_title ());
 
-	  if (title.isEmpty ())
-	    {
-	      if (m_title)
-		delete m_title;
-	      m_title = 0;
-	    }
-	  else
-	    {
-	      if (! m_title)
-		{
-		  QPalette pal = frame->palette ();
+          if (title.isEmpty ())
+            {
+              if (m_title)
+                delete m_title;
+              m_title = 0;
+            }
+          else
+            {
+              if (! m_title)
+                {
+                  QPalette pal = frame->palette ();
 
-		  m_title = new QLabel (title, frame);
-		  m_title->setAutoFillBackground (true);
-		  m_title->setContentsMargins (4, 0, 4, 0);
-		  m_title->setPalette (pal);
-		  m_title->setFont (Utils::computeFont<uipanel> (pp));
-		  m_title->show ();
-		}
-	      else
-		{
-		  m_title->setText (title);
-		  m_title->resize (m_title->sizeHint ());
-		}
-	    }
-	  updateLayout ();
-	}
+                  m_title = new QLabel (title, frame);
+                  m_title->setAutoFillBackground (true);
+                  m_title->setContentsMargins (4, 0, 4, 0);
+                  m_title->setPalette (pal);
+                  m_title->setFont (Utils::computeFont<uipanel> (pp));
+                  m_title->show ();
+                }
+              else
+                {
+                  m_title->setText (title);
+                  m_title->resize (m_title->sizeHint ());
+                }
+            }
+          updateLayout ();
+        }
     case uipanel::properties::ID_TITLEPOSITION:
       updateLayout ();
       break;
@@ -292,11 +292,11 @@
     case uipanel::properties::ID_FONTWEIGHT:
     case uipanel::properties::ID_FONTANGLE:
       if (m_title)
-	{
-	  m_title->setFont (Utils::computeFont<uipanel> (pp));
-	  m_title->resize (m_title->sizeHint ());
-	  updateLayout ();
-	}
+        {
+          m_title->setFont (Utils::computeFont<uipanel> (pp));
+          m_title->resize (m_title->sizeHint ());
+          updateLayout ();
+        }
       break;
     case uipanel::properties::ID_VISIBLE:
       frame->setVisible (pp.is_visible ());
@@ -326,9 +326,9 @@
   int bw = borderWidthFromProperties (pp);
 
   frame->setFrameRect (QRect (xround (bb(0)) - bw, xround (bb(1)) - bw,
-			      xround (bb(2)) + 2*bw, xround (bb(3)) + 2*bw));
+                              xround (bb(2)) + 2*bw, xround (bb(3)) + 2*bw));
   m_container->setGeometry (xround (bb(0)), xround (bb(1)),
-			    xround (bb(2)), xround (bb(3)));
+                            xround (bb(2)), xround (bb(3)));
 
   if (m_blockUpdates)
     pp.update_boundingbox ();
@@ -339,19 +339,19 @@
       int offset = 5;
 
       if (pp.titleposition_is ("lefttop"))
-	m_title->move (bw+offset, 0);
+        m_title->move (bw+offset, 0);
       else if (pp.titleposition_is ("righttop"))
-	m_title->move (frame->width () - bw - offset - sz.width (), 0);
+        m_title->move (frame->width () - bw - offset - sz.width (), 0);
       else if (pp.titleposition_is ("leftbottom"))
-	m_title->move (bw+offset, frame->height () - sz.height ());
+        m_title->move (bw+offset, frame->height () - sz.height ());
       else if (pp.titleposition_is ("rightbottom"))
-	m_title->move (frame->width () - bw - offset - sz.width (),
-		       frame->height () - sz.height ());
+        m_title->move (frame->width () - bw - offset - sz.width (),
+                       frame->height () - sz.height ());
       else if (pp.titleposition_is ("centertop"))
-	m_title->move (frame->width () / 2 - sz.width () / 2, 0);
+        m_title->move (frame->width () / 2 - sz.width () / 2, 0);
       else if (pp.titleposition_is ("centerbottom"))
-	m_title->move (frame->width () / 2 - sz.width () / 2,
-		       frame->height () - sz.height ());
+        m_title->move (frame->width () / 2 - sz.width () / 2,
+                       frame->height () - sz.height ());
     }
 }
 
--- a/libgui/graphics/PopupMenuControl.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/graphics/PopupMenuControl.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -42,7 +42,7 @@
       Container* container = parent->innerContainer ();
 
       if (container)
-	return new PopupMenuControl (go, new QComboBox (container));
+        return new PopupMenuControl (go, new QComboBox (container));
     }
 
   return 0;
@@ -56,7 +56,7 @@
   box->addItems (Utils::fromStdString (up.get_string_string ()).split ('|'));
 
   connect (box, SIGNAL (currentIndexChanged (int)),
-	   SLOT (currentIndexChanged (int)));
+           SLOT (currentIndexChanged (int)));
 }
 
 PopupMenuControl::~PopupMenuControl (void)
@@ -72,43 +72,43 @@
     {
     case uicontrol::properties::ID_STRING:
       m_blockUpdate = true;
-	{
-	  int oldCurrent = box->currentIndex ();
+        {
+          int oldCurrent = box->currentIndex ();
 
-	  box->clear ();
-	  box->addItems (Utils::fromStdString
-			 (up.get_string_string ()).split ('|'));
-	  if (box->count() > 0
-	      && oldCurrent >= 0
-	      && oldCurrent < box->count ())
-	    {
-	      box->setCurrentIndex (oldCurrent);
-	    }
-	  else
-	    {
-	      gh_manager::post_set (m_handle, "value",
-				    octave_value (box->count () > 0
-						  ? 1.0 : 0.0),
-				    false);
-	    }
-	}
+          box->clear ();
+          box->addItems (Utils::fromStdString
+                         (up.get_string_string ()).split ('|'));
+          if (box->count() > 0
+              && oldCurrent >= 0
+              && oldCurrent < box->count ())
+            {
+              box->setCurrentIndex (oldCurrent);
+            }
+          else
+            {
+              gh_manager::post_set (m_handle, "value",
+                                    octave_value (box->count () > 0
+                                                  ? 1.0 : 0.0),
+                                    false);
+            }
+        }
       m_blockUpdate = false;
       break;
     case uicontrol::properties::ID_VALUE:
-	{
-	  Matrix value = up.get_value ().matrix_value ();
+        {
+          Matrix value = up.get_value ().matrix_value ();
 
-	  if (value.numel () > 0)
-	    {
-	      int newIndex = int (value(0)) - 1;
+          if (value.numel () > 0)
+            {
+              int newIndex = int (value(0)) - 1;
 
-	      if (newIndex >= 0 && newIndex < box->count ()
-		  && newIndex != box->currentIndex ())
-		{
-		  box->setCurrentIndex (newIndex);
-		}
-	    }
-	}
+              if (newIndex >= 0 && newIndex < box->count ()
+                  && newIndex != box->currentIndex ())
+                {
+                  box->setCurrentIndex (newIndex);
+                }
+            }
+        }
       break;
     default:
       BaseControl::update (pId);
@@ -121,8 +121,8 @@
   if (! m_blockUpdate)
     {
       gh_manager::post_set (m_handle, "value",
-			    octave_value (double (index + 1)),
-			    false);
+                            octave_value (double (index + 1)),
+                            false);
       gh_manager::post_callback (m_handle, "callback");
     }
 }
--- a/libgui/graphics/PushButtonControl.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/graphics/PushButtonControl.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -43,7 +43,7 @@
       Container* container = parent->innerContainer ();
 
       if (container)
-	return new PushButtonControl (go, new QPushButton (container));
+        return new PushButtonControl (go, new QPushButton (container));
     }
 
   return 0;
--- a/libgui/graphics/PushTool.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/graphics/PushTool.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -40,7 +40,7 @@
       QWidget* parentWidget = parent->qWidget<QWidget> ();
 
       if (parentWidget)
-	return new PushTool (go, new QAction (parentWidget));
+        return new PushTool (go, new QAction (parentWidget));
     }
 
   return 0;
--- a/libgui/graphics/QtHandlesUtils.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/graphics/QtHandlesUtils.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -108,9 +108,9 @@
 }
 
 template QFont computeFont<uicontrol> (const uicontrol::properties& props,
-				       int height);
+                                       int height);
 template QFont computeFont<uipanel> (const uipanel::properties& props,
-				     int height);
+                                     int height);
 
 QColor fromRgb (const Matrix& rgb)
 {
@@ -142,26 +142,26 @@
       Qt::KeyboardModifiers mods = event->modifiers ();
 
       if (mods == Qt::NoModifier)
-	{
-	  if (buttons == Qt::LeftButton)
-	    return std::string ("normal");
-	  else if (buttons == Qt::RightButton)
-	    return std::string ("alt");
+        {
+          if (buttons == Qt::LeftButton)
+            return std::string ("normal");
+          else if (buttons == Qt::RightButton)
+            return std::string ("alt");
 #if defined (Q_WS_WIN)
-	  else if (buttons == (Qt::LeftButton|Qt::RightButton))
-	    return std::string ("extend");
+          else if (buttons == (Qt::LeftButton|Qt::RightButton))
+            return std::string ("extend");
 #elif defined (Q_WS_X11)
-	  else if (buttons == Qt::MidButton)
-	    return std::string ("extend");
+          else if (buttons == Qt::MidButton)
+            return std::string ("extend");
 #endif
-	}
+        }
       else if (buttons == Qt::LeftButton)
-	{
-	  if (mods == Qt::ShiftModifier)
-	    return std::string ("extend");
-	  else if (mods == Qt::ControlModifier)
-	    return std::string ("alt");
-	}
+        {
+          if (mods == Qt::ShiftModifier)
+            return std::string ("extend");
+          else if (mods == Qt::ControlModifier)
+            return std::string ("alt");
+        }
     }
 
   return std::string ("normal");
@@ -176,20 +176,20 @@
       Container* c = tkFig->innerContainer ();
 
       if (c)
-	{
-	  QPoint qp = c->mapFromGlobal (event->globalPos ());
+        {
+          QPoint qp = c->mapFromGlobal (event->globalPos ());
 
-	  return
-	    tkFig->properties<figure> ().map_from_boundingbox (qp.x (),
-							       qp.y ());
-	}
+          return
+            tkFig->properties<figure> ().map_from_boundingbox (qp.x (),
+                                                               qp.y ());
+        }
     }
 
   return Matrix (1, 2, 0.0);
 }
 
 Qt::Alignment fromHVAlign (const caseless_str& halign,
-			   const caseless_str& valign)
+                           const caseless_str& valign)
 {
   Qt::Alignment flags;
 
@@ -230,58 +230,58 @@
       img.fill (qRgba (0, 0, 0, 0));
 
       if (v.is_uint8_type ())
-	{
-	  uint8NDArray d = v.uint8_array_value ();
+        {
+          uint8NDArray d = v.uint8_array_value ();
 
-	  for (int i = 0; i < w; i++)
-	    for (int j = 0; j < h; j++)
-	      {
-		int r = d(j, i, 0);
-		int g = d(j, i, 1);
-		int b = d(j, i, 2);
-		int a = 255;
+          for (int i = 0; i < w; i++)
+            for (int j = 0; j < h; j++)
+              {
+                int r = d(j, i, 0);
+                int g = d(j, i, 1);
+                int b = d(j, i, 2);
+                int a = 255;
 
-		img.setPixel (x_off + i, y_off + j, qRgba (r, g, b, a));
-	      }
-	}
+                img.setPixel (x_off + i, y_off + j, qRgba (r, g, b, a));
+              }
+        }
       else if (v.is_single_type ())
-	{
-	  FloatNDArray f = v.float_array_value ();
+        {
+          FloatNDArray f = v.float_array_value ();
 
-	  for (int i = 0; i < w; i++)
-	    for (int j = 0; j < h; j++)
-	      {
-		float r = f(j, i, 0);
-		float g = f(j, i, 1);
-		float b = f(j, i, 2);
-		int a = (xisnan (r) || xisnan (g) || xisnan (b) ? 0 : 255);
+          for (int i = 0; i < w; i++)
+            for (int j = 0; j < h; j++)
+              {
+                float r = f(j, i, 0);
+                float g = f(j, i, 1);
+                float b = f(j, i, 2);
+                int a = (xisnan (r) || xisnan (g) || xisnan (b) ? 0 : 255);
 
-		img.setPixel (x_off + i, y_off + j,
-			      qRgba (xround (r * 255),
-				     xround (g * 255),
-				     xround (b * 255),
-				     a));
-	      }
-	}
+                img.setPixel (x_off + i, y_off + j,
+                              qRgba (xround (r * 255),
+                                     xround (g * 255),
+                                     xround (b * 255),
+                                     a));
+              }
+        }
       else if (v.is_real_type ())
-	{
-	  NDArray d = v.array_value ();
+        {
+          NDArray d = v.array_value ();
 
-	  for (int i = 0; i < w; i++)
-	    for (int j = 0; j < h; j++)
-	      {
-		double r = d(j, i, 0);
-		double g = d(j, i, 1);
-		double b = d(j, i, 2);
-		int a = (xisnan (r) || xisnan (g) || xisnan (b) ? 0 : 255);
+          for (int i = 0; i < w; i++)
+            for (int j = 0; j < h; j++)
+              {
+                double r = d(j, i, 0);
+                double g = d(j, i, 1);
+                double b = d(j, i, 2);
+                int a = (xisnan (r) || xisnan (g) || xisnan (b) ? 0 : 255);
 
-		img.setPixel (x_off + i, y_off + j,
-			      qRgba (xround (r * 255),
-				     xround (g * 255),
-				     xround (b * 255),
-				     a));
-	      }
-	}
+                img.setPixel (x_off + i, y_off + j,
+                              qRgba (xround (r * 255),
+                                     xround (g * 255),
+                                     xround (b * 255),
+                                     a));
+              }
+        }
 
       return img;
     }
--- a/libgui/graphics/QtHandlesUtils.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/graphics/QtHandlesUtils.h	Mon Jan 12 09:17:35 2015 -0800
@@ -54,10 +54,10 @@
   Matrix toRgb (const QColor& c);
 
   Qt::Alignment fromHVAlign (const caseless_str& halign,
-			     const caseless_str& valign);
+                             const caseless_str& valign);
 
   std::string figureSelectionType (QMouseEvent* event,
-				   bool isDoubleClick = false);
+                                   bool isDoubleClick = false);
 
   Matrix figureCurrentPoint (const graphics_object& fig, QMouseEvent* event);
 
@@ -72,7 +72,7 @@
     { return Utils::properties<T> (gh_manager::get_object (h)); }
 
   QImage makeImageFromCData (const octave_value& v, int width = -1,
-			     int height = -1);
+                             int height = -1);
 
   octave_scalar_map makeKeyEventStruct (QKeyEvent* event);
 };
--- a/libgui/graphics/RadioButtonControl.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/graphics/RadioButtonControl.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -42,14 +42,14 @@
       Container* container = parent->innerContainer ();
 
       if (container)
-	return new RadioButtonControl (go, new QRadioButton (container));
+        return new RadioButtonControl (go, new QRadioButton (container));
     }
 
   return 0;
 }
 
 RadioButtonControl::RadioButtonControl (const graphics_object& go,
-					QRadioButton* radio)
+                                        QRadioButton* radio)
     : ButtonControl (go, radio)
 {
   radio->setAutoFillBackground (true);
--- a/libgui/graphics/SliderControl.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/graphics/SliderControl.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -44,14 +44,14 @@
       Container* container = parent->innerContainer ();
 
       if (container)
-	return new SliderControl (go, new QScrollBar (container));
+        return new SliderControl (go, new QScrollBar (container));
     }
 
   return 0;
 }
 
 SliderControl::SliderControl (const graphics_object& go,
-			      QAbstractSlider* slider)
+                              QAbstractSlider* slider)
     : BaseControl (go, slider), m_blockUpdates (false)
 {
   uicontrol::properties& up = properties<uicontrol> ();
@@ -70,7 +70,7 @@
       double dmin = up.get_min (), dmax = up.get_max ();
 
       slider->setValue (xround (((value(0) - dmin) / (dmax - dmin))
-				* RANGE_INT_MAX));
+                                * RANGE_INT_MAX));
     }
 
   connect (slider, SIGNAL (valueChanged (int)), SLOT (valueChanged (int)));
@@ -88,28 +88,28 @@
   switch (pId)
     {
     case uicontrol::properties::ID_SLIDERSTEP:
-	{
-	  Matrix steps = up.get_sliderstep ().matrix_value ();
+        {
+          Matrix steps = up.get_sliderstep ().matrix_value ();
 
-	  slider->setSingleStep (xround (steps(0) * RANGE_INT_MAX));
-	  slider->setPageStep (xround (steps(1) * RANGE_INT_MAX));
-	}
+          slider->setSingleStep (xround (steps(0) * RANGE_INT_MAX));
+          slider->setPageStep (xround (steps(1) * RANGE_INT_MAX));
+        }
       break;
     case uicontrol::properties::ID_VALUE:
-	{
-	  Matrix value = up.get_value ().matrix_value ();
-	  double dmax = up.get_max (), dmin = up.get_min ();
+        {
+          Matrix value = up.get_value ().matrix_value ();
+          double dmax = up.get_max (), dmin = up.get_min ();
 
-	  if (value.numel () > 0)
-	    {
-	      int ival = xround (((value(0) - dmin) / (dmax - dmin))
-				 * RANGE_INT_MAX);
+          if (value.numel () > 0)
+            {
+              int ival = xround (((value(0) - dmin) / (dmax - dmin))
+                                 * RANGE_INT_MAX);
 
-	      m_blockUpdates = true;
-	      slider->setValue (ival);
-	      m_blockUpdates = false;
-	    }
-	}
+              m_blockUpdates = true;
+              slider->setValue (ival);
+              m_blockUpdates = false;
+            }
+        }
       break;
     default:
       BaseControl::update (pId);
@@ -125,25 +125,25 @@
       graphics_object go = object ();
 
       if (go.valid_object ())
-	{
-	  uicontrol::properties& up = Utils::properties<uicontrol> (go);
+        {
+          uicontrol::properties& up = Utils::properties<uicontrol> (go);
 
-	  Matrix value = up.get_value ().matrix_value ();
-	  double dmin = up.get_min (), dmax = up.get_max ();
+          Matrix value = up.get_value ().matrix_value ();
+          double dmin = up.get_min (), dmax = up.get_max ();
 
-	  int ival_tmp = (value.numel () > 0 ?
-			  xround (((value(0) - dmin) / (dmax - dmin))
-				  * RANGE_INT_MAX) :
-			  0);
+          int ival_tmp = (value.numel () > 0 ?
+                          xround (((value(0) - dmin) / (dmax - dmin))
+                                  * RANGE_INT_MAX) :
+                          0);
 
-	  if (ival != ival_tmp || value.numel () > 0)
-	    {
-	      double dval = dmin + (ival * (dmax - dmin) / RANGE_INT_MAX);
+          if (ival != ival_tmp || value.numel () > 0)
+            {
+              double dval = dmin + (ival * (dmax - dmin) / RANGE_INT_MAX);
 
-	      gh_manager::post_set (m_handle, "value", octave_value (dval));
-	      gh_manager::post_callback (m_handle, "callback");
-	    }
-	}
+              gh_manager::post_set (m_handle, "value", octave_value (dval));
+              gh_manager::post_callback (m_handle, "callback");
+            }
+        }
     }
 }
 
--- a/libgui/graphics/TextControl.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/graphics/TextControl.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -42,7 +42,7 @@
       Container* container = parent->innerContainer ();
 
       if (container)
-	return new TextControl (go, new QLabel (container));
+        return new TextControl (go, new QLabel (container));
     }
 
   return 0;
@@ -57,7 +57,7 @@
   label->setTextFormat (Qt::PlainText);
   label->setWordWrap (false);
   label->setAlignment (Utils::fromHVAlign (up.get_horizontalalignment (),
-					   up.get_verticalalignment ()));
+                                           up.get_verticalalignment ()));
   // FIXME: support string_vector
   label->setText (Utils::fromStdString (up.get_string_string ()));
 }
@@ -80,7 +80,7 @@
     case uicontrol::properties::ID_HORIZONTALALIGNMENT:
     case uicontrol::properties::ID_VERTICALALIGNMENT:
       label->setAlignment (Utils::fromHVAlign (up.get_horizontalalignment (),
-					       up.get_verticalalignment ()));
+                                               up.get_verticalalignment ()));
       break;
     default:
       BaseControl::update (pId);
--- a/libgui/graphics/TextEdit.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/graphics/TextEdit.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -31,20 +31,20 @@
 namespace QtHandles
 {
 
-void TextEdit::focusOutEvent (QFocusEvent* event)
+void TextEdit::focusOutEvent (QFocusEvent* xevent)
 {
-  QTextEdit::focusOutEvent (event);
+  QTextEdit::focusOutEvent (xevent);
 
   emit editingFinished ();
 }
 
-void TextEdit::keyPressEvent (QKeyEvent* event)
+void TextEdit::keyPressEvent (QKeyEvent* xevent)
 {
-  QTextEdit::keyPressEvent (event);
+  QTextEdit::keyPressEvent (xevent);
 
-  if ((event->key () == Qt::Key_Return
-       || event->key () == Qt::Key_Enter)
-      && event->modifiers () == Qt::ControlModifier)
+  if ((xevent->key () == Qt::Key_Return
+       || xevent->key () == Qt::Key_Enter)
+      && xevent->modifiers () == Qt::ControlModifier)
     emit editingFinished ();
 }
 
--- a/libgui/graphics/TextEdit.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/graphics/TextEdit.h	Mon Jan 12 09:17:35 2015 -0800
@@ -33,7 +33,7 @@
   Q_OBJECT
 
 public:
-  TextEdit (QWidget* parent) : QTextEdit(parent) { }
+  TextEdit (QWidget* xparent) : QTextEdit (xparent) { }
   ~TextEdit (void) { }
 
 signals:
--- a/libgui/graphics/ToggleButtonControl.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/graphics/ToggleButtonControl.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -42,14 +42,14 @@
       Container* container = parent->innerContainer ();
 
       if (container)
-	return new ToggleButtonControl (go, new QPushButton (container));
+        return new ToggleButtonControl (go, new QPushButton (container));
     }
 
   return 0;
 }
 
 ToggleButtonControl::ToggleButtonControl (const graphics_object& go,
-					  QPushButton* btn)
+                                          QPushButton* btn)
     : ButtonControl (go, btn)
 {
   btn->setCheckable (true);
--- a/libgui/graphics/ToggleTool.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/graphics/ToggleTool.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -40,7 +40,7 @@
       QWidget* parentWidget = parent->qWidget<QWidget> ();
 
       if (parentWidget)
-	return new ToggleTool (go, new QAction (parentWidget));
+        return new ToggleTool (go, new QAction (parentWidget));
     }
 
   return 0;
@@ -55,7 +55,7 @@
   action->setChecked (tp.is_state ());
 
   connect (action, SIGNAL (toggled (bool)),
-	   this, SLOT (triggered (bool)));
+           this, SLOT (triggered (bool)));
 }
 
 ToggleTool::~ToggleTool (void)
@@ -82,9 +82,9 @@
 {
   gh_manager::post_set (m_handle, "state", checked, false);
   gh_manager::post_callback (m_handle,
-			     checked
-			     ? "oncallback"
-			     : "offcallback");
+                             checked
+                             ? "oncallback"
+                             : "offcallback");
   gh_manager::post_callback (m_handle, "clickedcallback");
 }
 
--- a/libgui/graphics/ToolBar.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/graphics/ToolBar.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -71,7 +71,7 @@
       QWidget* parentWidget = parent->qWidget<QWidget> ();
 
       if (parentWidget)
-	return new ToolBar (go, new QToolBar (parentWidget));
+        return new ToolBar (go, new QToolBar (parentWidget));
     }
 
   return 0;
@@ -110,7 +110,7 @@
     {
     case base_properties::ID_VISIBLE:
       if (m_figure)
-	m_figure->showCustomToolBar (bar, tp.is_visible ());
+        m_figure->showCustomToolBar (bar, tp.is_visible ());
       break;
     default:
       Object::update (pId);
@@ -118,36 +118,36 @@
     }
 }
 
-bool ToolBar::eventFilter (QObject* watched, QEvent* event)
+bool ToolBar::eventFilter (QObject* watched, QEvent* xevent)
 {
   if (watched == qObject ())
     {
-      switch (event->type ())
-	{
-	case QEvent::ActionAdded:
-	case QEvent::ActionRemoved:
-	    {
-	      QActionEvent* ae = dynamic_cast<QActionEvent*> (event);
-	      QToolBar* bar = qWidget<QToolBar> ();
+      switch (xevent->type ())
+        {
+        case QEvent::ActionAdded:
+        case QEvent::ActionRemoved:
+            {
+              QActionEvent* ae = dynamic_cast<QActionEvent*> (xevent);
+              QToolBar* bar = qWidget<QToolBar> ();
 
-	      if (ae->action () != m_empty)
-		{
-		  if (event->type () == QEvent::ActionAdded)
-		    {
-		      if (bar->actions ().size () == 2)
-			QTimer::singleShot (0, this, SLOT (hideEmpty (void)));
-		    }
-		  else
-		    {
-		      if (bar->actions ().size () == 1)
-			m_empty->setVisible (true);
-		    }
-		}
-	    }
-	  break;
-	default:
-	  break;
-	}
+              if (ae->action () != m_empty)
+                {
+                  if (xevent->type () == QEvent::ActionAdded)
+                    {
+                      if (bar->actions ().size () == 2)
+                        QTimer::singleShot (0, this, SLOT (hideEmpty (void)));
+                    }
+                  else
+                    {
+                      if (bar->actions ().size () == 1)
+                        m_empty->setVisible (true);
+                    }
+                }
+            }
+          break;
+        default:
+          break;
+        }
     }
 
   return false;
@@ -165,7 +165,7 @@
       QToolBar* bar = qWidget<QToolBar> ();
 
       if (bar)
-	m_figure->showCustomToolBar (bar, false);
+        m_figure->showCustomToolBar (bar, false);
     }
 }
 
--- a/libgui/graphics/ToolBarButton.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/graphics/ToolBarButton.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -74,38 +74,38 @@
     case base_properties::ID_VISIBLE:
       action->setVisible (tp.is_visible ());
       if (m_separator)
-	m_separator->setVisible (tp.is_visible ());
+        m_separator->setVisible (tp.is_visible ());
       break;
     case T::properties::ID_TOOLTIPSTRING:
       action->setToolTip (Utils::fromStdString (tp.get_tooltipstring ()));
       break;
     case T::properties::ID_CDATA:
-	{
-	  QImage img = Utils::makeImageFromCData (tp.get_cdata (), 16, 16);
+        {
+          QImage img = Utils::makeImageFromCData (tp.get_cdata (), 16, 16);
 
-	  action->setIcon (QIcon (QPixmap::fromImage (img)));
-	}
+          action->setIcon (QIcon (QPixmap::fromImage (img)));
+        }
       break;
     case T::properties::ID_SEPARATOR:
       if (tp.is_separator ())
-	{
-	  if (! m_separator)
-	    {
-	      m_separator = new QAction (action);
-	      m_separator->setSeparator (true);
-	      m_separator->setVisible (tp.is_visible ());
+        {
+          if (! m_separator)
+            {
+              m_separator = new QAction (action);
+              m_separator->setSeparator (true);
+              m_separator->setVisible (tp.is_visible ());
 
-	      QWidget* w = qobject_cast<QWidget*> (action->parent ());
+              QWidget* w = qobject_cast<QWidget*> (action->parent ());
 
-	      w->insertAction (action, m_separator);
-	    }
-	}
+              w->insertAction (action, m_separator);
+            }
+        }
       else
-	{
-	  if (m_separator)
-	    delete m_separator;
-	  m_separator = 0;
-	}
+        {
+          if (m_separator)
+            delete m_separator;
+          m_separator = 0;
+        }
       break;
     case T::properties::ID_ENABLE:
       action->setEnabled (tp.is_enable ());
--- a/libgui/graphics/__init_qt__.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/graphics/__init_qt__.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -48,45 +48,45 @@
   if (! qtHandlesInitialized)
     {
       if (qApp)
-	{
-	  qRegisterMetaType<graphics_object> ("graphics_object");
+        {
+          qRegisterMetaType<graphics_object> ("graphics_object");
 
-	  gh_manager::enable_event_processing (true);
+          gh_manager::enable_event_processing (true);
 
-	  graphics_toolkit tk (new Backend ());
+          graphics_toolkit tk (new Backend ());
           gtk_manager::load_toolkit (tk);
 
-	  octave_add_atexit_function ("__shutdown_qt__");
+          octave_add_atexit_function ("__shutdown_qt__");
 
-	  // Change some default settings to use Qt default colors
-	  QPalette p;
-	  graphics_object root = gh_manager::get_object (0);
+          // Change some default settings to use Qt default colors
+          QPalette p;
+          graphics_object root = gh_manager::get_object (0);
 
-	  /*
-	  root.set ("defaultfigurecolor",
-		    octave_value (Utils::toRgb (p.color (QPalette::Window))));
-	  */
-	  root.set ("defaultuicontrolbackgroundcolor",
-		    octave_value (Utils::toRgb (p.color (QPalette::Window))));
-	  root.set ("defaultuicontrolforegroundcolor",
-		    octave_value (Utils::toRgb
-				  (p.color (QPalette::WindowText))));
-	  root.set ("defaultuipanelbackgroundcolor",
-		    octave_value (Utils::toRgb (p.color (QPalette::Window))));
-	  root.set ("defaultuipanelforegroundcolor",
-		    octave_value (Utils::toRgb
-				  (p.color (QPalette::WindowText))));
-	  root.set ("defaultuipanelhighlightcolor",
-		    octave_value (Utils::toRgb (p.color (QPalette::Light))));
-	  root.set ("defaultuipanelshadowcolor",
-		    octave_value (Utils::toRgb (p.color (QPalette::Dark))));
+          /*
+          root.set ("defaultfigurecolor",
+                    octave_value (Utils::toRgb (p.color (QPalette::Window))));
+          */
+          root.set ("defaultuicontrolbackgroundcolor",
+                    octave_value (Utils::toRgb (p.color (QPalette::Window))));
+          root.set ("defaultuicontrolforegroundcolor",
+                    octave_value (Utils::toRgb
+                                  (p.color (QPalette::WindowText))));
+          root.set ("defaultuipanelbackgroundcolor",
+                    octave_value (Utils::toRgb (p.color (QPalette::Window))));
+          root.set ("defaultuipanelforegroundcolor",
+                    octave_value (Utils::toRgb
+                                  (p.color (QPalette::WindowText))));
+          root.set ("defaultuipanelhighlightcolor",
+                    octave_value (Utils::toRgb (p.color (QPalette::Light))));
+          root.set ("defaultuipanelshadowcolor",
+                    octave_value (Utils::toRgb (p.color (QPalette::Dark))));
 
-	  qtHandlesInitialized = true;
+          qtHandlesInitialized = true;
 
-	  return true;
-	}
+          return true;
+        }
       else
-	error ("__init_qt__: QApplication object must exist.");
+        error ("__init_qt__: QApplication object must exist.");
     }
 
   return false;
@@ -213,45 +213,45 @@
       QString filter;
       QStringList files =
         QFileDialog::getOpenFileNames (0, caption, defaultFileName,
-				       filterSpecs.join (";;"), &filter, 0);
+                                       filterSpecs.join (";;"), &filter, 0);
 
       if (! files.isEmpty ())
-	{
-	  Cell cFiles (1, files.length ());
-	  QString dirName;
-	  int i = 0;
+        {
+          Cell cFiles (1, files.length ());
+          QString dirName;
+          int i = 0;
 
-	  foreach (const QString& s, files)
-	    {
-	      QFileInfo fi (s);
+          foreach (const QString& s, files)
+            {
+              QFileInfo fi (s);
 
-	      if (dirName.isEmpty ())
-		dirName = appendDirSep (fi.canonicalPath ());
-	      cFiles(i++) = toStdString (fi.fileName ());
-	    }
+              if (dirName.isEmpty ())
+                dirName = appendDirSep (fi.canonicalPath ());
+              cFiles(i++) = toStdString (fi.fileName ());
+            }
 
-	  retval(0) = cFiles;
-	  retval(1) = toStdString (dirName);
-	  if (! filter.isEmpty ())
-	    retval(2) = static_cast<double> (filterSpecs.indexOf (filter) + 1);
-	}
+          retval(0) = cFiles;
+          retval(1) = toStdString (dirName);
+          if (! filter.isEmpty ())
+            retval(2) = static_cast<double> (filterSpecs.indexOf (filter) + 1);
+        }
     }
   else
     {
       QString filter;
       QString fileName =
         QFileDialog::getOpenFileName (0, caption, defaultFileName,
-				      filterSpecs.join (";;"), &filter, 0);
+                                      filterSpecs.join (";;"), &filter, 0);
 
       if (! fileName.isNull ())
-	{
-	  QFileInfo fi (fileName);
+        {
+          QFileInfo fi (fileName);
 
-	  retval(0) = toStdString (fi.fileName ());
-	  retval(1) = toStdString (appendDirSep (fi.canonicalPath ()));
-	  if (! filter.isEmpty ())
-	    retval(2) = static_cast<double> (filterSpecs.indexOf (filter) + 1);
-	}
+          retval(0) = toStdString (fi.fileName ());
+          retval(1) = toStdString (appendDirSep (fi.canonicalPath ()));
+          if (! filter.isEmpty ())
+            retval(2) = static_cast<double> (filterSpecs.indexOf (filter) + 1);
+        }
     }
 
   return retval;
@@ -289,7 +289,7 @@
   QString filter;
   QString fileName =
     QFileDialog::getSaveFileName (0, caption, defaultFileName,
-				  filterSpecs.join (";;"), &filter, 0);
+                                  filterSpecs.join (";;"), &filter, 0);
 
   if (! fileName.isNull ())
     {
@@ -297,11 +297,11 @@
 
       retval(0) = toStdString (fi.fileName ());
       if (fi.exists ())
-	retval(1) = toStdString (appendDirSep (fi.canonicalPath ()));
+        retval(1) = toStdString (appendDirSep (fi.canonicalPath ()));
       else
-	retval(1) = toStdString (appendDirSep (fi.absolutePath ()));
+        retval(1) = toStdString (appendDirSep (fi.absolutePath ()));
       if (! filter.isEmpty ())
-	retval(2) = static_cast<double> (filterSpecs.indexOf (filter) + 1);
+        retval(2) = static_cast<double> (filterSpecs.indexOf (filter) + 1);
     }
 
   return retval;
@@ -321,7 +321,7 @@
   QString defaultDirectory = fromStdString (args(0).string_value ());
 
   QString dirName = QFileDialog::getExistingDirectory (0, caption,
-						       defaultDirectory);
+                                                       defaultDirectory);
 
   if (! dirName.isNull ())
     retval = toStdString (dirName);
--- a/libgui/graphics/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/graphics/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -110,8 +110,9 @@
 
 graphics_libgui_graphics_la_CPPFLAGS = \
   $(AM_CPPFLAGS) \
-  $(FT2_CFLAGS) \
+  $(FT2_CPPFLAGS) \
   $(FONTCONFIG_CPPFLAGS) \
+  $(HDF5_CPPFLAGS) \
   @OCTGUI_DLL_DEFS@ \
   @QT_CPPFLAGS@ \
   -Igraphics -I$(srcdir)/graphics \
--- a/libgui/qterminal/libqterminal/QTerminal.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/qterminal/libqterminal/QTerminal.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -118,5 +118,5 @@
     (cursorUseForegroundColor,
      settings->value ("terminal/color_c",
                       QVariant (colors.at (3))).value<QColor> ());
-  setScrollBufferSize (settings->value ("terminal/history_buffer",1000).toInt() );
+  setScrollBufferSize (settings->value ("terminal/history_buffer",1000).toInt () );
 }
--- a/libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.cpp	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.cpp	Mon Jan 12 09:17:35 2015 -0800
@@ -1,5 +1,5 @@
 /*  Copyright (C) 2008 e_k (e_k@users.sourceforge.net)
-    Copyright (C) 2012-2013 Jacob Dawid <jacob.dawid@googlemail.com>
+    Copyright (C) 2012-2013 Jacob Dawid <jacob.dawid@cybercatalyst.com>
 
     This library is free software; you can redistribute it and/or
     modify it under the terms of the GNU Library General Public
--- a/libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.h	Mon Jan 12 09:17:35 2015 -0800
@@ -1,5 +1,5 @@
 /*  Copyright (C) 2008 e_k (e_k@users.sourceforge.net)
-    Copyright (C) 2012-2013 Jacob Dawid <jacob.dawid@googlemail.com>
+    Copyright (C) 2012-2013 Jacob Dawid <jacob.dawid@cybercatalyst.com>
 
     This library is free software; you can redistribute it and/or
     modify it under the terms of the GNU Library General Public
--- a/libgui/qterminal/libqterminal/unix/Screen.cpp	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/qterminal/libqterminal/unix/Screen.cpp	Mon Jan 12 09:17:35 2015 -0800
@@ -110,7 +110,7 @@
 
 // Cursor Setting --------------------------------------------------------------
 
-/*! \section Cursor
+/*! @section Cursor
 
     The `cursor' is a location within the screen that is implicitely used in
     many operations. The operations within this section allow to manipulate
@@ -502,7 +502,7 @@
 /*!
     returns the image.
 
-    Get the size of the image by \sa getLines and \sa getColumns.
+    Get the size of the image by @sa getLines and @sa getColumns.
 
     NOTE that the image returned by this function must later be
     freed.
@@ -861,7 +861,7 @@
 
 /*! scroll up `n' lines within current region.
     The `n' new lines are cleared.
-    \sa setRegion \sa scrollDown
+    @sa setRegion @sa scrollDown
 */
 
 QRect Screen::lastScrolledRegion() const
@@ -889,7 +889,7 @@
 
 /*! scroll down `n' lines within current region.
     The `n' new lines are cleared.
-    \sa setRegion \sa scrollUp
+    @sa setRegion @sa scrollUp
 */
 
 void Screen::scrollDown(int from, int n)
@@ -949,7 +949,7 @@
 
 // Erasing ---------------------------------------------------------------------
 
-/*! \section Erasing
+/*! @section Erasing
 
     This group of operations erase parts of the screen contents by filling
     it with spaces colored due to the current rendition settings.
--- a/libgui/qterminal/libqterminal/unix/Screen.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/qterminal/libqterminal/unix/Screen.h	Mon Jan 12 09:17:35 2015 -0800
@@ -50,7 +50,7 @@
 class TerminalCharacterDecoder;
 
 /**
-    \brief An image of characters with associated attributes.
+    @brief An image of characters with associated attributes.
 
     The terminal emulation ( Emulation ) receives a serial stream of
     characters from the program currently running in the terminal.
--- a/libgui/qterminal/libqterminal/unix/SelfListener.cpp	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/qterminal/libqterminal/unix/SelfListener.cpp	Mon Jan 12 09:17:35 2015 -0800
@@ -1,5 +1,5 @@
 /* qterminal - a terminal widget for Qt
- * Copyright (C) 2011, 2013 Jacob Dawid (jacob.dawid@googlemail.com)
+ * Copyright (C) 2011, 2013 Jacob Dawid (jacob.dawid@cybercatalyst.com)
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as
--- a/libgui/qterminal/libqterminal/unix/SelfListener.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/qterminal/libqterminal/unix/SelfListener.h	Mon Jan 12 09:17:35 2015 -0800
@@ -1,5 +1,5 @@
 /* qterminal - a terminal widget for Qt
- * Copyright (C) 2011, 2013 Jacob Dawid (jacob.dawid@googlemail.com)
+ * Copyright (C) 2011, 2013 Jacob Dawid (jacob.dawid@cybercatalyst.com)
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as
--- a/libgui/qterminal/libqterminal/unix/TerminalModel.cpp	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/qterminal/libqterminal/unix/TerminalModel.cpp	Mon Jan 12 09:17:35 2015 -0800
@@ -5,7 +5,7 @@
     Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
 
     Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008
-    Copyright (C) 2012-2013 Jacob Dawid <jacob.dawid@googlemail.com>
+    Copyright (C) 2012-2013 Jacob Dawid <jacob.dawid@cybercatalyst.com>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
--- a/libgui/qterminal/libqterminal/unix/TerminalModel.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/qterminal/libqterminal/unix/TerminalModel.h	Mon Jan 12 09:17:35 2015 -0800
@@ -5,7 +5,7 @@
     Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
 
     Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008
-    Copyright (C) 2012-2013 Jacob Dawid <jacob.dawid@googlemail.com>
+    Copyright (C) 2012-2013 Jacob Dawid <jacob.dawid@cybercatalyst.com>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
--- a/libgui/qterminal/libqterminal/unix/TerminalView.cpp	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/qterminal/libqterminal/unix/TerminalView.cpp	Mon Jan 12 09:17:35 2015 -0800
@@ -5,7 +5,7 @@
     Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
 
     Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008
-    Copyright (C) 2012-2013 Jacob Dawid <jacob.dawid@googlemail.com>
+    Copyright (C) 2012-2013 Jacob Dawid <jacob.dawid@cybercatalyst.com>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
--- a/libgui/qterminal/libqterminal/unix/TerminalView.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/qterminal/libqterminal/unix/TerminalView.h	Mon Jan 12 09:17:35 2015 -0800
@@ -3,7 +3,7 @@
     Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
 
     Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008
-    Copyright (C) 2012-2013 Jacob Dawid <jacob.dawid@googlemail.com>
+    Copyright (C) 2012-2013 Jacob Dawid <jacob.dawid@cybercatalyst.com>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
--- a/libgui/qterminal/libqterminal/unix/Vt102Emulation.cpp	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/qterminal/libqterminal/unix/Vt102Emulation.cpp	Mon Jan 12 09:17:35 2015 -0800
@@ -1221,10 +1221,10 @@
 
 /*! shows the contents of the scan buffer.
 
-    This functions is used for diagnostics. It is called by \e ReportErrorToken
+    This functions is used for diagnostics. It is called by @e ReportErrorToken
     to inform about strings that cannot be decoded or handled by the emulation.
 
-    \sa ReportErrorToken
+    @sa ReportErrorToken
 */
 
 static void hexdump(int* s, int len)
--- a/libgui/src/files-dock-widget.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/src/files-dock-widget.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -551,7 +551,7 @@
   QItemSelectionModel *m = _file_tree_view->selectionModel ();
   QModelIndexList rows = m->selectedRows ();
 
-  for ( QModelIndexList::iterator it = rows.begin (); it != rows.end (); it++)
+  for (QModelIndexList::iterator it = rows.begin (); it != rows.end (); it++)
     {
       QFileInfo file = _file_system_model->fileInfo (*it);
       if (file.exists ())
@@ -661,7 +661,7 @@
   QItemSelectionModel *m = _file_tree_view->selectionModel ();
   QModelIndexList rows = m->selectedRows ();
 
-  for ( QModelIndexList::iterator it = rows.begin (); it != rows.end (); it++)
+  for (QModelIndexList::iterator it = rows.begin (); it != rows.end (); it++)
     {
       QModelIndex index = *it;
 
--- a/libgui/src/files-dock-widget.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/src/files-dock-widget.h	Mon Jan 12 09:17:35 2015 -0800
@@ -40,8 +40,8 @@
 #include "octave-dock-widget.h"
 
 /**
-   \class files_dock_widget
-   \brief Dock widget to display files in the current directory.
+   @class files_dock_widget
+   @brief Dock widget to display files in the current directory.
 */
 class files_dock_widget : public octave_dock_widget
 {
--- a/libgui/src/find-files-model.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/src/find-files-model.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -101,7 +101,7 @@
 void
 find_files_model::addFile (const QFileInfo &info)
 {
-  beginInsertRows (QModelIndex (), _files.size (), _files.size () );
+  beginInsertRows (QModelIndex (), _files.size (), _files.size ());
 
   QList<QFileInfo>::Iterator it;
   find_file_less_than less_than (_sortorder);
--- a/libgui/src/m-editor/file-editor-interface.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/src/m-editor/file-editor-interface.h	Mon Jan 12 09:17:35 2015 -0800
@@ -40,7 +40,7 @@
 
   virtual ~file_editor_interface () { }
 
-  virtual QMenu *get_mru_menu ( ) = 0;
+  virtual QMenu *get_mru_menu () = 0;
   virtual QMenu *debug_menu () = 0;
   virtual QToolBar *toolbar () = 0;
 
--- a/libgui/src/m-editor/find-dialog.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/src/m-editor/find-dialog.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -252,7 +252,8 @@
 void
 find_dialog::find (bool forward)
 {
-  int line = -1, col = -1;
+  int line, col;
+  line = col = -1;
   bool do_wrap = _wrap_check_box->isChecked ();
   bool do_forward = forward;
 
--- a/libgui/src/m-editor/octave-qscintilla.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/src/m-editor/octave-qscintilla.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -189,7 +189,7 @@
 octave_qscintilla::contextMenuEvent (QContextMenuEvent *e)
 {
   QPoint global_pos, local_pos;                         // the menu's position
-  QMenu *context_menu = createStandardContextMenu ( );  // standard menu
+  QMenu *context_menu = createStandardContextMenu ();  // standard menu
 
   // fill context menu with editor's standard actions
   emit create_context_menu_signal (context_menu);
@@ -274,7 +274,7 @@
 {
   QStringList commands = selectedText ().split (QRegExp("[\r\n]"),
                                                 QString::SkipEmptyParts);
-  for (int i = 0; i < commands.size (); i++ )
+  for (int i = 0; i < commands.size (); i++)
     emit execute_command_in_terminal_signal (commands.at (i));
 }
 
--- a/libgui/src/main-window.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/src/main-window.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -2008,7 +2008,7 @@
 main_window::show_gui_info (void)
 {
   QString gui_info
-    ( QObject::tr ("<p><strong>A Note about Octave's New GUI</strong></p>"
+    (QObject::tr ("<p><strong>A Note about Octave's New GUI</strong></p>"
          "<p>One of the biggest new features for Octave 3.8 is a graphical "
          "user interface.  It is the one thing that users have requested "
          "most often over the last few years and now it is almost ready.  "
@@ -2508,7 +2508,7 @@
 
   QSettings *settings = resource_manager::get_settings ();
 
-  if (settings->value ("prompt_to_exit", false ).toBool())
+  if (settings->value ("prompt_to_exit", false).toBool ())
     {
       int ans = QMessageBox::question (this, tr ("Octave"),
          tr ("Are you sure you want to exit Octave?"),
--- a/libgui/src/main-window.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/src/main-window.h	Mon Jan 12 09:17:35 2015 -0800
@@ -58,7 +58,7 @@
 #include "find-files-dialog.h"
 
 /**
- * \class MainWindow
+ * @class MainWindow
  *
  * Represents the main window.
  */
--- a/libgui/src/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/src/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -179,8 +179,9 @@
 
 src_libgui_src_la_CPPFLAGS = \
   $(AM_CPPFLAGS) \
-  $(FT2_CFLAGS) \
+  $(FT2_CPPFLAGS) \
   $(FONTCONFIG_CPPFLAGS) \
+  $(HDF5_CPPFLAGS) \
   @OCTGUI_DLL_DEFS@ \
   @QT_CPPFLAGS@ \
   -I$(srcdir)/qterminal/libqterminal \
--- a/libgui/src/octave-dock-widget.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/src/octave-dock-widget.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -69,7 +69,7 @@
   _dock_button->setIconSize (QSize (12,12));
 
   _close_action = new QAction
-                   (QIcon (":/actions/icons/widget-close.png"), "", this );
+                   (QIcon (":/actions/icons/widget-close.png"), "", this);
   _close_action-> setToolTip (tr ("Hide widget"));
   connect (_close_action, SIGNAL (triggered (bool)),
            this, SLOT (change_visibility (bool)));
@@ -184,7 +184,7 @@
   _dock_action->setIcon (QIcon (":/actions/icons/widget-dock"+_icon_color+".png"));
   _dock_action->setToolTip (tr ("Dock widget"));
 
-  // restore the last geometry( when floating
+  // restore the last geometry when floating
   setGeometry (settings->value ("DockWidgets/" + objectName ()
                        + "_floating_geometry",QRect(50,100,480,480)).toRect ());
 
@@ -204,11 +204,15 @@
 
 // dock the widget
 void
+#if defined (Q_OS_WIN32)
 octave_dock_widget::make_widget (bool dock)
+#else
+octave_dock_widget::make_widget (bool)
+#endif
 {
 #if defined (Q_OS_WIN32)
 
-  // windows: Since floating widget has no parent, we have to readd it
+  // windows: Since floating widget has no parent, we have to read it
 
   QSettings *settings = resource_manager::get_settings ();
 
--- a/libgui/src/octave-gui.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/src/octave-gui.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -89,7 +89,7 @@
 // Disable all Qt messages by default.
 
 static void
-message_handler (QtMsgType type, const char *msg)
+message_handler (QtMsgType, const char *)
 {
 }
 
--- a/libgui/src/octave-qt-link.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/src/octave-qt-link.h	Mon Jan 12 09:17:35 2015 -0800
@@ -39,9 +39,9 @@
 // Defined for purposes of sending QList<int> as part of signal.
 typedef QList<int> QIntList;
 
-// \class OctaveLink
-// \brief Provides threadsafe access to octave.
-// \author Jacob Dawid
+// @class OctaveLink
+// @brief Provides threadsafe access to octave.
+// @author Jacob Dawid
 //
 // This class is a wrapper around octave and provides thread safety by
 // buffering access operations to octave and executing them in the
--- a/libgui/src/qtinfo/parser.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/src/qtinfo/parser.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -22,7 +22,7 @@
 */
 
 // Author: P. L. Lucas
-// Author: Jacob Dawid <jacob.dawid@gmail.com>
+// Author: Jacob Dawid <jacob.dawid@cybercatalyst.com>
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
@@ -94,7 +94,7 @@
 parser::open_file (QFileInfo & file_info)
 {
   QIODevice *iodevice = 0;
-  if ( _compressors_map.contains(file_info.suffix ()))
+  if (_compressors_map.contains (file_info.suffix ()))
     {
       QProcess gzip;
       gzip.start (_compressors_map.value (file_info.suffix ()).arg (file_info.absoluteFilePath ()));
@@ -298,7 +298,7 @@
   QRegExp re ("(\\*[N|n]ote|\n\\*)([ |\n]+)([^:]+):([^:\\.,]*)([:,\\.]+)");
   int i = 0, f;
 
-  while ( (i = re.indexIn (text,i)) != -1)
+  while ((i = re.indexIn (text,i)) != -1)
     {
       QString type     = re.cap (1);
       QString note     = re.cap (3);
@@ -351,7 +351,7 @@
 {
   QRegExp re ("`([^']+)'");
   int i = 0, f;
-  while ( (i = re.indexIn (text, i)) != -1)
+  while ((i = re.indexIn (text, i)) != -1)
     {
       QString t = re.cap (1);
       QString bold = "<font style=\"color:SteelBlue;font-weight:bold\">" + t +
@@ -457,7 +457,7 @@
       while (! (nodeText=get_next_node (io)).isEmpty () && foundCount < 2)
         {
           QString first_line = get_first_line (nodeText);
-          if (first_line.startsWith ("Tag") )
+          if (first_line.startsWith ("Tag"))
             {
               foundCount++;
               int pos = 0;
@@ -492,7 +492,7 @@
               foundCount++;
               int pos = 0;
 
-              while ( (pos = re_files.indexIn (nodeText, pos)) != -1)
+              while ((pos = re_files.indexIn (nodeText, pos)) != -1)
                 {
                   QString fileCap = re_files.cap (1).trimmed ();
                   int index = re_files.cap (2).toInt ();
@@ -522,7 +522,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);
@@ -559,7 +560,7 @@
 {
   int pos = 0;
 
-  while ( (pos = re.indexIn (text, pos)) != -1)
+  while ((pos = re.indexIn (text, pos)) != -1)
     {
       QString cap = text.mid (pos,re.matchedLength ());
       QString a (after);
@@ -599,7 +600,7 @@
         }
 
       QString node_text;
-      while ( !(node_text = get_next_node (io)).isEmpty ())
+      while (! (node_text = get_next_node (io)).isEmpty ())
         {
           QString firstLine = get_first_line (node_text);
           QString node = get_node_name (node_text);
--- a/libgui/src/qtinfo/parser.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/src/qtinfo/parser.h	Mon Jan 12 09:17:35 2015 -0800
@@ -22,7 +22,7 @@
 */
 
 // Author: P. L. Lucas
-// Author: Jacob Dawid <jacob.dawid@gmail.com>
+// Author: Jacob Dawid <jacob.dawid@cybercatalyst.com>
 
 #include <QStringList>
 #include <QIODevice>
@@ -30,7 +30,7 @@
 #include <QHash>
 
 /**
- * \class parser
+ * @class parser
  * This class gets nodes and searchs inside of 'info files'.
  * <p>Each info file has nodes. Every node has the documentation.
  * Info files contains a map with position of each node.</p>
@@ -103,9 +103,9 @@
   QIODevice *open_file(QFileInfo & fileInfo);
 
   /** Calculates real position of nodes.
-    * \param pos position from info file.
-    * \param fileInfo returns file what contains that position.
-    * \param realPos returns real position inside of fileInfo.
+    * @param pos position from info file.
+    * @param fileInfo returns file what contains that position.
+    * @param realPos returns real position inside of fileInfo.
     */
   void real_position (int pos, QFileInfo & file_info, int & real_pos);
 
--- a/libgui/src/qtinfo/webinfo.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/src/qtinfo/webinfo.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -22,7 +22,7 @@
 */
 
 // Author: P. L. Lucas
-// Author: Jacob Dawid <jacob.dawid@gmail.com>
+// Author: Jacob Dawid <jacob.dawid@cybercatalyst.com>
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
@@ -182,7 +182,7 @@
   _text_browser->show ();
 
   connect (_text_browser, SIGNAL (anchorClicked (const QUrl &)), this,
-           SLOT (link_clicked (const QUrl &)) );
+           SLOT (link_clicked (const QUrl &)));
   disconnect(_tab_bar, SIGNAL (currentChanged(int)), this,
              SLOT (current_tab_changed (int)));
 
--- a/libgui/src/qtinfo/webinfo.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/src/qtinfo/webinfo.h	Mon Jan 12 09:17:35 2015 -0800
@@ -22,7 +22,7 @@
 */
 
 // Author: P. L. Lucas
-// Author: 2012 Jacob Dawid <jacob.dawid@gmail.com>
+// Author: 2012 Jacob Dawid <jacob.dawid@cybercatalyst.com>
 
 #include <QTextBrowser>
 #include "parser.h"
--- a/libgui/src/settings-dialog.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/src/settings-dialog.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -158,7 +158,7 @@
   ui->customFileEditor->setText (
     settings->value ("customFileEditor").toString ());
   ui->editor_showLineNumbers->setChecked (
-    settings->value ("editor/showLineNumbers",true).toBool () );
+    settings->value ("editor/showLineNumbers",true).toBool ());
 
   default_var = QColor (240, 240, 240);
   QColor setting_color = settings->value ("editor/highlight_current_line_color",
@@ -170,7 +170,7 @@
   connect (ui->editor_highlightCurrentLine, SIGNAL (toggled (bool)),
            _editor_current_line_color, SLOT (setEnabled (bool)));
   ui->editor_highlightCurrentLine->setChecked (
-    settings->value ("editor/highlightCurrentLine",true).toBool () );
+    settings->value ("editor/highlightCurrentLine",true).toBool ());
   ui->editor_long_line_marker->setChecked (
     settings->value ("editor/long_line_marker",true).toBool ());
   ui->editor_long_line_column->setValue (
@@ -181,7 +181,7 @@
     settings->value ("editor/code_folding",true).toBool ());
 
   ui->editor_codeCompletion->setChecked (
-    settings->value ("editor/codeCompletion", true).toBool () );
+    settings->value ("editor/codeCompletion", true).toBool ());
   ui->editor_spinbox_ac_threshold->setValue (
     settings->value ("editor/codeCompletion_threshold",2).toInt ());
   ui->editor_checkbox_ac_keywords->setChecked (
@@ -251,7 +251,7 @@
 
   // terminal
   ui->terminal_fontName->setCurrentFont (QFont (
-    settings->value ("terminal/fontName","Courier New").toString ()) );
+    settings->value ("terminal/fontName","Courier New").toString ()));
   ui->terminal_fontSize->setValue (
     settings->value ("terminal/fontSize", 10).toInt ());
   ui->terminal_history_buffer->setValue (
@@ -310,7 +310,7 @@
 
   int currentIndex = 0;
   QString proxyTypeString = settings->value ("proxyType").toString ();
-  while ( (currentIndex < ui->proxyType->count ())
+  while ((currentIndex < ui->proxyType->count ())
           && (ui->proxyType->currentText () != proxyTypeString))
     {
       currentIndex++;
@@ -632,7 +632,7 @@
   settings->setValue ("toolbar_icon_size", ui->toolbar_icon_size->value ());
 
   // promp to exit
-  settings->setValue ( "prompt_to_exit", ui->cb_prompt_to_exit->isChecked ());
+  settings->setValue ("prompt_to_exit", ui->cb_prompt_to_exit->isChecked ());
 
   // status bar
   settings->setValue ( "show_status_bar", ui->cb_status_bar->isChecked ());
@@ -749,7 +749,7 @@
   settings->setValue ("terminal/focus_after_command",
                       ui->terminal_focus_command->isChecked ());
   settings->setValue ("terminal/history_buffer",
-                      ui->terminal_history_buffer->value() );
+                      ui->terminal_history_buffer->value ());
 
   // the cursor
   QString cursorType;
--- a/libgui/src/workspace-model.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libgui/src/workspace-model.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -141,7 +141,7 @@
 
       if (role == Qt::DisplayRole
           || (idx.column () == 0 && role == Qt::EditRole)
-          || (idx.column () == 0 && role == Qt::ToolTipRole) )
+          || (idx.column () == 0 && role == Qt::ToolTipRole))
         {
           switch (idx.column ())
             {
--- a/libinterp/Makefile.am	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/Makefile.am	Mon Jan 12 09:17:35 2015 -0800
@@ -32,7 +32,8 @@
   -I$(srcdir)/operators \
   -Iparse-tree -I$(srcdir)/parse-tree \
   -Icorefcn -I$(srcdir)/corefcn \
-  -I$(top_builddir)/libgnu -I$(top_srcdir)/libgnu
+  -I$(top_builddir)/libgnu -I$(top_srcdir)/libgnu \
+  $(HDF5_CPPFLAGS)
 
 AM_CFLAGS += $(WARN_CFLAGS)
 
--- a/libinterp/corefcn/Cell.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/Cell.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -212,6 +212,12 @@
   return retval;
 }
 
+/*
+%!test
+%! a = {"foo", "bar"};
+%! assert (a(), a)
+*/
+
 void
 Cell::assign (const octave_value_list& idx_arg, const Cell& rhs,
               const octave_value& fill_val)
@@ -248,6 +254,12 @@
   return -1;
 }
 
+/*
+%!error <wrong type argument 'cell array'> nnz ({0, 1, 2})
+%!error <wrong type argument 'cell array'> nnz (cell ())
+%!error <wrong type argument 'cell array'> nnz ({"foo", "bar"})
+*/
+
 Cell
 Cell::column (octave_idx_type i) const
 {
--- a/libinterp/corefcn/__contourc__.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/__contourc__.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -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 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/__pchip_deriv__.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -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 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/balance.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -68,7 +68,7 @@
 \n\
 If four output values are requested, compute @code{@var{AA} =\n\
 @var{CC}*@var{A}*@var{DD}} and @code{@var{BB} = @var{CC}*@var{B}*@var{DD}},\n\
-in which @var{AA} and @var{BB} have non-zero elements of approximately the\n\
+in which @var{AA} and @var{BB} have nonzero elements of approximately the\n\
 same magnitude and @var{CC} and @var{DD} are permuted diagonal matrices as\n\
 in @var{DD} for the algebraic eigenvalue problem.\n\
 \n\
@@ -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 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/besselj.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -598,7 +598,7 @@
         {
           int idx = nargin == 1 ? 0 : 1;
 
-          if (args (idx).is_single_type ())
+          if (args(idx).is_single_type ())
             {
               FloatComplexNDArray z = args(idx).float_complex_array_value ();
 
--- a/libinterp/corefcn/betainc.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/betainc.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -32,8 +32,6 @@
 #include "oct-obj.h"
 #include "utils.h"
 
-// FIXME: These functions do not need to be dynamically loaded.  They should
-//        be placed elsewhere in the Octave code hierarchy.
 
 DEFUN (betainc, args, ,
        "-*- texinfo -*-\n\
--- a/libinterp/corefcn/bitfcns.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/bitfcns.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -159,6 +159,10 @@
                               octave_float_scalar::static_class_name () &&
                               args(1).class_name () !=
                               octave_bool::static_class_name ());
+          bool arg0_is_bool = args(0).class_name () ==
+                              octave_bool::static_class_name ();
+          bool arg1_is_bool = args(1).class_name () ==
+                              octave_bool::static_class_name ();
           bool arg0_is_float = args(0).class_name () ==
                                octave_float_scalar::static_class_name ();
           bool arg1_is_float = args(1).class_name () ==
@@ -166,12 +170,12 @@
 
           if (! (arg0_is_int || arg1_is_int))
             {
-              if (! (arg0_is_float || arg1_is_float))
+              if (arg0_is_bool && arg1_is_bool)
                 {
-                  uint64NDArray x (args(0).array_value ());
-                  uint64NDArray y (args(1).array_value ());
+                  boolNDArray x (args(0).bool_array_value ());
+                  boolNDArray y (args(1).bool_array_value ());
                   if (! error_state)
-                    retval = bitopx (fname, x, y).array_value ();
+                    retval = bitopx (fname, x, y).bool_array_value ();
                 }
               else if (arg0_is_float && arg1_is_float)
                 {
@@ -180,6 +184,13 @@
                   if (! error_state)
                     retval = bitopx (fname, x, y).float_array_value ();
                 }
+              else if (! (arg0_is_float || arg1_is_float))
+                {
+                  uint64NDArray x (args(0).array_value ());
+                  uint64NDArray y (args(1).array_value ());
+                  if (! error_state)
+                    retval = bitopx (fname, x, y).array_value ();
+                }
               else
                 {
                   int p = (arg0_is_float ? 1 : 0);
@@ -377,6 +388,27 @@
   return bitop ("bitxor", args);
 }
 
+/*
+%!assert (bitand (true, false), false)
+%!assert (bitor  (true, false), true)
+%!assert (bitxor (true, false), true)
+
+%!assert (bitand (true, true), true)
+%!assert (bitor  (true, true), true)
+%!assert (bitxor (true, true), false)
+
+%!assert (bitand (true, 5), 1)
+
+%!assert (bitand (true, false), false)
+%!assert (bitand (true, true), true)
+%!assert (bitand (true, false), false)
+%!assert (bitand (true, false), false)
+
+## Test idx_arg.length () == 0
+%!error <size of X and Y must match> bitand ([0 0 0], [1 0])
+%!error <size of X and Y must match> bitand ([0; 0; 0], [0 0 0])
+*/
+
 template <typename T>
 static int64_t
 max_mantissa_value ()
@@ -595,7 +627,7 @@
           int bits_in_type = sizeof (double)
                              * std::numeric_limits<unsigned char>::digits;
           NDArray m = m_arg.array_value ();
-          DO_BITSHIFT ( );
+          DO_BITSHIFT ();
         }
       else if (cname == "single")
         {
@@ -621,6 +653,19 @@
   return retval;
 }
 
+/*
+%!assert (bitshift (uint8  (16), 1),  uint8 ( 32))
+%!assert (bitshift (uint16 (16), 2), uint16 ( 64))
+%!assert (bitshift (uint32 (16), 3), uint32 (128))
+%!assert (bitshift (uint64 (16), 4), uint64 (256))
+%!assert (bitshift (uint8 (255), 1), uint8 (254))
+
+%!error <expecting integer as second argument> bitshift (16, 1.5)
+%!error bitshift (16, {1})
+%!error <N must be a scalar integer> bitshift (10, [-2 -1 0 1 2], [1 1 1 1 1])
+%!error <N must be positive> bitshift (10, [-2 -1 0 1 2], -1)
+*/
+
 DEFUN (bitmax, args, ,
        "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {} bitmax ()\n\
--- a/libinterp/corefcn/bsxfun.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/bsxfun.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -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 ()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/corefcn/cdisplay.c	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,164 @@
+/*
+
+Copyright (C) 2009-2014 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 <stdlib.h>
+
+#if defined (OCTAVE_USE_WINDOWS_API)
+#include <windows.h>
+#elif defined (HAVE_FRAMEWORK_CARBON)
+#include <Carbon/Carbon.h>
+#elif defined (HAVE_X_WINDOWS)
+#include <X11/Xlib.h>
+#endif
+
+#include "cdisplay.h"
+
+const char *
+octave_get_display_info (int *ht, int *wd, int *dp, double *rx, double *ry,
+                         int *dpy_avail)
+{
+  const char *msg = 0;
+
+  *dpy_avail = 0;
+
+#if defined (OCTAVE_USE_WINDOWS_API)
+
+  HDC hdc = GetDC (0);
+
+  if (hdc)
+    {
+      *dp = GetDeviceCaps (hdc, BITSPIXEL);
+
+      *ht = GetDeviceCaps (hdc, VERTRES);
+      *wd = GetDeviceCaps (hdc, HORZRES);
+
+      double ht_mm = GetDeviceCaps (hdc, VERTSIZE);
+      double wd_mm = GetDeviceCaps (hdc, HORZSIZE);
+
+      *rx = *wd * 25.4 / wd_mm;
+      *ry = *ht * 25.4 / ht_mm;
+
+      *dpy_avail = 1;
+    }
+  else
+    msg = "no graphical display found";
+
+#elif defined (HAVE_FRAMEWORK_CARBON)
+
+  CGDirectDisplayID display = CGMainDisplayID ();
+
+  if (display)
+    {
+#if defined (HAVE_CARBON_CGDISPLAYBITSPERPIXEL)
+
+      *dp = CGDisplayBitsPerPixel (display);
+
+#else
+
+      /* FIXME: This will only work for MacOS > 10.5. For earlier versions
+         this code is not needed (use CGDisplayBitsPerPixel instead).  */
+
+      CGDisplayModeRef mode = CGDisplayCopyDisplayMode (display);
+      CFStringRef pixelEncoding = CGDisplayModeCopyPixelEncoding (mode);
+
+      if (CFStringCompare (pixelEncoding, CFSTR (IO32BitDirectPixels), 0) == 0)
+        *dp = 32;
+      else if (CFStringCompare (pixelEncoding,
+                                CFSTR (IO16BitDirectPixels), 0) == 0)
+        *dp = 16;
+      else
+        *dp = 8;
+
+#endif
+
+      *ht = CGDisplayPixelsHigh (display);
+      *wd = CGDisplayPixelsWide (display);
+
+      CGSize sz_mm = CGDisplayScreenSize (display);
+
+      /* For MacOS >= 10.6, CGSize is a struct keeping 2 CGFloat
+         values, but the CGFloat typedef is not present on older
+         systems, so use double instead.  */
+
+      double ht_mm = sz_mm.height;
+      double wd_mm = sz_mm.width;
+
+      *rx = *wd * 25.4 / wd_mm;
+      *ry = *ht * 25.4 / ht_mm;
+
+      *dpy_avail = 1;
+    }
+  else
+    msg = "no graphical display found";
+
+#elif defined (HAVE_X_WINDOWS)
+
+  const char *display_name = getenv ("DISPLAY");
+
+  if (display_name && *display_name)
+    {
+      Display *display = XOpenDisplay (display_name);
+
+      if (display)
+        {
+          Screen *screen = DefaultScreenOfDisplay (display);
+
+          if (screen)
+            {
+              *dp = DefaultDepthOfScreen (screen);
+
+              *ht = HeightOfScreen (screen);
+              *wd = WidthOfScreen (screen);
+
+              int screen_number = XScreenNumberOfScreen (screen);
+
+              double ht_mm = DisplayHeightMM (display, screen_number);
+              double wd_mm = DisplayWidthMM (display, screen_number);
+
+              *rx = *wd * 25.4 / wd_mm;
+              *ry = *ht * 25.4 / ht_mm;
+            }
+          else
+            msg = "X11 display has no default screen";
+
+          XCloseDisplay (display);
+
+          *dpy_avail = 1;
+        }
+      else
+        msg = "unable to open X11 DISPLAY";
+    }
+  else
+    msg = "X11 DISPLAY environment variable not set";
+
+#else
+
+  msg = "no graphical display found";
+
+#endif
+
+  return msg;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/corefcn/cdisplay.h	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,38 @@
+/*
+
+Copyright (C) 2014 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_cdisplay_h)
+#define octave_cdisplay_h 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+OCTINTERP_API extern const char *
+octave_get_display_info (int *ht, int *wd, int *dp, double *rx, double *ry,
+                         int *dpy_avail);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- a/libinterp/corefcn/cellfun.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/cellfun.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -319,9 +319,9 @@
 \n\
 Additionally, @code{cellfun} accepts an arbitrary function @var{func}\n\
 in the form of an inline function, function handle, or the name of a\n\
-function (in a character string). The function can take one or more arguments,\n\
-with the inputs arguments given by @var{C}, @var{D}, etc.  Equally the\n\
-function can return one or more output arguments.  For example:\n\
+function (in a character string).  The function can take one or more\n\
+arguments, with the inputs arguments given by @var{C}, @var{D}, etc.  \n\
+Equally the function can return one or more output arguments.  For example:\n\
 \n\
 @example\n\
 @group\n\
@@ -440,7 +440,7 @@
 
       if (! valid_identifier (name))
         {
-          std::string fcn_name = unique_symbol_name ("__cellfun_fcn_");
+          std::string fcn_name = unique_symbol_name ("__cellfun_fcn__");
           std::string fname = "function y = " + fcn_name + "(x) y = ";
 
           octave_function *ptr_func
@@ -1193,7 +1193,7 @@
 
       if (! valid_identifier (name))
         {
-          std::string fcn_name = unique_symbol_name ("__arrayfun_fcn_");
+          std::string fcn_name = unique_symbol_name ("__arrayfun_fcn__");
           std::string fname = "function y = " + fcn_name + "(x) y = ";
 
           octave_function *ptr_func
@@ -1227,7 +1227,7 @@
       // fewer polymorphic function calls as the function gets called
       // for each value of the array.
 
-      if (! symbol_table_lookup )
+      if (! symbol_table_lookup)
         {
           if (func.is_function_handle ())
             {
@@ -1783,7 +1783,8 @@
 
       NDA parray = array.permute (perm);
 
-      octave_idx_type nela = arraydv.numel (), nelc = celldv.numel ();
+      octave_idx_type nela = arraydv.numel ();
+      octave_idx_type nelc = celldv.numel ();
       parray = parray.reshape (dim_vector (nela, nelc));
 
       Cell retval (celldv);
@@ -1901,7 +1902,7 @@
       octave_value array = args(0);
       Array<int> dimv;
       if (nargin > 1)
-        dimv = args (1).int_vector_value (true);
+        dimv = args(1).int_vector_value (true);
 
       if (error_state)
         ;
@@ -2036,7 +2037,8 @@
   if (ivec >= 0)
     {
       // Vector split. Use 1D indexing.
-      octave_idx_type l = 0, nidx = (ivec == 0 ? nridx : ncidx);
+      octave_idx_type l = 0;
+      octave_idx_type nidx = (ivec == 0 ? nridx : ncidx);
       for (octave_idx_type i = 0; i < nidx; i++)
         {
           octave_idx_type u = l + d[ivec](i);
--- a/libinterp/corefcn/colloc.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/colloc.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -38,8 +38,8 @@
        "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {[@var{r}, @var{amat}, @var{bmat}, @var{q}] =} colloc (@var{n}, \"left\", \"right\")\n\
 Compute derivative and integral weight matrices for orthogonal\n\
-collocation using the subroutines given in J. Villadsen and\n\
-M. L. Michelsen, @cite{Solution of Differential Equation Models by\n\
+collocation using the subroutines given in @nospell{J. Villadsen} and\n\
+@nospell{M. L. Michelsen}, @cite{Solution of Differential Equation Models by\n\
 Polynomial Approximation}.\n\
 @end deftypefn")
 {
--- a/libinterp/corefcn/cutils.c	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/cutils.c	Mon Jan 12 09:17:35 2015 -0800
@@ -53,8 +53,3 @@
   nanosleep (&delay, &remaining);
 }
 
-int
-octave_raw_vsnprintf (char *buf, size_t n, const char *fmt, va_list args)
-{
-  return vsnprintf (buf, n, fmt, args);
-}
--- a/libinterp/corefcn/cutils.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/cutils.h	Mon Jan 12 09:17:35 2015 -0800
@@ -33,9 +33,6 @@
 
 OCTINTERP_API void octave_usleep (unsigned int useconds);
 
-OCTINTERP_API int
-octave_raw_vsnprintf (char *buf, size_t n, const char *fmt, va_list args);
-
 #ifdef __cplusplus
 }
 #endif
--- a/libinterp/corefcn/data.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/data.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -112,15 +112,15 @@
 @deftypefn  {Built-in Function} {} all (@var{x})\n\
 @deftypefnx {Built-in Function} {} all (@var{x}, @var{dim})\n\
 For a vector argument, return true (logical 1) if all elements of the vector\n\
-are non-zero.\n\
+are nonzero.\n\
 \n\
 For a matrix argument, return a row vector of logical ones and\n\
 zeros with each element indicating whether all of the elements of the\n\
-corresponding column of the matrix are non-zero.  For example:\n\
+corresponding column of the matrix are nonzero.  For example:\n\
 \n\
 @example\n\
 @group\n\
-all ([2, 3; 1, 0]))\n\
+all ([2, 3; 1, 0])\n\
     @result{} [ 1, 0 ]\n\
 @end group\n\
 @end example\n\
@@ -159,11 +159,11 @@
 @deftypefn  {Built-in Function} {} any (@var{x})\n\
 @deftypefnx {Built-in Function} {} any (@var{x}, @var{dim})\n\
 For a vector argument, return true (logical 1) if any element of the vector\n\
-is non-zero.\n\
+is nonzero.\n\
 \n\
 For a matrix argument, return a row vector of logical ones and\n\
 zeros with each element indicating whether any of the elements of the\n\
-corresponding column of the matrix are non-zero.  For example:\n\
+corresponding column of the matrix are nonzero.  For example:\n\
 \n\
 @example\n\
 @group\n\
@@ -333,7 +333,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 ())
@@ -575,8 +576,7 @@
 
 DEFUN (rem, args, ,
        "-*- texinfo -*-\n\
-@deftypefn  {Mapping Function} {} rem (@var{x}, @var{y})\n\
-@deftypefnx {Mapping Function} {} fmod (@var{x}, @var{y})\n\
+@deftypefn {Mapping Function} {} rem (@var{x}, @var{y})\n\
 Return the remainder of the division @code{@var{x} / @var{y}}, computed\n\
 using the expression\n\
 \n\
@@ -621,7 +621,7 @@
                     X##NDArray a1 = args(1).X##_array_value (); \
                     retval = binmap<octave_##X,octave_##X,octave_##X> (a0, a1, rem, "rem"); \
                     } \
-                  break
+                  break;
                 MAKE_INT_BRANCH (int8);
                 MAKE_INT_BRANCH (int16);
                 MAKE_INT_BRANCH (int32);
@@ -676,11 +676,11 @@
 }
 
 /*
-%!assert (size (fmod (zeros (0, 2), zeros (0, 2))), [0, 2])
-%!assert (size (fmod (rand (2, 3, 4), zeros (2, 3, 4))), [2, 3, 4])
-%!assert (size (fmod (rand (2, 3, 4), 1)), [2, 3, 4])
-%!assert (size (fmod (1, rand (2, 3, 4))), [2, 3, 4])
-%!assert (size (fmod (1, 2)), [1, 1])
+%!assert (size (rem (zeros (0, 2), zeros (0, 2))), [0, 2])
+%!assert (size (rem (rand (2, 3, 4), zeros (2, 3, 4))), [2, 3, 4])
+%!assert (size (rem (rand (2, 3, 4), 1)), [2, 3, 4])
+%!assert (size (rem (1, rand (2, 3, 4))), [2, 3, 4])
+%!assert (size (rem (1, 2)), [1, 1])
 
 %!assert (rem ([1, 2, 3; -1, -2, -3], 2), [1, 0, 1; -1, 0, -1])
 %!assert (rem ([1, 2, 3; -1, -2, -3], 2 * ones (2, 3)),[1, 0, 1; -1, 0, -1])
@@ -726,8 +726,6 @@
 %!assert (rem (0.94, 0.01), 0.0);
 */
 
-DEFALIAS (fmod, rem)
-
 DEFUN (mod, args, ,
        "-*- texinfo -*-\n\
 @deftypefn {Mapping Function} {} mod (@var{x}, @var{y})\n\
@@ -780,7 +778,7 @@
                     X##NDArray a1 = args(1).X##_array_value (); \
                     retval = binmap<octave_##X,octave_##X,octave_##X> (a0, a1, mod, "mod"); \
                     } \
-                  break
+                  break;
                 MAKE_INT_BRANCH (int8);
                 MAKE_INT_BRANCH (int16);
                 MAKE_INT_BRANCH (int32);
@@ -1262,7 +1260,7 @@
                 retval = arg.X ## _array_value ().cumsum (dim); \
               else \
                 retval = arg.array_value ().cumsum (dim); \
-              break
+              break;
             MAKE_INT_BRANCH (int8);
             MAKE_INT_BRANCH (int16);
             MAKE_INT_BRANCH (int32);
@@ -1332,8 +1330,8 @@
 @deftypefnx {Built-in Function} {@var{v} =} diag (@var{M}, @var{k})\n\
 Return a diagonal matrix with vector @var{v} on diagonal @var{k}.  The\n\
 second argument is optional.  If it is positive, the vector is placed on\n\
-the @var{k}-th super-diagonal.  If it is negative, it is placed on the\n\
-@var{-k}-th sub-diagonal.  The default value of @var{k} is 0, and the\n\
+the @var{k}-th superdiagonal.  If it is negative, it is placed on the\n\
+@var{-k}-th subdiagonal.  The default value of @var{k} is 0, and the\n\
 vector is placed on the main diagonal.  For example:\n\
 \n\
 @example\n\
@@ -1438,6 +1436,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)
@@ -1458,12 +1461,144 @@
        "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {} prod (@var{x})\n\
 @deftypefnx {Built-in Function} {} prod (@var{x}, @var{dim})\n\
-Product of elements along dimension @var{dim}.  If @var{dim} is\n\
-omitted, it defaults to the first non-singleton dimension.\n\
+@deftypefnx {Built-in Function} {} prod (@dots{}, \"native\")\n\
+@deftypefnx {Built-in Function} {} prod (@dots{}, \"double\")\n\
+Product of elements along dimension @var{dim}.\n\
+\n\
+If @var{dim} is omitted, it defaults to the first non-singleton dimension.\n\
+\n\
+The optional @qcode{\"type\"} input determines the class of the variable\n\
+used for calculations.  If the argument @qcode{\"native\"} is given, then\n\
+the operation is performed in the same type as the original argument, rather\n\
+than the default double type.\n\
+\n\
+For example:\n\
+\n\
+@example\n\
+@group\n\
+prod ([true, true])\n\
+   @result{} 1\n\
+prod ([true, true], \"native\")\n\
+   @result{} true\n\
+@end group\n\
+@end example\n\
+\n\
+On the contrary, if @qcode{\"double\"} is given, the operation is performed\n\
+in double precision even for single precision inputs.\n\
 @seealso{cumprod, sum}\n\
 @end deftypefn")
 {
-  DATA_REDUCTION (prod);
+  octave_value retval;
+
+  int nargin = args.length ();
+
+  bool isnative = false;
+  bool isdouble = false;
+
+  if (nargin > 1 && args(nargin - 1).is_string ())
+    {
+      std::string str = args(nargin - 1).string_value ();
+
+      if (! error_state)
+        {
+          if (str == "native")
+            isnative = true;
+          else if (str == "double")
+            isdouble = true;
+          else
+            error ("prod: unrecognized type argument '%s'", str.c_str ());
+          nargin --;
+        }
+    }
+
+  if (error_state)
+    return retval;
+
+  if (nargin == 1 || nargin == 2)
+    {
+      octave_value arg = args(0);
+
+      int dim = -1;
+      if (nargin == 2)
+        {
+          dim = args(1).int_value () - 1;
+          if (dim < 0)
+            error ("prod: invalid dimension DIM = %d", dim + 1);
+        }
+
+      if (! error_state)
+        {
+          switch (arg.builtin_type ())
+            {
+            case btyp_double:
+              if (arg.is_sparse_type ())
+                retval = arg.sparse_matrix_value ().prod (dim);
+              else
+                retval = arg.array_value ().prod (dim);
+              break;
+            case btyp_complex:
+              if (arg.is_sparse_type ())
+                retval = arg.sparse_complex_matrix_value ().prod (dim);
+              else
+                retval = arg.complex_array_value ().prod (dim);
+              break;
+            case btyp_float:
+              if (isdouble)
+                retval = arg.float_array_value ().dprod (dim);
+              else
+                retval = arg.float_array_value ().prod (dim);
+              break;
+            case btyp_float_complex:
+              if (isdouble)
+                retval = arg.float_complex_array_value ().dprod (dim);
+              else
+                retval = arg.float_complex_array_value ().prod (dim);
+              break;
+
+#define MAKE_INT_BRANCH(X) \
+            case btyp_ ## X: \
+              if (isnative) \
+                retval = arg.X ## _array_value ().prod (dim); \
+              else \
+                retval = arg.array_value ().prod (dim); \
+              break;
+            MAKE_INT_BRANCH (int8);
+            MAKE_INT_BRANCH (int16);
+            MAKE_INT_BRANCH (int32);
+            MAKE_INT_BRANCH (int64);
+            MAKE_INT_BRANCH (uint8);
+            MAKE_INT_BRANCH (uint16);
+            MAKE_INT_BRANCH (uint32);
+            MAKE_INT_BRANCH (uint64);
+#undef MAKE_INT_BRANCH
+
+            // GAGME: Accursed Matlab compatibility...
+            case btyp_char:
+              retval = arg.array_value (true).prod (dim);
+              break;
+            case btyp_bool:
+              if (arg.is_sparse_type ())
+                {
+                  if (isnative)
+                    retval = arg.sparse_bool_matrix_value ().all (dim);
+                  else
+                    retval = arg.sparse_matrix_value ().prod (dim);
+                }
+              else if (isnative)
+                retval = arg.bool_array_value ().all (dim);
+              else
+                retval = NDArray (arg.bool_array_value ().all (dim));
+              break;
+
+            default:
+              gripe_wrong_type_arg ("prod", arg);
+            }
+        }
+    }
+  else
+    print_usage ();
+
+  return retval;
 }
 
 /*
@@ -1477,6 +1612,13 @@
 %!assert (prod (single ([i, 2+i, -3+2i, 4])), single (-4 - 32i))
 %!assert (prod (single ([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i])), single ([-1+i, -8+8i, -27+27i]))
 
+%% Test sparse
+%!assert (prod (sparse ([1, 2, 3])), sparse (6))
+%!assert (prod (sparse ([-1; -2; -3])), sparse (-6))
+## Commented out until bug #42290 is fixed
+#%!assert (prod (sparse ([i, 2+i, -3+2i, 4])), sparse (-4 - 32i))
+#%!assert (prod (sparse ([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i])), sparse ([-1+i, -8+8i, -27+27i]))
+
 %!assert (prod ([1, 2; 3, 4], 1), [3, 8])
 %!assert (prod ([1, 2; 3, 4], 2), [2; 12])
 %!assert (prod (zeros (1, 0)), 1)
@@ -1507,7 +1649,24 @@
 %!assert (prod (zeros (0, 2, "single"), 1), single ([1, 1]))
 %!assert (prod (zeros (0, 2, "single"), 2), zeros (0, 1, "single"))
 
+%% Test "double" type argument
+%!assert (prod (single ([1, 2, 3]), "double"), 6)
+%!assert (prod (single ([-1; -2; -3]), "double"), -6)
+%!assert (prod (single ([i, 2+i, -3+2i, 4]), "double"), -4 - 32i)
+%!assert (prod (single ([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i]), "double"), [-1+i, -8+8i, -27+27i])
+
+%% Test "native" type argument
+%!assert (prod (uint8 ([1, 2, 3]), "native"), uint8 (6))
+%!assert (prod (uint8 ([-1; -2; -3]), "native"), uint8 (0))
+%!assert (prod (int8 ([1, 2, 3]), "native"), int8 (6))
+%!assert (prod (int8 ([-1; -2; -3]), "native"), int8 (-6))
+%!assert (prod ([true false; true true], "native"), [true false])
+%!assert (prod ([true false; true true], 2, "native"), [false; true])
+
+%% Test input validation
 %!error prod ()
+%!error prod (1,2,3)
+%!error <unrecognized type argument 'foobar'> prod (1, "foobar")
 */
 
 static bool
@@ -1928,7 +2087,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)
@@ -1942,12 +2101,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)
                 {
@@ -2406,8 +2565,8 @@
 %!assert (cat (3, [], [], [1,2;3,4]), [1,2;3,4])
 %!assert (cat (4, [], [], [1,2;3,4]), [1,2;3,4])
 
-%!assert ([zeros(3,2,2); ones(1,2,2)], repmat ([0;0;0;1],[1,2,2]) )
-%!assert ([zeros(3,2,2); ones(1,2,2)], vertcat (zeros (3,2,2), ones (1,2,2)) )
+%!assert ([zeros(3,2,2); ones(1,2,2)], repmat ([0;0;0;1],[1,2,2]))
+%!assert ([zeros(3,2,2); ones(1,2,2)], vertcat (zeros (3,2,2), ones (1,2,2)))
 
 %!error <dimension mismatch> cat (3, cat (3, [], []), [1,2;3,4])
 %!error <dimension mismatch> cat (3, zeros (0, 0, 2), [1,2;3,4])
@@ -2447,6 +2606,27 @@
 Return the generalized transpose for an N-D array object @var{A}.\n\
 The permutation vector @var{perm} must contain the elements\n\
 @code{1:ndims (A)} (in any order, but each element must appear only once).\n\
+\n\
+The @var{N}th dimension of @var{A} gets remapped to dimension \n\
+@code{@var{PERM}(@var{N})}.  For example:\n\
+\n\
+@example\n\
+@group\n\
+@var{x} = zeros ([2, 3, 5, 7]);\n\
+size (@var{x})\n\
+   @result{}  2   3   5   7\n\
+\n\
+size (permute (@var{x}, [2, 1, 3, 4]))\n\
+   @result{}  3   2   5   7\n\
+\n\
+size (permute (@var{x}, [1, 3, 4, 2]))\n\
+   @result{}  2   5   7   3\n\
+\n\
+## The identity permutation\n\
+size (permute (@var{x}, [1, 2, 3, 4]))\n\
+   @result{}  2   3   5   7\n\
+@end group\n\
+@end example\n\
 @seealso{ipermute}\n\
 @end deftypefn")
 {
@@ -2693,7 +2873,7 @@
 DEFUN (nnz, args, ,
        "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {@var{n} =} nnz (@var{a})\n\
-Return the number of non-zero elements in @var{a}.\n\
+Return the number of nonzero elements in @var{a}.\n\
 @seealso{nzmax, nonzeros, find}\n\
 @end deftypefn")
 {
@@ -2769,12 +2949,16 @@
 @deftypefnx {Built-in Function} {} sum (@dots{}, \"native\")\n\
 @deftypefnx {Built-in Function} {} sum (@dots{}, \"double\")\n\
 @deftypefnx {Built-in Function} {} sum (@dots{}, \"extra\")\n\
-Sum of elements along dimension @var{dim}.  If @var{dim} is\n\
-omitted, it defaults to the first non-singleton dimension.\n\
-\n\
-If the optional argument @qcode{\"native\"} is given, then the sum is\n\
-performed in the same type as the original argument, rather than in the\n\
-default double type.  For example:\n\
+Sum of elements along dimension @var{dim}.\n\
+\n\
+If @var{dim} is omitted, it defaults to the first non-singleton dimension.\n\
+\n\
+The optional @qcode{\"type\"} input determines the class of the variable\n\
+used for calculations.  If the argument @qcode{\"native\"} is given, then\n\
+the operation is performed in the same type as the original argument, rather\n\
+than the default double type.\n\
+\n\
+For example:\n\
 \n\
 @example\n\
 @group\n\
@@ -2788,8 +2972,8 @@
 On the contrary, if @qcode{\"double\"} is given, the sum is performed in\n\
 double precision even for single precision inputs.\n\
 \n\
-For double precision inputs, @qcode{\"extra\"} indicates that a more accurate\n\
-algorithm than straightforward summation is to be used.  For single precision\n\
+For double precision inputs, the @qcode{\"extra\"} option will use a more\n\
+accurate algorithm than straightforward summation.  For single precision\n\
 inputs, @qcode{\"extra\"} is the same as @qcode{\"double\"}.  Otherwise,\n\
 @qcode{\"extra\"} has no effect.\n\
 @seealso{cumsum, sumsq, prod}\n\
@@ -2816,7 +3000,7 @@
           else if (str == "extra")
             isextra = true;
           else
-            error ("sum: unrecognized string argument");
+            error ("sum: unrecognized type argument '%s'", str.c_str ());
           nargin --;
         }
     }
@@ -2883,7 +3067,7 @@
                 retval = arg.X ## _array_value ().sum (dim); \
               else \
                 retval = arg.X ## _array_value ().dsum (dim); \
-              break
+              break;
             MAKE_INT_BRANCH (int8);
             MAKE_INT_BRANCH (int16);
             MAKE_INT_BRANCH (int32);
@@ -2893,7 +3077,8 @@
             MAKE_INT_BRANCH (uint32);
             MAKE_INT_BRANCH (uint64);
 #undef MAKE_INT_BRANCH
-              // GAGME: Accursed Matlab compatibility...
+            
+            // GAGME: Accursed Matlab compatibility...
             case btyp_char:
               if (isextra)
                 retval = arg.array_value (true).xsum (dim);
@@ -2926,11 +3111,6 @@
 }
 
 /*
-%!assert (sum ([true,true]), 2)
-%!assert (sum ([true,true],"native"), true)
-%!assert (sum (int8 ([127,10,-20])), 117)
-%!assert (sum (int8 ([127,10,-20]),'native'), int8 (107))
-
 %!assert (sum ([1, 2, 3]), 6)
 %!assert (sum ([-1; -2; -3]), -6)
 %!assert (sum ([i, 2+i, -3+2i, 4]), 3+4i)
@@ -2981,10 +3161,18 @@
 %!assert (sum (zeros (2, 2, 0, 3, "single"), 4), zeros (2, 2, 0, "single"))
 %!assert (sum (zeros (2, 2, 0, 3, "single"), 7), zeros (2, 2, 0, 3, "single"))
 
+## Test "native"
+%!assert (sum ([true,true]), 2)
+%!assert (sum ([true,true], "native"), true)
+%!assert (sum (int8 ([127,10,-20])), 117)
+%!assert (sum (int8 ([127,10,-20]), "native"), int8 (107))
+
 ;-)
 %!assert (sum ("Octave") + "8", sumsq (primes (17)))
 
 %!error sum ()
+%!error sum (1,2,3)
+%!error <unrecognized type argument 'foobar'> sum (1, "foobar")
 */
 
 DEFUN (sumsq, args, ,
@@ -3495,6 +3683,164 @@
 %!assert (isnumeric (sparse ([true, false])), false)
 */
 
+DEFUN (isscalar, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {} isscalar (@var{x})\n\
+Return true if @var{x} is a scalar.\n\
+@seealso{isvector, ismatrix}\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+  if (args.length () == 1)
+    retval = args(0).numel () == 1;
+  else
+    print_usage ();
+
+  return retval;
+}
+
+/*
+%!assert (isscalar (1))
+%!assert (isscalar ([1, 2]), false)
+%!assert (isscalar ([]), false)
+%!assert (isscalar ([1, 2; 3, 4]), false)
+
+%!assert (isscalar ("t"))
+%!assert (isscalar ("test"), false)
+%!assert (isscalar (["test"; "ing"]), false)
+
+%!test
+%! s.a = 1;
+%! assert (isscalar (s));
+
+%% Test input validation
+%!error isscalar ()
+%!error isscalar (1, 2)
+*/
+
+DEFUN (isvector, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Function File} {} isvector (@var{x})\n\
+Return true if @var{x} is a vector.\n\
+\n\
+A vector is a 2-D array where one of the dimensions is equal to 1.  As a\n\
+consequence a 1x1 array, or scalar, is also a vector.\n\
+@seealso{isscalar, ismatrix, size, rows, columns, length}\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+  if (args.length () == 1)
+    {
+      dim_vector sz = args(0).dims ();
+      retval = sz.length () == 2 && (sz(0) == 1 || sz(1) == 1);
+    }
+  else
+    print_usage ();
+
+  return retval;
+}
+
+/*
+%!assert (isvector (1))
+%!assert (isvector ([1; 2; 3]))
+%!assert (isvector ([]), false)
+%!assert (isvector ([1, 2; 3, 4]), false)
+
+%!assert (isvector ("t"))
+%!assert (isvector ("test"))
+%!assert (isvector (["test"; "ing"]), false)
+
+%!test
+%! s.a = 1;
+%! assert (isvector (s));
+
+%% Test input validation
+%!error isvector ()
+%!error isvector ([1, 2], 2)
+*/
+
+DEFUN (isrow, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Function File} {} isrow (@var{x})\n\
+Return true if @var{x} is a row vector.\n\
+@seealso{iscolumn, isscalar, isvector, ismatrix}\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+  if (args.length () == 1)
+    {
+      dim_vector sz = args(0).dims ();
+      retval = sz.length () == 2 && sz(0) == 1;
+    }
+  else
+    print_usage ();
+
+  return retval;
+}
+
+/*
+%!assert (isrow ([1, 2, 3]))
+%!assert (isrow ([1; 2; 3]), false)
+%!assert (isrow (1))
+%!assert (isrow ([]), false)
+%!assert (isrow ([1, 2; 3, 4]), false)
+
+%!assert (isrow ("t"))
+%!assert (isrow ("test"))
+%!assert (isrow (["test"; "ing"]), false)
+
+%!test
+%! s.a = 1;
+%! assert (isrow (s));
+
+%% Test input validation
+%!error isrow ()
+%!error isrow ([1, 2], 2)
+*/
+
+DEFUN (iscolumn, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Function File} {} iscolumn (@var{x})\n\
+Return true if @var{x} is a column vector.\n\
+@seealso{isrow, isscalar, isvector, ismatrix}\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+  if (args.length () == 1)
+    {
+      dim_vector sz = args(0).dims ();
+      retval = sz.length () == 2 && sz(1) == 1;
+    }
+  else
+    print_usage ();
+
+  return retval;
+}
+
+/*
+%!assert (iscolumn ([1, 2, 3]), false)
+%!assert (iscolumn ([1; 2; 3]))
+%!assert (iscolumn (1))
+%!assert (iscolumn ([]), false)
+%!assert (iscolumn ([1, 2; 3, 4]), false)
+
+%!assert (iscolumn ("t"))
+%!assert (iscolumn ("test"), false)
+%!assert (iscolumn (["test"; "ing"]), false)
+
+%!test
+%! s.a = 1;
+%! assert (iscolumn (s));
+
+%% Test input validation
+%!error iscolumn ()
+%!error iscolumn ([1, 2], 2)
+*/
+
 DEFUN (ismatrix, args, ,
        "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} ismatrix (@var{a})\n\
@@ -3545,6 +3891,47 @@
 %!error ismatrix ([1, 2; 3, 4], 2)
 */
 
+DEFUN (issquare, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Function File} {} issquare (@var{x})\n\
+Return true if @var{x} is a square matrix.\n\
+@seealso{isscalar, isvector, ismatrix, size}\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+  if (args.length () == 1)
+    {
+      dim_vector sz = args(0).dims ();
+      retval = sz.length () == 2 && sz(0) == sz(1);
+    }
+  else
+    print_usage ();
+
+  return retval;
+}
+
+/*
+%!assert (issquare ([]))
+%!assert (issquare (1))
+%!assert (! issquare ([1, 2]))
+%!assert (issquare ([1, 2; 3, 4]))
+%!assert (! issquare ([1, 2; 3, 4; 5, 6]))
+%!assert (! issquare (ones (3,3,3)))
+%!assert (issquare ("t"))
+%!assert (! issquare ("test"))
+%!assert (issquare (["test"; "ing"; "1"; "2"]))
+%!test
+%! s.a = 1;
+%! assert (issquare (s));
+%!assert (issquare ({1, 2; 3, 4}))
+%!assert (sparse (([1, 2; 3, 4])))
+
+%% Test input validation
+%!error issquare ()
+%!error issquare ([1, 2; 3, 4], 2)
+*/
+
 static octave_value
 fill_matrix (const octave_value_list& args, int val, const char *fcn)
 {
@@ -4690,7 +5077,7 @@
 @equiv{}\n\
 eye (2, 2)\n\
 @equiv{}\n\
-eye (size ([1, 2; 3, 4])\n\
+eye (size ([1, 2; 3, 4]))\n\
 @end group\n\
 @end example\n\
 \n\
@@ -5436,7 +5823,7 @@
 %!assert (norm (x,"inf"), single (7))
 %!assert (norm (x,"fro"), single (10), -eps ("single"))
 %!assert (norm (x), single (10))
-%!assert (norm (single ([1e200, 1])), single (1e200))
+%!assert (norm (single ([1e38, 1])), single (1e38))
 %!assert (norm (single ([3+4i, 3-4i, sqrt(31)])), single (9), -4*eps ("single"))
 %!shared m
 %! m = single (magic (4));
@@ -5485,9 +5872,10 @@
 
 DEFUN (not, args, ,
        "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {} not (@var{x})\n\
-Return the logical NOT of @var{x}.  This function is equivalent to\n\
-@code{! x}.\n\
+@deftypefn {Built-in Function} {@var{z} =} not (@var{x})\n\
+Return the logical NOT of @var{x}.\n\
+\n\
+This function is equivalent to the operator syntax @w{@code{! x}}.\n\
 @seealso{and, or, xor}\n\
 @end deftypefn")
 {
@@ -5826,12 +6214,13 @@
 
 DEFUN (and, args, ,
        "-*- texinfo -*-\n\
-@deftypefn  {Built-in Function} {} and (@var{x}, @var{y})\n\
-@deftypefnx {Built-in Function} {} and (@var{x1}, @var{x2}, @dots{})\n\
+@deftypefn  {Built-in Function} {@var{z} =} and (@var{x}, @var{y})\n\
+@deftypefnx {Built-in Function} {@var{z} =} and (@var{x1}, @var{x2}, @dots{})\n\
 Return the logical AND of @var{x} and @var{y}.\n\
-This function is equivalent to @w{@code{x & y}}.\n\
-If more arguments are given, the logical and is applied\n\
-cumulatively from left to right:\n\
+\n\
+This function is equivalent to the operator syntax @w{@code{x & y}}.  If\n\
+more than two arguments are given, the logical AND is applied cumulatively\n\
+from left to right:\n\
 \n\
 @example\n\
 (@dots{}((x1 & x2) & x3) & @dots{})\n\
@@ -5847,12 +6236,13 @@
 
 DEFUN (or, args, ,
        "-*- texinfo -*-\n\
-@deftypefn  {Built-in Function} {} or (@var{x}, @var{y})\n\
-@deftypefnx {Built-in Function} {} or (@var{x1}, @var{x2}, @dots{})\n\
+@deftypefn  {Built-in Function} {@var{z} =} or (@var{x}, @var{y})\n\
+@deftypefnx {Built-in Function} {@var{z} =} or (@var{x1}, @var{x2}, @dots{})\n\
 Return the logical OR of @var{x} and @var{y}.\n\
-This function is equivalent to @w{@code{x | y}}.\n\
-If more arguments are given, the logical or is applied\n\
-cumulatively from left to right:\n\
+\n\
+This function is equivalent to the operator syntax @w{@code{x | y}}.  If\n\
+more than two arguments are given, the logical OR is applied cumulatively\n\
+from left to right:\n\
 \n\
 @example\n\
 (@dots{}((x1 | x2) | x3) | @dots{})\n\
@@ -6465,18 +6855,20 @@
   // FIXME: shouldn't these modes be scoped inside a class?
   sortmode smode = UNSORTED;
 
-  std::string mode = arg.string_value ();
-
-  if (error_state)
-    error ("issorted: expecting %s argument to be a character string", argn);
-  else if (mode == "ascending")
-    smode = ASCENDING;
-  else if (mode == "descending")
-    smode = DESCENDING;
-  else if (mode == "either")
-    smode = UNSORTED;
+  if (arg.is_string ())
+    {
+      std::string mode = arg.string_value ();
+      if (mode == "ascending")
+        smode = ASCENDING;
+      else if (mode == "descending")
+        smode = DESCENDING;
+      else if (mode == "either")
+        smode = UNSORTED;
+      else
+        error ("issorted: MODE must be \"ascending\", \"descending\", or \"either\"");
+    }
   else
-    error ("issorted: MODE must be \"ascending\", \"descending\", or \"either\"");
+    error ("issorted: expecting %s argument to be a string", argn);
 
   return smode;
 }
@@ -6520,17 +6912,16 @@
       if (nargin == 3)
         smode = get_sort_mode_option (args(2), "third");
 
-      std::string tmp = args(1).string_value ();
-
-      if (! error_state)
+      if (args(1).is_string ())
         {
+          std::string tmp = args(1).string_value ();
           if (tmp == "rows")
             by_rows = true;
           else
             smode = get_sort_mode_option (args(1), "second");
         }
       else
-        error ("expecting second argument to be character string");
+        error ("issorted: second argument must be a string");
 
       if (error_state)
         return retval;
@@ -6653,7 +7044,7 @@
 #define MAKE_INT_BRANCH(X) \
         case btyp_ ## X: \
           retval = argx.X ## _array_value ().nth_element (n, dim); \
-          break
+          break;
 
         MAKE_INT_BRANCH (int8);
         MAKE_INT_BRANCH (int16);
@@ -6797,7 +7188,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 ())
             {
@@ -6824,7 +7216,7 @@
               retval = do_accumarray_minmax (idx, vals.X ## _array_value (), \
                                              n, ismin, \
                                              zero.X ## _scalar_value ()); \
-              break
+              break;
 
             MAKE_INT_BRANCH (int8);
             MAKE_INT_BRANCH (int16);
@@ -6879,7 +7271,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 ();
@@ -6958,7 +7351,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))
@@ -6968,14 +7362,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;
             }
@@ -7052,7 +7448,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 ())
@@ -7330,7 +7727,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);
@@ -7417,7 +7815,7 @@
 #define BTYP_BRANCH(X, EX) \
             case btyp_ ## X: \
               retval = do_repelems (x.EX ## _value (), r); \
-              break
+              break;
 
               BTYP_BRANCH (double, array);
               BTYP_BRANCH (float, float_array);
--- a/libinterp/corefcn/debug.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/debug.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -85,7 +85,6 @@
           if (file.eof ())
             {
               // Expected to read the entire file.
-
               retval = buf;
             }
           else
@@ -99,8 +98,7 @@
 static std::deque<size_t>
 get_line_offsets (const std::string& buf)
 {
-  // This could maybe be smarter.  Is deque the right thing to use
-  // here?
+  // This could maybe be smarter.  Is deque the right thing to use here?
 
   std::deque<size_t> offsets;
 
@@ -207,28 +205,47 @@
   if (args.length () == 0)
     return;
 
-  // If we are already in a debugging function.
-  if (octave_call_stack::caller_user_code ())
-    {
-      idx = 0;
-      symbol_name = get_user_code ()->name ();
-    }
+  if (args(0).is_string ())
+  {
+    // string could be function name or line number
+    int isint = atoi (args(0).string_value ().c_str ());
+
+    if (error_state)
+      return;
+
+    if (isint == 0)
+      {
+        // It was a function name
+        symbol_name = args(0).string_value ();
+        if (error_state)
+          return;
+        idx = 1;
+      }
+    else
+      {
+        // It was a line number.  Need to get function name from debugger.
+        if (Vdebugging)
+          {
+            symbol_name = get_user_code ()->name ();
+            idx = 0;
+          }
+        else
+          {
+            error ("%s: no function specified", who);
+          }
+      }
+  }
   else if (args(0).is_map ())
     {
-      // Problem because parse_dbfunction_params() can only pass out a
-      // single function
-    }
-  else if (args(0).is_string ())
-    {
-      symbol_name = args(0).string_value ();
-      if (error_state)
-        return;
-      idx = 1;
+      // This is a problem because parse_dbfunction_params()
+      // can only pass out a single function.
+      error ("%s: struct input not implemented", who);
+      return;
     }
   else
     error ("%s: invalid parameter specified", who);
 
-  for (int i = idx; i < nargin; i++ )
+  for (int i = idx; i < nargin; i++)
     {
       if (args(i).is_string ())
         {
@@ -238,7 +255,7 @@
           lines[list_idx++] = line;
         }
       else if (args(i).is_map ())
-        octave_stdout << who << ": accepting a struct" << std::endl;
+        octave_stdout << who << ": skipping struct input" << std::endl;
       else
         {
           const NDArray arg = args(i).array_value ();
@@ -356,7 +373,6 @@
   return retval;
 }
 
-
 int
 bp_table::do_remove_breakpoint_1 (octave_user_code *fcn,
                                   const std::string& fname,
@@ -522,9 +538,12 @@
 void
 bp_table::do_remove_all_breakpoints (void)
 {
-  for (const_bp_set_iterator it = bp_set.begin (); it != bp_set.end (); it++)
-    remove_all_breakpoints_in_file (*it);
-
+  // Odd loop structure required because delete will invalidate bp_set iterators
+  for (const_bp_set_iterator it=bp_set.begin (), it_next=it; it != bp_set.end (); it=it_next)
+    {
+      ++it_next;
+      remove_all_breakpoints_in_file (*it);
+    }
 
   tree_evaluator::debug_mode = bp_table::have_breakpoints () || Vdebugging;
 }
@@ -537,7 +556,7 @@
 
   for (int i = 0; i < slist.length (); i++)
     {
-      if (slist (i).string_value () == match)
+      if (slist(i).string_value () == match)
         {
           retval = slist(i).string_value ();
           break;
@@ -547,7 +566,6 @@
   return retval;
 }
 
-
 bp_table::fname_line_map
 bp_table::do_get_breakpoint_list (const octave_value_list& fname_list)
 {
@@ -576,7 +594,7 @@
                       bp_table::intmap bkpts_vec;
 
                       for (int i = 0; i < len; i++)
-                        bkpts_vec[i] = bkpts (i).double_value ();
+                        bkpts_vec[i] = bkpts(i).double_value ();
 
                       std::string symbol_name = f->name ();
 
@@ -615,31 +633,36 @@
 
 DEFUN (dbstop, args, ,
        "-*- texinfo -*-\n\
-@deftypefn  {Built-in Function} {@var{rline} =} dbstop (\"@var{func}\")\n\
+@deftypefn  {Command} {} dbstop @var{func}\n\
+@deftypefnx {Command} {} dbstop @var{func} @var{line}\n\
+@deftypefnx {Command} {} dbstop @var{func} @var{line1} @var{line2} @dots{}\n\
+@deftypefnx {Command} {} dbstop @var{line} @dots{}\n\
+@deftypefnx {Built-in Function} {@var{rline} =} dbstop (\"@var{func}\")\n\
 @deftypefnx {Built-in Function} {@var{rline} =} dbstop (\"@var{func}\", @var{line})\n\
 @deftypefnx {Built-in Function} {@var{rline} =} dbstop (\"@var{func}\", @var{line1}, @var{line2}, @dots{})\n\
-Set a breakpoint in function @var{func}.\n\
+@deftypefnx {Built-in Function} {} dbstop (\"@var{func}\", [@var{line1}, @dots{}])\n\
+@deftypefnx {Built-in Function} {} dbstop (@var{line}, @dots{})\n\
+Set a breakpoint at line number @var{line} in function @var{func}.\n\
 \n\
 Arguments are\n\
 \n\
 @table @var\n\
 @item func\n\
-Function name as a string variable.  When already in debug\n\
-mode this should be left out and only the line should be given.\n\
+Function name as a string variable.  When already in debug mode this argument\n\
+can be omitted and the current function will be used.\n\
 \n\
 @item line\n\
-Line number where the breakpoint should be set.  Multiple\n\
-lines may be given as separate arguments or as a vector.\n\
+Line number where the breakpoint should be set.  Multiple lines may be given\n\
+as separate arguments or as a vector.\n\
 @end table\n\
 \n\
-When called with a single argument @var{func}, the breakpoint\n\
-is set at the first executable line in the named function.\n\
+When called with a single argument @var{func}, the breakpoint is set at the\n\
+first executable line in the named function.\n\
 \n\
-The optional output @var{rline} is the real line number where the\n\
-breakpoint was set.  This can differ from specified line if\n\
-the line is not executable.  For example, if a breakpoint attempted on a\n\
-blank line then Octave will set the real breakpoint at the\n\
-next executable line.\n\
+The optional output @var{rline} is the real line number where the breakpoint\n\
+was set.  This can differ from the specified line if the line is not\n\
+executable.  For example, if a breakpoint attempted on a blank line then\n\
+Octave will set the real breakpoint at the next executable line.\n\
 @seealso{dbclear, dbstatus, dbstep, debug_on_error, debug_on_warning, debug_on_interrupt}\n\
 @end deftypefn")
 {
@@ -660,28 +683,38 @@
 
 DEFUN (dbclear, args, ,
        "-*- texinfo -*-\n\
-@deftypefn  {Built-in Function} {} dbclear (\"@var{func}\")\n\
-@deftypefnx {Built-in Function} {} dbclear (\"@var{func}\", @var{line}, @dots{})\n\
+@deftypefn  {Command} {} dbclear @var{func}\n\
+@deftypefnx {Command} {} dbclear @var{func} @var{line}\n\
+@deftypefnx {Command} {} dbclear @var{func} @var{line1} @var{line2} @dots{}\n\
+@deftypefnx {Command} {} dbclear @var{line} @dots{}\n\
+@deftypefnx {Command} {} dbclear all\n\
+@deftypefnx {Built-in Function} {} dbclear (\"@var{func}\")\n\
+@deftypefnx {Built-in Function} {} dbclear (\"@var{func}\", @var{line})\n\
+@deftypefnx {Built-in Function} {} dbclear (\"@var{func}\", @var{line1}, @var{line2}, @dots{})\n\
+@deftypefnx {Built-in Function} {} dbclear (\"@var{func}\", [@var{line1}, @dots{}])\n\
 @deftypefnx {Built-in Function} {} dbclear (@var{line}, @dots{})\n\
-Delete a breakpoint in the function @var{func}.\n\
+@deftypefnx {Built-in Function} {} dbclear (\"all\")\n\
+Delete a breakpoint at line number @var{line} in the function @var{func}.\n\
 \n\
 Arguments are\n\
 \n\
 @table @var\n\
 @item func\n\
-Function name as a string variable.  When already in debug\n\
-mode this argument should be omitted and only the line number should be\n\
-given.\n\
+Function name as a string variable.  When already in debug mode this argument\n\
+can be omitted and the current function will be used.\n\
 \n\
 @item line\n\
-Line number from which to remove a breakpoint.  Multiple\n\
-lines may be given as separate arguments or as a vector.\n\
+Line number from which to remove a breakpoint.  Multiple lines may be given\n\
+as separate arguments or as a vector.\n\
 @end table\n\
 \n\
-When called without a line number specification all breakpoints\n\
-in the named function are cleared.\n\
+When called without a line number specification all breakpoints in the named\n\
+function are cleared.\n\
 \n\
 If the requested line is not a breakpoint no action is performed.\n\
+\n\
+The special keyword @qcode{\"all\"} will clear all breakpoints from all\n\
+files.\n\
 @seealso{dbstop, dbstatus, dbwhere}\n\
 @end deftypefn")
 {
@@ -689,10 +722,17 @@
   std::string symbol_name = "";
   bp_table::intmap lines;
 
+  int nargin = args.length (); 
+
   parse_dbfunction_params ("dbclear", args, symbol_name, lines);
 
-  if (! error_state)
-    bp_table::remove_breakpoint (symbol_name, lines);
+  if (nargin == 1 && symbol_name == "all")
+    bp_table::remove_all_breakpoints ();
+  else
+  {
+    if (! error_state)
+      bp_table::remove_breakpoint (symbol_name, lines);
+  }
 
   return retval;
 }
@@ -724,6 +764,9 @@
 A line number, or vector of line numbers, with a breakpoint.\n\
 @end table\n\
 \n\
+Note: When @code{dbstatus} is called from the debug prompt within a function,\n\
+the list of breakpoints is automatically trimmed to the breakpoints in the\n\
+current function.\n\
 @seealso{dbclear, dbwhere}\n\
 @end deftypefn")
 {
@@ -752,11 +795,14 @@
     }
   else
     {
-      octave_user_code *dbg_fcn = get_user_code ();
-      if (dbg_fcn)
+      if (Vdebugging)
         {
-          symbol_name = dbg_fcn->name ();
-          fcn_list(0) = symbol_name;
+          octave_user_code *dbg_fcn = get_user_code ();
+          if (dbg_fcn)
+            {
+              symbol_name = dbg_fcn->name ();
+              fcn_list(0) = symbol_name;
+            }
         }
 
       bp_list = bp_table::get_breakpoint_list (fcn_list);
@@ -844,7 +890,7 @@
 
       if (l > 0)
         {
-          octave_stdout << " line " << l << std::endl;
+          octave_stdout << "line " << l << std::endl;
 
           if (have_file)
             {
@@ -855,7 +901,7 @@
             }
         }
       else
-        octave_stdout << " <unknown line>" << std::endl;
+        octave_stdout << "<unknown line>" << std::endl;
     }
   else
     error ("dbwhere: must be inside a user function to use dbwhere\n");
@@ -863,8 +909,6 @@
   return retval;
 }
 
-// Copied and modified from the do_type command in help.cc
-// Maybe we could share some code?
 void
 do_dbtype (std::ostream& os, const std::string& name, int start, int end)
 {
@@ -876,30 +920,16 @@
 
       if (fs)
         {
-          char ch;
           int line = 1;
-          bool isnewline = true;
+          std::string text;  
 
-          // FIXME: Why not use line-oriented input here [getline()]?
-          while (fs.get (ch) && line <= end)
-            {
-              if (isnewline && line >= start)
-                {
-                  os << line << "\t";
-                  isnewline = false;
-                }
-
-              if (line >= start)
-                {
-                  os << ch;
-                }
-
-              if (ch == '\n')
-                {
-                  line++;
-                  isnewline = true;
-                }
-            }
+          while (std::getline (fs, text) && line <= end)
+          {
+            if (line >= start)
+              os << line << "\t" << text << "\n";
+            
+            line++;
+          }
         }
       else
         os << "dbtype: unable to open '" << ff << "' for reading!\n";
@@ -946,13 +976,14 @@
           dbg_fcn = get_user_code ();
 
           if (dbg_fcn)
-            do_dbtype (octave_stdout, dbg_fcn->name (), 0,
-                       std::numeric_limits<int>::max ());
+            do_dbtype (octave_stdout, dbg_fcn->fcn_file_name (),
+                       0, std::numeric_limits<int>::max ());
           else
             error ("dbtype: must be inside a user function to give no arguments to dbtype\n");
+
           break;
 
-        case 1: // (dbtype func) || (dbtype start:end)
+        case 1: // (dbtype start:end) || (dbtype func) || (dbtype lineno)
           {
             std::string arg = argv[1];
 
@@ -975,28 +1006,51 @@
                       end = atoi (end_str.c_str ());
 
                     if (std::min (start, end) <= 0)
-                      error ("dbtype: start and end lines must be >= 1\n");
+                      {
+                        error ("dbtype: start and end lines must be >= 1\n");
+                        break;
+                      }
 
                     if (start <= end)
-                      do_dbtype (octave_stdout, dbg_fcn->name (), start, end);
+                      do_dbtype (octave_stdout, dbg_fcn->fcn_file_name (),
+                                 start, end);
                     else
                       error ("dbtype: start line must be less than end line\n");
                   }
               }
-            else  // (dbtype func)
+            else  // (dbtype func) || (dbtype lineno)
               {
-                dbg_fcn = get_user_code (arg);
+                int line = atoi (arg.c_str ());
+
+                if (line == 0)  // (dbtype func)
+                  {
+                    dbg_fcn = get_user_code (arg);
 
-                if (dbg_fcn)
-                  do_dbtype (octave_stdout, dbg_fcn->name (), 0,
-                             std::numeric_limits<int>::max ());
-                else
-                  error ("dbtype: function <%s> not found\n", arg.c_str ());
+                    if (dbg_fcn)
+                      do_dbtype (octave_stdout, dbg_fcn->fcn_file_name (),
+                                 0, std::numeric_limits<int>::max ());
+                    else
+                      error ("dbtype: function <%s> not found\n", arg.c_str ());
+                  }
+                else  // (dbtype lineno)
+                  {
+                    if (line <= 0)
+                      {
+                        error ("dbtype: start and end lines must be >= 1\n");
+                        break;
+                      }
+
+                    dbg_fcn = get_user_code ();
+
+                    if (dbg_fcn)
+                      do_dbtype (octave_stdout, dbg_fcn->fcn_file_name (),
+                                 line, line);
+                  }
               }
           }
           break;
 
-        case 2: // (dbtype func start:end) , (dbtype func start)
+        case 2: // (dbtype func start:end) || (dbtype func start)
           dbg_fcn = get_user_code (argv[1]);
 
           if (dbg_fcn)
@@ -1023,10 +1077,14 @@
                 }
 
               if (std::min (start, end) <= 0)
-                error ("dbtype: start and end lines must be >= 1\n");
+                {
+                  error ("dbtype: start and end lines must be >= 1\n");
+                  break;
+                }
 
               if (start <= end)
-                do_dbtype (octave_stdout, dbg_fcn->name (), start, end);
+                do_dbtype (octave_stdout, dbg_fcn->fcn_file_name (),
+                           start, end);
               else
                 error ("dbtype: start line must be less than end line\n");
             }
@@ -1096,13 +1154,13 @@
             {
               int l_min = std::max (l - n/2, 0);
               int l_max = l + n/2;
-              do_dbtype (octave_stdout, dbg_fcn->name (), l_min, l-1);
+              do_dbtype (octave_stdout, name, l_min, l-1);
 
               std::string line = get_file_line (name, l);
               if (! line.empty ())
                 octave_stdout << l << "-->\t" << line << std::endl;
 
-              do_dbtype (octave_stdout, dbg_fcn->name (), l+1, l_max);
+              do_dbtype (octave_stdout, name, l+1, l_max);
             }
         }
       else
@@ -1166,10 +1224,9 @@
 
   if (! error_state)
     {
-      octave_map stk = octave_call_stack::backtrace (nskip, curr_frame);
-
       if (nargout == 0)
         {
+          octave_map stk = octave_call_stack::backtrace (nskip, curr_frame);
           octave_idx_type nframes_to_display = stk.numel ();
 
           if (nframes_to_display > 0)
@@ -1215,6 +1272,10 @@
         }
       else
         {
+          octave_map stk = octave_call_stack::backtrace (nskip,
+                                                         curr_frame,
+                                                         false);
+
           retval(1) = curr_frame < 0 ? 1 : curr_frame + 1;
           retval(0) = stk;
         }
@@ -1309,8 +1370,8 @@
 
 DEFUN (dbup, args, ,
        "-*- texinfo -*-\n\
-@deftypefn  {Built-in Function} {} dbup\n\
-@deftypefnx {Built-in Function} {} dbup (@var{n})\n\
+@deftypefn  {Command} {} dbup\n\
+@deftypefnx {Command} {} dbup @var{n}\n\
 In debugging mode, move up the execution stack @var{n} frames.\n\
 If @var{n} is omitted, move up one frame.\n\
 @seealso{dbstack, dbdown}\n\
@@ -1325,8 +1386,8 @@
 
 DEFUN (dbdown, args, ,
        "-*- texinfo -*-\n\
-@deftypefn  {Built-in Function} {} dbdown\n\
-@deftypefnx {Built-in Function} {} dbdown (@var{n})\n\
+@deftypefn  {Command} {} dbdown\n\
+@deftypefnx {Command} {} dbdown @var{n}\n\
 In debugging mode, move down the execution stack @var{n} frames.\n\
 If @var{n} is omitted, move down one frame.\n\
 @seealso{dbstack, dbup}\n\
@@ -1401,7 +1462,7 @@
                 }
             }
           else
-            error ("dbstep: input argument must be a character string");
+            error ("dbstep: input argument must be a string");
         }
       else
         {
@@ -1488,7 +1549,7 @@
 
 DEFUN (db_next_breakpoint_quiet, args, ,
        "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {} db_next_breakpoint_quiet ()\n\
+@deftypefn  {Built-in Function} {} db_next_breakpoint_quiet ()\n\
 @deftypefnx {Built-in Function} {} db_next_breakpoint_quiet (@var{flag})\n\
 Disable line info printing at the next breakpoint.  With a logical\n\
 argument, set the state on or off.\n\
--- a/libinterp/corefcn/defaults.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/defaults.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -74,6 +74,7 @@
 std::string Vlocal_api_fcn_file_dir;
 std::string Vlocal_fcn_file_dir;
 
+std::string Voct_data_dir;
 std::string Voct_etc_dir;
 std::string Voct_locale_dir;
 
@@ -219,6 +220,12 @@
 }
 
 static void
+set_default_oct_data_dir (void)
+{
+  Voct_data_dir = subst_octave_home (OCTAVE_OCTDATADIR);
+}
+
+static void
 set_default_oct_etc_dir (void)
 {
   Voct_etc_dir = subst_octave_home (OCTAVE_OCTETCDIR);
@@ -435,6 +442,7 @@
   set_default_local_api_fcn_file_dir ();
   set_default_local_fcn_file_dir ();
 
+  set_default_oct_data_dir ();
   set_default_oct_etc_dir ();
   set_default_oct_locale_dir ();
 
@@ -594,7 +602,8 @@
 DEFUNX ("OCTAVE_VERSION", FOCTAVE_VERSION, args, ,
         "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} OCTAVE_VERSION ()\n\
-Return the version number of Octave, as a string.\n\
+Return the version number of Octave as a string.\n\
+@seealso{ver, version}\n\
 @end deftypefn")
 {
   octave_value retval;
--- a/libinterp/corefcn/defaults.in.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/defaults.in.h	Mon Jan 12 09:17:35 2015 -0800
@@ -148,6 +148,10 @@
 #define OCTAVE_MANDIR %OCTAVE_MANDIR%
 #endif
 
+#ifndef OCTAVE_OCTDATADIR
+#define OCTAVE_OCTDATADIR %OCTAVE_OCTDATADIR%
+#endif
+
 #ifndef OCTAVE_OCTFILEDIR
 #define OCTAVE_OCTFILEDIR %OCTAVE_OCTFILEDIR%
 #endif
@@ -202,6 +206,7 @@
 extern OCTINTERP_API std::string Vlocal_api_fcn_file_dir;
 extern OCTINTERP_API std::string Vlocal_fcn_file_dir;
 
+extern OCTINTERP_API std::string Voct_data_dir;
 extern OCTINTERP_API std::string Voct_etc_dir;
 extern OCTINTERP_API std::string Voct_locale_dir;
 
--- a/libinterp/corefcn/dirfns.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/dirfns.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -608,7 +608,7 @@
         [2,1] = file2\n\
       @}\n\
 @end example\n\
-@seealso{ls, dir, readdir, what, fnmatch}\n\
+@seealso{ls, dir, readdir, what}\n\
 @end deftypefn")
 {
   octave_value retval;
@@ -634,7 +634,7 @@
 
 /*
 %!test
-%! tmpdir = tmpnam;
+%! tmpdir = tempname;
 %! filename = {"file1", "file2", "file3", "myfile1", "myfile1b"};
 %! if (mkdir (tmpdir))
 %!   cwd = pwd;
@@ -664,7 +664,7 @@
 %! assert (result3, {"file1"; "file2"});
 */
 
-DEFUNX ("fnmatch", Ffnmatch, args, ,
+DEFUN (__fnmatch__, args, ,
         "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} fnmatch (@var{pattern}, @var{string})\n\
 Return true or false for each element of @var{string} that matches any of\n\
--- a/libinterp/corefcn/display.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/display.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -24,143 +24,28 @@
 #include <config.h>
 #endif
 
-#include <cstdlib>
-
-#if defined (OCTAVE_USE_WINDOWS_API)
-#include <windows.h>
-#elif defined (HAVE_FRAMEWORK_CARBON)
-#include <Carbon/Carbon.h>
-#elif defined (HAVE_X_WINDOWS)
-#include <X11/Xlib.h>
-#endif
-
 #include "singleton-cleanup.h"
 
+#include "cdisplay.h"
 #include "display.h"
 #include "error.h"
 
 display_info *display_info::instance = 0;
 
-#if defined (HAVE_FRAMEWORK_CARBON) && ! defined (HAVE_CARBON_CGDISPLAYBITSPERPIXEL)
-// FIXME: This will only work for MacOS > 10.5. For earlier versions
-// this code is not needed (use CGDisplayBitsPerPixel instead).
-size_t DisplayBitsPerPixel (CGDirectDisplayID display)
-{
-  CGDisplayModeRef mode = CGDisplayCopyDisplayMode (display);
-  CFStringRef pixelEncoding = CGDisplayModeCopyPixelEncoding (mode);
-
-  if (CFStringCompare (pixelEncoding, CFSTR (IO32BitDirectPixels), 0) == 0)
-    return 32;
-  else if (CFStringCompare (pixelEncoding, CFSTR (IO16BitDirectPixels), 0) == 0)
-    return 16;
-  else
-    return 8;
-}
-#endif
-
 void
 display_info::init (bool query)
 {
   if (query)
     {
-#if defined (OCTAVE_USE_WINDOWS_API)
-
-      HDC hdc = GetDC (0);
-
-      if (hdc)
-        {
-          dp = GetDeviceCaps (hdc, BITSPIXEL);
-
-          ht = GetDeviceCaps (hdc, VERTRES);
-          wd = GetDeviceCaps (hdc, HORZRES);
-
-          double ht_mm = GetDeviceCaps (hdc, VERTSIZE);
-          double wd_mm = GetDeviceCaps (hdc, HORZSIZE);
-
-          rx = wd * 25.4 / wd_mm;
-          ry = ht * 25.4 / ht_mm;
-
-          dpy_avail = true;
-        }
-      else
-        err_msg = "no graphical display found";
-
-#elif defined (HAVE_FRAMEWORK_CARBON)
+      int avail = 0;
 
-      CGDirectDisplayID display = CGMainDisplayID ();
-
-      if (display)
-        {
-#  if defined (HAVE_CARBON_CGDISPLAYBITSPERPIXEL)
-          // For MacOS < 10.7 use the line below
-          dp = CGDisplayBitsPerPixel (display);
-#  else
-          // For MacOS > 10.5 use the line below
-          dp = DisplayBitsPerPixel (display);
-#  endif
-
-          ht = CGDisplayPixelsHigh (display);
-          wd = CGDisplayPixelsWide (display);
-
-          CGSize sz_mm = CGDisplayScreenSize (display);
-          // For MacOS >= 10.6, CGSize is a struct keeping 2 CGFloat values,
-          // but the CGFloat typedef is not present on older systems,
-          // so use double instead.
-          double ht_mm = sz_mm.height;
-          double wd_mm = sz_mm.width;
-
-          rx = wd * 25.4 / wd_mm;
-          ry = ht * 25.4 / ht_mm;
+      const char *msg = octave_get_display_info (&ht, &wd, &dp, &rx, &ry,
+                                                 &avail);
 
-          dpy_avail = true;
-        }
-      else
-        err_msg = "no graphical display found";
-
-#elif defined (HAVE_X_WINDOWS)
-
-      const char *display_name = getenv ("DISPLAY");
-
-      if (display_name && *display_name)
-        {
-          Display *display = XOpenDisplay (display_name);
-
-          if (display)
-            {
-              Screen *screen = DefaultScreenOfDisplay (display);
-
-              if (screen)
-                {
-                  dp = DefaultDepthOfScreen (screen);
-
-                  ht = HeightOfScreen (screen);
-                  wd = WidthOfScreen (screen);
+      dpy_avail = avail;
 
-                  int screen_number = XScreenNumberOfScreen (screen);
-
-                  double ht_mm = DisplayHeightMM (display, screen_number);
-                  double wd_mm = DisplayWidthMM (display, screen_number);
-
-                  rx = wd * 25.4 / wd_mm;
-                  ry = ht * 25.4 / ht_mm;
-                }
-              else
-                err_msg = "X11 display has no default screen";
-
-              XCloseDisplay (display);
-
-              dpy_avail = true;
-            }
-          else
-            err_msg = "unable to open X11 DISPLAY";
-        }
-      else
-        err_msg = "X11 DISPLAY environment variable not set";
-#else
-
-      err_msg = "no graphical display found";
-
-#endif
+      if (msg)
+        err_msg = msg;
     }
 }
 
--- a/libinterp/corefcn/dlmread.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/dlmread.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -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;
@@ -483,7 +491,7 @@
 
 /*
 %!shared file
-%! file = tmpnam ();
+%! file = tempname ();
 %! fid = fopen (file, "wt");
 %! fwrite (fid, "1, 2, 3\n4, 5, 6\n7, 8, 9\n10, 11, 12");
 %! fclose (fid);
@@ -502,7 +510,7 @@
 %! unlink (file);
 
 %!shared file
-%! file = tmpnam ();
+%! file = tempname ();
 %! fid = fopen (file, "wt");
 %! fwrite (fid, "1, 2, 3\n4+4i, 5, 6\n7, 8, 9\n10, 11, 12");
 %! fclose (fid);
--- a/libinterp/corefcn/dot.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/dot.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -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 ())
@@ -245,10 +247,12 @@
 %! x = [2, 1; 2, 1];
 %! y = [-0.5, 2; 0.5, -2];
 %! assert (dot (x, y), [0 0]);
+%! assert (dot (single (x), single (y)), single ([0 0]));
 
 %!test
 %! x = [1+i, 3-i; 1-i, 3-i];
 %! assert (dot (x, x), [4, 20]);
+%! assert (dot (single (x), single (x)), single ([4, 20]));
 
 %!test
 %! x = int8 ([1 2]);
@@ -301,13 +305,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;
@@ -390,4 +399,24 @@
 %! z(:,:,1) = [7 10; 15 22];
 %! z(:,:,2) = [2 2; 2 2];
 %! assert (blkmm (x,x), z);
+%! assert (blkmm (single (x), single (x)), single (z));
+%! assert (blkmm (x, single (x)), single (z));
+
+%!test
+%! x(:,:,1) = [1 2; 3 4];
+%! x(:,:,2) = [1i 1i; 1i 1i];
+%! z(:,:,1) = [7 10; 15 22];
+%! z(:,:,2) = [-2 -2; -2 -2];
+%! assert (blkmm (x,x), z);
+%! assert (blkmm (single (x), single (x)), single (z));
+%! assert (blkmm (x, single (x)), single (z));
+
+%% Test input validation
+%!error blkmm ()
+%!error blkmm (1)
+%!error blkmm (1,2,3)
+%!error <A and B dimensions don't match> blkmm (ones (2,2), ones (3,3))
+%!error <A and B must be numeric> blkmm ({1,2}, [3,4])
+%!error <A and B must be numeric> blkmm ([3,4], {1,2})
 */
+
--- a/libinterp/corefcn/eig.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/eig.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -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/ellipj.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/ellipj.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -67,7 +67,7 @@
 return @code{NaN}.\n\
 @end enumerate\n\
 \n\
-Reference: Milton Abramowitz and Irene A Stegun,\n\
+Reference: Milton @nospell{Abramowitz} and Irene A @nospell{Stegun},\n\
 @cite{Handbook of Mathematical Functions}, Chapter 16 (Sections 16.4, 16.13,\n\
 and 16.15), Dover, 1965.\n\
 \n\
@@ -919,6 +919,15 @@
 %! assert (cn, C, 8*eps);
 %! assert (dn, D, 8*eps);
 
+%!test
+%! ## Test continuity of dn when cn is near zero (bug #43344)
+%! m = 0.5;
+%! u = ellipke (0.5);
+%! x = [-1e-3, -1e-12, 0, 1e-12, 1e-3];
+%! [~, ~, dn] = ellipj (u + x, m);
+%! D = 1/sqrt (2) * ones (size (x));
+%! assert (dn, D, 1e-6);
+
 %!error ellipj ()
 %!error ellipj (1)
 %!error ellipj (1,2,3,4)
--- a/libinterp/corefcn/error.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/error.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -27,6 +27,7 @@
 #include <cstdarg>
 #include <cstring>
 
+#include <iomanip>
 #include <iostream>
 #include <sstream>
 #include <string>
@@ -40,6 +41,7 @@
 #include "utils.h"
 #include "ov.h"
 #include "ov-usr-fcn.h"
+#include "pt-eval.h"
 #include "pt-pr-code.h"
 #include "pt-stmt.h"
 #include "toplev.h"
@@ -66,8 +68,7 @@
 // TRUE means that Octave will print a verbose warning.  Currently unused.
 static bool Vverbose_warning;
 
-// TRUE means that Octave will print no warnings, but lastwarn will be
-//updated
+// TRUE means that Octave will print no warnings, but lastwarn will be updated
 static bool Vquiet_warning = false;
 
 // A structure containing (most of) the current state of warnings.
@@ -170,13 +171,8 @@
 
   std::string msg_string = output_buf.str ();
 
-  if (! warning_state)
-    {
-      // This is the first warning in a possible series.
-
-      Vlast_warning_id = id;
-      Vlast_warning_message = msg_string;
-    }
+  Vlast_warning_id = id;
+  Vlast_warning_message = msg_string;
 
   if (! Vquiet_warning)
     {
@@ -267,6 +263,70 @@
     }
 }
 
+static void
+pr_where_2 (const char *fmt, va_list args)
+{
+  if (fmt)
+    {
+      if (*fmt)
+        {
+          size_t len = strlen (fmt);
+
+          if (len > 0)
+            {
+              if (fmt[len - 1] == '\n')
+                {
+                  if (len > 1)
+                    {
+                      char *tmp_fmt = strsave (fmt);
+                      tmp_fmt[len - 1] = '\0';
+                      verror (false, std::cerr, 0, "", tmp_fmt, args);
+                      delete [] tmp_fmt;
+                    }
+                }
+              else
+                verror (false, std::cerr, 0, "", fmt, args);
+            }
+        }
+    }
+  else
+    panic ("pr_where_2: invalid format");
+}
+
+static void
+pr_where_1 (const char *fmt, ...)
+{
+  va_list args;
+  va_start (args, fmt);
+  pr_where_2 (fmt, args);
+  va_end (args);
+}
+
+static void
+pr_where (const char *who)
+{
+  std::list<octave_call_stack::stack_frame> frames
+    = octave_call_stack::backtrace_frames ();
+
+  size_t nframes = frames.size ();
+
+  if (nframes > 0)
+    pr_where_1 ("%s: called from\n", who);
+
+  for (std::list<octave_call_stack::stack_frame>::const_iterator p = frames.begin ();
+       p != frames.end (); p++)
+    {
+      const octave_call_stack::stack_frame& elt = *p;
+
+      std::string fcn_name = elt.fcn_name ();
+      int line = elt.line ();
+      int column = elt.column ();
+
+      pr_where_1 ("    %s at line %d column %d\n",
+                  fcn_name.c_str (), line, column);
+    }
+}
+
 // Note that we don't actually print any message if the error string
 // is just "" or "\n".  This allows error ("") and error ("\n") to
 // just set the error state.
@@ -381,82 +441,16 @@
 }
 
 static void
-pr_where_2 (const char *fmt, va_list args)
-{
-  if (fmt)
-    {
-      if (*fmt)
-        {
-          size_t len = strlen (fmt);
-
-          if (len > 0)
-            {
-              if (fmt[len - 1] == '\n')
-                {
-                  if (len > 1)
-                    {
-                      char *tmp_fmt = strsave (fmt);
-                      tmp_fmt[len - 1] = '\0';
-                      verror (false, std::cerr, 0, "", tmp_fmt, args);
-                      delete [] tmp_fmt;
-                    }
-                }
-              else
-                verror (false, std::cerr, 0, "", fmt, args);
-            }
-        }
-    }
-  else
-    panic ("pr_where_2: invalid format");
-}
-
-static void
-pr_where_1 (const char *fmt, ...)
-{
-  va_list args;
-  va_start (args, fmt);
-  pr_where_2 (fmt, args);
-  va_end (args);
-}
-
-static void
-pr_where (const char *who)
-{
-  octave_idx_type curr_frame = -1;
-
-  octave_map stk = octave_call_stack::backtrace (0, curr_frame);
-
-  octave_idx_type nframes_to_display = stk.numel ();
-
-  if (nframes_to_display > 0)
-    {
-      pr_where_1 ("%s: called from\n", who);
-
-      Cell names = stk.contents ("name");
-      Cell lines = stk.contents ("line");
-      Cell columns = stk.contents ("column");
-
-      for (octave_idx_type i = 0; i < nframes_to_display; i++)
-        {
-          octave_value name = names(i);
-          octave_value line = lines(i);
-          octave_value column = columns(i);
-
-          std::string nm = name.string_value ();
-
-          pr_where_1 ("    %s at line %d column %d\n", nm.c_str (),
-                      line.int_value (), column.int_value ());
-        }
-    }
-}
-
-static void
 error_2 (const char *id, const char *fmt, va_list args, bool with_cfn = false)
 {
   int init_state = error_state;
 
   error_1 (std::cerr, "error", id, fmt, args, with_cfn);
 
+  if (error_state != -2 && ! symbol_table::at_top_level ()
+      && ! discard_error_messages)
+    pr_where ("error");
+
   if ((interactive || forced_interactive)
       && Vdebug_on_error && init_state == 0
       && octave_call_stack::caller_user_code ())
@@ -467,7 +461,9 @@
 
       error_state = 0;
 
-      pr_where ("error");
+      tree_evaluator::debug_mode = true;
+
+      tree_evaluator::current_frame = octave_call_stack::current_frame ();
 
       do_keyboard (octave_value_list ());
     }
@@ -657,6 +653,10 @@
           frame.protect_var (Vdebug_on_warning);
           Vdebug_on_warning = false;
 
+          tree_evaluator::debug_mode = true;
+
+          tree_evaluator::current_frame = octave_call_stack::current_frame ();
+
           do_keyboard (octave_value_list ());
         }
     }
@@ -1217,6 +1217,127 @@
   return retval;
 }
 
+static std::string
+default_warning_state (void)
+{
+  std::string retval = "on";
+
+  Cell ident = warning_options.contents ("identifier");
+  Cell state = warning_options.contents ("state");
+
+  octave_idx_type nel = ident.numel ();
+
+  for (octave_idx_type i = 0; i < nel; i++)
+    {
+      if (ident(i).string_value () == "all")
+        {
+          retval = state(i).string_value ();
+          break;
+        }
+    }
+
+  return retval;
+}
+
+static void
+display_warning_options (std::ostream& os)
+{
+  Cell ident = warning_options.contents ("identifier");
+  Cell state = warning_options.contents ("state");
+
+  octave_idx_type nel = ident.numel ();
+
+  std::string all_state = default_warning_state ();
+
+  if (all_state == "on")
+    os << "By default, warnings are enabled.";
+  else if (all_state == "off")
+    os << "By default, warnings are disabled.";
+  else if (all_state == "error")
+    os << "By default, warnings are treated as errors.";
+  else
+    panic_impossible ();
+  
+  if (nel > 1)
+    os << "\n\n";
+
+  // The state for all is always supposed to be first in the list.
+
+  for (octave_idx_type i = 1; i < nel; i++)
+    {
+      std::string tid = ident(i).string_value ();
+      std::string tst = state(i).string_value ();
+
+      os << std::setw (7) << tst << "  " << tid << "\n";
+    }
+
+  os << std::endl;
+}
+
+static void
+set_warning_option (const std::string& state, const std::string& ident)
+{
+  if (ident == "all")
+    {
+      initialize_warning_options (state);
+      return;
+    }
+
+  std::string all_state = default_warning_state ();
+
+  if (state != "on" && state != "off" && state != "error")
+    error ("invalid warning state: %s", state.c_str ());
+
+  Cell tid = warning_options.contents ("identifier");
+  Cell tst = warning_options.contents ("state");
+
+  octave_idx_type nel = tid.numel ();
+
+  for (octave_idx_type i = 0; i < nel; i++)
+    {
+      if (tid(i).string_value () == ident)
+        {
+          // We found it in the current list of options.  If the state
+          // for "all" is same as arg1, we can simply remove the item
+          // from the list.
+
+          if (state == all_state)
+            {
+              for (i = i + 1; i < nel; i++)
+                {
+                  tid(i-1) = tid(i);
+                  tst(i-1) = tst(i);
+                }
+
+              tid.resize (dim_vector (1, nel-1));
+              tst.resize (dim_vector (1, nel-1));
+            }
+          else
+            tst(i) = state;
+
+          warning_options.clear ();
+
+          warning_options.assign ("identifier", tid);
+          warning_options.assign ("state", tst);
+
+          return;
+        }
+    }
+
+  // The option wasn't already in the list.  Append it.
+
+  tid.resize (dim_vector (1, nel+1));
+  tst.resize (dim_vector (1, nel+1));
+
+  tid(nel) = ident;
+  tst(nel) = state;
+
+  warning_options.clear ();
+
+  warning_options.assign ("identifier", tid);
+  warning_options.assign ("state", tst);
+}
+
 DEFUN (warning, args, nargout,
        "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {} warning (@var{template}, @dots{})\n\
@@ -1471,49 +1592,7 @@
                   if (arg2 == "last")
                     arg2 = Vlast_warning_id;
 
-                  if (arg2 == "all")
-                    initialize_warning_options (arg1);
-                  else
-                    {
-                      Cell ident = warning_options.contents ("identifier");
-                      Cell state = warning_options.contents ("state");
-
-                      octave_idx_type nel = ident.numel ();
-
-                      bool found = false;
-
-                      for (octave_idx_type i = 0; i < nel; i++)
-                        {
-                          if (ident(i).string_value () == arg2)
-                            {
-                              // FIXME: if state for "all" is  same as arg1,
-                              //        we can simply remove the item
-                              //        from the list.
-
-                              state(i) = arg1;
-                              warning_options.assign ("state", state);
-                              found = true;
-                              break;
-                            }
-                        }
-
-                      if (! found)
-                        {
-                          // FIXME: if state for "all" is same as arg1,
-                          //        we don't need to do anything.
-
-                          ident.resize (dim_vector (1, nel+1));
-                          state.resize (dim_vector (1, nel+1));
-
-                          ident(nel) = arg2;
-                          state(nel) = arg1;
-
-                          warning_options.clear ();
-
-                          warning_options.assign ("identifier", ident);
-                          warning_options.assign ("state", state);
-                        }
-                    }
+                  set_warning_option (arg1, arg2);
 
                   done = true;
                 }
@@ -1550,7 +1629,10 @@
     }
   else if (argc == 1)
     {
-      retval = warning_options;
+      if (nargout > 0)
+        retval = warning_options;
+      else
+        display_warning_options (octave_stdout);
 
       done = true;
     }
@@ -1565,7 +1647,25 @@
           octave_map m = arg.map_value ();
 
           if (m.contains ("identifier") && m.contains ("state"))
-            warning_options = m;
+            {
+              // Simply step through the struct elements one at a time.
+
+              Cell ident = m.contents ("identifier");
+              Cell state = m.contents ("state");
+
+              octave_idx_type nel = ident.numel ();
+
+              for (octave_idx_type i = 0; i < nel; i++)
+                {
+                  std::string tst = state(i).string_value ();
+                  std::string tid = ident(i).string_value ();
+
+                  if (error_state)
+                    return retval;
+
+                  set_warning_option (tst, tid);
+                }
+            }
           else
             error ("warning: expecting structure with fields 'identifier' and 'state'");
 
@@ -1620,7 +1720,7 @@
 void
 disable_warning (const std::string& id)
 {
-  set_warning_state (id, "off");
+  set_warning_option ("off", id);
 }
 
 void
@@ -1858,7 +1958,7 @@
             }
         }
       else
-        error ("lasterr: expecting arguments to be character strings");
+        error ("lasterr: all arguments must be strings");
     }
   else
     print_usage ();
@@ -1905,7 +2005,7 @@
             }
         }
       else
-        error ("lastwarn: expecting arguments to be character strings");
+        error ("lastwarn: all arguments must be strings");
     }
   else
     print_usage ();
@@ -1913,7 +2013,7 @@
   return retval;
 }
 
-DEFUN (usage, args, ,
+DEFUN (__usage__, args, ,
        "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} usage (@var{msg})\n\
 Print the message @var{msg}, prefixed by the string @samp{usage: }, and\n\
--- a/libinterp/corefcn/file-io.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/file-io.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -240,10 +240,17 @@
        "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {} fclose (@var{fid})\n\
 @deftypefnx {Built-in Function} {} fclose (\"all\")\n\
-Close the specified file.  If successful, @code{fclose} returns 0,\n\
-otherwise, it returns -1.  The second form of the @code{fclose} call closes\n\
-all open files except @code{stdout}, @code{stderr}, and @code{stdin}.\n\
-@seealso{fopen, freport}\n\
+@deftypefnx {Built-in Function} {@var{status} =} fclose (\"all\")\n\
+Close the file specified by the file descriptor @var{fid}.\n\
+\n\
+If successful, @code{fclose} returns 0, otherwise, it returns -1.  The\n\
+second form of the @code{fclose} call closes all open files except\n\
+@code{stdout}, @code{stderr}, and @code{stdin}.\n\
+\n\
+Programming Note: When using @qcode{\"all\"} the file descriptors associated\n\
+with gnuplot will also be closed.  This will prevent further plotting with\n\
+gnuplot until Octave is closed and restarted.\n\
+@seealso{fopen, fflush, freport}\n\
 @end deftypefn")
 {
   octave_value retval = -1;
@@ -261,8 +268,9 @@
 DEFUN (fclear, args, ,
        "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} fclear (@var{fid})\n\
-Clear the stream state for the specified file.\n\
-@seealso{fopen}\n\
+Clear the stream state for the file specified by the file descriptor\n\
+@var{fid}.\n\
+@seealso{ferror, fopen}\n\
 @end deftypefn")
 {
   octave_value retval;
@@ -271,7 +279,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");
 
@@ -287,13 +295,15 @@
 DEFUN (fflush, args, ,
        "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} fflush (@var{fid})\n\
-Flush output to @var{fid}.  This is useful for ensuring that all\n\
-pending output makes it to the screen before some other event occurs.\n\
-For example, it is always a good idea to flush the standard output\n\
-stream before calling @code{input}.\n\
+Flush output to file descriptor @var{fid}.\n\
 \n\
 @code{fflush} returns 0 on success and an OS dependent error value\n\
 (@minus{}1 on Unix) on error.\n\
+\n\
+Programming Note: Flushing is useful for ensuring that all pending output\n\
+makes it to the screen before some other event occurs.  For example, it is\n\
+always a good idea to flush the standard output stream before calling\n\
+@code{input}.\n\
 @seealso{fopen, fclose}\n\
 @end deftypefn")
 {
@@ -305,7 +315,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)
         {
@@ -335,8 +345,7 @@
 or @var{len} characters have been read.  The characters read, excluding\n\
 the possible trailing newline, are returned as a string.\n\
 \n\
-If @var{len} is omitted, @code{fgetl} reads until the next newline\n\
-character.\n\
+If @var{len} is omitted, @code{fgetl} reads until the next newline character.\n\
 \n\
 If there are no more characters to read, @code{fgetl} returns @minus{}1.\n\
 \n\
@@ -386,8 +395,7 @@
 or @var{len} characters have been read.  The characters read, including\n\
 the possible trailing newline, are returned as a string.\n\
 \n\
-If @var{len} is omitted, @code{fgets} reads until the next newline\n\
-character.\n\
+If @var{len} is omitted, @code{fgets} reads until the next newline character.\n\
 \n\
 If there are no more characters to read, @code{fgets} returns @minus{}1.\n\
 \n\
@@ -434,7 +442,9 @@
 @deftypefn  {Built-in Function} {@var{nlines} =} fskipl (@var{fid})\n\
 @deftypefnx {Built-in Function} {@var{nlines} =} fskipl (@var{fid}, @var{count})\n\
 @deftypefnx {Built-in Function} {@var{nlines} =} fskipl (@var{fid}, Inf)\n\
-Read and skip @var{count} lines from the file descriptor @var{fid}.\n\
+Read and skip @var{count} lines from the file specified by the file\n\
+descriptor @var{fid}.\n\
+\n\
 @code{fskipl} discards characters until an end-of-line is encountered exactly\n\
 @var{count}-times, or until the end-of-file marker is found.\n\
 \n\
@@ -500,23 +510,8 @@
 
           file_stat fs (fname);
 
-          if (! (md & std::ios::out
-                 || octave_env::absolute_pathname (fname)
-                 || octave_env::rooted_relative_pathname (fname)))
-            {
-              if (! fs.exists ())
-                {
-                  std::string tmp
-                    = octave_env::make_absolute (load_path::find_file (fname));
-
-                  if (! tmp.empty ())
-                    {
-                      warning_with_id ("Octave:fopen-file-in-path",
-                                       "fopen: file found in load path");
-                      fname = tmp;
-                    }
-                }
-            }
+          if (! (md & std::ios::out))
+            fname = find_data_file_in_load_path ("fopen", fname);
 
           if (! fs.is_dir ())
             {
@@ -562,18 +557,20 @@
 
   fid = -1;
 
-  std::string name = tc_name.string_value ();
-
-  if (! error_state)
+  if (tc_name.is_string ())
     {
-      std::string mode = tc_mode.string_value ();
+      std::string name = tc_name.string_value ();
 
-      if (! error_state)
+      if (tc_mode.is_string ())
         {
-          std::string arch = tc_arch.string_value ();
+          std::string mode = tc_mode.string_value ();
 
-          if (! error_state)
-            retval = do_stream_open (name, mode, arch, fid);
+          if (tc_arch.is_string ())
+            {
+              std::string arch = tc_arch.string_value ();
+
+              retval = do_stream_open (name, mode, arch, fid);
+            }
           else
             ::error ("%s: architecture type must be a string", fcn);
         }
@@ -588,7 +585,10 @@
 
 DEFUN (fopen, args, nargout,
        "-*- texinfo -*-\n\
-@deftypefn  {Built-in Function} {[@var{fid}, @var{msg}] =} fopen (@var{name}, @var{mode}, @var{arch})\n\
+@deftypefn  {Built-in Function} {@var{fid} =} fopen (@var{name})\n\
+@deftypefnx {Built-in Function} {@var{fid} =} fopen (@var{name}, @var{mode})\n\
+@deftypefnx {Built-in Function} {@var{fid} =} fopen (@var{name}, @var{mode}, @var{arch})\n\
+@deftypefnx {Built-in Function} {[@var{fid}, @var{msg}] =} fopen (@dots{})\n\
 @deftypefnx {Built-in Function} {@var{fid_list} =} fopen (\"all\")\n\
 @deftypefnx {Built-in Function} {[@var{file}, @var{mode}, @var{arch}] =} fopen (@var{fid})\n\
 The first form of the @code{fopen} function opens the named file with\n\
@@ -627,7 +627,7 @@
 The possible values @samp{mode} may have are\n\
 \n\
 @table @asis\n\
-@item @samp{r}\n\
+@item @samp{r} (default)\n\
 Open a file for reading.\n\
 \n\
 @item @samp{w}\n\
@@ -652,7 +652,7 @@
 @qcode{\"b\"} to open in binary mode.  On Windows and Macintosh systems, text\n\
 mode reading and writing automatically converts linefeeds to the\n\
 appropriate line end character for the system (carriage-return linefeed\n\
-on Windows, carriage-return on Macintosh).  The default if no mode is\n\
+on Windows, carriage-return on Macintosh).  The default when no mode is\n\
 specified is binary mode.\n\
 \n\
 Additionally, you may append a @qcode{\"z\"} to the mode string to open a\n\
@@ -663,8 +663,8 @@
 for the file.  Valid values for @var{arch} are:\n\
 \n\
 @table @samp\n\
-@item native\n\
-The format of the current machine (this is the default).\n\
+@item native (default)\n\
+The format of the current machine.\n\
 \n\
 @item ieee-be\n\
 IEEE big endian format.\n\
@@ -753,15 +753,15 @@
 @group\n\
 freport ()\n\
 \n\
-     @print{}  number  mode  name\n\
-     @print{}\n\
-     @print{}       0     r  stdin\n\
-     @print{}       1     w  stdout\n\
-     @print{}       2     w  stderr\n\
-     @print{}       3     r  myfile\n\
+     @print{}  number  mode  arch       name\n\
+     @print{}  ------  ----  ----       ----\n\
+     @print{}     0     r    ieee-le    stdin\n\
+     @print{}     1     w    ieee-le    stdout\n\
+     @print{}     2     w    ieee-le    stderr\n\
+     @print{}     3     r    ieee-le    myfile\n\
 @end group\n\
 @end example\n\
-@seealso{fopen, fclose}\n\
+@seealso{fopen, fclose, is_valid_file_id}\n\
 @end deftypefn")
 {
   octave_value_list retval;
@@ -778,10 +778,13 @@
 
 DEFUN (frewind, args, nargout,
        "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {} frewind (@var{fid})\n\
-Move the file pointer to the beginning of the file @var{fid}, returning\n\
-0 for success, and -1 if an error was encountered.  It is equivalent to\n\
-@code{fseek (@var{fid}, 0, SEEK_SET)}.\n\
+@deftypefn  {Built-in Function} {} frewind (@var{fid})\n\
+@deftypefnx {Built-in Function} {@var{status} =} frewind (@var{fid})\n\
+Move the file pointer to the beginning of the file specified by file\n\
+descriptor @var{fid}.\n\
+\n\
+@code{frewind} returns 0 for success, and -1 if an error is encountered.  It\n\
+is equivalent to @code{fseek (@var{fid}, 0, SEEK_SET)}.\n\
 @seealso{fseek, ftell, fopen}\n\
 @end deftypefn")
 {
@@ -812,7 +815,7 @@
 @deftypefn  {Built-in Function} {} fseek (@var{fid}, @var{offset})\n\
 @deftypefnx {Built-in Function} {} fseek (@var{fid}, @var{offset}, @var{origin})\n\
 @deftypefnx {Built-in Function} {@var{status} =} fseek (@dots{})\n\
-Set the file pointer to any location within the file @var{fid}.\n\
+Set the file pointer to the location @var{offset} within the file @var{fid}.\n\
 \n\
 The pointer is positioned @var{offset} characters from the @var{origin},\n\
 which may be one of the predefined variables @w{@code{SEEK_CUR}} (current\n\
@@ -822,7 +825,7 @@
 be positive, negative, or zero but not all combinations of @var{origin} and\n\
 @var{offset} can be realized.\n\
 \n\
-Return 0 on success and -1 on error.\n\
+@code{fseek} returns 0 on success and -1 on error.\n\
 @seealso{fskipl, frewind, ftell, fopen}\n\
 @end deftypefn")
 {
@@ -850,10 +853,10 @@
 
 DEFUN (ftell, args, ,
        "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {} ftell (@var{fid})\n\
-Return the position of the file pointer as the number of characters\n\
-from the beginning of the file @var{fid}.\n\
-@seealso{fseek, feof, fopen}\n\
+@deftypefn {Built-in Function} {@var{pos} =} ftell (@var{fid})\n\
+Return the position of the file pointer as the number of characters from the\n\
+beginning of the file specified by file descriptor @var{fid}.\n\
+@seealso{fseek, frewind, feof, fopen}\n\
 @end deftypefn")
 {
   octave_value retval = -1;
@@ -875,10 +878,16 @@
 
 DEFUN (fprintf, args, nargout,
        "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {} fprintf (@var{fid}, @var{template}, @dots{})\n\
-This function is just like @code{printf}, except that the output is\n\
-written to the stream @var{fid} instead of @code{stdout}.\n\
-If @var{fid} is omitted, the output is written to @code{stdout}.\n\
+@deftypefn  {Built-in Function} {} fprintf (@var{fid}, @var{template}, @dots{})\n\
+@deftypefnx {Built-in Function} {} fprintf (@var{template}, @dots{})\n\
+@deftypefnx {Built-in Function} {@var{numbytes} =} fprintf (@dots{})\n\
+This function is equivalent to @code{printf}, except that the output is\n\
+written to the file descriptor @var{fid} instead of @code{stdout}.\n\
+\n\
+If @var{fid} is omitted, the output is written to @code{stdout} making the\n\
+function exactly equivalent to @code{printf}.\n\
+\n\
+The optional output returns the number of bytes written to the file.\n\
 @seealso{fputs, fdisp, fwrite, fscanf, printf, sprintf, fopen}\n\
 @end deftypefn")
 {
@@ -986,10 +995,15 @@
 
 DEFUN (fputs, args, ,
        "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {} fputs (@var{fid}, @var{string})\n\
-Write a string to a file with no formatting.\n\
+@deftypefn  {Built-in Function} {} fputs (@var{fid}, @var{string})\n\
+@deftypefnx {Built-in Function} {@var{status} =} fputs (@var{fid}, @var{string})\n\
+Write the string @var{string} to the file with file descriptor @var{fid}.\n\
 \n\
-Return a non-negative number on success and EOF on error.\n\
+The string is written to the file with no additional formatting.  Use\n\
+@code{fdisp} instead to automatically append a newline character appropriate\n\
+for the local machine.\n\
+\n\
+Return a non-negative number on success or EOF on error.\n\
 @seealso{fdisp, fprintf, fwrite, fopen}\n\
 @end deftypefn")
 {
@@ -1014,9 +1028,13 @@
 
 DEFUN (puts, args, ,
        "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {} puts (@var{string})\n\
+@deftypefn  {Built-in Function} {} puts (@var{string})\n\
+@deftypefnx {Built-in Function} {@var{status} =} puts (@var{string})\n\
 Write a string to the standard output with no formatting.\n\
 \n\
+The string is written verbatim to the standard output.  Use @code{disp} to\n\
+automatically append a newline character appropriate for the local machine.\n\
+\n\
 Return a non-negative number on success and EOF on error.\n\
 @seealso{fputs, disp}\n\
 @end deftypefn")
@@ -1327,8 +1345,7 @@
 @deftypefnx {Built-in Function} {[@var{v1}, @var{v2}, @dots{}, @var{count}, @var{errmsg}]] =} scanf (@var{template}, \"C\")\n\
 This is equivalent to calling @code{fscanf} with @var{fid} = @code{stdin}.\n\
 \n\
-It is currently not useful to call @code{scanf} in interactive\n\
-programs.\n\
+It is currently not useful to call @code{scanf} in interactive programs.\n\
 @seealso{fscanf, sscanf, printf}\n\
 @end deftypefn")
 {
@@ -1338,7 +1355,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);
 }
@@ -1356,10 +1373,10 @@
 
   if (! error_state)
     {
-      std::string prec = prec_arg.string_value ();
+      if (prec_arg.is_string ())
+        {
+          std::string prec = prec_arg.string_value ();
 
-      if (! error_state)
-        {
           int block_size = 1;
           oct_data_conv::data_type input_type;
           oct_data_conv::data_type output_type;
@@ -1373,10 +1390,10 @@
 
               if (! error_state)
                 {
-                  std::string arch = arch_arg.string_value ();
+                  if (arch_arg.is_string ())
+                    {
+                      std::string arch = arch_arg.string_value ();
 
-                  if (! error_state)
-                    {
                       oct_mach_info::float_format flt_fmt
                         = oct_mach_info::string_to_float_format (arch);
 
@@ -1404,9 +1421,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 file specified by the file descriptor @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 +1580,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")
 {
@@ -1622,10 +1643,10 @@
 {
   int retval = -1;
 
-  std::string prec = prec_arg.string_value ();
+  if (prec_arg.is_string ())
+    {
+      std::string prec = prec_arg.string_value ();
 
-  if (! error_state)
-    {
       int block_size = 1;
       oct_data_conv::data_type output_type;
 
@@ -1637,10 +1658,10 @@
 
           if (! error_state)
             {
-              std::string arch = arch_arg.string_value ();
+              if (arch_arg.is_string ())
+                {
+                  std::string arch = arch_arg.string_value ();
 
-              if (! error_state)
-                {
                   oct_mach_info::float_format flt_fmt
                     = oct_mach_info::string_to_float_format (arch);
 
@@ -1665,10 +1686,14 @@
 
 DEFUN (fwrite, args, ,
        "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {@var{count} =} fwrite (@var{fid}, @var{data}, @var{precision}, @var{skip}, @var{arch})\n\
-Write data in binary form of type @var{precision} to the specified file\n\
-ID @var{fid}, returning the number of values successfully written to the\n\
-file.\n\
+@deftypefn  {Built-in Function} {} fwrite (@var{fid}, @var{data})\n\
+@deftypefnx {Built-in Function} {} fwrite (@var{fid}, @var{data}, @var{precision})\n\
+@deftypefnx {Built-in Function} {} fwrite (@var{fid}, @var{data}, @var{precision}, @var{skip})\n\
+@deftypefnx {Built-in Function} {} fwrite (@var{fid}, @var{data}, @var{precision}, @var{skip}, @var{arch})\n\
+@deftypefnx {Built-in Function} {@var{count} =} fwrite (@dots{})\n\
+Write data in binary form to the file specified by the file descriptor\n\
+@var{fid}, returning the number of values @var{count} successfully written\n\
+to the file.\n\
 \n\
 The argument @var{data} is a matrix of values that are to be written to\n\
 the file.  The values are extracted in column-major order.\n\
@@ -1726,12 +1751,14 @@
 
 DEFUNX ("feof", Ffeof, args, ,
         "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {} feof (@var{fid})\n\
-Return 1 if an end-of-file condition has been encountered for a given\n\
-file and 0 otherwise.  Note that it will only return 1 if the end of the\n\
-file has already been encountered, not if the next read operation will\n\
-result in an end-of-file condition.\n\
-@seealso{fread, fopen}\n\
+@deftypefn {Built-in Function} {@var{status} =} feof (@var{fid})\n\
+Return 1 if an end-of-file condition has been encountered for the file\n\
+specified by file descriptor @var{fid} and 0 otherwise.\n\
+\n\
+Note that @code{feof} will only return 1 if the end of the file has already\n\
+been encountered, not if the next read operation will result in an\n\
+end-of-file condition.\n\
+@seealso{fread, frewind, fseek, fclear, fopen}\n\
 @end deftypefn")
 {
   octave_value retval = -1;
@@ -1753,15 +1780,22 @@
 
 DEFUNX ("ferror", Fferror, args, ,
         "-*- texinfo -*-\n\
-@deftypefn  {Built-in Function} {[@var{err}, @var{msg}] =} ferror (@var{fid})\n\
-@deftypefnx {Built-in Function} {[@var{err}, @var{msg}] =} ferror (@var{fid}, \"clear\")\n\
-Return 1 if an error condition has been encountered for the file ID\n\
-@var{fid} and 0 otherwise.  Note that it will only return 1 if an error\n\
-has already been encountered, not if the next operation will result in\n\
-an error condition.\n\
+@deftypefn  {Built-in Function} {@var{msg} =} ferror (@var{fid})\n\
+@deftypefnx {Built-in Function} {[@var{msg}, @var{err}] =} ferror (@var{fid})\n\
+@deftypefnx {Built-in Function} {[@var{dots}] =} ferror (@var{fid}, \"clear\")\n\
+Query the error status of the stream specified by file descriptor @var{fid}\n\
+\n\
+If an error condition exists then return a string @var{msg} describing the\n\
+error.  Otherwise, return an empty string @qcode{\"\"}.\n\
 \n\
-The second argument is optional.  If it is supplied, also clear the\n\
-error condition.\n\
+The optional second output is a numeric indication of the error status.\n\
+@var{err} is 1 if an error condition has been encountered and 0 otherwise.\n\
+\n\
+Note that @code{ferror} indicates if an error has already occurred, not\n\
+whether the next operation will result in an error condition.\n\
+\n\
+The second input @qcode{\"clear\"} is optional.  If supplied, the error\n\
+state on the stream will be cleared.\n\
 @seealso{fclear, fopen}\n\
 @end deftypefn")
 {
@@ -1833,6 +1867,7 @@
    @print{} drwxrwxrwt  15 root  root  2048 Feb 17 14:53 tmp\n\
 @end group\n\
 @end example\n\
+@seealso{popen2}\n\
 @end deftypefn")
 {
   octave_value retval = -1;
@@ -1841,14 +1876,14 @@
 
   if (nargin == 2)
     {
-      std::string name = args(0).string_value ();
-
-      if (! error_state)
+      if (args(0).is_string ())
         {
-          std::string mode = args(1).string_value ();
+          std::string name = args(0).string_value ();
 
-          if (! error_state)
+          if (args(1).is_string ())
             {
+              std::string mode = args(1).string_value ();
+
               if (mode == "r")
                 {
                   octave_stream ips = octave_iprocstream::create (name);
@@ -1879,8 +1914,10 @@
 DEFUNX ("pclose", Fpclose, args, ,
         "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} pclose (@var{fid})\n\
-Close a file identifier that was opened by @code{popen}.  You may also\n\
-use @code{fclose} for the same purpose.\n\
+Close a file identifier that was opened by @code{popen}.\n\
+\n\
+The function @code{fclose} may also be used for the same purpose.\n\
+@seealso{fclose, popen}\n\
 @end deftypefn")
 {
   octave_value retval = -1;
@@ -1895,23 +1932,23 @@
   return retval;
 }
 
-DEFUNX ("tmpnam", Ftmpnam, args, ,
-        "-*- texinfo -*-\n\
-@c List other forms of function in documentation index\n\
-@findex octave_tmp_file_name\n\
-\n\
-@deftypefn  {Built-in Function} {} tmpnam ()\n\
-@deftypefnx {Built-in Function} {} tmpnam (@var{dir})\n\
-@deftypefnx {Built-in Function} {} tmpnam (@var{dir}, @var{prefix})\n\
+DEFUN (tempname, args, ,
+       "-*- texinfo -*-\n\
+@deftypefn  {Built-in Function} {@var{fname} =} tempname ()\n\
+@deftypefnx {Built-in Function} {@var{fname} =} tempname (@var{dir})\n\
+@deftypefnx {Built-in Function} {@var{fname} =} tempname (@var{dir}, @var{prefix})\n\
 Return a unique temporary file name as a string.\n\
 \n\
 If @var{prefix} is omitted, a value of @qcode{\"oct-\"} is used.\n\
 If @var{dir} is also omitted, the default directory for temporary files\n\
-is used.  If @var{dir} is provided, it must exist, otherwise the default\n\
-directory for temporary files is used.  Since the named file is not\n\
-opened, by @code{tmpnam}, it is possible (though relatively unlikely)\n\
-that it will not be available by the time your program attempts to open it.\n\
-@seealso{tmpfile, mkstemp, P_tmpdir}\n\
+(@code{P_tmpdir}) is used.  If @var{dir} is provided, it must exist,\n\
+otherwise the default directory for temporary files is used.\n\
+\n\
+Programming Note: Because the named file is not opened by @code{tempname},\n\
+it is possible, though relatively unlikely, that it will not be available\n\
+by the time your program attempts to open it.  If this is a concern,\n\
+see @code{tmpfile}.\n\
+@seealso{mkstemp, tempdir, P_tmpdir, tmpfile}\n\
 @end deftypefn")
 {
   octave_value retval;
@@ -1920,20 +1957,25 @@
 
   if (len < 3)
     {
-      std::string dir = len > 0 ? args(0).string_value () : std::string ();
-
-      if (! error_state)
+      std::string dir;
+      if (len > 0)
         {
-          std::string pfx
-            = len > 1 ? args(1).string_value () : std::string ("oct-");
+          if (args(0).is_string ())
+            dir = args(0).string_value ();
+          else
+            ::error ("DIR must be a string");
+        }
 
-          if (! error_state)
-            retval = octave_tempnam (dir, pfx);
+      std::string pfx ("oct-");
+      if (len > 1)
+        {
+          if (args(1).is_string ())
+            pfx = args(1).string_value ();
           else
             ::error ("PREFIX must be a string");
         }
-      else
-        ::error ("DIR argument must be a string");
+
+      retval = octave_tempnam (dir, pfx);
     }
   else
     print_usage ();
@@ -1941,20 +1983,67 @@
   return retval;
 }
 
-DEFALIAS (octave_tmp_file_name, tmpnam);
+/*
+%!test
+%! if (ispc ())
+%!   envname = "TMP";
+%! else
+%!   envname = "TMPDIR";
+%! endif
+%! envdir = getenv (envname);
+%! unsetenv (envname);
+%! unwind_protect
+%!   ## Test 0-argument form
+%!   fname = tempname ();
+%!   [tmpdir, tmpfname] = fileparts (fname); 
+%!   assert (tmpdir, P_tmpdir);
+%!   assert (tmpfname (1:4), "oct-");
+%!   ## Test 1-argument form 
+%!   tmp_tmpdir = [P_tmpdir filesep() substr(tmpfname, -5)];
+%!   mkdir (tmp_tmpdir) || error ("Unable to create tmp dir");
+%!   setenv (envname, P_tmpdir);
+%!   fname = tempname (tmp_tmpdir);
+%!   [tmpdir, tmpfname] = fileparts (fname); 
+%!   assert (tmpdir, tmp_tmpdir);
+%!   assert (tmpfname (1:4), "oct-");
+%!   ## Test 1-argument form w/null tmpdir
+%!   fname = tempname ("");
+%!   [tmpdir, tmpfname] = fileparts (fname); 
+%!   assert (tmpdir, P_tmpdir);
+%!   assert (tmpfname (1:4), "oct-");
+%!   ## Test 2-argument form 
+%!   fname = tempname (tmp_tmpdir, "pfx-");
+%!   [tmpdir, tmpfname] = fileparts (fname); 
+%!   assert (tmpdir, tmp_tmpdir);
+%!   assert (tmpfname (1:4), "pfx-");
+%!   ## Test 2-argument form w/null prefix
+%!   fname = tempname (tmp_tmpdir, "");
+%!   [tmpdir, tmpfname] = fileparts (fname); 
+%!   assert (tmpdir, tmp_tmpdir);
+%!   assert (tmpfname (1:4), "file");
+%! unwind_protect_cleanup
+%!   rmdir (tmp_tmpdir);
+%!   if (isempty (envdir))
+%!     unsetenv (envname);
+%!   else
+%!     setenv (envname, envdir);
+%!   endif
+%! end_unwind_protect
+*/
 
 DEFUN (tmpfile, args, ,
        "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {[@var{fid}, @var{msg}] =} tmpfile ()\n\
 Return the file ID corresponding to a new temporary file with a unique\n\
-name.  The file is opened in binary read/write (@qcode{\"w+b\"}) mode.\n\
-The file will be deleted automatically when it is closed or when Octave\n\
-exits.\n\
+name.\n\
+\n\
+The file is opened in binary read/write (@qcode{\"w+b\"}) mode and will be\n\
+deleted automatically when it is closed or when Octave exits.\n\
 \n\
 If successful, @var{fid} is a valid file ID and @var{msg} is an empty\n\
 string.  Otherwise, @var{fid} is -1 and @var{msg} contains a\n\
 system-dependent error message.\n\
-@seealso{tmpnam, mkstemp, P_tmpdir}\n\
+@seealso{tempname, mkstemp, tempdir, P_tmpdir}\n\
 @end deftypefn")
 {
   octave_value_list retval;
@@ -1996,23 +2085,25 @@
 
 DEFUN (mkstemp, args, ,
        "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {[@var{fid}, @var{name}, @var{msg}] =} mkstemp (@var{template}, @var{delete})\n\
-Return the file ID corresponding to a new temporary file with a unique\n\
-name created from @var{template}.  The last six characters of @var{template}\n\
-must be @code{XXXXXX} and these are replaced with a string that makes the\n\
-filename unique.  The file is then created with mode read/write and\n\
-permissions that are system dependent (on GNU/Linux systems, the permissions\n\
-will be 0600 for versions of glibc 2.0.7 and later).  The file is opened\n\
-in binary mode and with the @w{@code{O_EXCL}} flag.\n\
+@deftypefn  {Built-in Function} {[@var{fid}, @var{name}, @var{msg}] =} mkstemp (\"@var{template}\")\n\
+@deftypefnx {Built-in Function} {[@var{fid}, @var{name}, @var{msg}] =} mkstemp (\"@var{template}\", @var{delete})\n\
+Return the file descriptor @var{fid} corresponding to a new temporary file\n\
+with a unique name created from @var{template}.\n\
 \n\
-If the optional argument @var{delete} is supplied and is true,\n\
-the file will be deleted automatically when Octave exits.\n\
+The last six characters of @var{template} must be @qcode{\"XXXXXX\"} and\n\
+these are replaced with a string that makes the filename unique.  The file\n\
+is then created with mode read/write and permissions that are system\n\
+dependent (on GNU/Linux systems, the permissions will be 0600 for versions of\n\
+glibc 2.0.7 and later).  The file is opened in binary mode and with the\n\
+@w{@code{O_EXCL}} flag.\n\
 \n\
-If successful, @var{fid} is a valid file ID, @var{name} is the name of\n\
-the file, and @var{msg} is an empty string.  Otherwise, @var{fid}\n\
-is -1, @var{name} is empty, and @var{msg} contains a system-dependent\n\
-error message.\n\
-@seealso{tmpfile, tmpnam, P_tmpdir}\n\
+If the optional argument @var{delete} is supplied and is true, the file will\n\
+be deleted automatically when Octave exits.\n\
+\n\
+If successful, @var{fid} is a valid file ID, @var{name} is the name of the\n\
+file, and @var{msg} is an empty string.  Otherwise, @var{fid} is -1,\n\
+@var{name} is empty, and @var{msg} contains a system-dependent error message.\n\
+@seealso{tempname, tempdir, P_tmpdir, tmpfile, fopen}\n\
 @end deftypefn")
 {
   octave_value_list retval;
@@ -2025,10 +2116,10 @@
 
   if (nargin == 1 || nargin == 2)
     {
-      std::string tmpl8 = args(0).string_value ();
+      if (args(0).is_string ())
+        {
+          std::string tmpl8 = args(0).string_value ();
 
-      if (! error_state)
-        {
           OCTAVE_LOCAL_BUFFER (char, tmp, tmpl8.size () + 1);
           strcpy (tmp, tmpl8.c_str ());
 
@@ -2112,10 +2203,12 @@
 DEFUNX ("umask", Fumask, args, ,
         "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} umask (@var{mask})\n\
-Set the permission mask for file creation.  The parameter @var{mask}\n\
-is an integer, interpreted as an octal number.  If successful,\n\
-returns the previous value of the mask (as an integer to be\n\
+Set the permission mask for file creation.\n\
+\n\
+The parameter @var{mask} is an integer, interpreted as an octal number.  If\n\
+successful, returns the previous value of the mask (as an integer to be\n\
 interpreted as an octal number); otherwise an error message is printed.\n\
+@seealso{fopen, mkdir}\n\
 @end deftypefn")
 {
   octave_value_list retval;
@@ -2174,8 +2267,14 @@
 DEFUNX ("P_tmpdir", FP_tmpdir, args, ,
         "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} P_tmpdir ()\n\
-Return the default name of the directory for temporary files on\n\
-this system.  The name of this directory is system dependent.\n\
+Return the name of the host system's @strong{default} directory for\n\
+temporary files.\n\
+\n\
+Programming Note: The value returned by @code{P_tmpdir} is always the\n\
+default location.  This value may not agree with that returned from\n\
+@code{tempdir} if the user has overriden the default with the @env{TMPDIR}\n\
+environment variable.\n\
+@seealso{tempdir, tempname, mkstemp, tmpfile}\n\
 @end deftypefn")
 {
   octave_value retval;
@@ -2198,8 +2297,8 @@
 @deftypefn  {Built-in Function} {} SEEK_SET ()\n\
 @deftypefnx {Built-in Function} {} SEEK_CUR ()\n\
 @deftypefnx {Built-in Function} {} SEEK_END ()\n\
-Return the numerical value to pass to @code{fseek} to perform\n\
-one of the following actions:\n\
+Return the numerical value to pass to @code{fseek} to perform one of the\n\
+following actions:\n\
 \n\
 @table @code\n\
 @item SEEK_SET\n\
@@ -2259,7 +2358,8 @@
         "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} stdin ()\n\
 Return the numeric value corresponding to the standard input stream.\n\
-When Octave is used interactively, this is filtered through the command\n\
+\n\
+When Octave is used interactively, stdin is filtered through the command\n\
 line editing functions.\n\
 @seealso{stdout, stderr}\n\
 @end deftypefn")
@@ -2271,6 +2371,7 @@
         "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} stdout ()\n\
 Return the numeric value corresponding to the standard output stream.\n\
+\n\
 Data written to the standard output is normally filtered through the pager.\n\
 @seealso{stdin, stderr}\n\
 @end deftypefn")
@@ -2282,8 +2383,9 @@
         "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} stderr ()\n\
 Return the numeric value corresponding to the standard error stream.\n\
-Even if paging is turned on, the standard error is not sent to the\n\
-pager.  It is useful for error messages and prompts.\n\
+\n\
+Even if paging is turned on, the standard error is not sent to the pager.\n\
+It is useful for error messages and prompts.\n\
 @seealso{stdin, stdout}\n\
 @end deftypefn")
 {
--- a/libinterp/corefcn/filter.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/filter.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -77,7 +77,7 @@
 
   if (norm == static_cast<T>(0.0))
     {
-      error ("filter: the first element of A must be non-zero");
+      error ("filter: the first element of A must be nonzero");
       return y;
     }
 
--- a/libinterp/corefcn/find.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/find.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -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;
@@ -165,7 +166,7 @@
       // Search for elements to return.  Only search the region where there
       // are elements to be found using the count that we want to find.
       for (octave_idx_type j = start_nc, cx = 0; j < end_nc; j++)
-        for (octave_idx_type i = v.cidx (j); i < v.cidx (j+1); i++ )
+        for (octave_idx_type i = v.cidx (j); i < v.cidx (j+1); i++)
           {
             OCTAVE_QUIT;
             if (direction < 0 && i < nz - count)
@@ -241,7 +242,6 @@
   if (n_to_find < 0 || n_to_find >= nc)
     {
       start_nc = 0;
-      n_to_find = nc;
       count = nc;
     }
   else if (direction > 0)
@@ -263,33 +263,15 @@
 
   if (count > 0)
     {
-      const octave_idx_type* p = v.data ();
-      if (v.is_col_perm ())
+      const Array<octave_idx_type>& p = v.col_perm_vec ();
+      for (octave_idx_type k = 0; k < count; k++)
         {
-          for (octave_idx_type k = 0; k < count; k++)
-            {
-              OCTAVE_QUIT;
-              const octave_idx_type j = start_nc + k;
-              const octave_idx_type i = p[j];
-              i_idx(k) = static_cast<double> (1+i);
-              j_idx(k) = static_cast<double> (1+j);
-              idx(k) = j * nc + i + 1;
-            }
-        }
-      else
-        {
-          for (octave_idx_type k = 0; k < count; k++)
-            {
-              OCTAVE_QUIT;
-              const octave_idx_type i = start_nc + k;
-              const octave_idx_type j = p[i];
-              // Scatter into the index arrays according to
-              // j adjusted by the start point.
-              const octave_idx_type koff = j - start_nc;
-              i_idx(koff) = static_cast<double> (1+i);
-              j_idx(koff) = static_cast<double> (1+j);
-              idx(koff) = j * nc + i + 1;
-            }
+          OCTAVE_QUIT;
+          const octave_idx_type j = start_nc + k;
+          const octave_idx_type i = p(j);
+          i_idx(k) = static_cast<double> (1+i);
+          j_idx(k) = static_cast<double> (1+j);
+          idx(k) = j * nc + i + 1;
         }
     }
   else
@@ -394,7 +376,7 @@
 ascending order.\n\
 \n\
 Note that this function is particularly useful for sparse matrices, as\n\
-it extracts the non-zero elements as vectors, which can then be used to\n\
+it extracts the nonzero elements as vectors, which can then be used to\n\
 create the original matrix.  For example:\n\
 \n\
 @example\n\
--- a/libinterp/corefcn/gammainc.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/gammainc.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -57,7 +57,8 @@
 \n\
 @end ifnottex\n\
 with the limiting value of 1 as @var{x} approaches infinity.\n\
-The standard notation is @math{P(a,x)}, e.g., Abramowitz and Stegun (6.5.1).\n\
+The standard notation is @math{P(a,x)}, e.g., @nospell{Abramowitz} and\n\
+@nospell{Stegun} (6.5.1).\n\
 \n\
 If @var{a} is scalar, then @code{gammainc (@var{x}, @var{a})} is returned\n\
 for each element of @var{x} and vice versa.\n\
@@ -72,7 +73,7 @@
 @example\n\
 gammainc (@var{x}, @var{a}) @equiv{} 1 - gammainc (@var{x}, @var{a}, \"upper\")\n\
 @end example\n\
-@seealso{gamma, lgamma}\n\
+@seealso{gamma, gammaln}\n\
 @end deftypefn")
 {
   octave_value retval;
--- a/libinterp/corefcn/gcd.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/gcd.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -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++)
@@ -436,25 +441,16 @@
        "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {@var{g} =} gcd (@var{a1}, @var{a2}, @dots{})\n\
 @deftypefnx {Built-in Function} {[@var{g}, @var{v1}, @dots{}] =} gcd (@var{a1}, @var{a2}, @dots{})\n\
-\n\
-Compute the greatest common divisor of @var{a1}, @var{a2}, @dots{}.  If more\n\
-than one argument is given all arguments must be the same size or scalar.\n\
-In this case the greatest common divisor is calculated for each element\n\
-individually.  All elements must be ordinary or Gaussian (complex)\n\
-integers.  Note that for Gaussian integers, the gcd is not unique up to\n\
-units (multiplication by 1, -1, @var{i} or -@var{i}), so an arbitrary\n\
-greatest common divisor amongst four possible is returned.\n\
+Compute the greatest common divisor of @var{a1}, @var{a2}, @dots{}.\n\
 \n\
-Example code:\n\
+If more than one argument is given then all arguments must be the same size\n\
+or scalar.  In this case the greatest common divisor is calculated for each\n\
+element individually.  All elements must be ordinary or Gaussian (complex)\n\
+integers.  Note that for Gaussian integers, the gcd is only unique up to a\n\
+phase factor (multiplication by 1, -1, i, or -i), so an arbitrary greatest\n\
+common divisor amongst four possible is returned.\n\
 \n\
-@example\n\
-@group\n\
-gcd ([15, 9], [20, 18])\n\
-   @result{}  5  9\n\
-@end group\n\
-@end example\n\
-\n\
-Optional return arguments @var{v1}, etc., contain integer vectors such\n\
+Optional return arguments @var{v1}, @dots{}, contain integer vectors such\n\
 that,\n\
 \n\
 @tex\n\
@@ -468,7 +464,16 @@
 \n\
 @end ifnottex\n\
 \n\
-@seealso{lcm, factor}\n\
+Example code:\n\
+\n\
+@example\n\
+@group\n\
+gcd ([15, 9], [20, 18])\n\
+   @result{}  5  9\n\
+@end group\n\
+@end example\n\
+\n\
+@seealso{lcm, factor, isprime}\n\
 @end deftypefn")
 {
   octave_value_list retval;
@@ -520,6 +525,19 @@
 %!assert (gcd (uint64 (200), uint64 (300), uint64 (50), uint64 (35)), uint64 (5))
 %!assert (gcd (18-i, -29+3i), -3-4i)
 
+%!test
+%! p = [953 967];
+%! u = [953 + i*971, 967 + i*977];
+%! [d, k(1), k(2)] = gcd (p(1), p(2));
+%! [z, w(1), w(2)] = gcd (u(1), u(2));
+%! assert (d, 1)
+%! assert (sum (p.*k), d)
+%! assert (abs (z), sqrt (2))
+%! assert (abs (sum (u.*w)), sqrt (2))
+
+%!error <all values must be integers> gcd (1/2, 2);
+%!error <all complex parts must be integers> gcd (e + i*pi, 1);
+
 %!error gcd ()
 
 %!test
--- a/libinterp/corefcn/givens.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/givens.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -32,10 +32,12 @@
 
 DEFUN (givens, args, nargout,
        "-*- texinfo -*-\n\
-@deftypefn  {Built-in Function} {@var{g} =} givens (@var{x}, @var{y})\n\
+@deftypefn  {Built-in Function} {@var{G} =} givens (@var{x}, @var{y})\n\
 @deftypefnx {Built-in Function} {[@var{c}, @var{s}] =} givens (@var{x}, @var{y})\n\
+Compute the Givens rotation matrix @var{G}.\n\
+\n\
 @tex\n\
-Return a $2\\times 2$ orthogonal matrix\n\
+The Givens matrix is a $2\\times 2$ orthogonal matrix\n\
 $$\n\
  G = \\left[\\matrix{c & s\\cr -s'& c\\cr}\\right]\n\
 $$\n\
@@ -46,11 +48,20 @@
 with $x$ and $y$ scalars.\n\
 @end tex\n\
 @ifnottex\n\
-Return a 2 by 2 orthogonal matrix\n\
-@code{@var{g} = [@var{c} @var{s}; -@var{s}' @var{c}]} such that\n\
-@code{@var{g} [@var{x}; @var{y}] = [*; 0]} with @var{x} and @var{y} scalars.\n\
+The Givens matrix is a 2 by 2 orthogonal matrix\n\
+\n\
+@code{@var{g} = [@var{c} @var{s}; -@var{s}' @var{c}]}\n\
+\n\
+such that\n\
+\n\
+@code{@var{g} [@var{x}; @var{y}] = [*; 0]}\n\
+\n\
+with @var{x} and @var{y} scalars.\n\
 @end ifnottex\n\
 \n\
+If two output arguments are requested, return the factors @var{c} and\n\
+@var{s} rather than the Givens rotation matrix.\n\
+\n\
 For example:\n\
 \n\
 @example\n\
@@ -60,6 +71,7 @@
        -0.70711   0.70711\n\
 @end group\n\
 @end example\n\
+@seealso{planerot}\n\
 @end deftypefn")
 {
   octave_value_list retval;
@@ -97,10 +109,6 @@
                           retval(1) = result (0, 1);
                           retval(0) = result (0, 0);
                           break;
-
-                        default:
-                          error ("givens: invalid number of output arguments");
-                          break;
                         }
                     }
                 }
@@ -127,10 +135,6 @@
                           retval(1) = result (0, 1);
                           retval(0) = result (0, 0);
                           break;
-
-                        default:
-                          error ("givens: invalid number of output arguments");
-                          break;
                         }
                     }
                 }
@@ -160,10 +164,6 @@
                           retval(1) = result (0, 1);
                           retval(0) = result (0, 0);
                           break;
-
-                        default:
-                          error ("givens: invalid number of output arguments");
-                          break;
                         }
                     }
                 }
@@ -190,10 +190,6 @@
                           retval(1) = result (0, 1);
                           retval(0) = result (0, 0);
                           break;
-
-                        default:
-                          error ("givens: invalid number of output arguments");
-                          break;
                         }
                     }
                 }
@@ -211,4 +207,5 @@
 
 %!error givens ()
 %!error givens (1)
+%!error [a,b,c] = givens (1, 1)
 */
--- a/libinterp/corefcn/gl-render.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/gl-render.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -37,6 +37,28 @@
 
 #define LIGHT_MODE GL_FRONT_AND_BACK
 
+// Use symbolic names for axes
+enum {
+  X_AXIS,
+  Y_AXIS,
+  Z_AXIS
+};
+
+// Use symbolic names for color mode
+enum {
+  UNIFORM,
+  FLAT,
+  INTERP,
+  TEXTURE
+};
+
+// Use symbolic names for lighting
+enum {
+  NONE,
+  //FLAT,  // Already declared in anonymous enum for color mode
+  GOURAUD = 2
+};
+
 // Win32 API requires the CALLBACK attributes for
 // GLU callback functions. Define it to empty on
 // other platforms.
@@ -147,7 +169,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;
 
@@ -400,7 +423,7 @@
 opengl_renderer::patch_tesselator : public opengl_tesselator
 {
 public:
-  patch_tesselator (opengl_renderer *r, int cmode, int lmode, int idx = 0)
+  patch_tesselator (opengl_renderer *r, int cmode, int lmode, float idx = 0.0)
     : opengl_tesselator (), renderer (r),
       color_mode (cmode), light_mode (lmode), index (idx),
       first (true), tmp_vdata ()
@@ -412,13 +435,13 @@
     //printf ("patch_tesselator::begin (%d)\n", type);
     first = true;
 
-    if (color_mode == 2 || light_mode == 2)
+    if (color_mode == INTERP || light_mode == GOURAUD)
       glShadeModel (GL_SMOOTH);
     else
       glShadeModel (GL_FLAT);
 
     if (is_filled ())
-      renderer->set_polygon_offset (true, 1+index);
+      renderer->set_polygon_offset (true, index);
 
     glBegin (type);
   }
@@ -436,12 +459,10 @@
       = reinterpret_cast<vertex_data::vertex_data_rep *> (data);
     //printf ("patch_tesselator::vertex (%g, %g, %g)\n", v->coords(0), v->coords(1), v->coords(2));
 
-    // FIXME: why did I need to keep the first vertex of the face
-    // in JHandles? I think it's related to the fact that the
-    // tessellation process might re-order the vertices, such that
-    // the first one you get here might not be the first one of the face;
-    // but I can't figure out the actual reason.
-    if (color_mode > 0 && (first || color_mode == 2))
+    // NOTE: OpenGL can re-order vertices.  For "flat" coloring of FaceColor
+    // the first vertex must be identified in the draw_patch routine.
+
+    if (color_mode == INTERP || (color_mode == FLAT && ! is_filled ()))
       {
         Matrix col = v->color;
 
@@ -458,12 +479,12 @@
 
                 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);
               }
           }
       }
 
-    if (light_mode > 0 && (first || light_mode == 2))
+    if (light_mode > 0 && (first || light_mode == GOURAUD))
       glNormal3dv (v->normal.data ());
 
     glVertex3dv (v->coords.data ());
@@ -471,8 +492,7 @@
     first = false;
   }
 
-  void combine (GLdouble xyz[3], void *data[4], GLfloat w[4],
-                void **out_data)
+  void combine (GLdouble xyz[3], void *data[4], GLfloat w[4], void **out_data)
   {
     //printf ("patch_tesselator::combine\n");
 
@@ -530,8 +550,8 @@
   patch_tesselator& operator = (const patch_tesselator&);
 
   opengl_renderer *renderer;
-  int color_mode;       // 0: uni,  1: flat, 2: interp
-  int light_mode;       // 0: none, 1: flat, 2: gouraud
+  int color_mode;
+  int light_mode;
   int index;
   bool first;
   std::list<vertex_data> tmp_vdata;
@@ -624,7 +644,17 @@
   if (enhanced)
     {
       glEnable (GL_BLEND);
-      glEnable (GL_LINE_SMOOTH);
+      glEnable (GL_MULTISAMPLE);
+      GLint iMultiSample, iNumSamples;
+      glGetIntegerv (GL_SAMPLE_BUFFERS, &iMultiSample);
+      glGetIntegerv (GL_SAMPLES, &iNumSamples);
+      if (iMultiSample != GL_TRUE || iNumSamples == 0)
+        {
+          // MultiSample not implemented.  Use old-style anti-aliasing
+          glDisable (GL_MULTISAMPLE);
+          glEnable (GL_LINE_SMOOTH);
+          glHint (GL_LINE_SMOOTH_HINT, GL_NICEST);
+        }
     }
   else
     {
@@ -654,7 +684,7 @@
       double val = ticks(i);
       if (lim1 <= val && val <= lim2)
         {
-          if (xyz == 0) // X
+          if (xyz == X_AXIS)
             {
               glVertex3d (val, p1N, p2);
               glVertex3d (val, p1, p2);
@@ -664,7 +694,7 @@
                   glVertex3d (val, p1, p2);
                 }
             }
-          else if (xyz == 1) // Y
+          else if (xyz == Y_AXIS)
             {
               glVertex3d (p1N, val, p2);
               glVertex3d (p1, val, p2);
@@ -674,7 +704,7 @@
                   glVertex3d (p1, val, p2);
                 }
             }
-          else if (xyz == 2) // Z
+          else if (xyz == Z_AXIS)
             {
               glVertex3d (p1N, p2, val);
               glVertex3d (p1, p2, val);
@@ -703,7 +733,7 @@
 
       if (lim1 <= val && val <= lim2)
         {
-          if (xyz == 0) // X
+          if (xyz == X_AXIS)
             {
               glVertex3d (val, p1, p2);
               glVertex3d (val, p1+dy, p2+dz);
@@ -713,7 +743,7 @@
                   glVertex3d (val, p1N-dy, p2N-dz);
                 }
             }
-          else if (xyz == 1) // Y
+          else if (xyz == Y_AXIS)
             {
               glVertex3d (p1, val, p2);
               glVertex3d (p1+dx, val, p2+dz);
@@ -723,7 +753,7 @@
                   glVertex3d (p1N-dx, val, p2N-dz);
                 }
             }
-          else if (xyz == 2) // Z
+          else if (xyz == Z_AXIS)
             {
               glVertex3d (p1, p2, val);
               glVertex3d (p1+dx, p2+dy, val);
@@ -765,17 +795,17 @@
           label.erase (0, label.find_first_not_of (" "));
           label = label.substr (0, label.find_last_not_of (" ")+1);
 
-          // FIXME: as tick text is transparent, shouldn't it be
+          // FIXME: As tick text is transparent, shouldn't it be
           //        drawn after axes object, for correct rendering?
-          if (xyz == 0) // X
+          if (xyz == X_AXIS)
             {
               b = render_text (label, val, p1, p2, ha, va);
             }
-          else if (xyz == 1) // Y
+          else if (xyz == Y_AXIS)
             {
               b = render_text (label, p1, val, p2, ha, va);
             }
-          else if (xyz == 2) // Z
+          else if (xyz == Z_AXIS)
             {
               b = render_text (label, p1, p2, val, ha, va);
             }
@@ -819,8 +849,6 @@
 
   glClear (GL_DEPTH_BUFFER_BIT);
 
-  glDisable (GL_LINE_SMOOTH);
-
   // store axes transformation data
 
   xform = props.get_transform ();
@@ -829,6 +857,10 @@
 void
 opengl_renderer::draw_axes_planes (const axes::properties& props)
 {
+  Matrix axe_color = props.get_color_rgb ();
+  if (axe_color.numel () == 0 || ! props.is_visible ())
+    return;
+
   double xPlane = props.get_xPlane ();
   double yPlane = props.get_yPlane ();
   double zPlane = props.get_zPlane ();
@@ -837,42 +869,43 @@
   double zPlaneN = props.get_zPlaneN ();
 
   // Axes planes
-  Matrix axe_color = props.get_color_rgb ();
-  if (axe_color.numel () > 0 && props.is_visible ())
-    {
-      set_color (axe_color);
-      set_polygon_offset (true, 2.5);
-
-      glBegin (GL_QUADS);
-
-      // X plane
-      glVertex3d (xPlane, yPlaneN, zPlaneN);
-      glVertex3d (xPlane, yPlane, zPlaneN);
-      glVertex3d (xPlane, yPlane, zPlane);
-      glVertex3d (xPlane, yPlaneN, zPlane);
-
-      // Y plane
-      glVertex3d (xPlaneN, yPlane, zPlaneN);
-      glVertex3d (xPlane, yPlane, zPlaneN);
-      glVertex3d (xPlane, yPlane, zPlane);
-      glVertex3d (xPlaneN, yPlane, zPlane);
-
-      // Z plane
-      glVertex3d (xPlaneN, yPlaneN, zPlane);
-      glVertex3d (xPlane, yPlaneN, zPlane);
-      glVertex3d (xPlane, yPlane, zPlane);
-      glVertex3d (xPlaneN, yPlane, zPlane);
-
-      glEnd ();
-
-      set_polygon_offset (false);
-    }
+  set_color (axe_color);
+  set_polygon_offset (true, 2.5);
+
+  glBegin (GL_QUADS);
+
+  // X plane
+  glVertex3d (xPlane, yPlaneN, zPlaneN);
+  glVertex3d (xPlane, yPlane, zPlaneN);
+  glVertex3d (xPlane, yPlane, zPlane);
+  glVertex3d (xPlane, yPlaneN, zPlane);
+
+  // Y plane
+  glVertex3d (xPlaneN, yPlane, zPlaneN);
+  glVertex3d (xPlane, yPlane, zPlaneN);
+  glVertex3d (xPlane, yPlane, zPlane);
+  glVertex3d (xPlaneN, yPlane, zPlane);
+
+  // Z plane
+  glVertex3d (xPlaneN, yPlaneN, zPlane);
+  glVertex3d (xPlane, yPlaneN, zPlane);
+  glVertex3d (xPlane, yPlane, zPlane);
+  glVertex3d (xPlaneN, yPlane, zPlane);
+
+  glEnd ();
+
+  set_polygon_offset (false);
 }
 
 void
 opengl_renderer::draw_axes_boxes (const axes::properties& props)
 {
+  if (! props.is_visible ())
+    return;
+
   bool xySym = props.get_xySym ();
+  bool layer2Dtop = props.get_layer2Dtop ();
+  bool is2d = props.get_is2D ();
   double xPlane = props.get_xPlane ();
   double yPlane = props.get_yPlane ();
   double zPlane = props.get_zPlane ();
@@ -893,106 +926,114 @@
   set_linestyle ("-", true);
   set_linewidth (props.get_linewidth ());
 
-  if (props.is_visible ())
+  glBegin (GL_LINES);
+
+  if (layer2Dtop)
+    std::swap (zpTick, zpTickN);
+
+  // X box
+  set_color (props.get_xcolor_rgb ());
+  glVertex3d (xPlaneN, ypTick, zpTick);
+  glVertex3d (xPlane, ypTick, zpTick);
+
+  if (props.is_box ())
     {
-      glBegin (GL_LINES);
-
-      // X box
-      set_color (props.get_xcolor_rgb ());
-      glVertex3d (xPlaneN, ypTick, zpTick);
-      glVertex3d (xPlane, ypTick, zpTick);
-
-      if (props.is_box ())
+      glVertex3d (xPlaneN, ypTickN, zpTick);
+      glVertex3d (xPlane, ypTickN, zpTick);
+      if (! is2d)
         {
-          glVertex3d (xPlaneN, ypTickN, zpTick);
-          glVertex3d (xPlane, ypTickN, zpTick);
           glVertex3d (xPlaneN, ypTickN, zpTickN);
           glVertex3d (xPlane, ypTickN, zpTickN);
           glVertex3d (xPlaneN, ypTick, zpTickN);
           glVertex3d (xPlane, ypTick, zpTickN);
         }
-
-      // Y box
-      set_color (props.get_ycolor_rgb ());
-      glVertex3d (xpTick, yPlaneN, zpTick);
-      glVertex3d (xpTick, yPlane, zpTick);
-
-      if (props.is_box () && ! plotyy)
+    }
+
+  // Y box
+  set_color (props.get_ycolor_rgb ());
+  glVertex3d (xpTick, yPlaneN, zpTick);
+  glVertex3d (xpTick, yPlane, zpTick);
+
+  if (props.is_box () && ! plotyy)
+    {
+      glVertex3d (xpTickN, yPlaneN, zpTick);
+      glVertex3d (xpTickN, yPlane, zpTick);
+
+      if (! is2d)
         {
-          glVertex3d (xpTickN, yPlaneN, zpTick);
-          glVertex3d (xpTickN, yPlane, zpTick);
           glVertex3d (xpTickN, yPlaneN, zpTickN);
           glVertex3d (xpTickN, yPlane, zpTickN);
           glVertex3d (xpTick, yPlaneN, zpTickN);
           glVertex3d (xpTick, yPlane, zpTickN);
         }
-
-      // Z box
-      set_color (props.get_zcolor_rgb ());
+    }
+
+  // Z box
+  set_color (props.get_zcolor_rgb ());
+
+  if (xySym)
+    {
+      glVertex3d (xPlaneN, yPlane, zPlaneN);
+      glVertex3d (xPlaneN, yPlane, zPlane);
+    }
+  else
+    {
+      glVertex3d (xPlane, yPlaneN, zPlaneN);
+      glVertex3d (xPlane, yPlaneN, zPlane);
+    }
+
+  if (props.is_box ())
+    {
+      glVertex3d (xPlane, yPlane, zPlaneN);
+      glVertex3d (xPlane, yPlane, zPlane);
 
       if (xySym)
         {
-          glVertex3d (xPlaneN, yPlane, zPlaneN);
-          glVertex3d (xPlaneN, yPlane, zPlane);
-        }
-      else
-        {
           glVertex3d (xPlane, yPlaneN, zPlaneN);
           glVertex3d (xPlane, yPlaneN, zPlane);
         }
-
-      if (props.is_box ())
+      else
         {
-          glVertex3d (xPlane, yPlane, zPlaneN);
-          glVertex3d (xPlane, yPlane, zPlane);
-
-          if (xySym)
-            {
-              glVertex3d (xPlane, yPlaneN, zPlaneN);
-              glVertex3d (xPlane, yPlaneN, zPlane);
-            }
-          else
-            {
-              glVertex3d (xPlaneN, yPlane, zPlaneN);
-              glVertex3d (xPlaneN, yPlane, zPlane);
-            }
-
-          glVertex3d (xPlaneN, yPlaneN, zPlaneN);
-          glVertex3d (xPlaneN, yPlaneN, zPlane);
+          glVertex3d (xPlaneN, yPlane, zPlaneN);
+          glVertex3d (xPlaneN, yPlane, zPlane);
         }
 
-      glEnd ();
+      glVertex3d (xPlaneN, yPlaneN, zPlaneN);
+      glVertex3d (xPlaneN, yPlaneN, zPlane);
     }
+
+  glEnd ();
 }
 
 void
 opengl_renderer::draw_axes_x_grid (const axes::properties& props)
 {
   int xstate = props.get_xstate ();
-  int zstate = props.get_zstate ();
-  bool x2Dtop = props.get_x2Dtop ();
-  bool layer2Dtop = props.get_layer2Dtop ();
-  bool xyzSym = props.get_xyzSym ();
-  bool nearhoriz = props.get_nearhoriz ();
-  double xticklen = props.get_xticklen ();
-  double xtickoffset = props.get_xtickoffset ();
-  double fy = props.get_fy ();
-  double fz = props.get_fz ();
-  double x_min = props.get_x_min ();
-  double x_max = props.get_x_max ();
-  double yPlane = props.get_yPlane ();
-  double yPlaneN = props.get_yPlaneN ();
-  double ypTick = props.get_ypTick ();
-  double ypTickN = props.get_ypTickN ();
-  double zPlane = props.get_zPlane ();
-  double zPlaneN = props.get_zPlaneN ();
-  double zpTick = props.get_zpTick ();
-  double zpTickN = props.get_zpTickN ();
-
-  // X grid
 
   if (props.is_visible () && xstate != AXE_DEPTH_DIR)
     {
+      int zstate = props.get_zstate ();
+      bool x2Dtop = props.get_x2Dtop ();
+      bool layer2Dtop = props.get_layer2Dtop ();
+      bool xyzSym = props.get_xyzSym ();
+      bool nearhoriz = props.get_nearhoriz ();
+      double xticklen = props.get_xticklen ();
+      double xtickoffset = props.get_xtickoffset ();
+      double fy = props.get_fy ();
+      double fz = props.get_fz ();
+      double x_min = props.get_x_min ();
+      double x_max = props.get_x_max ();
+      double yPlane = props.get_yPlane ();
+      double yPlaneN = props.get_yPlaneN ();
+      double ypTick = props.get_ypTick ();
+      double ypTickN = props.get_ypTickN ();
+      double zPlane = props.get_zPlane ();
+      double zPlaneN = props.get_zPlaneN ();
+      double zpTick = props.get_zpTick ();
+      double zpTickN = props.get_zpTickN ();
+
+      // X grid
+
       std::string gridstyle = props.get_gridlinestyle ();
       std::string minorgridstyle = props.get_minorgridlinestyle ();
       bool do_xgrid = (props.is_xgrid () && (gridstyle != "none"));
@@ -1002,7 +1043,8 @@
       Matrix xticks = xform.xscale (props.get_xtick ().matrix_value ());
       Matrix xmticks = xform.xscale (props.get_xmtick ().matrix_value ());
       string_vector xticklabels = props.get_xticklabel ().all_strings ();
-      int wmax = 0, hmax = 0;
+      int wmax = 0;
+      int hmax = 0;
       bool tick_along_z = nearhoriz || xisinf (fy);
       bool mirror = props.is_box () && xstate != AXE_ANY_DIR;
 
@@ -1077,30 +1119,31 @@
 opengl_renderer::draw_axes_y_grid (const axes::properties& props)
 {
   int ystate = props.get_ystate ();
-  int zstate = props.get_zstate ();
-  bool y2Dright = props.get_y2Dright ();
-  bool layer2Dtop = props.get_layer2Dtop ();
-  bool xyzSym = props.get_xyzSym ();
-  bool nearhoriz = props.get_nearhoriz ();
-  double yticklen = props.get_yticklen ();
-  double ytickoffset = props.get_ytickoffset ();
-  double fx = props.get_fx ();
-  double fz = props.get_fz ();
-  double xPlane = props.get_xPlane ();
-  double xPlaneN = props.get_xPlaneN ();
-  double xpTick = props.get_xpTick ();
-  double xpTickN = props.get_xpTickN ();
-  double y_min = props.get_y_min ();
-  double y_max = props.get_y_max ();
-  double zPlane = props.get_zPlane ();
-  double zPlaneN = props.get_zPlaneN ();
-  double zpTick = props.get_zpTick ();
-  double zpTickN = props.get_zpTickN ();
-
-  // Y grid
 
   if (ystate != AXE_DEPTH_DIR && props.is_visible ())
     {
+      int zstate = props.get_zstate ();
+      bool y2Dright = props.get_y2Dright ();
+      bool layer2Dtop = props.get_layer2Dtop ();
+      bool xyzSym = props.get_xyzSym ();
+      bool nearhoriz = props.get_nearhoriz ();
+      double yticklen = props.get_yticklen ();
+      double ytickoffset = props.get_ytickoffset ();
+      double fx = props.get_fx ();
+      double fz = props.get_fz ();
+      double xPlane = props.get_xPlane ();
+      double xPlaneN = props.get_xPlaneN ();
+      double xpTick = props.get_xpTick ();
+      double xpTickN = props.get_xpTickN ();
+      double y_min = props.get_y_min ();
+      double y_max = props.get_y_max ();
+      double zPlane = props.get_zPlane ();
+      double zPlaneN = props.get_zPlaneN ();
+      double zpTick = props.get_zpTick ();
+      double zpTickN = props.get_zpTickN ();
+
+      // Y grid
+
       std::string gridstyle = props.get_gridlinestyle ();
       std::string minorgridstyle = props.get_minorgridlinestyle ();
       bool do_ygrid = (props.is_ygrid () && (gridstyle != "none"));
@@ -1110,7 +1153,8 @@
       Matrix yticks = xform.yscale (props.get_ytick ().matrix_value ());
       Matrix ymticks = xform.yscale (props.get_ymtick ().matrix_value ());
       string_vector yticklabels = props.get_yticklabel ().all_strings ();
-      int wmax = 0, hmax = 0;
+      int wmax = 0;
+      int hmax = 0;
       bool tick_along_z = nearhoriz || xisinf (fx);
       bool mirror = props.is_box () && ystate != AXE_ANY_DIR
                     && (! props.has_property ("__plotyy_axes__"));
@@ -1183,23 +1227,24 @@
 opengl_renderer::draw_axes_z_grid (const axes::properties& props)
 {
   int zstate = props.get_zstate ();
-  bool xySym = props.get_xySym ();
-  bool zSign = props.get_zSign ();
-  double zticklen = props.get_zticklen ();
-  double ztickoffset = props.get_ztickoffset ();
-  double fx = props.get_fx ();
-  double fy = props.get_fy ();
-  double xPlane = props.get_xPlane ();
-  double xPlaneN = props.get_xPlaneN ();
-  double yPlane = props.get_yPlane ();
-  double yPlaneN = props.get_yPlaneN ();
-  double z_min = props.get_z_min ();
-  double z_max = props.get_z_max ();
-
-  // Z Grid
 
   if (zstate != AXE_DEPTH_DIR && props.is_visible ())
     {
+      bool xySym = props.get_xySym ();
+      bool zSign = props.get_zSign ();
+      double zticklen = props.get_zticklen ();
+      double ztickoffset = props.get_ztickoffset ();
+      double fx = props.get_fx ();
+      double fy = props.get_fy ();
+      double xPlane = props.get_xPlane ();
+      double xPlaneN = props.get_xPlaneN ();
+      double yPlane = props.get_yPlane ();
+      double yPlaneN = props.get_yPlaneN ();
+      double z_min = props.get_z_min ();
+      double z_max = props.get_z_max ();
+
+      // Z Grid
+
       std::string gridstyle = props.get_gridlinestyle ();
       std::string minorgridstyle = props.get_minorgridlinestyle ();
       bool do_zgrid = (props.is_zgrid () && (gridstyle != "none"));
@@ -1209,7 +1254,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 ());
@@ -1324,12 +1370,6 @@
 {
   // Children
 
-  GLboolean antialias;
-  glGetBooleanv (GL_LINE_SMOOTH, &antialias);
-
-  if (antialias == GL_TRUE)
-    glEnable (GL_LINE_SMOOTH);
-
   Matrix children = props.get_all_children ();
   std::list<graphics_object> obj_list;
   std::list<graphics_object>::iterator it;
@@ -1337,11 +1377,11 @@
   // 1st pass: draw light objects
 
   // Start with the last element of the array of child objects to
-  // display them in the oder they were added to the array.
+  // display them in the order they were added to the array.
 
   for (octave_idx_type i = children.numel () - 1; i >= 0; i--)
     {
-      graphics_object go = gh_manager::get_object (children (i));
+      graphics_object go = gh_manager::get_object (children(i));
 
       if (go.get_properties ().is_visible ())
         {
@@ -1407,12 +1447,18 @@
   if (x_max > floatmax || y_max > floatmax || z_max > floatmax
       || x_min < -floatmax || y_min < -floatmax || z_min < -floatmax)
     {
-      warning ("gl-render: data values greater than float capacity.  (1) Scale data, or (2) Use gnuplot");
+      warning ("opengl_renderer: data values greater than float capacity.  (1) Scale data, or (2) Use gnuplot");
       return;
     }
 
   setup_opengl_transformation (props);
 
+  // Disable line smoothing for axes 
+  GLboolean antialias;
+  glGetBooleanv (GL_LINE_SMOOTH, &antialias);
+  if (antialias == GL_TRUE)
+    glDisable (GL_LINE_SMOOTH);
+
   // draw axes object
 
   draw_axes_planes (props);
@@ -1428,6 +1474,10 @@
 
   set_clipbox (x_min, x_max, y_min, y_max, z_min, z_max);
 
+  // Re-enable line smoothing for children
+  if (antialias == GL_TRUE)
+    glEnable (GL_LINE_SMOOTH);
+
   draw_axes_children (props);
 }
 
@@ -1545,7 +1595,7 @@
         {
           if (clip[i] == clip_ok)
             draw_marker (x(i), y(i),
-                         has_z ? z(i) : static_cast<double> (i) / n,
+                         has_z ? z(i) : 0.0,
                          lc, fc);
         }
 
@@ -1562,7 +1612,8 @@
   const Matrix y = xform.yscale (props.get_ydata ().matrix_value ());
   const Matrix z = xform.zscale (props.get_zdata ().matrix_value ());
 
-  int zr = z.rows (), zc = z.columns ();
+  int zr = z.rows ();
+  int zc = z.columns ();
 
   NDArray c;
   const NDArray n = props.get_vertexnormals ().array_value ();
@@ -1571,7 +1622,7 @@
   Matrix a;
 
   if (props.facelighting_is ("phong") || props.edgelighting_is ("phong"))
-    warning ("opengl_renderer::draw: phong light model not supported");
+    warning ("opengl_renderer: phong light model not supported");
 
   int fc_mode = (props.facecolor_is_rgb () ? 0 :
                  (props.facecolor_is ("flat") ? 1 :
@@ -1589,8 +1640,8 @@
   int ea_mode = (props.edgealpha_is_double () ? 0 :
                  (props.edgealpha_is ("flat") ? 1 : 2));
 
-  Matrix fcolor = (fc_mode == 3 ? Matrix (1, 3, 1.0)
-                                : props.get_facecolor_rgb ());
+  Matrix fcolor = (fc_mode == TEXTURE ? Matrix (1, 3, 1.0)
+                                      : props.get_facecolor_rgb ());
   Matrix ecolor = props.get_edgecolor_rgb ();
 
   float as = props.get_ambientstrength ();
@@ -1641,16 +1692,16 @@
       glMaterialf (LIGHT_MODE, GL_SHININESS, se);
     }
 
-  // FIXME: good candidate for caching, transfering pixel
-  // data to OpenGL is time consuming.
-  if (fc_mode == 3)
+  // FIXME: good candidate for caching,
+  //        transferring pixel data to OpenGL is time consuming.
+  if (fc_mode == TEXTURE)
     tex = opengl_texture::create (props.get_color_data ());
 
   if (! props.facecolor_is ("none"))
     {
       if (props.get_facealpha_double () == 1)
         {
-          if (fc_mode == 0 || fc_mode == 3)
+          if (fc_mode == UNIFORM || fc_mode == TEXTURE)
             {
               glColor3dv (fcolor.data ());
               if (fl_mode > 0)
@@ -1667,9 +1718,10 @@
 
           if (fl_mode > 0)
             glEnable (GL_LIGHTING);
-          glShadeModel ((fc_mode == 2 || fl_mode == 2) ? GL_SMOOTH : GL_FLAT);
+          glShadeModel ((fc_mode == INTERP || fl_mode == GOURAUD) ? GL_SMOOTH
+                                                                  : GL_FLAT);
           set_polygon_offset (true, 1);
-          if (fc_mode == 3)
+          if (fc_mode == TEXTURE)
             glEnable (GL_TEXTURE_2D);
 
           for (int i = 1; i < zc; i++)
@@ -1687,13 +1739,13 @@
                       || clip(j-1, i) || clip(j, i))
                     continue;
 
-                  if (fc_mode == 1)
+                  if (fc_mode == FLAT)
                     {
                       // "flat" only needs color at lower-left vertex
                       if (! xfinite (c(j-1,i-1)))
                         continue;
                     }
-                  else if (fc_mode == 2)
+                  else if (fc_mode == INTERP)
                     {
                       // "interp" needs valid color at all 4 vertices
                       if (! (xfinite (c(j-1, i-1)) && xfinite (c(j, i-1))
@@ -1710,7 +1762,7 @@
                   glBegin (GL_QUADS);
 
                   // Vertex 1
-                  if (fc_mode == 3)
+                  if (fc_mode == TEXTURE)
                     tex.tex_coord (double (i-1) / (zc-1),
                                    double (j-1) / (zr-1));
                   else if (fc_mode > 0)
@@ -1743,9 +1795,9 @@
                   glVertex3d (x(j1,i-1), y(j-1,i1), z(j-1,i-1));
 
                   // Vertex 2
-                  if (fc_mode == 3)
+                  if (fc_mode == TEXTURE)
                     tex.tex_coord (double (i) / (zc-1), double (j-1) / (zr-1));
-                  else if (fc_mode == 2)
+                  else if (fc_mode == INTERP)
                     {
                       for (int k = 0; k < 3; k++)
                         cb[k] = c(j-1, i, k);
@@ -1763,7 +1815,7 @@
                         }
                     }
 
-                  if (fl_mode == 2)
+                  if (fl_mode == GOURAUD)
                     {
                       d = sqrt (n(j-1,i,0) * n(j-1,i,0)
                                 + n(j-1,i,1) * n(j-1,i,1)
@@ -1774,9 +1826,9 @@
                   glVertex3d (x(j1,i), y(j-1,i2), z(j-1,i));
 
                   // Vertex 3
-                  if (fc_mode == 3)
+                  if (fc_mode == TEXTURE)
                     tex.tex_coord (double (i) / (zc-1), double (j) / (zr-1));
-                  else if (fc_mode == 2)
+                  else if (fc_mode == INTERP)
                     {
                       for (int k = 0; k < 3; k++)
                         cb[k] = c(j, i, k);
@@ -1793,7 +1845,7 @@
                           glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
                         }
                     }
-                  if (fl_mode == 2)
+                  if (fl_mode == GOURAUD)
                     {
                       d = sqrt (n(j,i,0) * n(j,i,0)
                                 + n(j,i,1) * n(j,i,1)
@@ -1803,9 +1855,9 @@
                   glVertex3d (x(j2,i), y(j,i2), z(j,i));
 
                   // Vertex 4
-                  if (fc_mode == 3)
+                  if (fc_mode == TEXTURE)
                     tex.tex_coord (double (i-1) / (zc-1), double (j) / (zr-1));
-                  else if (fc_mode == 2)
+                  else if (fc_mode == INTERP)
                     {
                       for (int k = 0; k < 3; k++)
                         cb[k] = c(j, i-1, k);
@@ -1822,7 +1874,7 @@
                           glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
                         }
                     }
-                  if (fl_mode == 2)
+                  if (fl_mode == GOURAUD)
                     {
                       d = sqrt (n(j,i-1,0) * n(j,i-1,0)
                                 + n(j,i-1,1) * n(j,i-1,1)
@@ -1836,7 +1888,7 @@
             }
 
           set_polygon_offset (false);
-          if (fc_mode == 3)
+          if (fc_mode == TEXTURE)
             glDisable (GL_TEXTURE_2D);
 
           if (fl_mode > 0)
@@ -1852,7 +1904,7 @@
     {
       if (props.get_edgealpha_double () == 1)
         {
-          if (ec_mode == 0)
+          if (ec_mode == UNIFORM)
             {
               glColor3dv (ecolor.data ());
               if (fl_mode > 0)
@@ -1869,7 +1921,8 @@
 
           if (el_mode > 0)
             glEnable (GL_LIGHTING);
-          glShadeModel ((ec_mode == 2 || el_mode == 2) ? GL_SMOOTH : GL_FLAT);
+          glShadeModel ((ec_mode == INTERP || el_mode == GOURAUD) ? GL_SMOOTH
+                                                                  : GL_FLAT);
 
           set_linestyle (props.get_linestyle (), false);
           set_linewidth (props.get_linewidth ());
@@ -1891,13 +1944,13 @@
                       if (clip(j-1,i) || clip(j,i))
                         continue;
 
-                      if (ec_mode == 1)
+                      if (ec_mode == FLAT)
                         {
                           // "flat" only needs color at lower-left vertex
                           if (! xfinite (c(j-1,i)))
                             continue;
                         }
-                      else if (ec_mode == 2)
+                      else if (ec_mode == INTERP)
                         {
                           // "interp" needs valid color at both vertices
                           if (! (xfinite (c(j-1, i)) && xfinite (c(j, i))))
@@ -1940,7 +1993,7 @@
                       glVertex3d (x(j1,i), y(j-1,i2), z(j-1,i));
 
                       // Vertex 2
-                      if (ec_mode == 2)
+                      if (ec_mode == INTERP)
                         {
                           for (int k = 0; k < 3; k++)
                             cb[k] = c(j, i, k);
@@ -1957,7 +2010,7 @@
                               glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
                             }
                         }
-                      if (el_mode == 2)
+                      if (el_mode == GOURAUD)
                         {
                           d = sqrt (n(j,i,0) * n(j,i,0)
                                     + n(j,i,1) * n(j,i,1)
@@ -1988,13 +2041,13 @@
                       if (clip(j,i-1) || clip(j,i))
                         continue;
 
-                      if (ec_mode == 1)
+                      if (ec_mode == FLAT)
                         {
                           // "flat" only needs color at lower-left vertex
                           if (! xfinite (c(j,i-1)))
                             continue;
                         }
-                      else if (ec_mode == 2)
+                      else if (ec_mode == INTERP)
                         {
                           // "interp" needs valid color at both vertices
                           if (! (xfinite (c(j, i-1)) && xfinite (c(j, i))))
@@ -2037,7 +2090,7 @@
                       glVertex3d (x(j2,i-1), y(j,i1), z(j,i-1));
 
                       // Vertex 2
-                      if (ec_mode == 2)
+                      if (ec_mode == INTERP)
                         {
                           for (int k = 0; k < 3; k++)
                             cb[k] = c(j, i, k);
@@ -2054,7 +2107,7 @@
                               glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
                             }
                         }
-                      if (el_mode == 2)
+                      if (el_mode == GOURAUD)
                         {
                           d = sqrt (n(j,i,0) * n(j,i,0)
                                     + n(j,i,1) * n(j,i,1)
@@ -2150,11 +2203,19 @@
     }
 }
 
-// FIXME: global optimization (rendering, data structures...), there
-// is probably a smarter/faster/less-memory-consuming way to do this.
+// FIXME: global optimization (rendering, data structures...),
+// there is probably a smarter/faster/less-memory-consuming way to do this.
 void
 opengl_renderer::draw_patch (const patch::properties &props)
 {
+  // Do not render if the patch has incoherent data
+  std::string msg;
+  if (props.has_bad_data (msg))
+    {
+      warning ("opengl_renderer: %s. Not rendering.", msg.c_str ());
+      return;
+    }
+
   const Matrix f = props.get_faces ().matrix_value ();
   const Matrix v = xform.scale (props.get_vertices ().matrix_value ());
   Matrix c;
@@ -2162,7 +2223,6 @@
   Matrix a;
 
   int nv = v.rows ();
-  // int vmax = v.columns ();
   int nf = f.rows ();
   int fcmax = f.columns ();
 
@@ -2228,13 +2288,13 @@
           if (fc_mode > 0)
             {
               fcolor = c;
-              fc_mode = 0;
+              fc_mode = UNIFORM;
             }
 
           if (ec_mode > 0)
             {
               ecolor = c;
-              ec_mode = 0;
+              ec_mode = UNIFORM;
             }
 
           c = Matrix ();
@@ -2260,7 +2320,7 @@
 
         Matrix vv (1, 3, 0.0);
         Matrix cc;
-        Matrix nn(1, 3, 0.0);
+        Matrix nn (1, 3, 0.0);
         double aa = 1.0;
 
         vv(0) = v(idx,0); vv(1) = v(idx,1);
@@ -2284,8 +2344,7 @@
               aa = a(idx);
           }
 
-        vdata[i+j*fr] =
-          vertex_data (vv, cc, nn, aa, as, ds, ss, se);
+        vdata[i+j*fr] = vertex_data (vv, cc, nn, aa, as, ds, ss, se);
       }
 
   if (fl_mode > 0 || el_mode > 0)
@@ -2301,7 +2360,7 @@
       // FIXME: adapt to double-radio property
       if (props.get_facealpha_double () == 1)
         {
-          if (fc_mode == 0)
+          if (fc_mode == UNIFORM)
             {
               glColor3dv (fcolor.data ());
               if (fl_mode > 0)
@@ -2321,8 +2380,11 @@
           if (fl_mode > 0)
             glEnable (GL_LIGHTING);
 
-          // FIXME: use __index__ property from patch object
-          patch_tesselator tess (this, fc_mode, fl_mode, 0);
+          // NOTE: Push filled part of patch backwards to avoid Z-fighting with
+          // tesselator outline.  A value of 1.0 seems to work fine.  Value
+          // can't be too large or the patch will be pushed below the axes
+          // planes at +2.5.
+          patch_tesselator tess (this, fc_mode, fl_mode, 1.0);
 
           for (int i = 0; i < nf; i++)
             {
@@ -2332,13 +2394,44 @@
               tess.begin_polygon (true);
               tess.begin_contour ();
 
-              for (int j = 0; j < count_f(i); j++)
+              // Add vertices in reverse order for Matlab compatibility
+              for (int j = count_f(i)-1; j > 0; j--)
                 {
                   vertex_data::vertex_data_rep *vv = vdata[i+j*fr].get_rep ();
 
                   tess.add_vertex (vv->coords.fortran_vec (), vv);
                 }
 
+              if (count_f(i) > 0)
+                {
+                  vertex_data::vertex_data_rep *vv = vdata[i].get_rep ();
+
+                  if (fc_mode == FLAT)
+                    {
+                      // For "flat" shading, use color of 1st vertex.
+                      Matrix col = vv->color;
+
+                      if (col.numel () == 3)
+                        {
+                          glColor3dv (col.data ());
+                          if (fl_mode > 0)
+                            {
+                              float cb[4] = { 0, 0, 0, 1 };
+
+                              for (int k = 0; k < 3; k++)
+                                cb[k] = (vv->ambient * col(k));
+                              glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
+
+                              for (int k = 0; k < 3; k++)
+                                cb[k] = (vv->diffuse * col(k));
+                              glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
+                            }
+                        }
+                    }
+
+                  tess.add_vertex (vv->coords.fortran_vec (), vv);
+                }
+
               tess.end_contour ();
               tess.end_polygon ();
             }
@@ -2357,7 +2450,7 @@
       // FIXME: adapt to double-radio property
       if (props.get_edgealpha_double () == 1)
         {
-          if (ec_mode == 0)
+          if (ec_mode == UNIFORM)
             {
               glColor3dv (ecolor.data ());
               if (el_mode > 0)
@@ -2380,19 +2473,25 @@
           set_linestyle (props.get_linestyle (), false);
           set_linewidth (props.get_linewidth ());
 
-
-          // FIXME: use __index__ property from patch object; should we
-          // offset patch contour as well?
+          // NOTE: patch contour cannot be offset.  Offset must occur with the
+          // filled portion of the patch above.  The tesselator uses
+          // GLU_TESS_BOUNDARY_ONLY to get the outline of the patch and OpenGL
+          // automatically sets the glType to GL_LINE_LOOP.  This primitive is
+          // not supported by glPolygonOffset which is used to do Z offsets. 
           patch_tesselator tess (this, ec_mode, el_mode);
 
           for (int i = 0; i < nf; i++)
             {
               if (clip_f(i))
                 {
-                  // This is an unclosed contour. Draw it as a line
+                  // This is an unclosed contour.  Draw it as a line.
                   bool flag = false;
 
-                  for (int j = 0; j < count_f(i); j++)
+                  glShadeModel ((ec_mode == INTERP || el_mode == GOURAUD)
+                                ? GL_SMOOTH : GL_FLAT);
+
+                  // Add vertices in reverse order for Matlab compatibility
+                  for (int j = count_f(i)-1; j >= 0; j--)
                     {
                       if (! clip(int (f(i,j) - 1)))
                         {
@@ -2404,6 +2503,13 @@
                               flag = true;
                               glBegin (GL_LINE_STRIP);
                             }
+                          if (ec_mode != UNIFORM)
+                            {
+                              Matrix col = vv->color;
+
+                              if (col.numel () == 3)
+                                glColor3dv (col.data ());
+                            }
                           glVertex3d (m(0), m(1), m(2));
                         }
                       else if (flag)
@@ -2412,16 +2518,33 @@
                           glEnd ();
                         }
                     }
+                  // Do loop body with vertex N to "close" GL_LINE_STRIP
+                  // from vertex 0 to vertex N.
+                  int j = count_f(i)-1;
+                  if (flag && ! clip(int (f(i,j) - 1)))
+                    {
+                      vertex_data::vertex_data_rep *vv
+                        = vdata[i+j*fr].get_rep ();
+                      const Matrix m = vv->coords;
+                      if (ec_mode != UNIFORM)
+                        {
+                          Matrix col = vv->color;
+
+                          if (col.numel () == 3)
+                            glColor3dv (col.data ());
+                        }
+                      glVertex3d (m(0), m(1), m(2));
+                    }
 
                   if (flag)
                     glEnd ();
                 }
-              else
+              else  // Normal edge contour drawn with tesselator
                 {
                   tess.begin_polygon (false);
                   tess.begin_contour ();
 
-                  for (int j = 0; j < count_f(i); j++)
+                  for (int j = count_f(i)-1; j >= 0; j--)
                     {
                       vertex_data::vertex_data_rep *vv
                         = vdata[i+j*fr].get_rep ();
@@ -2529,6 +2652,8 @@
   if (props.get_string ().is_empty ())
     return;
 
+  set_font (props);
+
   Matrix pos = xform.scale (props.get_data_position ());
   const Matrix bbox = props.get_extent_matrix ();
 
@@ -2552,7 +2677,8 @@
 {
   octave_value cdata = props.get_color_data ();
   dim_vector dv (cdata.dims ());
-  int h = dv(0), w = dv(1);
+  int h = dv(0);
+  int w = dv(1);
 
   Matrix x = props.get_xdata ().matrix_value ();
   Matrix y = props.get_ydata ().matrix_value ();
@@ -2572,7 +2698,7 @@
 
   if (xisnan (p0(0)) || xisnan (p0(1)) || xisnan (p1(0)) || xisnan (p1(1)))
     {
-      warning ("gl-render: image x,y data too large to draw");
+      warning ("opengl_renderer: image X,Y data too large to draw");
       return;
     }
 
@@ -2605,13 +2731,12 @@
       nor_dy = 1;
     }
 
-
-  // OpenGL won't draw the image if it's origin is outside the
-  // viewport/clipping plane so we must do the clipping
-  // ourselfes - only draw part of the image
-
-  int j0 = 0, j1 = w;
-  int i0 = 0, i1 = h;
+  // OpenGL won't draw any of the image if it's origin is outside the
+  // viewport/clipping plane so we must do the clipping ourselves.
+
+  int j0, j1, i0, i1;
+  j0 = 0, j1 = w;
+  i0 = 0, i1 = h;
 
   float im_xmin = x(0) - nor_dx/2;
   float im_xmax = x(1) + nor_dx/2;
@@ -2644,7 +2769,7 @@
   glRasterPos3d (im_xmin + nor_dx*j0, im_ymin + nor_dy*i0, 0);
 
   // by default this is 4
-  glPixelStorei (GL_UNPACK_ALIGNMENT,1);
+  glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
 
   // Expect RGB data
   if (dv.length () == 3 && dv(2) == 3)
@@ -2668,6 +2793,44 @@
           draw_pixels (j1-j0, i1-i0, GL_RGB, GL_FLOAT, a);
 
         }
+      else if (cdata.is_single_type ())
+        {
+          const FloatNDArray xcdata = cdata.float_array_value ();
+
+          OCTAVE_LOCAL_BUFFER (GLfloat, a, 3*(j1-j0)*(i1-i0));
+
+          for (int i = i0; i < i1; i++)
+            {
+              for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3)
+                {
+                  a[idx]   = xcdata(i,j,0);
+                  a[idx+1] = xcdata(i,j,1);
+                  a[idx+2] = xcdata(i,j,2);
+                }
+            }
+
+          draw_pixels (j1-j0, i1-i0, GL_RGB, GL_FLOAT, a);
+
+        }
+      else if (cdata.is_uint8_type ())
+        {
+          const uint8NDArray xcdata = cdata.uint8_array_value ();
+
+          OCTAVE_LOCAL_BUFFER (GLubyte, a, 3*(j1-j0)*(i1-i0));
+
+          for (int i = i0; i < i1; i++)
+            {
+              for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3)
+                {
+                  a[idx]   = xcdata(i,j,0);
+                  a[idx+1] = xcdata(i,j,1);
+                  a[idx+2] = xcdata(i,j,2);
+                }
+            }
+
+          draw_pixels (j1-j0, i1-i0, GL_RGB, GL_UNSIGNED_BYTE, a);
+
+        }
       else if (cdata.is_uint16_type ())
         {
           const uint16NDArray xcdata = cdata.uint16_array_value ();
@@ -2687,29 +2850,11 @@
           draw_pixels (j1-j0, i1-i0, GL_RGB, GL_UNSIGNED_SHORT, a);
 
         }
-      else if (cdata.is_uint8_type ())
-        {
-          const uint8NDArray xcdata = cdata.uint8_array_value ();
-
-          OCTAVE_LOCAL_BUFFER (GLubyte, a, 3*(j1-j0)*(i1-i0));
-
-          for (int i = i0; i < i1; i++)
-            {
-              for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3)
-                {
-                  a[idx]   = xcdata(i,j,0);
-                  a[idx+1] = xcdata(i,j,1);
-                  a[idx+2] = xcdata(i,j,2);
-                }
-            }
-
-          draw_pixels (j1-j0, i1-i0, GL_RGB, GL_UNSIGNED_BYTE, a);
-        }
       else
-        warning ("opengl_texture::draw: invalid image data type (expected double, uint16, or uint8)");
+        warning ("opengl_renderer: invalid image data type (expected double, single, uint8, or uint16)");
     }
   else
-    warning ("opengl_texture::draw: invalid image size (expected n*m*3 or n*m)");
+    warning ("opengl_renderer: invalid image size (expected MxNx3 or MxN)");
 
   glPixelZoom (1, 1);
 }
@@ -2743,18 +2888,18 @@
   text_renderer.set_font (props.get ("fontname").string_value (),
                           props.get ("fontweight").string_value (),
                           props.get ("fontangle").string_value (),
-                          props.get ("fontsize").double_value ());
+                          props.get ("fontsize_points").double_value ());
 #endif
 }
 
 void
-opengl_renderer::set_polygon_offset (bool on, double offset)
+opengl_renderer::set_polygon_offset (bool on, float offset)
 {
   if (on)
     {
-      glPolygonOffset (offset, offset);
       glEnable (GL_POLYGON_OFFSET_FILL);
       glEnable (GL_POLYGON_OFFSET_LINE);
+      glPolygonOffset (offset, offset);
     }
   else
     {
@@ -2782,7 +2927,7 @@
   else if (s == ":")
     glLineStipple (1, static_cast<unsigned short> (0x8888));
   else if (s == "--")
-    glLineStipple (1, static_cast<unsigned short> (0x0FFF));
+    glLineStipple (1, static_cast<unsigned short> (0xF0F0));
   else if (s == "-.")
     glLineStipple (1, static_cast<unsigned short> (0x020F));
   else
@@ -2934,30 +3079,30 @@
     {
     case '+':
       glBegin (GL_LINES);
-      glVertex2f (-sz/2, 0);
-      glVertex2f (sz/2, 0);
-      glVertex2f (0, -sz/2);
-      glVertex2f (0, sz/2);
+      glVertex2d (-sz/2, 0);
+      glVertex2d (sz/2, 0);
+      glVertex2d (0, -sz/2);
+      glVertex2d (0, sz/2);
       glEnd ();
       break;
     case 'x':
       glBegin (GL_LINES);
-      glVertex2f (-sz/2, -sz/2);
-      glVertex2f (sz/2, sz/2);
-      glVertex2f (-sz/2, sz/2);
-      glVertex2f (sz/2, -sz/2);
+      glVertex2d (-sz/2, -sz/2);
+      glVertex2d (sz/2, sz/2);
+      glVertex2d (-sz/2, sz/2);
+      glVertex2d (sz/2, -sz/2);
       glEnd ();
       break;
     case '*':
       glBegin (GL_LINES);
-      glVertex2f (-sz/2, 0);
-      glVertex2f (sz/2, 0);
-      glVertex2f (0, -sz/2);
-      glVertex2f (0, sz/2);
-      glVertex2f (-tt, -tt);
-      glVertex2f (+tt, +tt);
-      glVertex2f (-tt, +tt);
-      glVertex2f (+tt, -tt);
+      glVertex2d (-sz/2, 0);
+      glVertex2d (sz/2, 0);
+      glVertex2d (0, -sz/2);
+      glVertex2d (0, sz/2);
+      glVertex2d (-tt, -tt);
+      glVertex2d (+tt, +tt);
+      glVertex2d (-tt, +tt);
+      glVertex2d (+tt, -tt);
       glEnd ();
       break;
     case '.':
@@ -2998,30 +3143,30 @@
       break;
     case 'v':
       glBegin ((filled ? GL_POLYGON : GL_LINE_LOOP));
-      glVertex2f (0, sz/2);
-      glVertex2f (sz/2, -sz/2);
-      glVertex2f (-sz/2, -sz/2);
+      glVertex2d (0, sz/2);
+      glVertex2d (sz/2, -sz/2);
+      glVertex2d (-sz/2, -sz/2);
       glEnd ();
       break;
     case '^':
       glBegin ((filled ? GL_POLYGON : GL_LINE_LOOP));
-      glVertex2f (0, -sz/2);
-      glVertex2f (-sz/2, sz/2);
-      glVertex2f (sz/2, sz/2);
+      glVertex2d (0, -sz/2);
+      glVertex2d (-sz/2, sz/2);
+      glVertex2d (sz/2, sz/2);
       glEnd ();
       break;
     case '>':
       glBegin ((filled ? GL_POLYGON : GL_LINE_LOOP));
-      glVertex2f (sz/2, 0);
-      glVertex2f (-sz/2, sz/2);
-      glVertex2f (-sz/2, -sz/2);
+      glVertex2d (sz/2, 0);
+      glVertex2d (-sz/2, sz/2);
+      glVertex2d (-sz/2, -sz/2);
       glEnd ();
       break;
     case '<':
       glBegin ((filled ? GL_POLYGON : GL_LINE_LOOP));
-      glVertex2f (-sz/2, 0);
-      glVertex2f (sz/2, -sz/2);
-      glVertex2f (sz/2, sz/2);
+      glVertex2d (-sz/2, 0);
+      glVertex2d (sz/2, -sz/2);
+      glVertex2d (sz/2, sz/2);
       glEnd ();
       break;
     case 'p':
@@ -3057,8 +3202,7 @@
       }
       break;
     default:
-      warning ("opengl_renderer: unsupported marker '%s'",
-               marker.c_str ());
+      warning ("opengl_renderer: unsupported marker '%s'", marker.c_str ());
       break;
     }
 
@@ -3106,7 +3250,7 @@
 
   return bbox;
 #else
-  ::warning ("render_text: cannot render text, Freetype library not available");
+  warning ("opengl_renderer: cannot render text, FreeType library not available");
   return Matrix (1, 4, 0.0);
 #endif
 }
--- a/libinterp/corefcn/gl-render.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/gl-render.h	Mon Jan 12 09:17:35 2015 -0800
@@ -99,7 +99,7 @@
   virtual void setup_opengl_transformation (const axes::properties& props);
 
   virtual void set_color (const Matrix& c);
-  virtual void set_polygon_offset (bool on, double offset = 0.0);
+  virtual void set_polygon_offset (bool on, float offset = 0.0);
   virtual void set_linewidth (float w);
   virtual void set_linestyle (const std::string& s, bool stipple = false);
   virtual void set_clipbox (double x1, double x2, double y1, double y2,
@@ -206,7 +206,7 @@
   ColumnVector camera_pos, camera_dir;
 
 #if HAVE_FREETYPE
-  // freetype render, used for text rendering
+  // FreeType render, used for text rendering
   ft_render text_renderer;
 #endif
 
--- a/libinterp/corefcn/gl2ps-renderer.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/gl2ps-renderer.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -44,7 +44,8 @@
     {
       in_draw = true;
 
-      GLint buffsize = 0, state = GL2PS_OVERFLOW;
+      GLint buffsize = 0;
+      GLint state = GL2PS_OVERFLOW;
       GLint viewport[4];
 
       glGetIntegerv (GL_VIEWPORT, viewport);
@@ -52,13 +53,13 @@
       GLint gl2ps_term;
       if (term.find ("eps") != std::string::npos) gl2ps_term = GL2PS_EPS;
       else if (term.find ("pdf") != std::string::npos) gl2ps_term = GL2PS_PDF;
+      else if (term.find ("ps") != std::string::npos) gl2ps_term = GL2PS_PS;
       else if (term.find ("svg") != std::string::npos) gl2ps_term = GL2PS_SVG;
-      else if (term.find ("ps") != std::string::npos) gl2ps_term = GL2PS_PS;
       else if (term.find ("pgf") != std::string::npos) gl2ps_term = GL2PS_PGF;
       else if (term.find ("tex") != std::string::npos) gl2ps_term = GL2PS_TEX;
       else
         {
-          error ("gl2ps-renderer:: Unknown terminal");
+          error ("gl2ps-renderer::draw: Unknown terminal %s", term.c_str ());
           return;
         }
 
@@ -67,7 +68,9 @@
 
       // Default sort order optimizes for 3D plots
       GLint gl2ps_sort = GL2PS_BSP_SORT;
-      if (term.find ("is2D") != std::string::npos) gl2ps_sort = GL2PS_NO_SORT;
+      // For 2D plots we can use a simpler Z-depth sorting algorithm
+      if (term.find ("is2D") != std::string::npos)
+        gl2ps_sort = GL2PS_SIMPLE_SORT;
 
       while (state == GL2PS_OVERFLOW)
         {
@@ -92,16 +95,25 @@
           else
             include_graph = "foobar-inc";
           buffsize += 1024*1024;
-          gl2psBeginPage ("glps_renderer figure", "Octave", viewport,
-                          gl2ps_term, gl2ps_sort,
-                          (GL2PS_SILENT | GL2PS_SIMPLE_LINE_OFFSET
-                           | GL2PS_NO_BLENDING | GL2PS_OCCLUSION_CULL
-                           | GL2PS_BEST_ROOT | gl2ps_text
-                           | GL2PS_NO_PS3_SHADING),
-                          GL_RGBA, 0, NULL, 0, 0, 0,
-                          buffsize, fp, include_graph.c_str ());
+          // GL2PS_SILENT was removed to allow gl2ps printing errors on stderr
+          GLint ret = gl2psBeginPage ("glps_renderer figure", "Octave", viewport,
+                                      gl2ps_term, gl2ps_sort,
+                                      (  GL2PS_NO_BLENDING
+                                       | GL2PS_OCCLUSION_CULL
+                                       | GL2PS_BEST_ROOT
+                                       | gl2ps_text
+                                       | GL2PS_NO_PS3_SHADING),
+                                      GL_RGBA, 0, NULL, 0, 0, 0,
+                                      buffsize, fp, include_graph.c_str ());
+          if (ret == GL2PS_ERROR)
+            error ("gl2ps-renderer::draw: gl2psBeginPage returned GL2PS_ERROR");
           old_print_cmd = print_cmd;
           opengl_renderer::draw (go);
+
+          // Force execution of GL commands in finite time.
+          // Without glFlush () there may primitives be missing in the gl2ps output.
+          glFlush ();
+
           state = gl2psEndPage ();
         }
 
@@ -158,7 +170,7 @@
                 alignment_to_mode (ha, va), rotation);
 
   // FIXME?
-  // We have no way of getting a bounding box from gl2ps, so we use freetype.
+  // We have no way of getting a bounding box from gl2ps, so we use FreeType.
   Matrix bbox;
   uint8NDArray pixels;
   text_to_pixels (txt, pixels, bbox, 0, 0, rotation);
@@ -170,7 +182,7 @@
 {
   opengl_renderer::set_font (props);
 
-  fontsize = props.get ("fontsize").double_value ();
+  fontsize = props.get ("fontsize_points").double_value ();
 
   caseless_str fn = props.get ("fontname").string_value ();
   fontname = "";
@@ -195,9 +207,9 @@
   OCTAVE_LOCAL_BUFFER (GLfloat, a, 3*w*h);
 
   // Convert to GL_FLOAT as it is the only type gl2ps accepts.
-  for (unsigned int i = 0; i < 3*w*h; i++)
+  for (int i = 0; i < 3*w*h; i++)
     a[i] = data[i] / maxval;
-  
+
   gl2psDrawPixels (w, h, 0, 0, format, GL_FLOAT, a);
 }
 
@@ -225,7 +237,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 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/graphics.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -58,6 +58,7 @@
 #include "toplev.h"
 #include "txt-eng-ft.h"
 #include "unwind-prot.h"
+#include "octave-default-image.h"
 
 // forward declarations
 static octave_value xget (const graphics_handle& h, const caseless_str& name);
@@ -255,6 +256,93 @@
 }
 
 static Matrix
+default_image_cdata (void)
+{
+  Matrix m (64, 64, 0.0);
+  int i = 0;
+  for (int col = 0; col < 64; col++)
+    for (int row = 0; row < 64; row++)
+      {
+        m(col,row) = static_cast<double> (default_im_data[i]);
+        i++;
+      }
+
+  return m;
+}
+
+static Matrix
+default_surface_xdata (void)
+{
+  Matrix m (3, 3, 0.0);
+  for (int col = 0; col < 3; col++)
+    for (int row = 0; row < 3; row++)
+      m(row,col) = col+1;
+
+  return m;
+}
+
+static Matrix
+default_surface_ydata (void)
+{
+  Matrix m (3, 3, 0.0);
+  for (int row = 0; row < 3; row++)
+    for (int col = 0; col < 3; col++)
+      m(row,col) = row+1;
+
+  return m;
+}
+
+static Matrix
+default_surface_zdata (void)
+{
+  Matrix m (3, 3, 0.0);
+  for (int row = 0; row < 3; row++)
+    m(row,row) = 1.0;
+  return m;
+}
+
+static Matrix
+default_surface_cdata (void)
+{
+  return default_surface_zdata ();
+}
+
+static Matrix
+default_patch_faces (void)
+{
+  Matrix m (1, 3, 1.0);
+  m(1) = 2.0;
+  m(2) = 3.0;
+  return m;
+}
+
+static Matrix
+default_patch_vertices (void)
+{
+  Matrix m (3, 2, 0);
+  m(1) = 1.0;
+  m(3) = 1.0;
+  m(4) = 1.0;
+  return m;
+}
+
+static Matrix
+default_patch_xdata (void)
+{
+  Matrix m (3, 1, 0.0);
+  m(1) = 1.0;
+  return m;
+}
+
+static Matrix
+default_patch_ydata (void)
+{
+  Matrix m (3, 1, 1.0);
+  m(2) = 0.0;
+  return m;
+}
+
+static Matrix
 default_axes_position (void)
 {
   Matrix m (1, 4, 0.0);
@@ -274,6 +362,14 @@
 }
 
 static Matrix
+default_axes_view (void)
+{
+  Matrix m (1, 2, 0.0);
+  m(1) = 90.0;
+  return m;
+}
+
+static Matrix
 default_axes_tick (void)
 {
   Matrix m (1, 6, 0.0);
@@ -668,13 +764,13 @@
 }
 
 static void
-convert_cdata_2 (bool is_scaled, double clim_0, double clim_1,
+convert_cdata_2 (bool is_scaled, bool is_real, double clim_0, double clim_1,
                  const double *cmapv, double x, octave_idx_type lda,
                  octave_idx_type nc, octave_idx_type i, double *av)
 {
   if (is_scaled)
     x = xround ((nc - 1) * (x - clim_0) / (clim_1 - clim_0));
-  else
+  else if (is_real)
     x = xround (x - 1);
 
   if (xisnan (x))
@@ -700,12 +796,13 @@
 
 template <class T>
 void
-convert_cdata_1 (bool is_scaled, double clim_0, double clim_1,
+convert_cdata_1 (bool is_scaled, bool is_real, double clim_0, double clim_1,
                  const double *cmapv, const T *cv, octave_idx_type lda,
                  octave_idx_type nc, double *av)
 {
   for (octave_idx_type i = 0; i < lda; i++)
-    convert_cdata_2 (is_scaled, clim_0, clim_1, cmapv, cv[i], lda, nc, i, av);
+    convert_cdata_2 (is_scaled, is_real,
+                     clim_0, clim_1, cmapv, cv[i], lda, nc, i, av);
 }
 
 static octave_value
@@ -714,6 +811,7 @@
 {
   dim_vector dv (cdata.dims ());
 
+  // TrueColor data doesn't require conversion
   if (dv.length () == cdim && dv(cdim-1) == 3)
     return cdata;
 
@@ -758,22 +856,34 @@
   double clim_0 = clim(0);
   double clim_1 = clim(1);
 
-#define CONVERT_CDATA_1(ARRAY_T, VAL_FN) \
+  // FIXME: There is a lot of processing time spent just on data conversion
+  //        both here in graphics.cc and again in gl-render.cc.  There must
+  //        be room for improvement!  Here a macro expands to a templated
+  //        function which in turn calls another function (covert_cdata_2).
+  //        And in gl-render.cc (opengl_renderer::draw_image), only GLfloat
+  //        is supported anyways so there is another double for loop across
+  //        height and width to convert all of the input data to GLfloat.
+
+#define CONVERT_CDATA_1(ARRAY_T, VAL_FN, IS_REAL) \
   do \
     { \
       ARRAY_T tmp = cdata. VAL_FN ## array_value (); \
  \
-      convert_cdata_1 (is_scaled, clim_0, clim_1, cmapv, \
+      convert_cdata_1 (is_scaled, IS_REAL, clim_0, clim_1, cmapv, \
                        tmp.data (), lda, nc, av); \
     } \
   while (0)
 
   if (cdata.is_uint8_type ())
-    CONVERT_CDATA_1 (uint8NDArray, uint8_);
+    CONVERT_CDATA_1 (uint8NDArray, uint8_, false);
+  else if (cdata.is_uint16_type ())
+    CONVERT_CDATA_1 (uint16NDArray, uint16_, false);
+  else if (cdata.is_double_type ())
+    CONVERT_CDATA_1 (NDArray, , true);
   else if (cdata.is_single_type ())
-    CONVERT_CDATA_1 (FloatNDArray, float_);
-  else if (cdata.is_double_type ())
-    CONVERT_CDATA_1 (NDArray, );
+    CONVERT_CDATA_1 (FloatNDArray, float_, true);
+  else if (cdata.is_bool_type ())
+    CONVERT_CDATA_1 (boolNDArray, bool_, false);
   else
     error ("unsupported type for cdata (= %s)", cdata.type_name ().c_str ());
 
@@ -1012,7 +1122,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 +1137,10 @@
             retval += " | " + *it;
         }
     }
-  if (retval != "")
+
+  if (! retval.empty ())
     retval = "[ " + retval + " ]";
+
   return retval;
 }
 
@@ -1044,10 +1156,13 @@
 }
 
 bool
-color_values::str2rgb (std::string str)
-{
+color_values::str2rgb (const std::string& str_arg)
+{
+  bool retval = true;
+
   double tmp_rgb[3] = {0, 0, 0};
-  bool retval = true;
+
+  std::string str = str_arg;
   unsigned int len = str.length ();
 
   std::transform (str.begin (), str.end (), str.begin (), tolower);
@@ -1232,7 +1347,7 @@
 
       // check dimensional size constraints until a match is found
       for (std::list<dim_vector>::const_iterator it = size_constraints.begin ();
-           ! xok && it != size_constraints.end (); ++it)
+           ! xok && it != size_constraints.end ();++it)
         {
           dim_vector itdims = (*it);
 
@@ -2640,6 +2755,38 @@
   finalize (go);
 }
 
+static void
+xreset_default_properties (graphics_handle gh,
+                           property_list::pval_map_type factory_pval)
+{
+  graphics_object obj = gh_manager::get_object (gh);
+
+  property_list::pval_map_type pval;
+
+  for (property_list::pval_map_const_iterator it = factory_pval.begin ();
+       it != factory_pval.end (); it++)
+    {
+      std::string pname = it->first;
+
+      // Don't reset internal properties and handle_properties
+      if (! obj.has_readonly_property (pname) &&
+          pname.find ("__") != 0 && pname.find ("current") != 0 &&
+          pname != "uicontextmenu" && pname != "parent")
+        {
+          // Store *mode prop/val in order to set them last 
+          if (pname.find ("mode") == (pname.length () - 4))
+            pval[pname] = it->second;
+          else
+            obj.set (pname, it->second);
+        }
+    }
+
+  // set *mode properties
+  for (property_list::pval_map_const_iterator it = pval.begin ();
+       it != pval.end (); it++)
+    obj.set (it->first, it->second);
+}
+
 // ---------------------------------------------------------------------
 
 void
@@ -2671,6 +2818,22 @@
     }
 }
 
+/*
+## test defaults are set in the order they were stored
+%!test
+%! set(0, "defaultfigureunits", "normalized");
+%! set(0, "defaultfigureposition", [0.7 0 0.3 0.3]);
+%! hf = figure ("visible", "off");
+%! tol = 20 * eps;
+%! unwind_protect
+%!   assert (get (hf, "position"), [0.7 0 0.3 0.3], tol);
+%! unwind_protect_cleanup
+%!   close (hf);
+%!   set(0, "defaultfigureunits", "remove");
+%!   set(0, "defaultfigureposition", "remove");
+%! end_unwind_protect
+*/
+
 octave_value
 base_properties::get_dynamic (const caseless_str& name) const
 {
@@ -2772,7 +2935,13 @@
               // Remove child from current parent
               graphics_object old_parent_obj;
               old_parent_obj = gh_manager::get_object (get_parent ());
-              old_parent_obj.remove_child (__myhandle__);
+
+               
+              if (old_parent_obj.get_handle () != hnp) 
+                old_parent_obj.remove_child (__myhandle__);
+              else
+                // Do nothing more
+                return;
 
               // Check new parent's parent is not this child to avoid recursion
               graphics_object new_parent_obj;
@@ -2795,6 +2964,18 @@
     error ("set: expecting parent to be a graphics handle");
 }
 
+/*
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   hax = gca ();
+%!   set (hax, "parent", gcf ())
+%!   assert (gca (), hax)
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+*/
+
 void
 base_properties::mark_modified (void)
 {
@@ -2953,6 +3134,21 @@
     }
 }
 
+void 
+base_graphics_object::reset_default_properties (void)
+  {
+    if (valid_object ())
+      {
+        property_list::pval_map_type factory_pval = 
+          gh_manager::get_object (0).get_factory_defaults_list ()
+          .find (type ())->second;
+        
+        xreset_default_properties (get_handle (), factory_pval);
+
+        override_defaults (*this);
+      }
+  }
+
 std::string
 base_graphics_object::values_as_string (void)
 {
@@ -2961,10 +3157,12 @@
   if (valid_object ())
     {
       octave_map m = get ().map_value ();
+      graphics_object obj = gh_manager::get_object (get_handle ());
 
       for (octave_map::const_iterator pa = m.begin (); pa != m.end (); pa++)
         {
-          if (pa->first != "children")
+          if (pa->first != "children" &&
+              ! obj.has_readonly_property (pa->first))
             {
               property p = get_properties ().get_property (pa->first);
 
@@ -2976,7 +3174,8 @@
                 }
             }
         }
-      if (retval != "")
+
+      if (! retval.empty ())
         retval += "\n";
     }
   else
@@ -2985,6 +3184,35 @@
   return retval;
 }
 
+std::string
+base_graphics_object::value_as_string (const std::string& prop)
+{
+  std::string retval;
+
+  if (valid_object ())
+    {
+      graphics_object obj = gh_manager::get_object (get_handle ());
+
+      if (prop != "children" && ! obj.has_readonly_property (prop))
+        {
+          property p = get_properties ().get_property (prop);
+
+          if (p.ok () && ! p.is_hidden ())
+            {
+              if (p.is_radio ())
+                retval += p.values_as_string ();
+            }
+        }
+
+      if (! retval.empty ())
+        retval += "\n";
+    }
+  else
+    error ("base_graphics_object::value_as_string: invalid graphics object");
+
+  return retval;
+}
+
 octave_scalar_map
 base_graphics_object::values_as_struct (void)
 {
@@ -2993,11 +3221,13 @@
   if (valid_object ())
     {
       octave_scalar_map m = get ().scalar_map_value ();
+      graphics_object obj = gh_manager::get_object (get_handle ());
 
       for (octave_scalar_map::const_iterator pa = m.begin ();
            pa != m.end (); pa++)
         {
-          if (pa->first != "children")
+          if (pa->first != "children"
+              && ! obj.has_readonly_property (pa->first))
             {
               property p = get_properties ().get_property (pa->first);
 
@@ -3017,6 +3247,25 @@
   return retval;
 }
 
+/*
+%!test
+%! hfig = figure ("visible", "off");
+%! unwind_protect
+%!   hax = axes ();
+%!   ret = set (hax, "tightinset");
+%!   assert (isempty (ret));
+%!   ret = set (hax, "type");
+%!   assert (isempty (ret));
+%!   ret = set (hfig, "__graphics_toolkit__");
+%!   assert (isempty (ret));
+%!   ret = set (0, "commandwindowsize");
+%!   assert (isempty (ret));
+%!   ret = set (0);
+%!   assert (! isfield (ret, "commandwindowsize"));
+%! unwind_protect_cleanup
+%!   close (hfig);
+%! end_unwind_protect
+*/
 graphics_object
 graphics_object::get_ancestor (const std::string& obj_type) const
 {
@@ -3038,25 +3287,6 @@
 // ---------------------------------------------------------------------
 
 void
-root_figure::properties::set_currentfigure (const octave_value& v)
-{
-  graphics_handle val (v);
-
-  if (error_state)
-    return;
-
-  if (xisnan (val.value ()) || is_handle (val))
-    {
-      currentfigure = val;
-
-      if (val.ok ())
-        gh_manager::push_figure (val);
-    }
-  else
-    gripe_set_invalid ("currentfigure");
-}
-
-void
 root_figure::properties::set_callbackobject (const octave_value& v)
 {
   graphics_handle val (v);
@@ -3087,6 +3317,189 @@
 }
 
 void
+root_figure::properties::set_currentfigure (const octave_value& v)
+{
+  graphics_handle val (v);
+
+  if (error_state)
+    return;
+
+  if (xisnan (val.value ()) || is_handle (val))
+    {
+      currentfigure = val;
+
+      if (val.ok ())
+        gh_manager::push_figure (val);
+    }
+  else
+    gripe_set_invalid ("currentfigure");
+}
+
+std::string
+root_figure::properties::get_diary (void) const
+{
+  bool is_diary_on = F__diarystate__ ()(0).bool_value ();
+  if (is_diary_on)
+    return std::string ("on");
+  else
+    return std::string ("off");
+}
+
+void
+root_figure::properties::set_diary (const octave_value& val)
+{
+  if (! error_state)
+    {
+      // Input checking and abrev. matching
+      diary.set (val, false);
+      
+      if (! error_state)
+        {
+          Fdiary (ovl (diary.current_value ()));
+
+          diary.run_listeners ();
+        }
+    }
+}
+
+std::string
+root_figure::properties::get_diaryfile (void) const
+{
+  return F__diaryfile__ ()(0).string_value ();
+}
+
+void
+root_figure::properties::set_diaryfile (const octave_value& val)
+{
+  if (! error_state)
+    {
+      // Input checking and abrev. matching
+      diaryfile.set (val, false);
+      
+      if (! error_state)
+        {
+          Fdiary (ovl (diaryfile.string_value ()));
+
+          diaryfile.run_listeners ();
+        }
+    }
+}
+
+std::string
+root_figure::properties::get_echo (void) const
+{
+  bool is_echo_on = F__echostate__ ()(0).bool_value ();
+  if (is_echo_on)
+    return std::string ("on");
+  else
+    return std::string ("off");
+}
+
+void
+root_figure::properties::set_echo (const octave_value& val)
+{
+  if (! error_state)
+    {
+      // Input checking and abrev. matching
+      echo.set (val, false);
+      
+      if (! error_state)
+        {
+          Fecho (ovl (echo.current_value ()));
+
+          echo.run_listeners ();
+        }
+    }
+}
+
+std::string
+root_figure::properties::get_errormessage (void) const
+{
+  return Flasterr ()(0).string_value ();
+}
+
+std::string
+root_figure::properties::get_format (void) const
+{
+  return F__formatstring__ ()(0).string_value ();
+}
+
+void
+root_figure::properties::set_format (const octave_value& val)
+{
+  if (! error_state)
+    {
+      // Input checking and abrev. matching
+      format.set (val, false);
+      
+      if (! error_state)
+        {
+          Fformat (ovl (format.current_value ()));     
+
+          format.run_listeners ();
+        }
+    }
+}
+
+std::string
+root_figure::properties::get_formatspacing (void) const
+{
+  bool iscompact = F__compactformat__ ()(0).bool_value ();
+  if (iscompact)
+    return std::string ("compact");
+  else
+    return std::string ("loose");
+}
+
+void
+root_figure::properties::set_formatspacing (const octave_value& val)
+{
+  if (! error_state)
+    {
+      // Input checking and abrev. matching
+      formatspacing.set (val, false);
+      
+      if (! error_state)
+        {
+          std::string strval = formatspacing.current_value ();
+
+          if (strval == "compact")
+            F__compactformat__ (ovl (true));
+          else
+            F__compactformat__ (ovl (false));
+
+          formatspacing.run_listeners ();
+        }
+    }
+}
+
+
+double
+root_figure::properties::get_recursionlimit (void) const
+{
+  return Fmax_recursion_depth ()(0).double_value ();
+}
+
+void
+root_figure::properties::set_recursionlimit (const octave_value& val)
+{
+  if (! error_state)
+    {
+      // Input checking and abrev. matching
+      recursionlimit.set (val, false);
+      
+      if (! error_state)
+        {
+          double dval = recursionlimit.double_value ();
+
+          Fmax_recursion_depth (ovl (dval));
+
+          recursionlimit.run_listeners ();
+        }
+    }
+}
+
+void
 figure::properties::set_integerhandle (const octave_value& val)
 {
   if (! error_state)
@@ -3220,39 +3633,14 @@
 property_list
 root_figure::factory_properties = root_figure::init_factory_properties ();
 
-static void
-reset_default_properties (property_list& default_properties)
-{
-  property_list new_defaults;
-
-  for (property_list::plist_map_const_iterator p = default_properties.begin ();
-       p != default_properties.end (); p++)
-    {
-      const property_list::pval_map_type pval_map = p->second;
-      std::string prefix = p->first;
-
-      for (property_list::pval_map_const_iterator q = pval_map.begin ();
-           q != pval_map.end ();
-           q++)
-        {
-          std::string s = q->first;
-
-          if (prefix == "axes" && (s == "position" || s == "units"))
-            new_defaults.set (prefix + s, q->second);
-          else if (prefix == "figure" && (s == "position" || s == "units"
-                                          || s == "windowstyle"
-                                          || s == "paperunits"))
-            new_defaults.set (prefix + s, q->second);
-        }
-    }
-
-  default_properties = new_defaults;
-}
-
 void
 root_figure::reset_default_properties (void)
 {
-  ::reset_default_properties (default_properties);
+  // empty list of local defaults
+  default_properties = property_list ();
+
+  xreset_default_properties (get_handle (), 
+                             xproperties.factory_defaults ());
 }
 
 // ---------------------------------------------------------------------
@@ -3299,6 +3687,38 @@
     }
 }
 
+void 
+figure::properties::adopt (const graphics_handle& h)
+{
+  base_properties::adopt (h);
+
+  if (! get_currentaxes ().ok ())
+    {
+      graphics_object go = gh_manager::get_object (h);
+
+      if (go.type () == "axes")
+        set_currentaxes (h.as_octave_value ());
+    }
+}
+
+/*
+%!test
+%! hf1 = figure ("visible", "off");
+%! ax1 = subplot (1,2,1);
+%! ax2 = subplot (1,2,2);
+%! hf2 = figure ("visible", "off");
+%! unwind_protect
+%!   set (ax2, "parent", hf2);
+%!   assert (get (hf2, "currentaxes"), ax2);
+%!   assert (get (hf1, "currentaxes"), ax1);
+%!   set (ax1, "parent", hf2);
+%!   assert (get (hf2, "currentaxes"), ax2);
+%! unwind_protect_cleanup
+%!   close (hf1);
+%!   close (hf2);
+%! end_unwind_protect
+*/
+
 void
 figure::properties::set_visible (const octave_value& val)
 {
@@ -3409,6 +3829,9 @@
           position.run_listeners (POSTSET);
           mark_modified ();
         }
+      
+      if (paperpositionmode.is ("auto"))
+        paperposition.set (get_auto_paperposition ());
     }
 }
 
@@ -3628,6 +4051,122 @@
   return ret;
 }
 
+
+Matrix
+figure::properties::get_auto_paperposition (void)
+{
+  Matrix pos = get_position ().matrix_value ();
+  Matrix sz;
+  
+  caseless_str funits = get_units ();
+  caseless_str punits = get_paperunits ();
+
+  // Convert position from figure units to paperunits 
+  if (funits == "normalized" || punits == "normalized")
+    {
+      sz = screen_size_pixels ();
+      pos = convert_position (pos, funits, "inches", sz);
+
+      if (punits == "normalized")
+        sz = papersize_from_type ("points", get_papertype ());
+
+      pos = convert_position (pos, "inches", punits, sz);
+    }
+  else
+    pos = convert_position (pos, funits, punits, sz);
+
+  // Center the figure on the page
+  sz = get_papersize ().matrix_value ();
+
+  pos(0) = sz(0)/2 - pos(2)/2;
+  pos(1) = sz(1)/2 - pos(3)/2;
+
+  return pos;
+}
+
+/*
+%!test
+%! hf = figure ("visible", "off", "paperpositionmode", "auto");
+%! in_pos = [0 0 4 5];
+%! tol = 20 * eps ();
+%! unwind_protect
+%!   ## paperpositionmode "auto" converts figure size to paper units 
+%!   set (hf, "units", "inches");
+%!   set (hf, "position", in_pos);
+%!   set (hf, "paperunits", "centimeters");
+%!   psz = get (hf, "papersize");
+%!   fsz = in_pos(3:4) * 2.54;
+%!   pos = [(psz/2 .- fsz/2) fsz];  
+%!   set (hf, "paperpositionmode", "auto");
+%!   assert (get (hf, "paperposition"), pos, tol)
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+%!test
+%! hf = figure ("visible", "off", "paperpositionmode", "auto");
+%! in_pos = [0 0 4 5];
+%! tol = 20 * eps ();
+%! unwind_protect
+%!   ## likewise with normalized units 
+%!   set (hf, "units", "inches");
+%!   set (hf, "position", in_pos);
+%!   psz = get (hf, "papersize");
+%!   set (hf, "paperunits", "normalized");
+%!   fsz = in_pos(3:4) ./ psz;
+%!   pos = [([0.5 0.5] .- fsz/2) fsz];  
+%!   assert (get (hf, "paperposition"), pos, tol)
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+%!test
+%! hf = figure ("visible", "off", "paperpositionmode", "auto");
+%! in_pos = [0 0 4 5];
+%! tol = 20 * eps ();
+%! unwind_protect
+%!   ## changing papertype updates paperposition 
+%!   set (hf, "units", "inches");
+%!   set (hf, "position", in_pos);
+%!   set  (hf, "papertype", "a4");
+%!   psz = get (hf, "papersize");
+%!   fsz = in_pos(3:4);
+%!   pos = [(psz/2 .- fsz/2) fsz];  
+%!   assert (get (hf, "paperposition"), pos, tol)
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+%!test
+%! hf = figure ("visible", "off", "paperpositionmode", "auto");
+%! in_pos = [0 0 4 5];
+%! tol = 20 * eps ();
+%! unwind_protect
+%!   ## lanscape updates paperposition
+%!   set (hf, "units", "inches");
+%!   set (hf, "position", in_pos);
+%!   set (hf, "paperorientation", "landscape");
+%!   psz = get (hf, "papersize");
+%!   fsz = in_pos(3:4);
+%!   pos = [(psz/2 .- fsz/2) fsz];  
+%!   assert (get (hf, "paperposition"), pos, tol)
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+%!test
+%! hf = figure ("visible", "off", "paperpositionmode", "auto");
+%! in_pos = [0 0 4 5];
+%! unwind_protect
+%!   ## back to manual mode
+%!   set (hf, "paperposition", in_pos * 1.1)
+%!   assert (get (hf, "paperpositionmode"), "manual")
+%!   assert (get (hf, "paperposition"), in_pos * 1.1)
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+*/
+
 void
 figure::properties::update_paperunits (const caseless_str& old_paperunits)
 {
@@ -3696,6 +4235,9 @@
       // between update_papersize and update_papertype
       papersize.set (octave_value (sz));
     }
+
+  if (paperpositionmode.is ("auto"))
+    paperposition.set (get_auto_paperposition ());
 }
 
 void
@@ -3828,6 +4370,9 @@
       std::swap (sz(0), sz(1));
       papersize.set (octave_value (sz));
     }
+
+  if (paperpositionmode.is ("auto"))
+    paperposition.set (get_auto_paperposition ());
 }
 
 /*
@@ -3879,6 +4424,9 @@
       papersize.set (octave_value (sz));
       paperposition.set (octave_value (pos));
     }
+
+  if (paperpositionmode.is ("auto"))
+    paperposition.set (get_auto_paperposition ());
 }
 
 /*
@@ -3984,7 +4532,23 @@
 void
 figure::reset_default_properties (void)
 {
-  ::reset_default_properties (default_properties);
+  // empty list of local defaults
+  default_properties = property_list ();
+
+  property_list::pval_map_type plist = xproperties.factory_defaults ();
+  plist.erase ("units");
+  plist.erase ("position");
+  plist.erase ("paperunits");
+  plist.erase ("paperposition");
+  plist.erase ("windowstyle");
+  xreset_default_properties (get_handle (), plist);
+
+  // FIXME: the following short sleep is needed in order
+  //        to avoid a crash when using qt toolkit
+  Fsleep (octave_value (0.001));
+
+  // override with parents' defaults
+  override_defaults (*this);
 }
 
 // ---------------------------------------------------------------------
@@ -4202,28 +4766,23 @@
                                   const std::string& who,
                                   const octave_value& v)
 {
+  if (v.is_string ())
+    {
+      xset (hp.handle_value (), "string", v);
+      return;
+    }
+
   graphics_handle val;
-
-  if (v.is_string ())
-    {
-      val = gh_manager::make_graphics_handle ("text", __myhandle__,
-                                              false, false);
-
-      xset (val, "string", v);
-    }
-  else
-    {
-      graphics_object go = gh_manager::get_object (gh_manager::lookup (v));
-
-      if (go.isa ("text"))
-        val = ::reparent (v, "set", who, __myhandle__, false);
-      else
-        {
-          std::string cname = v.class_name ();
-
-          error ("set: expecting text graphics object or character string for %s property, found %s",
-                 who.c_str (), cname.c_str ());
-        }
+  graphics_object go = gh_manager::get_object (gh_manager::lookup (v));
+
+  if (go.isa ("text"))
+    val = ::reparent (v, "set", who, __myhandle__, false);
+  else
+    {
+      std::string cname = v.class_name ();
+
+      error ("set: expecting text graphics object or character string for %s property, found %s",
+             who.c_str (), cname.c_str ());
     }
 
   if (! error_state)
@@ -4405,27 +4964,42 @@
 
   visible = "on";
 
-  // Replace preserves Position and Units properties
-  if (mode != "replace")
+  // Replace/Reset preserves Position and Units properties
+  if (mode != "replace" && mode != "reset")
     {
       outerposition = default_axes_outerposition ();
       position = default_axes_position ();
       activepositionproperty = "outerposition";
     }
-
-  delete_children (true);
-
-  xlabel = gh_manager::make_graphics_handle ("text", __myhandle__,
-                                             false, false);
-
-  ylabel = gh_manager::make_graphics_handle ("text", __myhandle__,
-                                             false, false);
-
-  zlabel = gh_manager::make_graphics_handle ("text", __myhandle__,
-                                             false, false);
-
-  title = gh_manager::make_graphics_handle ("text", __myhandle__,
-                                            false, false);
+  
+  if (mode != "reset")
+    {
+      delete_children (true);
+
+      xlabel = gh_manager::make_graphics_handle ("text", __myhandle__,
+                                                 false, false);
+      ylabel = gh_manager::make_graphics_handle ("text", __myhandle__,
+                                                 false, false);
+      zlabel = gh_manager::make_graphics_handle ("text", __myhandle__,
+                                                 false, false);
+      title = gh_manager::make_graphics_handle ("text", __myhandle__,
+                                                false, false);
+      adopt (xlabel.handle_value ());
+      adopt (ylabel.handle_value ());
+      adopt (zlabel.handle_value ());
+      adopt (title.handle_value ());
+    }
+  else
+    {
+      graphics_object go = gh_manager::get_object (xlabel.handle_value ());
+      go.reset_default_properties ();
+      go = gh_manager::get_object (ylabel.handle_value ());
+      go.reset_default_properties ();
+      go = gh_manager::get_object (zlabel.handle_value ());
+      go.reset_default_properties ();
+      go = gh_manager::get_object (title.handle_value ());
+      go.reset_default_properties ();
+    }
 
   xset (xlabel.handle_value (), "handlevisibility", "off");
   xset (ylabel.handle_value (), "handlevisibility", "off");
@@ -4463,14 +5037,11 @@
   xset (zlabel.handle_value (), "autopos_tag", "zlabel");
   xset (title.handle_value (), "autopos_tag", "title");
 
-  adopt (xlabel.handle_value ());
-  adopt (ylabel.handle_value ());
-  adopt (zlabel.handle_value ());
-  adopt (title.handle_value ());
-
   update_transform ();
   sync_positions ();
   override_defaults (obj);
+  // Disable rotate3d and select pan for 2D axes
+  set_rotate3d (get_rotate3d ());
 }
 
 void
@@ -4508,13 +5079,25 @@
 axes::properties::remove_child (const graphics_handle& h)
 {
   if (xlabel.handle_value ().ok () && h == xlabel.handle_value ())
-    delete_text_child (xlabel);
+    {
+      delete_text_child (xlabel);
+      update_xlabel_position ();
+    }
   else if (ylabel.handle_value ().ok () && h == ylabel.handle_value ())
-    delete_text_child (ylabel);
+    {
+      delete_text_child (ylabel);
+      update_ylabel_position ();
+    }
   else if (zlabel.handle_value ().ok () && h == zlabel.handle_value ())
-    delete_text_child (zlabel);
+    {
+      delete_text_child (zlabel);
+      update_zlabel_position ();
+    }
   else if (title.handle_value ().ok () && h == title.handle_value ())
-    delete_text_child (title);
+    {
+      delete_text_child (title);
+      update_title_position ();
+    }
   else
     base_properties::remove_child (h);
 }
@@ -4704,7 +5287,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 +5313,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 +5376,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 +5483,11 @@
   const Matrix xlims = xform.xscale (get_xlim ().matrix_value ());
   const Matrix ylims = xform.yscale (get_ylim ().matrix_value ());
   const Matrix zlims = xform.zscale (get_zlim ().matrix_value ());
-  double x_min = xlims(0), x_max = xlims(1);
-  double y_min = ylims(0), y_max = ylims(1);
-  double z_min = zlims(0), z_max = zlims(1);
+
+  double x_min, x_max, y_min, y_max, z_min, z_max;
+  x_min = xlims(0), x_max = xlims(1);
+  y_min = ylims(0), y_max = ylims(1);
+  z_min = zlims(0), z_max = zlims(1);
 
   ColumnVector p1, p2, dir (3);
 
@@ -5011,18 +5599,14 @@
     {
       if (xaxislocation_is ("top"))
         {
-          double tmp = yPlane;
-          yPlane = yPlaneN;
-          yPlaneN = tmp;
+          std::swap (yPlane, yPlaneN);
           x2Dtop = true;
         }
       ypTick = yPlaneN;
       ypTickN = yPlane;
       if (yaxislocation_is ("right"))
         {
-          double tmp = xPlane;
-          xPlane = xPlaneN;
-          xPlaneN = tmp;
+          std::swap (xPlane, xPlaneN);
           y2Dright = true;
         }
       xpTick = xPlaneN;
@@ -5038,6 +5622,7 @@
 
   Matrix viewmat = get_view ().matrix_value ();
   nearhoriz = std::abs (viewmat(1)) <= 5;
+  is2D = viewmat(1) == 90;
 
   update_ticklength ();
 }
@@ -5139,7 +5724,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 +5827,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 +5922,9 @@
                                    get_zticklabel ().all_strings (),
                                    get_zlim ().matrix_value ());
 
-      double wmax = ext(0), hmax = ext(1), angle = 0;
+      double wmax = ext(0);
+      double hmax = ext(1);
+      double angle = 0;
       ColumnVector p;
 
       if (xySym)
@@ -5494,12 +6085,13 @@
     s = xmax(s, (limits(1) - limits(0)) / (pbfactor * dafactor));
 }
 
-static bool updating_aspectratios = false;
+static std::set<double> updating_aspectratios;
 
 void
 axes::properties::update_aspectratios (void)
 {
-  if (updating_aspectratios)
+  if (updating_aspectratios.find (get___myhandle__ ().value ()) !=
+      updating_aspectratios.end ())
     return;
 
   Matrix xlimits = get_xlim ().matrix_value ();
@@ -5565,7 +6157,7 @@
           unwind_protect frame;
           frame.protect_var (updating_aspectratios);
 
-          updating_aspectratios = true;
+          updating_aspectratios.insert (get___myhandle__ ().value ());
 
           dx = pba(0) *da(0);
           dy = pba(1) *da(1);
@@ -5616,7 +6208,7 @@
   text_renderer.set_font (get ("fontname").string_value (),
                           get ("fontweight").string_value (),
                           get ("fontangle").string_value (),
-                          get ("fontsize").double_value ());
+                          get ("fontsize_points").double_value ());
 #endif
 #endif
 }
@@ -5889,6 +6481,27 @@
 }
 
 void
+axes::properties::set_rotate3d (const octave_value& v)
+{
+  graphics_object parent_obj =
+    gh_manager::get_object (get_parent ());
+
+  int ndim = calc_dimensions (parent_obj);
+  rotate3d.set (v, false, false);
+  if (rotate3d_is ("on"))
+    {
+      // Disable rotate3d for 2D plots
+      if (ndim == 2)
+        {
+          rotate3d.set ("off", false, false);
+          pan.set ("on", false, false);
+        }
+      else
+        pan.set ("off", false, false);
+    }
+}
+
+void
 axes::properties::set_units (const octave_value& v)
 {
   if (! error_state)
@@ -6248,11 +6861,7 @@
   double tmp;
   // FIXME: should this be checked for somewhere else? (i.e. set{x,y,z}lim)
   if (hi < lo)
-    {
-      tmp = hi;
-      hi = lo;
-      lo = tmp;
-    }
+    std::swap (hi, lo);
 
   if (is_logscale)
     {
@@ -6269,15 +6878,17 @@
         }
     }
 
-  double tick_sep = calc_tick_sep (lo , hi);
-
-  if (is_logscale && ! (xisinf (hi) || xisinf (lo)))
-    {
-      // FIXME: what if (hi-lo) < tick_sep?
-      //         ex: loglog ([1 1.1])
-      tick_sep = std::max (tick_sep, 1.);
-      tick_sep = std::ceil (tick_sep);
-    }
+  double tick_sep;
+  
+  if (is_logscale)
+    {
+      if (! (xisinf (hi) || xisinf (lo)))
+        tick_sep = 1;  // Tick is every order of magnitude (bug #39449)
+      else
+        tick_sep = 0;
+    }
+  else
+    tick_sep = calc_tick_sep (lo , hi);
 
   int i1 = static_cast<int> (gnulib::floor (lo / tick_sep));
   int i2 = static_cast<int> (std::ceil (hi / tick_sep));
@@ -6402,7 +7013,8 @@
 #endif
 
   Matrix ext (1, 2, 0.0);
-  double wmax = 0., hmax = 0.;
+  double wmax, hmax;
+  wmax = hmax = 0.;
   int n = std::min (ticklabels.numel (), ticks.numel ());
   for (int i = 0; i < n; i++)
     {
@@ -6514,13 +7126,14 @@
     }
 }
 
-static bool updating_axis_limits = false;
+static std::set<double> updating_axis_limits;
 
 void
 axes::update_axis_limits (const std::string& axis_type,
                           const graphics_handle& h)
 {
-  if (updating_axis_limits)
+  if (updating_axis_limits.find (get_handle ().value ()) != 
+      updating_axis_limits.end ())
     return;
 
   Matrix kids = Matrix (1, 1, h.value ());
@@ -6679,7 +7292,7 @@
   unwind_protect frame;
   frame.protect_var (updating_axis_limits);
 
-  updating_axis_limits = true;
+  updating_axis_limits.insert (get_handle ().value ());
 
   switch (update_type)
     {
@@ -6722,7 +7335,10 @@
 void
 axes::update_axis_limits (const std::string& axis_type)
 {
-  if (updating_axis_limits || updating_aspectratios)
+  if ((updating_axis_limits.find (get_handle ().value ()) != 
+       updating_axis_limits.end ()) ||
+      (updating_aspectratios.find (get_handle ().value ()) !=
+       updating_aspectratios.end ()))
     return;
 
   Matrix kids = xproperties.get_children ();
@@ -6838,7 +7454,7 @@
   unwind_protect frame;
   frame.protect_var (updating_axis_limits);
 
-  updating_axis_limits = true;
+  updating_axis_limits.insert (get_handle ().value ());
 
   switch (update_type)
     {
@@ -6878,14 +7494,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; }
-  else
-    { return x; }
+    return upper;
+  else
+    return x;
 }
 
 static Matrix
@@ -7127,7 +7743,11 @@
 void
 axes::reset_default_properties (void)
 {
-  ::reset_default_properties (default_properties);
+  // empty list of local defaults
+  default_properties = property_list ();
+
+  // reset factory defaults
+  set_defaults ("reset");
 }
 
 void
@@ -7207,6 +7827,40 @@
 }
 
 void
+text::properties::set_fontunits (const octave_value& v)
+{
+  if (! error_state)
+    {
+      caseless_str old_fontunits = get_fontunits ();
+      if (fontunits.set (v, true))
+        {
+          update_fontunits (old_fontunits);
+          mark_modified ();
+        }
+    }
+}
+
+void
+text::properties::update_fontunits (const caseless_str& old_units)
+{
+  caseless_str new_units = get_fontunits ();
+  double parent_height = 0;
+  double fsz = get_fontsize ();
+
+  if (new_units == "normalized")
+    {
+      graphics_object go (gh_manager::get_object (get___myhandle__ ()));
+      graphics_object ax (go.get_ancestor ("axes"));
+
+      parent_height = ax.get_properties ().get_boundingbox (true).elem (3);
+    }
+
+  fsz = convert_font_size (fsz, old_units, new_units, parent_height);
+
+  set_fontsize (octave_value (fsz));
+}
+
+void
 text::properties::update_font (void)
 {
 #ifdef HAVE_FREETYPE
@@ -7214,7 +7868,7 @@
   renderer.set_font (get ("fontname").string_value (),
                      get ("fontweight").string_value (),
                      get ("fontangle").string_value (),
-                     get ("fontsize").double_value ());
+                     get ("fontsize_points").double_value ());
 #endif
   renderer.set_color (get_color_rgb ());
 #endif
@@ -7225,7 +7879,8 @@
 {
 #ifdef HAVE_FREETYPE
 
-  int halign = 0, valign = 0;
+  int halign = 0;
+  int valign = 0;
 
   if (horizontalalignment_is ("center"))
     halign = 1;
@@ -7340,6 +7995,197 @@
     return convert_cdata (*this, fvc,cdatamapping_is ("scaled"), 2);
 }
 
+static bool updating_patch_data = false;
+
+void
+patch::properties::update_fvc (void)
+{
+  if (updating_patch_data)
+    return;
+
+  Matrix xd = get_xdata ().matrix_value ();
+  Matrix yd = get_ydata ().matrix_value ();
+  Matrix zd = get_zdata ().matrix_value ();
+  NDArray cd = get_cdata ().array_value ();
+
+  bad_data_msg = std::string ();
+  if (xd.dims () != yd.dims () || 
+      (xd.dims () != zd.dims () && ! zd.is_empty ()))
+    {
+      bad_data_msg = "x/y/zdata should have the same dimensions";
+      return;
+    }
+
+  // Faces and Vertices
+  dim_vector dv;
+  bool is3D = false;
+  octave_idx_type nr = xd.rows ();
+  octave_idx_type nc = xd.columns ();
+  if (nr == 1 && nc > 1)
+    {
+      nr = nc;
+      nc = 1;
+      xd = xd.as_column ();
+      yd = yd.as_column ();
+      zd = zd.as_column ();
+    }
+
+  dv(0) = nr * nc;
+  if (zd.is_empty ())
+    dv(1) = 2;
+  else
+    {
+      dv(1) = 3;
+      is3D = true;
+    }
+
+  Matrix vert (dv);
+  Matrix idx (nc, nr);
+
+  octave_idx_type kk = 0;
+  for (octave_idx_type jj = 0; jj < nc; jj++)
+    {
+      for (octave_idx_type ii = 0; ii < nr; ii++)
+        {
+          vert(kk,0) = xd(ii,jj);
+          vert(kk,1) = yd(ii,jj);
+          if (is3D)
+            vert(kk,2) = zd(ii,jj);
+
+          idx(jj,ii) = static_cast<double> (kk+1);
+
+          kk++;
+        }
+    }
+
+  // facevertexcdata
+  Matrix fvc;
+  if (cd.ndims () == 3)
+    {
+      dv(0) = cd.rows () * cd.columns ();
+      dv(1) = cd.dims ()(2);
+      fvc = cd.reshape (dv);
+    }
+  else
+    fvc = cd.as_column ();
+
+  // FIXME: shouldn't we update facevertexalphadata here ?
+
+  unwind_protect frame;
+  frame.protect_var (updating_patch_data);
+  updating_patch_data = true;
+
+  faces.set (idx);
+  vertices.set (vert);
+  facevertexcdata.set (fvc);
+}
+
+
+void
+patch::properties::update_data (void)
+{
+  if (updating_patch_data)
+    return;
+
+  Matrix idx = get_faces ().matrix_value ().transpose ();
+  Matrix vert = get_vertices ().matrix_value ();
+  NDArray fvc = get_facevertexcdata ().array_value ();
+
+  octave_idx_type nfaces = idx.columns ();
+  octave_idx_type nvert = vert.rows ();
+
+  // Check all vertices in faces are defined
+  bad_data_msg = std::string ();
+  if (static_cast<double> (nvert) < idx.row_max ().max ())
+    {
+      bad_data_msg = "some vertices in \"faces\" property are undefined";
+      return;
+    }
+
+  // Replace NaNs
+  if (idx.any_element_is_inf_or_nan ())
+    {
+      for (octave_idx_type jj = 0; jj < idx.columns (); jj++)
+        {
+          double valid_vert = idx(0,jj);
+          bool turn_valid = false;
+          for (octave_idx_type ii = 0; ii < idx.rows (); ii++)
+            {
+              if (xisnan (idx(ii,jj)) || turn_valid)
+                {
+                  idx(ii,jj) = valid_vert;
+                  turn_valid = true;
+                }
+              else
+                valid_vert = idx(ii,jj);
+            }
+        }
+    }
+  
+  // Build cdata
+  dim_vector dv = dim_vector::alloc (3);
+  NDArray cd;
+  bool pervertex = false;
+
+  if (fvc.rows () == nfaces || fvc.rows () == 1)
+    {
+      dv(0) = 1;
+      dv(1) = fvc.rows ();
+      dv(2) = fvc.columns ();
+      cd = fvc.reshape (dv);
+    }
+  else 
+    {
+      if (! fvc.is_empty ())
+        {
+          dv(0) = idx.rows ();
+          dv(1) = nfaces;
+          dv(2) = fvc.columns ();
+          cd.resize (dv);
+          pervertex = true;
+        }
+    }
+
+  // Build x,y,zdata and eventually per vertex cdata 
+  Matrix xd (idx.dims ()); 
+  Matrix yd (idx.dims ());
+  Matrix zd;
+  bool has_zd = false;
+  if (vert.columns () > 2)
+    {
+      zd = Matrix (idx.dims ());
+      has_zd = true;
+    }
+
+  
+  for (octave_idx_type jj = 0; jj < nfaces; jj++)
+    {
+      for (octave_idx_type ii = 0; ii < idx.rows (); ii++)
+        {
+          octave_idx_type row = static_cast<octave_idx_type> (idx(ii,jj)-1);
+          xd(ii,jj) = vert(row,0);
+          yd(ii,jj) = vert(row,1);
+
+          if (has_zd)
+            zd(ii,jj) = vert(row,2);
+          
+          if (pervertex)
+            for (int kk = 0; kk < fvc.columns (); kk++)
+              cd(ii,jj,kk) = fvc(row,kk);
+        }
+    }
+
+
+  unwind_protect frame;
+  frame.protect_var (updating_patch_data);
+  updating_patch_data = true;
+
+  set_xdata (xd);
+  set_ydata (yd);
+  set_zdata (zd);
+  set_cdata (cd);
+}
+
 // ---------------------------------------------------------------------
 
 octave_value
@@ -7367,15 +8213,26 @@
       Matrix y = get_ydata ().matrix_value ();
       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 ();
+
+      // FIXME: There might be a cleaner way to do this.  When data is changed
+      // the update_xdata, update_ydata, update_zdata routines are called in a
+      // serial fashion.  Until the final call to update_zdata the matrices
+      // will be of mismatched dimensions which can cause an out-of-bound
+      // indexing in the code below.  This one-liner prevents calculating
+      // normals until dimensions match.
+      if (x.columns () != p || y.rows () != q)
+        return;
+
+      NDArray n (dim_vector (q, p, 3), 0.0);
 
       bool x_mat = (x.rows () == q);
       bool y_mat = (y.columns () == p);
 
-      NDArray n (dim_vector (q, p, 3), 0.0);
+      int i1, i2, i3, j1, j2, j3;
+      i1 = i2 = i3 = 0;
+      j1 = j2 = j3 = 0;
 
       for (int i = 0; i < p; i++)
         {
@@ -7969,7 +8826,14 @@
 void
 uitoolbar::reset_default_properties (void)
 {
-  ::reset_default_properties (default_properties);
+  // empty list of local defaults
+  default_properties = property_list ();
+
+  xreset_default_properties (get_handle (), 
+                             xproperties.factory_defaults ());
+
+  // override with parents' defaults
+  override_defaults (*this);
 }
 
 // ---------------------------------------------------------------------
@@ -8144,9 +9008,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 +9212,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 +9262,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;
@@ -8579,7 +9443,7 @@
 
 DEFUN (__is_handle_visible__, args, ,
        "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} __is_handle_visible__ (@var{h})\n\
+@deftypefn {Built-in Function} {} __is_handle_visible__ (@var{h})\n\
 Undocumented internal function.\n\
 @end deftypefn")
 {
@@ -8595,12 +9459,17 @@
 
 DEFUN (reset, args, ,
        "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {} reset (@var{h}, @var{property})\n\
-Remove any defaults set for the handle @var{h}.  The default figure\n\
-properties of @qcode{\"position\"}, @qcode{\"units\"},\n\
-@qcode{\"windowstyle\"} and @qcode{\"paperunits\"} and the default axes\n\
-properties of @qcode{\"position\"} and @qcode{\"units\"} are not reset.\n\
-@seealso{cla, clf}\n\
+@deftypefn {Built-in Function} {} reset (@var{h})\n\
+Reset the properties of the graphic object @var{h} to their default values.\n\
+\n\
+For figures, the properties @qcode{\"position\"}, @qcode{\"units\"},\n\
+@qcode{\"windowstyle\"}, and @qcode{\"paperunits\"} are not affected.\n\
+For axes, the properties @qcode{\"position\"} and @qcode{\"units\"} are\n\
+not affected.\n\
+\n\
+The input @var{h} may also be a vector of graphic handles in which case\n\
+each individual object will be reset.\n\
+@seealso{cla, clf, newplot}\n\
 @end deftypefn")
 {
   int nargin = args.length ();
@@ -8617,20 +9486,148 @@
           // loop over graphics objects
           for (octave_idx_type n = 0; n < hcv.length (); n++)
             gh_manager::get_object (hcv(n)).reset_default_properties ();
+
+          if (! error_state)
+            Fdrawnow ();
         }
     }
 
   return octave_value ();
 }
 
+/*
+
+%!test  # line object
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   tol = 20 * eps;
+%!   hax = axes ("defaultlinelinewidth", 3);
+%!   
+%!   hli = line (1:10, 1:10, 1:10, "marker", "o",
+%!               "markerfacecolor", "b", "linestyle", ":");
+%!   
+%!   reset (hli);
+%!   assert (get (hli, "marker"), get (0, "defaultlinemarker"));
+%!   assert (get (hli, "markerfacecolor"), 
+%!           get (0, "defaultlinemarkerfacecolor"));
+%!   assert (get (hli, "linestyle"), 
+%!           get (0, "defaultlinelinestyle"));
+%!   assert (get (hli, "linewidth"), 3, tol);  # parent axes defaults  
+%!   
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+%!test  # patch object
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   tol = 20 * eps;
+%!   t1 = (1/16:1/8:1)' * 2*pi;
+%!   t2 = ((1/16:1/16:1)' + 1/32) * 2*pi;
+%!   x1 = sin (t1) - 0.8;
+%!   y1 = cos (t1);
+%!   x2 = sin (t2) + 0.8;
+%!   y2 = cos (t2);
+%!   vert = [x1, y1; x2, y2];
+%!   fac = [1:8,NaN(1,8);9:24];
+%!   hpa = patch ("Faces",fac, "Vertices",vert, "FaceColor","r");
+%!
+%!   reset (hpa);
+%!   assert (get (hpa, "faces"), get (0, "defaultpatchfaces"), tol);
+%!   assert (get (hpa, "vertices"), get (0, "defaultpatchvertices"), tol);
+%!   assert (get (hpa, "facevertexcdata"),
+%!           get (0, "defaultpatchfacevertexcdata"), tol);
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+%!test  # surface object
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   tol = 20 * eps;
+%!   hsu = surface (peaks, "edgecolor", "none");
+%!
+%!   reset (hsu);
+%!   assert (get (hsu, "xdata"), get (0, "defaultsurfacexdata"), tol);
+%!   assert (get (hsu, "ydata"), get (0, "defaultsurfaceydata"), tol);
+%!   assert (get (hsu, "zdata"), get (0, "defaultsurfacezdata"), tol);
+%!   assert (get (hsu, "edgecolor"),
+%!           get (0, "defaultsurfaceedgecolor"), tol);
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+%!test  # image object
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   tol = 20 * eps;   
+%!   him = image (rand (10,10), "cdatamapping", "scaled");
+%!
+%!   reset (him);
+%!   assert (get (him, "cdata"), get (0, "defaultimagecdata"), tol);
+%!   assert (get (him, "cdatamapping"),
+%!           get (0, "defaultimagecdatamapping"), tol);
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+%!test  # text object
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   tol = 20 * eps;   
+%!   hte = text (5, 5, "Hi!", "fontsize", 20 ,"color", "r");
+%!
+%!   reset (hte);
+%!   assert (get (hte, "position"), get (0, "defaulttextposition"), tol);
+%!   assert (get (hte, "fontsize"), get (0, "defaulttextfontsize"), tol);
+%!   assert (get (hte, "color"), get (0, "defaulttextcolor"), tol);
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+%!test  # axes object  
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   tol = 20 * eps;
+%!   pos = get (0, "defaultaxesposition") * .5;
+%!   hax = axes ("linewidth", 2, "position", pos);
+%!   title ("Reset me, please!");
+%! 
+%!   reset (hax);
+%!   assert (get (hax, "linewidth"), get (0, "defaultaxeslinewidth"), tol);
+%!   assert (get (hax, "position"), pos, tol); # axes position is unchanged
+%!   assert (get (hax, "default"), struct ()); # no more axes' defaults
+%!   assert (get (get (hax, "title"), "string"), "");
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+%!test  # root figure object
+%! set (0, "defaultfigurevisible", "off");
+%! hf = figure ("visible", "off", "paperunits", "centimeters", 
+%!              "papertype", "a4");
+%! unwind_protect
+%!   reset (hf);
+%!   assert (get (hf, "papertype"), get (0, "defaultfigurepapertype"));
+%!   assert (get (hf, "paperunits"), "centimeters"); # paperunits is unchanged
+%!   assert (get (hf, "visible"), get (0, "defaultfigurevisible"));
+%! unwind_protect_cleanup
+%!   close (hf);
+%!   set (0, "defaultfigurevisible", "remove");
+%! end_unwind_protect
+
+*/
+
 DEFUN (set, args, nargout,
        "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {} set (@var{h}, @var{property}, @var{value}, @dots{})\n\
 @deftypefnx {Built-in Function} {} set (@var{h}, @var{properties}, @var{values})\n\
 @deftypefnx {Built-in Function} {} set (@var{h}, @var{pv})\n\
+@deftypefnx {Built-in Function} {@var{value_list} =} set (@var{h}, @var{property})\n\
+@deftypefnx {Built-in Function} {@var{all_value_list} =} set (@var{h})\n\
 Set named property values for the graphics handle (or vector of graphics\n\
 handles) @var{h}.\n\
-There are three ways how to give the property names and values:\n\
+There are three ways to give the property names and values:\n\
 \n\
 @itemize\n\
 @item as a comma separated list of @var{property}, @var{value} pairs\n\
@@ -8656,6 +9653,32 @@
 elements of @var{pv} will be set in all handles in @var{h} independent of\n\
 the dimensions of @var{pv}.\n\
 @end itemize\n\
+\n\
+@code{set} is also used to query the list of values a named property will\n\
+take.  @code{@var{clist} = set (@var{h}, \"property\")} will return the list\n\
+of possible values for @qcode{\"property\"} in the cell list @var{clist}.\n\
+If no output variable is used then the list is formatted and printed to the\n\
+screen.\n\
+\n\
+If no property is specified (@code{@var{slist} = set (@var{h})}) then a\n\
+structure @var{slist} is returned where the fieldnames are the properties of\n\
+the object @var{h} and the fields are the list of possible values for each\n\
+property.  If no output variable is used then the list is formatted and\n\
+printed to the screen.\n\
+\n\
+For example,\n\
+\n\
+@example\n\
+@group\n\
+hf = figure ();\n\
+set (hf, \"paperorientation\")\n\
+@result{}  paperorientation:  [ landscape | @{portrait@} | rotated ]\n\
+@end group\n\
+@end example\n\
+\n\
+@noindent\n\
+shows the paperorientation property can take three values with the default\n\
+being @qcode{\"portrait\"}.\n\
 @seealso{get}\n\
 @end deftypefn")
 {
@@ -8706,6 +9729,35 @@
                     {
                       obj.set (args(1).map_value ());
                     }
+                  else if (nargin == 2 && args(1).is_string ())
+                    {
+                      std::string property = args(1).string_value ();
+                      
+                      octave_map pmap = obj.values_as_struct ();
+
+                      if (obj.has_readonly_property (property))
+                        if (nargout != 0)
+                          retval = Matrix ();
+                        else
+                          octave_stdout << "set: " << property
+                                        <<" is read-only" << std::endl;
+                      else if (pmap.isfield (property))
+                        {
+                          if (nargout != 0)
+                            retval = pmap.getfield (property)(0);
+                          else
+                            {
+                              std::string s = obj.value_as_string (property);
+                              if (! error_state)
+                                octave_stdout << s;
+                            }
+                        }
+                      else
+                        {
+                          error ("set: unknown property");
+                          break;
+                        }
+                    }
                   else if (nargin == 1)
                     {
                       if (nargout != 0)
@@ -8748,7 +9800,7 @@
 }
 
 static std::string
-get_graphics_object_type (const double val)
+get_graphics_object_type (double val)
 {
   std::string retval;
 
@@ -9380,7 +10432,7 @@
     {
       graphics_handle h = octave_NaN;
 
-      const NDArray vals = args (0).array_value ();
+      const NDArray vals = args(0).array_value ();
 
       if (! error_state)
         {
@@ -9657,12 +10709,13 @@
 
           while (pa != available_toolkits.end ())
             {
-              std::string toolkit = *pa++;
-
-              if (toolkit == "qt"
-                  || (toolkit == "fltk"
-                      && available_toolkits.find ("qt") == available_toolkits.end ()))
-                dtk = toolkit;
+              std::string tk_name = *pa++;
+
+              if (tk_name == "qt"
+                  || (tk_name == "fltk"
+                      && (available_toolkits.find ("qt")
+                          == available_toolkits.end ())))
+                dtk = tk_name;
             }
         }
     }
@@ -9693,12 +10746,13 @@
 
   if (args.length () == 1)
     {
-      std::string name = args(0).string_value ();
-
-      if (! error_state)
-        gtk_manager::register_toolkit (name);
+      if (args(0).is_string ())
+        {
+          std::string name = args(0).string_value ();
+          gtk_manager::register_toolkit (name);
+        }
       else
-        error ("register_graphics_toolkit: expecting character string");
+        error ("register_graphics_toolkit: TOOLKIT must be a string");
     }
   else
     print_usage ();
@@ -10011,8 +11065,8 @@
                                                  POSTSET);
                   else
                     {
-                      caseless_str persistent = args(2).string_value ();
-                      if (persistent.compare ("persistent"))
+                      if (args(2).is_string () &&
+                          args(2).string_value () == "persistent")
                         {
                           go.delete_property_listener (pname, octave_value (),
                                                        PERSISTENT);
@@ -10206,7 +11260,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 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/graphics.in.h	Mon Jan 12 09:17:35 2015 -0800
@@ -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);
   }
@@ -1989,10 +1989,76 @@
 
 // ---------------------------------------------------------------------
 
+typedef std::pair <std::string, octave_value> pval_pair;
+
+class pval_vector : public std::vector <pval_pair>
+{
+ public:
+  const_iterator find (const std::string pname) const
+  {
+    const_iterator it;
+ 
+    for (it = (*this).begin (); it != (*this).end (); it++)
+      if (pname.compare ((*it).first) == 0)
+        return it;
+    
+    return (*this).end ();
+  }
+
+  iterator find (const std::string pname)
+  {
+    iterator it;
+ 
+    for (it = (*this).begin (); it != (*this).end (); it++)
+      if (pname.compare ((*it).first) == 0)
+        return it;
+    
+    return (*this).end ();
+  }
+  
+  octave_value lookup (const std::string pname) const
+  {
+    octave_value retval;
+
+    const_iterator it = find (pname);
+
+    if (it != (*this).end ())
+     retval = (*it).second;
+
+    return retval;
+  }
+
+  octave_value& operator [] (const std::string pname)   
+  {
+    iterator it = find (pname);
+    
+    if (it == (*this).end ())
+      {
+        push_back (pval_pair (pname, octave_value ()));
+        return (*this).back ().second;
+      }
+    
+    return (*it).second;
+  }
+
+  void erase (const std::string pname)
+  {
+    iterator it = find (pname);
+    if (it != (*this).end ())
+      erase (it);
+  }
+  
+  void erase (iterator it)
+  {
+    std::vector <pval_pair>::erase (it);
+  }
+
+};
+
 class property_list
 {
 public:
-  typedef std::map<std::string, octave_value> pval_map_type;
+  typedef pval_vector pval_map_type;
   typedef std::map<std::string, pval_map_type> plist_map_type;
 
   typedef pval_map_type::iterator pval_map_iterator;
@@ -2594,7 +2660,7 @@
 protected:
   struct cmp_caseless_str
   {
-    bool operator () (const caseless_str &a, const caseless_str &b) const
+    bool operator () (const caseless_str& a, const caseless_str& b) const
     {
       std::string a1 = a;
       std::transform (a1.begin (), a1.end (), a1.begin (), tolower);
@@ -2698,8 +2764,21 @@
     return octave_value ();
   }
 
+  virtual property_list get_factory_defaults_list (void) const
+  {
+    error ("base_graphics_object::get_factory_defaults_list: invalid graphics object");
+    return property_list ();
+  }
+
+  virtual bool has_readonly_property (const caseless_str& pname) const
+  {
+    return base_properties::has_readonly_property (pname);
+  }
+
   virtual std::string values_as_string (void);
 
+  virtual std::string value_as_string (const std::string& prop);
+
   virtual octave_scalar_map values_as_struct (void);
 
   virtual graphics_handle get_parent (void) const
@@ -2822,16 +2901,7 @@
 
   virtual void remove_all_listeners (void);
 
-  virtual void reset_default_properties (void)
-  {
-    if (valid_object ())
-      {
-        std::string msg = (type () + "::reset_default_properties");
-        gripe_not_implemented (msg.c_str ());
-      }
-    else
-      error ("base_graphics_object::default: invalid graphics object");
-  }
+  virtual void reset_default_properties (void);
 
 protected:
   virtual void initialize (const graphics_object& go)
@@ -2969,8 +3039,23 @@
     return rep->get_factory_defaults ();
   }
 
+  property_list get_factory_defaults_list (void) const
+  {
+    return rep->get_factory_defaults_list ();
+  }
+
+  bool has_readonly_property (const caseless_str& pname) const
+  {
+    return rep->has_readonly_property (pname);
+  }
+
   std::string values_as_string (void) { return rep->values_as_string (); }
 
+  std::string value_as_string (const std::string& prop) 
+  { 
+    return rep->value_as_string (prop); 
+  }
+
   octave_map values_as_struct (void) { return rep->values_as_struct (); }
 
   graphics_handle get_parent (void) const { return rep->get_parent (); }
@@ -3090,20 +3175,10 @@
     // See the genprops.awk script for an explanation of the
     // properties declarations.
 
-    // FIXME: it seems strange to me that the diary, diaryfile,
-    // echo, errormessage, format, formatspacing, language, and
-    // recursionlimit properties are here.
-    // WTF do they have to do with graphics?
-    // Also note that these properties (and the monitorpositions,
-    // pointerlocation, and pointerwindow properties) are not yet used
-    // by Octave, so setting them will have no effect, and changes
-    // made elswhere (say, the diary or format functions) will not
-    // cause these properties to be updated.
-    // ANSWER: Matlab defines these properties and uses them in
-    // the same way that Octave uses an internal static variable to
-    // keep track of state.  set (0, "echo", "on") is equivalent
-    // to Octave's echo ("on").  Maybe someday we can connect callbacks
-    // that actually call Octave's own functions for this.
+    // FIXME: Properties that still dont have callbacks are:
+    // language, monitorpositions, pointerlocation, pointerwindow.
+    // Note that these properties are not yet used by Octave, so setting
+    // them will have no effect.
 
     // Programming note: Keep property list sorted if new ones are added.
 
@@ -3111,18 +3186,18 @@
       handle_property callbackobject Sr , graphics_handle ()
       array_property commandwindowsize r , Matrix (1, 2, 0)
       handle_property currentfigure S , graphics_handle ()
-      bool_property diary , "off"
-      string_property diaryfile , "diary"
-      bool_property echo , "off"
-      string_property errormessage , ""
+      bool_property diary GS , "off"
+      string_property diaryfile GS , "diary"
+      bool_property echo GS , "off"
+      string_property errormessage Gr , ""
       string_property fixedwidthfontname , "Courier"
-      radio_property format , "+|bank|bit|hex|long|longe|longeng|longg|native-bit|native-hex|none|rational|{short}|shorte|shorteng|shortg"
-      radio_property formatspacing , "compact|{loose}"
+      radio_property format GS , "+|bank|bit|hex|long|longe|longeng|longg|native-bit|native-hex|none|rat|{short}|shorte|shorteng|shortg"
+      radio_property formatspacing GS , "compact|{loose}"
       string_property language , "ascii"
       array_property monitorpositions , Matrix (1, 4, 0)
       array_property pointerlocation , Matrix (1, 2, 0)
       double_property pointerwindow r , 0.0
-      double_property recursionlimit , 256.0
+      double_property recursionlimit GS , 256.0
       double_property screendepth r , default_screendepth ()
       double_property screenpixelsperinch r , default_screenpixelsperinch ()
       array_property screensize r , default_screensize ()
@@ -3132,6 +3207,7 @@
 
   private:
     std::list<graphics_handle> cbo_stack;
+
   };
 
 private:
@@ -3217,6 +3293,11 @@
     return factory_properties.as_struct ("factory");
   }
 
+  property_list get_factory_defaults_list (void) const
+  {
+    return factory_properties;
+  }
+
   base_properties& get_properties (void) { return xproperties; }
 
   const base_properties& get_properties (void) const { return xproperties; }
@@ -3224,6 +3305,14 @@
   bool valid_object (void) const { return true; }
 
   void reset_default_properties (void);
+  
+  bool has_readonly_property (const caseless_str& pname) const
+  {
+    bool retval = xproperties.has_readonly_property (pname);
+    if (! retval)
+      retval = base_properties::has_readonly_property (pname);
+    return retval;
+  }
 
 private:
   property_list default_properties;
@@ -3283,6 +3372,8 @@
         }
     }
 
+    void adopt (const graphics_handle& h);
+
     void set_position (const octave_value& val,
                        bool do_notify_toolkit = true);
 
@@ -3333,8 +3424,8 @@
       bool_property numbertitle , "on"
       array_property outerposition s , Matrix (1, 4, -1.0)
       radio_property paperorientation U , "{portrait}|landscape|rotated"
-      array_property paperposition , default_figure_paperposition ()
-      radio_property paperpositionmode , "auto|{manual}"
+      array_property paperposition m , default_figure_paperposition ()
+      radio_property paperpositionmode au , "auto|{manual}"
       array_property papersize U , default_figure_papersize ()
       radio_property papertype SU , "{usletter}|uslegal|a0|a1|a2|a3|a4|a5|b0|b1|b2|b3|b4|b5|arch-a|arch-b|arch-c|arch-d|arch-e|a|b|c|d|e|tabloid|<custom>"
       radio_property paperunits Su , "{inches}|centimeters|normalized|points"
@@ -3346,7 +3437,7 @@
       radio_property renderermode , "{auto}|manual"
       bool_property resize , "on"
       callback_property resizefcn , Matrix ()
-      radio_property selectiontype , "{normal}|open|alt|extend"
+      radio_property selectiontype , "{normal}|open|alternate|extend"
       radio_property toolbar , "none|{auto}|figure"
       radio_property units Su , "inches|centimeters|normalized|points|{pixels}|characters"
       callback_property windowbuttondownfcn , Matrix ()
@@ -3381,7 +3472,15 @@
       position.add_constraint (dim_vector (1, 4));
     }
 
-  private:
+  private:    
+    Matrix get_auto_paperposition (void);
+
+    void update_paperpositionmode (void)
+    {
+      if (paperpositionmode.is ("auto"))
+        paperposition.set (get_auto_paperposition ());
+    }
+
     mutable graphics_toolkit toolkit;
   };
 
@@ -3448,6 +3547,14 @@
   bool valid_object (void) const { return true; }
 
   void reset_default_properties (void);
+  
+  bool has_readonly_property (const caseless_str& pname) const
+  {
+    bool retval = xproperties.has_readonly_property (pname);
+    if (! retval)
+      retval = base_properties::has_readonly_property (pname);
+    return retval;
+  }
 
 private:
   property_list default_properties;
@@ -3633,6 +3740,7 @@
     bool get_x2Dtop (void) const { return x2Dtop; }
     bool get_y2Dright (void) const { return y2Dright; }
     bool get_layer2Dtop (void) const { return layer2Dtop; }
+    bool get_is2D (void) const { return is2D; }
     bool get_xySym (void) const { return xySym; }
     bool get_xyzSym (void) const { return xyzSym; }
     bool get_zSign (void) const { return zSign; }
@@ -3671,11 +3779,11 @@
     double fx, fy, fz;
     double xticklen, yticklen, zticklen;
     double xtickoffset, ytickoffset, ztickoffset;
-    bool x2Dtop, y2Dright, layer2Dtop;
+    bool x2Dtop, y2Dright, layer2Dtop, is2D;
     bool xySym, xyzSym, zSign, nearhoriz;
 
 #if HAVE_FREETYPE
-    // freetype renderer, used for calculation of text (tick labels) size
+    // FreeType renderer, used for calculation of text (tick labels) size
     ft_render text_renderer;
 #endif
 
@@ -3684,6 +3792,13 @@
 
     void delete_text_child (handle_property& h);
 
+    void set_pan (const octave_value& val)
+    {
+      pan.set (val, false, false);
+      if (pan_is ("on") || pan_is ("xon") || pan_is ("yon"))
+        rotate3d.set ("off", false, false);
+    }
+
     // See the genprops.awk script for an explanation of the
     // properties declarations.
     // Programming note: Keep property list sorted if new ones are added.
@@ -3698,7 +3813,7 @@
       radio_property camerapositionmode , "{auto}|manual"
       array_property cameratarget m , Matrix (1, 3, 0.0)
       radio_property cameratargetmode , "{auto}|manual"
-      array_property cameraupvector m , Matrix ()
+      array_property cameraupvector m , Matrix (1, 3, 0.0)
       radio_property cameraupvectormode , "{auto}|manual"
       double_property cameraviewangle m , 10.0
       radio_property cameraviewanglemode , "{auto}|manual"
@@ -3724,12 +3839,15 @@
       any_property linestyleorder S , "-"
       double_property linewidth , 0.5
       radio_property minorgridlinestyle , "-|--|{:}|-.|none"
+      double_property mouse_wheel_zoom , 0.05
       radio_property nextplot , "add|replacechildren|{replace}"
       array_property outerposition u , default_axes_outerposition ()
+      radio_property pan s , "{on}|xon|yon|off"
       array_property plotboxaspectratio mu , Matrix (1, 3, 1.0)
       radio_property plotboxaspectratiomode u , "{auto}|manual"
       array_property position u , default_axes_position ()
       radio_property projection , "{orthographic}|perspective"
+      radio_property rotate3d S , "{off}|on"
       radio_property tickdir mu , "{in}|out"
       radio_property tickdirmode u , "{auto}|manual"
       array_property ticklength u , default_axes_ticklength ()
@@ -3737,7 +3855,7 @@
       handle_property title SOf , gh_manager::make_graphics_handle ("text", __myhandle__, false, false, false)
       // FIXME: uicontextmenu should be moved here.
       radio_property units SU , "{normalized}|inches|centimeters|points|pixels|characters"
-      array_property view u , Matrix ()
+      array_property view u , default_axes_view ()
       radio_property xaxislocation u , "{bottom}|top|zero"
       color_property xcolor , color_values (0, 0, 0)
       radio_property xdir u , "{normal}|reverse"
@@ -3796,6 +3914,8 @@
       row_vector_property xmtick h , Matrix ()
       row_vector_property ymtick h , Matrix ()
       row_vector_property zmtick h , Matrix ()
+      // hidden property for text rendering
+      double_property fontsize_points hgr , 0
    END_PROPERTIES
 
   protected:
@@ -4100,8 +4220,8 @@
   axes (const graphics_handle& mh, const graphics_handle& p)
     : base_graphics_object (), xproperties (mh, p), default_properties ()
   {
+    xproperties.update_transform ();
     xproperties.override_defaults (*this);
-    xproperties.update_transform ();
   }
 
   ~axes (void) { }
@@ -4133,7 +4253,6 @@
 
   void set_defaults (const std::string& mode)
   {
-    remove_all_listeners ();
     xproperties.set_defaults (*this, mode);
   }
 
@@ -4170,6 +4289,14 @@
 
   void reset_default_properties (void);
 
+  bool has_readonly_property (const caseless_str& pname) const
+  {
+    bool retval = xproperties.has_readonly_property (pname);
+    if (! retval)
+      retval = base_properties::has_readonly_property (pname);
+    return retval;
+  }
+
 protected:
   void initialize (const graphics_object& go);
 
@@ -4250,6 +4377,14 @@
   const base_properties& get_properties (void) const { return xproperties; }
 
   bool valid_object (void) const { return true; }
+
+  bool has_readonly_property (const caseless_str& pname) const
+  {
+    bool retval = xproperties.has_readonly_property (pname);
+    if (! retval)
+      retval = base_properties::has_readonly_property (pname);
+    return retval;
+  }
 };
 
 // ---------------------------------------------------------------------
@@ -4301,13 +4436,13 @@
       radio_property fontangle u , "{normal}|italic|oblique"
       string_property fontname u , OCTAVE_DEFAULT_FONTNAME
       double_property fontsize u , 10
-      radio_property fontunits , "inches|centimeters|normalized|{points}|pixels"
+      radio_property fontunits SU , "inches|centimeters|normalized|{points}|pixels"
       radio_property fontweight u , "light|{normal}|demi|bold"
       radio_property horizontalalignment mu , "{left}|center|right"
       radio_property interpreter u , "{tex}|none|latex"
       radio_property linestyle , "{-}|--|:|-.|none"
       double_property linewidth , 0.5
-      double_property margin , 1
+      double_property margin , 2
       array_property position smu , Matrix (1, 3, 0.0)
       double_property rotation mu , 0
       text_label_property string u , ""
@@ -4327,13 +4462,15 @@
       radio_property horizontalalignmentmode hu , "{auto}|manual"
       radio_property verticalalignmentmode hu , "{auto}|manual"
       radio_property autopos_tag h , "{none}|xlabel|ylabel|zlabel|title"
+      // hidden property for text rendering
+      double_property fontsize_points hgr , 0
     END_PROPERTIES
 
     Matrix get_data_position (void) const;
     Matrix get_extent_matrix (void) const;
     const uint8NDArray& get_pixels (void) const { return pixels; }
 #if HAVE_FREETYPE
-    // freetype renderer, used for calculation of text size
+    // FreeType renderer, used for calculation of text size
     ft_render renderer;
 #endif
 
@@ -4391,6 +4528,7 @@
     void update_verticalalignment (void) { update_text_extent (); }
 
     void update_units (void);
+    void update_fontunits (const caseless_str& old_fontunits);
 
   private:
     std::string cached_units;
@@ -4415,6 +4553,14 @@
   const base_properties& get_properties (void) const { return xproperties; }
 
   bool valid_object (void) const { return true; }
+
+  bool has_readonly_property (const caseless_str& pname) const
+  {
+    bool retval = xproperties.has_readonly_property (pname);
+    if (! retval)
+      retval = base_properties::has_readonly_property (pname);
+    return retval;
+  }
 };
 
 // ---------------------------------------------------------------------
@@ -4437,18 +4583,21 @@
 
     octave_value get_color_data (void) const;
 
+    void initialize_data (void) { update_cdata (); }
+
     // See the genprops.awk script for an explanation of the
     // properties declarations.
     // Programming note: Keep property list sorted if new ones are added.
 
     BEGIN_PROPERTIES (image)
-      array_property alphadata u , Matrix ()
-      radio_property alphadatamapping al , "none|direct|{scaled}"
-      array_property cdata u , Matrix ()
+      array_property alphadata u , Matrix (1, 1, 1.0)
+      radio_property alphadatamapping al , "{none}|direct|scaled"
+      array_property cdata u , default_image_cdata ()
       radio_property cdatamapping al , "scaled|{direct}"
+      string_property displayname , ""
       radio_property erasemode , "{normal}|none|xor|background"
-      row_vector_property xdata u , Matrix ()
-      row_vector_property ydata u , Matrix ()
+      row_vector_property xdata mu , Matrix ()
+      row_vector_property ydata mu , Matrix ()
       // hidden properties for limit computation
       row_vector_property alim hlr , Matrix ()
       row_vector_property clim hlr , Matrix ()
@@ -4458,6 +4607,8 @@
       bool_property climinclude hlg , "on"
       bool_property xliminclude hl , "on"
       bool_property yliminclude hl , "on"
+      radio_property xdatamode ha , "{auto}|manual"
+      radio_property ydatamode ha , "{auto}|manual"
     END_PROPERTIES
 
   protected:
@@ -4494,10 +4645,25 @@
         set_clim (cdata.get_limits ());
       else
         clim = cdata.get_limits ();
+
+      if (xdatamode.is ("auto"))
+        update_xdata ();
+      
+      if (ydatamode.is ("auto"))
+        update_ydata ();
     }
 
     void update_xdata (void)
     {
+      if (xdata.get ().is_empty ())
+        set_xdatamode ("auto");
+        
+      if (xdatamode.is ("auto"))
+        {
+          set_xdata (get_auto_xdata ());
+          set_xdatamode ("auto");
+        }
+      
       Matrix limits = xdata.get_limits ();
       float dp = pixel_xsize ();
 
@@ -4508,6 +4674,15 @@
 
     void update_ydata (void)
     {
+      if (ydata.get ().is_empty ())
+        set_ydatamode ("auto");
+        
+      if (ydatamode.is ("auto"))
+        {
+          set_ydata (get_auto_ydata ()); 
+          set_ydatamode ("auto");
+        }
+      
       Matrix limits = ydata.get_limits ();
       float dp = pixel_ysize ();
 
@@ -4516,6 +4691,30 @@
       set_ylim (limits);
     }
 
+    Matrix get_auto_xdata (void)
+    {
+      dim_vector dv = get_cdata ().dims ();
+      Matrix data;
+      if (dv(1) > 0.)
+        {
+          data = Matrix (1, 2, 1);
+          data(1) = dv(1);
+        }
+      return data;
+    }
+
+    Matrix get_auto_ydata (void)
+    {
+      dim_vector dv = get_cdata ().dims ();
+      Matrix data;
+      if (dv(0) > 0.)
+        {
+          data = Matrix (1, 2, 1);
+          data(1) = dv(0);
+        }
+      return data;
+    }
+
     float pixel_size (octave_idx_type dim, const Matrix limits)
     {
       octave_idx_type l = dim - 1;
@@ -4553,6 +4752,7 @@
     : base_graphics_object (), xproperties (mh, p)
   {
     xproperties.override_defaults (*this);
+    xproperties.initialize_data ();
   }
 
   ~image (void) { }
@@ -4562,6 +4762,14 @@
   const base_properties& get_properties (void) const { return xproperties; }
 
   bool valid_object (void) const { return true; }
+
+  bool has_readonly_property (const caseless_str& pname) const
+  {
+    bool retval = xproperties.has_readonly_property (pname);
+    if (! retval)
+      retval = base_properties::has_readonly_property (pname);
+    return retval;
+  }
 };
 
 // ---------------------------------------------------------------------
@@ -4574,6 +4782,14 @@
   public:
     octave_value get_color_data (void) const;
 
+    // Matlab allows incoherent data to be stored into patch properties.
+    // The patch should then be ignored by the renderer. 
+    bool has_bad_data (std::string &msg) const 
+      { 
+        msg = bad_data_msg;
+        return ! msg.empty ();
+      }
+
     bool is_aliminclude (void) const
     { return (aliminclude.is_on () && alphadatamapping.is ("scaled")); }
     std::string get_aliminclude (void) const
@@ -4603,9 +4819,9 @@
       double_radio_property facealpha , double_radio_property (1.0, radio_values ("flat|interp"))
       color_property facecolor , color_property (color_values (0, 0, 0), radio_values ("none|flat|interp"))
       radio_property facelighting , "{none}|flat|gouraud|phong"
-      array_property faces , Matrix ()
+      array_property faces u , default_patch_faces ()
       array_property facevertexalphadata , Matrix ()
-      array_property facevertexcdata , Matrix ()
+      array_property facevertexcdata u , Matrix ()
       // FIXME: interpreter is not a property of a Matlab patch.
       //        Octave uses this for legend() with the string displayname.
       radio_property interpreter , "{tex}|none|latex"
@@ -4618,11 +4834,11 @@
       radio_property normalmode , "{auto}|manual"
       double_property specularcolorreflectance , 1.0
       double_property specularexponent , 10.0
-      double_property specularstrength , 0.6
+      double_property specularstrength , 0.9
       array_property vertexnormals , Matrix ()
-      array_property vertices , Matrix ()
-      array_property xdata u , Matrix ()
-      array_property ydata u , Matrix ()
+      array_property vertices u , default_patch_vertices ()
+      array_property xdata u , default_patch_xdata ()
+      array_property ydata u , default_patch_ydata ()
       array_property zdata u , Matrix ()
 
       // hidden properties for limit computation
@@ -4656,17 +4872,67 @@
     }
 
   private:
-    void update_xdata (void) { set_xlim (xdata.get_limits ()); }
-    void update_ydata (void) { set_ylim (ydata.get_limits ()); }
-    void update_zdata (void) { set_zlim (zdata.get_limits ()); }
+    std::string bad_data_msg;
+
+    void update_faces (void) { update_data ();}
+
+    void update_vertices (void)  {  update_data ();}
+
+    void update_facevertexcdata (void) { update_data ();}
+
+    void update_fvc (void);
+
+    void update_xdata (void) 
+    { 
+      if (get_xdata ().is_empty ())
+        {
+          // For compatibility with matlab behavior, 
+          // if x/ydata are set empty, silently empty other *data and 
+          // faces properties while vertices remain unchanged. 
+          set_ydata (Matrix ());
+          set_zdata (Matrix ());
+          set_cdata (Matrix ());
+          set_faces (Matrix ());
+        }
+      else
+        update_fvc ();
+
+      set_xlim (xdata.get_limits ());
+    }
+
+    void update_ydata (void) 
+    { 
+      if (get_ydata ().is_empty ())
+        {
+          set_xdata (Matrix ());
+          set_zdata (Matrix ());
+          set_cdata (Matrix ());
+          set_faces (Matrix ());
+        }
+      else
+        update_fvc ();
+
+      set_ylim (ydata.get_limits ());
+    }
+
+    void update_zdata (void) 
+    { 
+      update_fvc ();
+      set_zlim (zdata.get_limits ());
+    }
 
     void update_cdata (void)
     {
+      update_fvc ();
+
       if (cdatamapping_is ("scaled"))
         set_clim (cdata.get_limits ());
       else
         clim = cdata.get_limits ();
     }
+
+
+    void update_data (void);
   };
 
 private:
@@ -4686,6 +4952,14 @@
   const base_properties& get_properties (void) const { return xproperties; }
 
   bool valid_object (void) const { return true; }
+
+  bool has_readonly_property (const caseless_str& pname) const
+  {
+    bool retval = xproperties.has_readonly_property (pname);
+    if (! retval)
+      retval = base_properties::has_readonly_property (pname);
+    return retval;
+  }
 };
 
 // ---------------------------------------------------------------------
@@ -4713,11 +4987,11 @@
     // Programming note: Keep property list sorted if new ones are added.
 
     BEGIN_PROPERTIES (surface)
-      array_property alphadata u , Matrix ()
+      array_property alphadata u , Matrix (1, 1, 1.0)
       radio_property alphadatamapping l , "none|direct|{scaled}"
       double_property ambientstrength , 0.3
       radio_property backfacelighting , "unlit|lit|{reverselit}"
-      array_property cdata u , Matrix ()
+      array_property cdata u , default_surface_cdata ()
       radio_property cdatamapping al , "{scaled}|direct"
       string_property cdatasource , ""
       double_property diffusestrength , 0.6
@@ -4744,11 +5018,11 @@
       double_property specularexponent , 10
       double_property specularstrength , 0.9
       array_property vertexnormals u , Matrix ()
-      array_property xdata u , Matrix ()
+      array_property xdata u , default_surface_xdata ()
       string_property xdatasource , ""
-      array_property ydata u , Matrix ()
+      array_property ydata u , default_surface_ydata ()
       string_property ydatasource , ""
-      array_property zdata u , Matrix ()
+      array_property zdata u , default_surface_zdata ()
       string_property zdatasource , ""
 
       // hidden properties for limit computation
@@ -4778,6 +5052,7 @@
       alphadata.add_constraint ("uint8");
       alphadata.add_constraint (dim_vector (-1, -1));
       vertexnormals.add_constraint (dim_vector (-1, -1, 3));
+      vertexnormals.add_constraint (dim_vector (0, 0));
     }
 
   private:
@@ -4841,6 +5116,14 @@
   const base_properties& get_properties (void) const { return xproperties; }
 
   bool valid_object (void) const { return true; }
+
+  bool has_readonly_property (const caseless_str& pname) const
+  {
+    bool retval = xproperties.has_readonly_property (pname);
+    if (! retval)
+      retval = base_properties::has_readonly_property (pname);
+    return retval;
+  }
 };
 
 // ---------------------------------------------------------------------
@@ -4919,6 +5202,14 @@
   void update_axis_limits (const std::string& axis_type,
                            const graphics_handle& h);
 
+  bool has_readonly_property (const caseless_str& pname) const
+  {
+    bool retval = xproperties.has_readonly_property (pname);
+    if (! retval)
+      retval = base_properties::has_readonly_property (pname);
+    return retval;
+  }
+
 };
 
 // ---------------------------------------------------------------------
@@ -4980,6 +5271,14 @@
 
   bool valid_object (void) const { return true; }
 
+  bool has_readonly_property (const caseless_str& pname) const
+  {
+    bool retval = xproperties.has_readonly_property (pname);
+    if (! retval)
+      retval = base_properties::has_readonly_property (pname);
+    return retval;
+  }
+
 };
 
 // ---------------------------------------------------------------------
@@ -5027,6 +5326,14 @@
 
   bool valid_object (void) const { return true; }
 
+  bool has_readonly_property (const caseless_str& pname) const
+  {
+    bool retval = xproperties.has_readonly_property (pname);
+    if (! retval)
+      retval = base_properties::has_readonly_property (pname);
+    return retval;
+  }
+
 };
 
 // ---------------------------------------------------------------------
@@ -5119,6 +5426,14 @@
   const base_properties& get_properties (void) const { return xproperties; }
 
   bool valid_object (void) const { return true; }
+
+  bool has_readonly_property (const caseless_str& pname) const
+  {
+    bool retval = xproperties.has_readonly_property (pname);
+    if (! retval)
+      retval = base_properties::has_readonly_property (pname);
+    return retval;
+  }
 };
 
 // ---------------------------------------------------------------------
@@ -5186,6 +5501,14 @@
   const base_properties& get_properties (void) const { return xproperties; }
 
   bool valid_object (void) const { return true; }
+
+  bool has_readonly_property (const caseless_str& pname) const
+  {
+    bool retval = xproperties.has_readonly_property (pname);
+    if (! retval)
+      retval = base_properties::has_readonly_property (pname);
+    return retval;
+  }
 };
 
 // ---------------------------------------------------------------------
@@ -5273,6 +5596,14 @@
 
   void reset_default_properties (void);
 
+  bool has_readonly_property (const caseless_str& pname) const
+  {
+    bool retval = xproperties.has_readonly_property (pname);
+    if (! retval)
+      retval = base_properties::has_readonly_property (pname);
+    return retval;
+  }
+
 private:
   property_list default_properties;
 };
@@ -5325,6 +5656,14 @@
 
   bool valid_object (void) const { return true; }
 
+  bool has_readonly_property (const caseless_str& pname) const
+  {
+    bool retval = xproperties.has_readonly_property (pname);
+    if (! retval)
+      retval = base_properties::has_readonly_property (pname);
+    return retval;
+  }
+
 };
 
 // ---------------------------------------------------------------------
@@ -5378,16 +5717,24 @@
 
   bool valid_object (void) const { return true; }
 
+  bool has_readonly_property (const caseless_str& pname) const
+  {
+    bool retval = xproperties.has_readonly_property (pname);
+    if (! retval)
+      retval = base_properties::has_readonly_property (pname);
+    return retval;
+  }
+
 };
 
 // ---------------------------------------------------------------------
 
 octave_value
-get_property_from_handle (double handle, const std::string &property,
-                          const std::string &func);
+get_property_from_handle (double handle, const std::string& property,
+                          const std::string& func);
 bool
-set_property_in_handle (double handle, const std::string &property,
-                        const octave_value &arg, const std::string &func);
+set_property_in_handle (double handle, const std::string& property,
+                        const octave_value& arg, const std::string& func);
 
 // ---------------------------------------------------------------------
 
@@ -5858,12 +6205,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/gripes.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/gripes.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -245,3 +245,11 @@
   error ("%s: support for %s was disabled when %s was built",
          func.c_str (), feature.c_str (), pkg.c_str ());
 }
+
+void
+gripe_data_file_in_path (const std::string& fcn, const std::string& file)
+{
+  warning_with_id ("Octave:data-file-in-path",
+                   "%s: '%s' found by searching load path",
+                   fcn.c_str (), file.c_str ());
+}
--- a/libinterp/corefcn/gripes.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/gripes.h	Mon Jan 12 09:17:35 2015 -0800
@@ -131,4 +131,8 @@
 extern OCTINTERP_API void
 gripe_disabled_feature (const std::string& func, const std::string& feature,
                         const std::string& pkg="Octave");
+
+extern OCTINTERP_API void
+gripe_data_file_in_path (const std::string& fcn, const std::string& file);
+
 #endif
--- a/libinterp/corefcn/help.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/help.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -40,6 +40,7 @@
 #include "file-ops.h"
 #include "file-stat.h"
 #include "oct-env.h"
+#include "oct-locbuf.h"
 #include "str-vec.h"
 
 #include <defaults.h>
@@ -230,7 +231,7 @@
 
   pair_type (")",
     "-*- texinfo -*-\n\
-@deftypefn {Operator} {} )\n\
+@deftypefn {Operator} {})\n\
 Array index or function argument delimiter.\n\
 @end deftypefn"),
 
@@ -1078,7 +1079,7 @@
 
   if (args.length () == 1)
     {
-      const std::string name = args (0).string_value ();
+      const std::string name = args(0).string_value ();
 
       if (! error_state)
         {
@@ -1173,7 +1174,7 @@
 
 DEFUN (__operators__, , ,
        "-*- texinfo -*-\n\
-@deftypefn {Function File} __operators__ ()\n\
+@deftypefn {Function File} {} __operators__ ()\n\
 Undocumented internal function.\n\
 @end deftypefn")
 {
@@ -1185,7 +1186,7 @@
 
 DEFUN (__keywords__, , ,
        "-*- texinfo -*-\n\
-@deftypefn {Function File} __keywords__ ()\n\
+@deftypefn {Function File} {} __keywords__ ()\n\
 Undocumented internal function.\n\
 @end deftypefn")
 {
@@ -1197,7 +1198,7 @@
 
 DEFUN (__builtins__, , ,
        "-*- texinfo -*-\n\
-@deftypefn {Function File} __builtins__ ()\n\
+@deftypefn {Function File} {} __builtins__ ()\n\
 Undocumented internal function.\n\
 @end deftypefn")
 {
@@ -1365,27 +1366,24 @@
 
   if (args.length () == 0)
     retval = Cell (ffl.append (afl));
-  else
+  else if (args(0).is_string ())
     {
-      std::string dir = args (0).string_value ();
+      std::string dir = args(0).string_value ();
+
+      string_vector fl = load_path::files (dir, true);
 
       if (! error_state)
         {
-          string_vector fl = load_path::files (dir, true);
+          // Return a sorted list with unique entries (in case of
+          // .m and .oct versions of the same function in a given
+          // directory, for example).
+          fl.sort (true);
 
-          if (! error_state)
-            {
-              // Return a sorted list with unique entries (in case of
-              // .m and .oct versions of the same function in a given
-              // directory, for example).
-              fl.sort (true);
-
-              retval = Cell (fl);
-            }
+          retval = Cell (fl);
         }
-      else
-        error ("__list_functions__: DIRECTORY argument must be a string");
     }
+  else
+    error ("__list_functions__: DIRECTORY argument must be a string");
 
   return retval;
 }
--- a/libinterp/corefcn/hess.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/hess.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -58,8 +58,9 @@
 @end ifnottex\n\
 \n\
 The Hessenberg decomposition is usually used as the first step in an\n\
-eigenvalue computation, but has other applications as well (see Golub,\n\
-Nash, and Van Loan, IEEE Transactions on Automatic Control, 1979).\n\
+eigenvalue computation, but has other applications as well\n\
+(see @nospell{Golub, Nash, and Van Loan},\n\
+IEEE Transactions on Automatic Control, 1979).\n\
 @seealso{eig, chol, lu, qr, qz, schur, svd}\n\
 @end deftypefn")
 {
--- a/libinterp/corefcn/input.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/input.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -765,10 +765,10 @@
 @noindent\n\
 and waits for the user to enter a value.  The string entered by the user\n\
 is evaluated as an expression, so it may be a literal constant, a\n\
-variable name, or any other valid expression.\n\
+variable name, or any other valid Octave code.\n\
 \n\
-Currently, @code{input} only returns one value, regardless of the number\n\
-of values produced by the evaluation of the expression.\n\
+The number of return arguments, their size, and their class depend on the\n\
+expression entered.\n\
 \n\
 If you are only interested in getting a literal string value, you can\n\
 call @code{input} with the character string @qcode{\"s\"} as the second\n\
@@ -787,7 +787,7 @@
   int nargin = args.length ();
 
   if (nargin == 1 || nargin == 2)
-    retval = get_user_input (args, nargout);
+    retval = get_user_input (args, std::max (nargout, 1));
   else
     print_usage ();
 
@@ -837,11 +837,11 @@
 
       if (nargin == 1)
         {
-          prompt = args(0).string_value ();
-
-          if (error_state)
+          if (args(0).is_string ())
+            prompt = args(0).string_value ();
+          else
             {
-              error ("yes_or_no: PROMPT must be a character string");
+              error ("yes_or_no: PROMPT must be a string");
               return retval;
             }
         }
@@ -1021,6 +1021,15 @@
   return retval;
 }
 
+DEFUN (__echostate__, , ,
+       "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {@var{state} =} __echostate__ ()\n\
+Undocumented internal function\n\
+@end deftypefn")
+{
+  return ovl (Vecho_executing_commands == ECHO_SCRIPTS);
+}
+
 DEFUN (completion_matches, args, nargout,
        "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} completion_matches (@var{hint})\n\
@@ -1201,7 +1210,7 @@
           retval = hook_fcn.id ();
         }
       else
-        error ("add_input_event_hook: expecting function handle or character string as first argument");
+        error ("add_input_event_hook: FCN must be a function handle or string");
     }
   else
     print_usage ();
@@ -1426,11 +1435,12 @@
 DEFUN (filemarker, args, nargout,
        "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {@var{val} =} filemarker ()\n\
-@deftypefnx {Built-in Function} {} filemarker (@var{new_val})\n\
+@deftypefnx {Built-in Function} {@var{old_val} =} filemarker (@var{new_val})\n\
 @deftypefnx {Built-in Function} {} filemarker (@var{new_val}, \"local\")\n\
-Query or set the character used to separate filename from the\n\
-the subfunction names contained within the file.  This can be used in\n\
-a generic manner to interact with subfunctions.  For example,\n\
+Query or set the character used to separate the filename from the subfunction\n\
+names contained within the file.  By default this is the character @samp{>}.\n\
+This can be used in a generic manner to interact with subfunctions.\n\
+For example,\n\
 \n\
 @example\n\
 help ([\"myfunc\", filemarker, \"mysubfunc\"])\n\
@@ -1438,8 +1448,10 @@
 \n\
 @noindent\n\
 returns the help string associated with the subfunction @code{mysubfunc}\n\
-of the function @code{myfunc}.  Another use of @code{filemarker} is when\n\
-debugging it allows easier placement of breakpoints within subfunctions.\n\
+located in the file @file{myfunc.m}.\n\
+\n\
+@code{filemarker} is also useful during debugging for placing breakpoints\n\
+within subfunctions or nested functions.\n\
 For example,\n\
 \n\
 @example\n\
@@ -1450,7 +1462,7 @@
 will set a breakpoint at the first line of the subfunction @code{mysubfunc}.\n\
 \n\
 When called from inside a function with the @qcode{\"local\"} option, the\n\
-variable is changed locally for the function and any subroutines it calls.  \n\
+variable is changed locally for the function and any subroutines it calls.\n\
 The original variable value is restored when exiting the function.\n\
 @end deftypefn")
 {
--- a/libinterp/corefcn/inv.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/inv.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -227,8 +227,7 @@
         }
 
       if (nargout < 2 && (info == -1 || rcond_plus_one_eq_one))
-        warning ("inverse: matrix singular to machine precision, rcond = %g",
-                 (isfloat ? frcond : rcond));
+        gripe_singular_matrix (isfloat ? frcond : rcond);
     }
 
   return retval;
--- a/libinterp/corefcn/jit-typeinfo.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/jit-typeinfo.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -34,7 +34,12 @@
 
 #include "jit-typeinfo.h"
 
+#ifdef HAVE_LLVM_IR_VERIFIER_H
+#include <llvm/IR/Verifier.h>
+#else
 #include <llvm/Analysis/Verifier.h>
+#endif
+
 #include <llvm/ExecutionEngine/ExecutionEngine.h>
 
 #ifdef HAVE_LLVM_IR_FUNCTION_H
@@ -1247,6 +1252,8 @@
   destroy_fn.add_overload (create_identity(index));
   destroy_fn.add_overload (create_identity(complex));
 
+  // -------------------- scalar related operations --------------------
+
   // now for binary scalar operations
   add_binary_op (scalar, octave_value::op_add, llvm::Instruction::FAdd);
   add_binary_op (scalar, octave_value::op_sub, llvm::Instruction::FSub);
@@ -1335,6 +1342,7 @@
     val = builder.CreateFMul (val, mone);
     fn.do_return (builder, val);
   }
+  unary_ops[octave_value::op_uminus].add_overload (fn);
 
   fn = create_identity (scalar);
   unary_ops[octave_value::op_uplus].add_overload (fn);
@@ -1842,7 +1850,7 @@
   register_generic ("cos", matrix, matrix);
 
   add_builtin ("exp");
-  register_intrinsic ("exp", llvm::Intrinsic::cos, scalar, scalar);
+  register_intrinsic ("exp", llvm::Intrinsic::exp, scalar, scalar);
   register_generic ("exp", matrix, matrix);
 
   add_builtin ("balance");
--- a/libinterp/corefcn/jit-util.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/jit-util.h	Mon Jan 12 09:17:35 2015 -0800
@@ -42,8 +42,15 @@
 {
   class Value;
   class Module;
+#ifdef LEGACY_PASSMANAGER
+  namespace legacy {
+    class FunctionPassManager;
+    class PassManager;
+  }
+#else
   class FunctionPassManager;
   class PassManager;
+#endif
   class ExecutionEngine;
   class Function;
   class BasicBlock;
--- a/libinterp/corefcn/kron.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/kron.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -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,38 +134,20 @@
 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 ();
-  PermMatrix c(na*nb); // Row permutation.
-  octave_idx_type *pc = c.fortran_vec ();
-
-  bool cola = a.is_col_perm (), colb = b.is_col_perm ();
-  if (cola && colb)
-    {
-      for (octave_idx_type i = 0; i < na; i++)
-        for (octave_idx_type j = 0; j < nb; j++)
-          pc[pa[i]*nb+pb[j]] = i*nb+j;
-    }
-  else if (cola)
+  octave_idx_type na = a.rows ();
+  octave_idx_type nb = b.rows ();
+  const Array<octave_idx_type>& pa = a.col_perm_vec ();
+  const Array<octave_idx_type>& pb = b.col_perm_vec ();
+  Array<octave_idx_type> res_perm (dim_vector (na * nb, 1));
+  octave_idx_type rescol = 0;
+  for (octave_idx_type i = 0; i < na; i++)
     {
-      for (octave_idx_type i = 0; i < na; i++)
-        for (octave_idx_type j = 0; j < nb; j++)
-          pc[pa[i]*nb+j] = i*nb+pb[j];
-    }
-  else if (colb)
-    {
-      for (octave_idx_type i = 0; i < na; i++)
-        for (octave_idx_type j = 0; j < nb; j++)
-          pc[i*nb+pb[j]] = pa[i]*nb+j;
-    }
-  else
-    {
-      for (octave_idx_type i = 0; i < na; i++)
-        for (octave_idx_type j = 0; j < nb; j++)
-          pc[i*nb+j] = pa[i]*nb+pb[j];
+      octave_idx_type a_add = pa(i) * nb;
+      for (octave_idx_type j = 0; j < nb; j++)
+        res_perm.xelem (rescol++) = a_add + pb(j);
     }
 
-  return c;
+  return PermMatrix (res_perm, true);
 }
 
 template <class MTA, class MTB>
@@ -195,7 +182,7 @@
           // the diagonals as vectors and compute the product.  That
           // will be another vector, which we then use to construct a
           // diagonal matrix object.  Note that this will fail if our
-          // digaonal matrix object is modified to allow the non-zero
+          // digaonal matrix object is modified to allow the nonzero
           // values to be stored off of the principal diagonal (i.e., if
           // diag ([1,2], 3) is modified to return a diagonal matrix
           // object instead of a full matrix object).
@@ -282,7 +269,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));
@@ -299,13 +287,26 @@
 %! x = ones (2);
 %! assert (kron (x, x), ones (4));
 
-%!shared x, y, z
+%!shared x, y, z, p1, p2, d1, d2
 %! x =  [1, 2];
 %! y =  [-1, -2];
 %! z =  [1,  2,  3,  4; 1,  2,  3,  4; 1,  2,  3,  4];
+%! p1 = eye (3)([2, 3, 1], :);  ## Permutation matrix
+%! p2 = [0 1 0; 0 0 1; 1 0 0];  ## Non-permutation equivalent
+%! d1 = diag ([1 2 3]);         ## Diag type matrix
+%! d2 = [1 0 0; 0 2 0; 0 0 3];  ## Non-diag equivalent
 %!assert (kron (1:4, ones (3, 1)), z)
+%!assert (kron (single (1:4), ones (3, 1)), single (z))
+%!assert (kron (sparse (1:4), ones (3, 1)), sparse (z))
+%!assert (kron (complex (1:4), ones (3, 1)), z)
+%!assert (kron (complex (single(1:4)), ones (3, 1)), single(z))
 %!assert (kron (x, y, z), kron (kron (x, y), z))
 %!assert (kron (x, y, z), kron (x, kron (y, z)))
+%!assert (kron (p1, p1), kron (p2, p2))
+%!assert (kron (p1, p2), kron (p2, p1))
+%!assert (kron (d1, d1), kron (d2, d2))
+%!assert (kron (d1, d2), kron (d2, d1))
+
 
 %!assert (kron (diag ([1, 2]), diag ([3, 4])), diag ([3, 4, 6, 8]))
 
--- a/libinterp/corefcn/load-path.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/load-path.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -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)
 {
@@ -518,6 +569,7 @@
       maybe_add_path_elts (sys_path, Vlocal_fcn_file_dir);
       maybe_add_path_elts (sys_path, Voct_file_dir);
       maybe_add_path_elts (sys_path, Vfcn_file_dir);
+      maybe_add_path_elts (sys_path, Voct_data_dir);
     }
 
   std::string tpath = load_path::command_line_path;
@@ -544,9 +596,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 +736,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 +754,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 +775,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 +819,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 +828,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 +896,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 +909,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 +964,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 +1063,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 +1079,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 +1118,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 +1148,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 +1196,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 +1225,67 @@
 
   //  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)
+    {
+      // Even for private functions, dir_name doesn't contain the
+      // "private" directory component so we append it here in all
+      // cases.
+
+      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 +1296,42 @@
 {
   std::string retval;
 
+  if (octave_env::absolute_pathname (file)
+      || octave_env::rooted_relative_pathname (file))
+    {
+      file_stat fs (file);
+
+      return fs.exists () ? file : retval;
+    }
+  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++)
@@ -1244,7 +1383,7 @@
 
           size_t dir_len = dir.length ();
 
-          if (dname_len >= dir_len
+          if (dname_len > dir_len
               && file_ops::is_dir_sep (dname[dname_len - dir_len - 1])
               && dir.compare (dname.substr (dname_len - dir_len)) == 0)
             {
@@ -1291,7 +1430,7 @@
 
           size_t dir_len = dir.length ();
 
-          if (dname_len >= dir_len
+          if (dname_len > dir_len
               && file_ops::is_dir_sep (dname[dname_len - dir_len - 1])
               && dir.compare (dname.substr (dname_len - dir_len)) == 0)
             {
@@ -1515,6 +1654,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 +1802,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 +1830,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 +1948,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 +1957,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 +2027,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 +2113,7 @@
     {
       retval = dirname;
 
-      string_vector dirlist = dir.read ();
+      string_vector dirlist = dir.read ().sort (false);
 
       octave_idx_type len = dirlist.length ();
 
@@ -1937,7 +2121,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 +2149,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)
@@ -2013,7 +2213,7 @@
       if (! error_state)
         retval = genpath (dirname);
       else
-        error ("genpath: DIR must be a character string");
+        error ("genpath: DIR must be a string");
     }
   else if (nargin > 1)
     {
@@ -2032,7 +2232,7 @@
       if (! error_state)
         retval = genpath (dirname, skip);
       else
-        error ("genpath: all arguments must be character strings");
+        error ("genpath: all arguments must be strings");
     }
   else
     print_usage ();
@@ -2237,10 +2437,10 @@
 
       for (int i = 0; i < nargin; i++)
         {
-          std::string arg = args(i).string_value ();
-
-          if (! error_state)
+          if (args(i).is_string ())
             {
+              std::string arg = args(i).string_value ();
+
               std::list<std::string> dir_elts = split_path (arg);
 
               if (! append)
@@ -2264,7 +2464,7 @@
                 }
             }
           else
-            error ("addpath: all arguments must be character strings");
+            error ("addpath: all arguments must be strings");
         }
 
       if (need_to_update)
@@ -2306,10 +2506,9 @@
 
       for (int i = 0; i < nargin; i++)
         {
-          std::string arg = args(i).string_value ();
-
-          if (! error_state)
+          if (args(i).is_string ())
             {
+              std::string arg = args(i).string_value ();
               std::list<std::string> dir_elts = split_path (arg);
 
               for (std::list<std::string>::const_iterator p = dir_elts.begin ();
@@ -2328,7 +2527,7 @@
                 }
             }
           else
-            error ("addpath: all arguments must be character strings");
+            error ("addpath: all arguments must be strings");
         }
 
       if (need_to_update)
@@ -2339,3 +2538,10 @@
 
   return retval;
 }
+
+DEFUN (__dump_load_path__, , , "")
+{
+  load_path::display (octave_stdout);
+
+  return octave_value_list ();
+}
--- a/libinterp/corefcn/load-path.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/load-path.h	Mon Jan 12 09:17:35 2015 -0800
@@ -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 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/load-save.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -498,26 +498,7 @@
 std::string
 find_file_to_load (const std::string& name, const std::string& orig_name)
 {
-  std::string fname = name;
-
-  if (! (octave_env::absolute_pathname (fname)
-         || octave_env::rooted_relative_pathname (fname)))
-    {
-      file_stat fs (fname);
-
-      if (! (fs.exists () && fs.is_reg ()))
-        {
-          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");
-              fname = tmp;
-            }
-        }
-    }
+  std::string fname = find_data_file_in_load_path ("load", name, true);
 
   size_t dot_pos = fname.rfind (".");
   size_t sep_pos = fname.find_last_of (file_ops::dir_sep_chars ());
@@ -1071,7 +1052,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++)
     {
@@ -1500,17 +1482,17 @@
 @deftypefnx {Command} {} save options file\n\
 @deftypefnx {Command} {} save options file @var{v1} @var{v2} @dots{}\n\
 @deftypefnx {Command} {} save options file -struct @var{STRUCT} @var{f1} @var{f2} @dots{}\n\
+@deftypefnx {Command} {} {@var{s} =} save @samp{-} @var{v1} @var{v2} @dots{}\n\
 Save the named variables @var{v1}, @var{v2}, @dots{}, in the file\n\
-@var{file}.  The special filename @samp{-} may be used to write\n\
-output to the terminal.  If no variable names are listed, Octave saves\n\
-all the variables in the current scope.  Otherwise, full variable names or\n\
-pattern syntax can be used to specify the variables to save.\n\
-If the @option{-struct} modifier is used, fields @var{f1} @var{f2} @dots{}\n\
-of the scalar structure @var{STRUCT} are saved as if they were variables\n\
-with corresponding names.\n\
-Valid options for the @code{save} command are listed in the following table.\n\
-Options that modify the output format override the format specified by\n\
-@code{save_default_options}.\n\
+@var{file}.  The special filename @samp{-} may be used to return the\n\
+content of the variables as a string.  If no variable names are listed,\n\
+Octave saves all the variables in the current scope.  Otherwise, full\n\
+variable names or pattern syntax can be used to specify the variables to\n\
+save.  If the @option{-struct} modifier is used, fields @var{f1} @var{f2}\n\
+@dots{} of the scalar structure @var{STRUCT} are saved as if they were\n\
+variables with corresponding names.  Valid options for the @code{save}\n\
+command are listed in the following table.  Options that modify the output\n\
+format override the format specified by @code{save_default_options}.\n\
 \n\
 If save is invoked using the functional form\n\
 \n\
@@ -1621,8 +1603,6 @@
 {
   octave_value_list retval;
 
-  int argc = args.length ();
-
   string_vector argv = args.make_argv ();
 
   if (error_state)
@@ -1646,7 +1626,7 @@
   // override from command line
   argv = parse_save_options (argv, format, append, save_as_floats,
                              use_zlib);
-  argc = argv.length ();
+  int argc = argv.length ();
   int i = 0;
 
   if (error_state)
@@ -1679,11 +1659,10 @@
           if (append)
             warning ("save: ignoring -append option for output to stdout");
 
-          // FIXME: should things intended for the screen
-          //        end up in an octave_value (string)?
-
-          save_vars (argv, i, argc, octave_stdout, format,
+          std::ostringstream output_buf;
+          save_vars (argv, i, argc, output_buf, format,
                      save_as_floats, true);
+          retval = octave_value (output_buf.str());
         }
     }
 
--- a/libinterp/corefcn/lookup.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/lookup.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -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 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/ls-hdf5.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -263,7 +263,7 @@
   // Allow identifiers as all digits so we can load lists saved by
   // earlier versions of Octave.
 
-  if (! ident_valid )
+  if (! ident_valid)
     {
       // fix the identifier, replacing invalid chars with underscores
       vname = make_valid_identifier (vname);
@@ -528,6 +528,7 @@
         {
           warning ("load: can't read '%s' (unknown datatype)", name);
           retval = 0; // unknown datatype; skip
+          return retval;
         }
 
       // check for OCTAVE_GLOBAL attribute:
@@ -615,7 +616,7 @@
 
       len = H5Gget_objname_by_idx (hs.file_id, hs.current_item, 0, 0);
       var_name.resize (len+1);
-      H5Gget_objname_by_idx( hs.file_id, hs.current_item, &var_name[0], len+1);
+      H5Gget_objname_by_idx (hs.file_id, hs.current_item, &var_name[0], len+1);
 
       for (int i = argv_idx; i < argc; i++)
         {
@@ -738,7 +739,8 @@
   hsize_t sz = d.length ();
   OCTAVE_LOCAL_BUFFER (octave_idx_type, dims, sz);
   bool empty = false;
-  hid_t space_hid = -1, data_hid = -1;
+  hid_t space_hid = -1;
+  hid_t data_hid = -1;
   int retval;
   for (hsize_t i = 0; i < sz; i++)
     {
@@ -865,7 +867,9 @@
                bool mark_as_global, bool save_as_floats)
 {
   hsize_t dims[3];
-  hid_t type_id = -1, space_id = -1, data_id = -1, data_type_id = -1;
+  hid_t type_id, space_id, data_id, data_type_id;
+  type_id = space_id = data_id = data_type_id = -1;
+
   bool retval = false;
   octave_value val = tc;
   // FIXME: diagonal & permutation matrices currently don't know how to save
--- a/libinterp/corefcn/ls-mat4.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/ls-mat4.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -461,7 +461,6 @@
       len = nr * nc;
     }
 
-
   // LEN includes the terminating character, and the file is also
   // supposed to include it.
 
@@ -489,7 +488,10 @@
           for (octave_idx_type j = 0; j < ncol; j++)
             buf[j*nrow+i] = static_cast<double> (*s++ & 0x00FF);
         }
-      os.write (reinterpret_cast<char *> (buf), nrow*ncol*sizeof (double));
+      std::streamsize n_bytes = static_cast<std::streamsize> (nrow) *
+                                static_cast<std::streamsize> (ncol) *
+                                sizeof (double);
+      os.write (reinterpret_cast<char *> (buf), n_bytes);
     }
   else if (tc.is_range ())
     {
@@ -518,7 +520,8 @@
 
           for (octave_idx_type i = 0; i < len; i++)
             dtmp[i] = m.ridx (i) + 1;
-          os.write (reinterpret_cast<const char *> (dtmp), 8 * len);
+          std::streamsize n_bytes = 8 * static_cast<std::streamsize> (len);
+          os.write (reinterpret_cast<const char *> (dtmp), n_bytes);
           ds = nr;
           os.write (reinterpret_cast<const char *> (&ds), 8);
 
@@ -526,19 +529,19 @@
           for (octave_idx_type j = 0; j < nc; j++)
             for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++)
               dtmp[ii++] = j + 1;
-          os.write (reinterpret_cast<const char *> (dtmp), 8 * len);
+          os.write (reinterpret_cast<const char *> (dtmp), n_bytes);
           ds = nc;
           os.write (reinterpret_cast<const char *> (&ds), 8);
 
           for (octave_idx_type i = 0; i < len; i++)
             dtmp[i] = std::real (m.data (i));
-          os.write (reinterpret_cast<const char *> (dtmp), 8 * len);
+          os.write (reinterpret_cast<const char *> (dtmp), n_bytes);
           ds = 0.;
           os.write (reinterpret_cast<const char *> (&ds), 8);
 
           for (octave_idx_type i = 0; i < len; i++)
             dtmp[i] = std::imag (m.data (i));
-          os.write (reinterpret_cast<const char *> (dtmp), 8 * len);
+          os.write (reinterpret_cast<const char *> (dtmp), n_bytes);
           os.write (reinterpret_cast<const char *> (&ds), 8);
         }
       else
@@ -547,7 +550,8 @@
 
           for (octave_idx_type i = 0; i < len; i++)
             dtmp[i] = m.ridx (i) + 1;
-          os.write (reinterpret_cast<const char *> (dtmp), 8 * len);
+          std::streamsize n_bytes = 8 * static_cast<std::streamsize> (len);
+          os.write (reinterpret_cast<const char *> (dtmp), n_bytes);
           ds = nr;
           os.write (reinterpret_cast<const char *> (&ds), 8);
 
@@ -555,11 +559,11 @@
           for (octave_idx_type j = 0; j < nc; j++)
             for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++)
               dtmp[ii++] = j + 1;
-          os.write (reinterpret_cast<const char *> (dtmp), 8 * len);
+          os.write (reinterpret_cast<const char *> (dtmp), n_bytes);
           ds = nc;
           os.write (reinterpret_cast<const char *> (&ds), 8);
 
-          os.write (reinterpret_cast<const char *> (m.data ()), 8 * len);
+          os.write (reinterpret_cast<const char *> (m.data ()), n_bytes);
           ds = 0.;
           os.write (reinterpret_cast<const char *> (&ds), 8);
         }
@@ -567,7 +571,8 @@
   else if (tc.is_real_matrix ())
     {
       Matrix m = tc.matrix_value ();
-      os.write (reinterpret_cast<const char *> (m.data ()), 8 * len);
+      std::streamsize n_bytes = 8 * static_cast<std::streamsize> (len);
+      os.write (reinterpret_cast<const char *> (m.data ()), n_bytes);
     }
   else if (tc.is_complex_scalar ())
     {
@@ -578,9 +583,10 @@
     {
       ComplexMatrix m_cmplx = tc.complex_matrix_value ();
       Matrix m = ::real (m_cmplx);
-      os.write (reinterpret_cast<const char *> (m.data ()), 8 * len);
+      std::streamsize n_bytes = 8 * static_cast<std::streamsize> (len);
+      os.write (reinterpret_cast<const char *> (m.data ()), n_bytes);
       m = ::imag (m_cmplx);
-      os.write (reinterpret_cast<const char *> (m.data ()), 8 * len);
+      os.write (reinterpret_cast<const char *> (m.data ()), n_bytes);
     }
   else
     gripe_wrong_type_arg ("save", tc, false);
--- a/libinterp/corefcn/ls-mat5.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/ls-mat5.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -264,7 +264,8 @@
       if (len > 0) \
         { \
           OCTAVE_LOCAL_BUFFER (TYPE, ptr, len); \
-          stream.read (reinterpret_cast<char *> (ptr), size * len); \
+          std::streamsize n_bytes = size * static_cast<std::streamsize> (len); \
+          stream.read (reinterpret_cast<char *> (ptr), n_bytes); \
           if (swap) \
             swap_bytes< size > (ptr, len); \
           for (octave_idx_type i = 0; i < len; i++) \
@@ -439,7 +440,7 @@
   unsigned int upper;
   int32_t temp;
 
-  if (! is.read (reinterpret_cast<char *> (&temp), 4 ))
+  if (! is.read (reinterpret_cast<char *> (&temp), 4))
     goto data_read_error;
 
   if (swap)
@@ -456,7 +457,7 @@
     }
   else
     {
-      if (! is.read (reinterpret_cast<char *> (&temp), 4 ))
+      if (! is.read (reinterpret_cast<char *> (&temp), 4))
         goto data_read_error;
       if (swap)
         swap_bytes<4> (&temp);
@@ -650,7 +651,7 @@
   arrayclass = static_cast<arrayclasstype> (flags & 0xff);
 
   int32_t tmp_nzmax;
-  read_int (is, swap, tmp_nzmax);   // max number of non-zero in sparse
+  read_int (is, swap, tmp_nzmax);   // max number of nonzero in sparse
   nzmax = tmp_nzmax;
 
   // dimensions array subelement
@@ -709,7 +710,7 @@
 
     if (len)
       {
-        if (! is.read (name, len ))
+        if (! is.read (name, len))
           goto data_read_error;
 
         is.seekg (tmp_pos + static_cast<std::streamoff>
@@ -937,7 +938,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)
                           {
@@ -966,7 +967,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)
                           {
@@ -991,7 +992,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)
                       {
@@ -1171,7 +1172,7 @@
 
           if (len)
             {
-              if (! is.read (name, len ))
+              if (! is.read (name, len))
                 goto data_read_error;
 
               is.seekg (tmp_pos + static_cast<std::streamoff>
@@ -1201,7 +1202,7 @@
             goto data_read_error;
           }
 
-        if (! is.read (reinterpret_cast<char *> (&field_name_length), fn_len ))
+        if (! is.read (reinterpret_cast<char *> (&field_name_length), fn_len))
           goto data_read_error;
 
         if (swap)
@@ -1568,7 +1569,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);
@@ -1674,7 +1676,8 @@
       OCTAVE_LOCAL_BUFFER (TYPE, ptr, count); \
       for (octave_idx_type i = 0; i < count; i++) \
         ptr[i] = static_cast<TYPE> (data[i]); \
-      stream.write (reinterpret_cast<char *> (ptr), count * sizeof (TYPE)); \
+      std::streamsize n_bytes = sizeof (TYPE) * static_cast<std::streamsize> (count); \
+      stream.write (reinterpret_cast<char *> (ptr), n_bytes); \
     } \
   while (0)
 
--- a/libinterp/corefcn/lu.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/lu.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -137,7 +137,7 @@
 is embedded into @var{U} to give a return value similar to the full case.\n\
 For both full and sparse matrices, @code{lu} loses the permutation\n\
 information.\n\
-@seealso{luupdate, chol, hess, qr, qz, schur, svd}\n\
+@seealso{luupdate, ilu, chol, hess, qr, qz, schur, svd}\n\
 @end deftypefn")
 {
   octave_value_list retval;
@@ -158,11 +158,11 @@
   int n = 1;
   while (n < nargin && ! error_state)
     {
-      if (args (n).is_string ())
+      if (args(n).is_string ())
         {
           std::string tmp = args(n++).string_value ();
 
-          if (! error_state )
+          if (! error_state)
             {
               if (tmp.compare ("vector") == 0)
                 vecout = true;
@@ -174,7 +174,7 @@
         {
           Matrix tmp = args(n++).matrix_value ();
 
-          if (! error_state )
+          if (! error_state)
             {
               if (!issparse)
                 error ("lu: can not define pivoting threshold THRES for full matrices");
@@ -211,7 +211,7 @@
 
           SparseMatrix m = arg.sparse_matrix_value ();
 
-          if ( nargout < 4 )
+          if (nargout < 4)
             {
 
               ColumnVector Qinit;
@@ -220,7 +220,7 @@
                 Qinit (i) = i;
               SparseLU fact (m, Qinit, thres, false, true);
 
-              if ( nargout < 2 )
+              if (nargout < 2)
                   retval(0) = fact.Y ();
               else
                 {
@@ -233,15 +233,15 @@
 
                   PermMatrix P = fact.Pr_mat ();
                   SparseMatrix L = fact.L ();
-                  if ( nargout < 3 )
+                  if (nargout < 3)
                       retval(0)
-                        = octave_value ( P.transpose () * L,
+                        = octave_value (P.transpose () * L,
                             MatrixType (MatrixType::Permuted_Lower,
                                         nr, fact.row_perm ()));
                   else
                     {
                       retval(0) = L;
-                      if ( vecout )
+                      if (vecout)
                         retval(2) = fact.Pr_vec();
                       else
                         retval(2) = P;
@@ -279,7 +279,7 @@
         {
           SparseComplexMatrix m = arg.sparse_complex_matrix_value ();
 
-          if ( nargout < 4 )
+          if (nargout < 4)
             {
 
               ColumnVector Qinit;
@@ -288,7 +288,7 @@
                 Qinit (i) = i;
               SparseComplexLU fact (m, Qinit, thres, false, true);
 
-              if ( nargout < 2 )
+              if (nargout < 2)
 
                   retval(0) = fact.Y ();
 
@@ -303,15 +303,15 @@
 
                   PermMatrix P = fact.Pr_mat ();
                   SparseComplexMatrix L = fact.L ();
-                  if ( nargout < 3 )
+                  if (nargout < 3)
                       retval(0)
-                        = octave_value ( P.transpose () * L,
+                        = octave_value (P.transpose () * L,
                             MatrixType (MatrixType::Permuted_Lower,
                                         nr, fact.row_perm ()));
                   else
                     {
                       retval(0) = L;
-                      if ( vecout )
+                      if (vecout)
                         retval(2) = fact.Pr_vec();
                       else
                         retval(2) = P;
@@ -592,7 +592,9 @@
 bool check_lu_dims (const octave_value& l, const octave_value& u,
                     const octave_value& p)
 {
-  octave_idx_type m = l.rows (), k = u.rows (), n = u.columns ();
+  octave_idx_type m = l.rows ();
+  octave_idx_type k = u.rows ();
+  octave_idx_type n = u.columns ();
   return ((l.ndims () == 2 && u.ndims () == 2 && k == l.columns ())
           && k == std::min (m, n) &&
           (p.is_undefined () || p.rows () == m));
@@ -840,6 +842,20 @@
 %! assert (norm (vec (P'*L*U - A - u*v.'), Inf) < norm (A)*1e1*eps);
 %!
 %!testif HAVE_QRUPDATE_LUU
+%! [L,U,P] = lu (A);
+%! [~,ordcols] = max (P,[],1);
+%! [~,ordrows] = max (P,[],2);
+%! P1 = eye (size(P))(:,ordcols);
+%! P2 = eye (size(P))(ordrows,:);
+%! assert(P1 == P);
+%! assert(P2 == P);
+%! [L,U,P] = luupdate (L,U,P,u,v);
+%! [L,U,P1] = luupdate (L,U,P1,u,v);
+%! [L,U,P2] = luupdate (L,U,P2,u,v);
+%! assert(P1 == P);
+%! assert(P2 == P);
+%!
+%!testif HAVE_QRUPDATE_LUU
 %! [L,U,P] = lu (Ac);
 %! [L,U,P] = luupdate (L,U,P,uc,vc);
 %! assert (norm (vec (tril (L)-L), Inf) == 0);
--- a/libinterp/corefcn/luinc.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/luinc.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -37,7 +37,7 @@
 #include "ov-re-sparse.h"
 #include "ov-cx-sparse.h"
 
-DEFUN (luinc, args, nargout,
+DEFUN (__luinc__, args, nargout,
        "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {[@var{L}, @var{U}, @var{P}, @var{Q}] =} luinc (@var{A}, '0')\n\
 @deftypefnx {Built-in Function} {[@var{L}, @var{U}, @var{P}, @var{Q}] =} luinc (@var{A}, @var{droptol})\n\
@@ -49,7 +49,7 @@
 \n\
 Called with a second argument of @qcode{'0'}, the zero-level incomplete\n\
 LU@tie{}factorization is produced.  This creates a factorization of @var{A}\n\
-where the position of the non-zero arguments correspond to the same\n\
+where the position of the nonzero arguments correspond to the same\n\
 positions as in the matrix @var{A}.\n\
 \n\
 Alternatively, the fill-in of the incomplete LU@tie{}factorization can\n\
@@ -93,7 +93,7 @@
 \n\
 Given the string argument @qcode{\"vector\"}, @code{luinc} returns the\n\
 values of @var{p} @var{q} as vector values.\n\
-@seealso{sparse, lu}\n\
+@seealso{sparse, lu, ilu, ichol}\n\
 @end deftypefn")
 {
   int nargin = args.length ();
@@ -177,7 +177,7 @@
         {
           std::string tmp = args(2).string_value ();
 
-          if (! error_state )
+          if (! error_state)
             {
               if (tmp.compare ("vector") == 0)
                 vecout = true;
--- a/libinterp/corefcn/mappers.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/mappers.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -114,6 +114,20 @@
 %! v = single ([0, pi/6, pi/4, pi/3, pi/2, 2*pi/3, 3*pi/4, 5*pi/6, pi]);
 %! assert (acos (x), v, sqrt (eps ("single")));
 
+## Test values on either side of branch cut
+%!test
+%! rval = 0;
+%! ival = 1.31695789692481635;
+%! obs = acos ([2, 2-i*eps, 2+i*eps]);
+%! exp = [rval + ival*i, rval + ival*i, rval - ival*i];
+%! assert (obs, exp, 2*eps);
+%! rval = pi;
+%! obs = acos ([-2, -2-i*eps, -2+i*eps]);
+%! exp = [rval - ival*i, rval + ival*i, rval - ival*i];
+%! assert (obs, exp, 2*eps);
+%! assert (acos ([2 0]),  [ival*i, pi/2], 2*eps);
+%! assert (acos ([2 0i]), [ival*i, pi/2], 2*eps);
+
 %!error acos ()
 %!error acos (1, 2)
 */
@@ -236,12 +250,32 @@
 }
 
 /*
-%!test
+%!shared rt2, rt3
 %! rt2 = sqrt (2);
 %! rt3 = sqrt (3);
+
+%!test
 %! x = [0, 1/2, rt2/2, rt3/2, 1, rt3/2, rt2/2, 1/2, 0];
 %! v = [0, pi/6, pi/4, pi/3, pi/2, pi/3, pi/4, pi/6, 0];
-%! assert (all (abs (asin (x) - v) < sqrt (eps)));
+%! assert (asin (x), v, sqrt (eps));
+
+%!test
+%! x = single ([0, 1/2, rt2/2, rt3/2, 1, rt3/2, rt2/2, 1/2, 0]);
+%! v = single ([0, pi/6, pi/4, pi/3, pi/2, pi/3, pi/4, pi/6, 0]);
+%! assert (asin (x), v, sqrt (eps ("single")));
+
+## Test values on either side of branch cut
+%!test
+%! rval = pi/2;
+%! ival = 1.31695789692481635;
+%! obs = asin ([2, 2-i*eps, 2+i*eps]);
+%! exp = [rval - ival*i, rval - ival*i, rval + ival*i];
+%! assert (obs, exp, 2*eps);
+%! obs = asin ([-2, -2-i*eps, -2+i*eps]);
+%! exp = [-rval + ival*i, -rval - ival*i, -rval + ival*i];
+%! assert (obs, exp, 2*eps);
+%! assert (asin ([2 0]),  [rval - ival*i, 0], 2*eps);
+%! assert (asin ([2 0i]), [rval - ival*i, 0], 2*eps);
 
 %!error asin ()
 %!error asin (1, 2)
@@ -895,15 +929,15 @@
 
 DEFUN (isfinite, args, ,
        "-*- texinfo -*-\n\
-@deftypefn  {Mapping Function} {} isfinite (@var{x})\n\
-@deftypefnx {Mapping Function} {} finite (@var{x})\n\
+@deftypefn {Mapping Function} {} isfinite (@var{x})\n\
 Return a logical array which is true where the elements of @var{x} are\n\
 finite values and false where they are not.\n\
+\n\
 For example:\n\
 \n\
 @example\n\
 @group\n\
-finite ([13, Inf, NA, NaN])\n\
+isfinite ([13, Inf, NA, NaN])\n\
      @result{} [ 1, 0, 0, 0 ]\n\
 @end group\n\
 @end example\n\
@@ -920,16 +954,16 @@
 }
 
 /*
-%!assert (!finite (Inf))
-%!assert (!finite (NaN))
-%!assert (finite (rand (1,10)))
+%!assert (!isfinite (Inf))
+%!assert (!isfinite (NaN))
+%!assert (isfinite (rand (1,10)))
 
-%!assert (!finite (single (Inf)))
-%!assert (!finite (single (NaN)))
-%!assert (finite (single (rand (1,10))))
+%!assert (!isfinite (single (Inf)))
+%!assert (!isfinite (single (NaN)))
+%!assert (isfinite (single (rand (1,10))))
 
-%!error finite ()
-%!error finite (1, 2)
+%!error isfinite ()
+%!error isfinite (1, 2)
 */
 
 DEFUN (fix, args, ,
@@ -1024,7 +1058,13 @@
 @end example\n\
 \n\
 @end ifnottex\n\
-@seealso{gammainc, lgamma}\n\
+\n\
+Programming Note: The gamma function can grow quite large even for small\n\
+input values.  In many cases it may be preferable to use the natural\n\
+logarithm of the gamma function (@code{gammaln}) in calculations to minimize\n\
+loss of precision.  The final result is then\n\
+@code{exp (@var{result_using_gammaln}).}\n\
+@seealso{gammainc, gammaln, factorial}\n\
 @end deftypefn")
 {
   octave_value retval;
@@ -1574,8 +1614,8 @@
 
 DEFUN (lgamma, args, ,
        "-*- texinfo -*-\n\
-@deftypefn  {Mapping Function} {} lgamma (@var{x})\n\
-@deftypefnx {Mapping Function} {} gammaln (@var{x})\n\
+@deftypefn  {Mapping Function} {} gammaln (@var{x})\n\
+@deftypefnx {Mapping Function} {} lgamma (@var{x})\n\
 Return the natural logarithm of the gamma function of @var{x}.\n\
 @seealso{gamma, gammainc}\n\
 @end deftypefn")
@@ -1592,30 +1632,30 @@
 /*
 %!test
 %! a = -1i*sqrt (-1/(6.4187*6.4187));
-%! assert (lgamma (a), lgamma (real (a)));
+%! assert (gammaln (a), gammaln (real (a)));
 
 %!test
 %! x = [.5, 1, 1.5, 2, 3, 4, 5];
 %! v = [sqrt(pi), 1, .5*sqrt(pi), 1, 2, 6, 24];
-%! assert (lgamma (x), log (v), sqrt (eps))
+%! assert (gammaln (x), log (v), sqrt (eps))
 
 %!test
 %! a = single (-1i*sqrt (-1/(6.4187*6.4187)));
-%! assert (lgamma (a), lgamma (real (a)));
+%! assert (gammaln (a), gammaln (real (a)));
 
 %!test
 %! x = single ([.5, 1, 1.5, 2, 3, 4, 5]);
 %! v = single ([sqrt(pi), 1, .5*sqrt(pi), 1, 2, 6, 24]);
-%! assert (lgamma (x), log (v), sqrt (eps ("single")))
+%! assert (gammaln (x), log (v), sqrt (eps ("single")))
 
 %!test
 %! x = [-1, 0, 1, Inf];
 %! v = [Inf, Inf, 0, Inf];
-%! assert (lgamma (x), v);
-%! assert (lgamma (single (x)), single (v));
+%! assert (gammaln (x), v);
+%! assert (gammaln (single (x)), single (v));
 
-%!error lgamma ()
-%!error lgamma (1,2)
+%!error gammaln ()
+%!error gammaln (1,2)
 */
 
 DEFUN (log, args, ,
@@ -1886,7 +1926,7 @@
 Return logical true if the value of @var{x} has its sign bit set.\n\
 Otherwise return logical false.  This behavior is consistent with the other\n\
 logical functions.  See@ref{Logical Values}.  The behavior differs from the\n\
-C language function which returns non-zero if the sign bit is set.\n\
+C language function which returns nonzero if the sign bit is set.\n\
 \n\
 This is not the same as @code{x < 0.0}, because IEEE 754 floating point\n\
 allows zero to be signed.  The comparison @code{-0.0 < 0.0} is false,\n\
@@ -2156,8 +2196,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 +2256,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");
@@ -2225,4 +2283,3 @@
 
 DEFALIAS (gammaln, lgamma);
 
-DEFALIAS (finite, isfinite);
--- a/libinterp/corefcn/matrix_type.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/matrix_type.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -148,7 +148,7 @@
                 {
                   mattyp = args(0).matrix_type ();
 
-                  if (mattyp.is_unknown () && autocomp )
+                  if (mattyp.is_unknown () && autocomp)
                     {
                       SparseComplexMatrix m =
                         args(0).sparse_complex_matrix_value ();
@@ -213,18 +213,18 @@
           else
             {
               // Ok, we're changing the matrix type
-              std::string str_typ = args(1).string_value ();
-
-              // FIXME: why do I have to explicitly call the constructor?
-              MatrixType mattyp = MatrixType ();
-
-              octave_idx_type nl = 0;
-              octave_idx_type nu = 0;
-
-              if (error_state)
+              if (! args(1).is_string ())
                 error ("matrix_type: TYPE must be a string");
               else
                 {
+                  std::string str_typ = args(1).string_value ();
+
+                  // FIXME: why do I have to explicitly call the constructor?
+                  MatrixType mattyp = MatrixType ();
+
+                  octave_idx_type nl = 0;
+                  octave_idx_type nu = 0;
+
                   // Use STL function to convert to lower case
                   std::transform (str_typ.begin (), str_typ.end (),
                                   str_typ.begin (), tolower);
@@ -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");
@@ -416,15 +416,15 @@
           else
             {
               // Ok, we're changing the matrix type
-              std::string str_typ = args(1).string_value ();
-
-              // FIXME: why do I have to explicitly call the constructor?
-              MatrixType mattyp = MatrixType (MatrixType::Unknown, true);
-
-              if (error_state)
+              if (! args(1).is_string ())
                 error ("matrix_type: TYPE must be a string");
               else
                 {
+                  std::string str_typ = args(1).string_value ();
+
+                  // FIXME: why do I have to explicitly call the constructor?
+                  MatrixType mattyp = MatrixType (MatrixType::Unknown, true);
+
                   // Use STL function to convert to lower case
                   std::transform (str_typ.begin (), str_typ.end (),
                                   str_typ.begin (), tolower);
@@ -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 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/max.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -155,7 +155,7 @@
 
   octave_value retval;
 
-  if (argx.is_scalar_type () == 1)
+  if (argx.is_scalar_type ())
     {
       ScalarType x = octave_value_extract<ScalarType> (argx);
       ArrayType y = octave_value_extract<ArrayType> (argy);
@@ -167,7 +167,7 @@
       else
         retval = max (x, y);
     }
-  else if (argy.is_scalar_type () == 1)
+  else if (argy.is_scalar_type ())
     {
       ArrayType x = octave_value_extract<ArrayType> (argx);
       ScalarType y = octave_value_extract<ScalarType> (argy);
@@ -210,39 +210,26 @@
 {
   octave_value retval;
 
-  if (argx.is_scalar_type () == 1)
-    {
-      char x = octave_value_extract<char> (argx);
-      charNDArray y = octave_value_extract<charNDArray> (argy);
+  charNDArray x = octave_value_extract<charNDArray> (argx);
+  charNDArray y = octave_value_extract<charNDArray> (argy);
 
-      if (error_state)
-        ;
-      else if (ismin)
-        retval = NDArray (min (x, y));
+  if (error_state)
+    ;
+  else if (ismin)
+    {
+      if (x.numel () == 1)
+        retval = NDArray (min (x(0), y));
+      else if (y.numel () == 1)
+        retval = NDArray (min (x, y(0)));
       else
-        retval = NDArray (max (x, y));
-    }
-  else if (argy.is_scalar_type () == 1)
-    {
-      charNDArray x = octave_value_extract<charNDArray> (argx);
-      char y = octave_value_extract<char> (argy);
-
-      if (error_state)
-        ;
-      else if (ismin)
         retval = NDArray (min (x, y));
-      else
-        retval = NDArray (max (x, y));
     }
   else
     {
-      charNDArray x = octave_value_extract<charNDArray> (argx);
-      charNDArray y = octave_value_extract<charNDArray> (argy);
-
-      if (error_state)
-        ;
-      else if (ismin)
-        retval = NDArray (min (x, y));
+      if (x.numel () == 1)
+        retval = NDArray (max (x(0), y));
+      else if (y.numel () == 1)
+        retval = NDArray (max (x, y(0)));
       else
         retval = NDArray (max (x, y));
     }
@@ -284,7 +271,7 @@
             if (arg.is_range () && (dim == -1 || dim == 1))
               {
                 Range range = arg.range_value ();
-                if (range.nelem () == 0)
+                if (range.nelem () < 1)
                   {
                     retval(0) = arg;
                     if (nargout > 1)
@@ -354,11 +341,18 @@
     }
   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;
+      /*
+      FIXME: This is what should happen when boolNDArray has max()
+      else if (xtyp == btyp_bool && ytyp == btyp_bool)
+        rtyp = btyp_bool;
+      */
       else
         rtyp = btyp_mixed_numeric (xtyp, ytyp);
 
@@ -407,10 +401,21 @@
         MAKE_INT_BRANCH (uint32);
         MAKE_INT_BRANCH (uint64);
 #undef MAKE_INT_BRANCH
+        /*
+        FIXME: This is what should happen when boolNDArray has max()
+        case btyp_bool:
+          retval = do_minmax_bin_op<boolNDArray> (argx, argy, ismin);
+          break;
+        */
         default:
           error ("%s: cannot compute %s (%s, %s)", func, func,
                  argx.type_name ().c_str (), argy.type_name ().c_str ());
         }
+
+      // FIXME: Delete when boolNDArray has max()
+      if (xtyp == btyp_bool && ytyp == btyp_bool)
+        retval(0) = retval(0).bool_array_value ();
+
     }
   else
     print_usage ();
@@ -421,15 +426,23 @@
 DEFUN (min, args, nargout,
        "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {} min (@var{x})\n\
-@deftypefnx {Built-in Function} {} min (@var{x}, @var{y})\n\
 @deftypefnx {Built-in Function} {} min (@var{x}, [], @var{dim})\n\
-@deftypefnx {Built-in Function} {} min (@var{x}, @var{y}, @var{dim})\n\
 @deftypefnx {Built-in Function} {[@var{w}, @var{iw}] =} min (@var{x})\n\
-For a vector argument, return the minimum value.  For a matrix\n\
-argument, return the minimum value from each column, as a row\n\
-vector, or over the dimension @var{dim} if defined, in which case @var{y} \n\
-should be set to the empty matrix (it's ignored otherwise).  For two matrices\n\
-(or a matrix and scalar), return the pair-wise minimum.\n\
+@deftypefnx {Built-in Function} {} min (@var{x}, @var{y})\n\
+Find minimum values in the array @var{x}.\n\
+\n\
+For a vector argument, return the minimum value.\n\
+For a matrix argument, return a row vector with the minimum value of each\n\
+column.\n\
+For a multi-dimensional array, @code{min} operates along the first\n\
+non-singleton dimension.\n\
+\n\
+If the optional third argument @var{dim} is present then operate along\n\
+this dimension.  In this case the second argument is ignored and should be\n\
+set to the empty matrix.\n\
+\n\
+For two matrices (or a matrix and a scalar), return the pairwise minimum.\n\
+\n\
 Thus,\n\
 \n\
 @example\n\
@@ -437,7 +450,7 @@
 @end example\n\
 \n\
 @noindent\n\
-returns the smallest element of @var{x}, and\n\
+returns the smallest element of the 2-D matrix @var{x}, and\n\
 \n\
 @example\n\
 @group\n\
@@ -451,7 +464,19 @@
 returns a row vector of the minimum values.\n\
 \n\
 For complex arguments, the magnitude of the elements are used for\n\
-comparison.\n\
+comparison.  If the magnitudes are identical, then the results are ordered\n\
+by phase angle in the range (-pi, pi].  Hence,\n\
+\n\
+@example\n\
+@group\n\
+min ([-1 i 1 -i])\n\
+    @result{} -i\n\
+@end group\n\
+@end example\n\
+\n\
+@noindent\n\
+because all entries have magnitude 1, but -i has the smallest phase angle\n\
+with value -pi/2.\n\
 \n\
 If called with one input and two output arguments,\n\
 @code{min} also returns the first index of the\n\
@@ -471,40 +496,176 @@
 }
 
 /*
+## Test generic double class
 %!assert (min ([1, 4, 2, 3]), 1)
 %!assert (min ([1; -10; 5; -2]), -10)
-%!assert (min ([4, i; -2, 2]), [-2, i])
-%!assert (min (char(42)), 42)
-%!assert (min (char(21), char(3)), 3)
-%!assert (min([char(21), char(3)]), 3)
-%!assert (min([char(100) char(3)], [char(42) char(42)]), [42 3])
+%!assert (min ([4, 2i 4.999; -2, 2, 3+4i]), [-2, 2, 4.999])
+## Special routines for char arrays
+%!assert (min (["abc", "ABC"]), 65)
+%!assert (min (["abc"; "CBA"]), [67 66 65])
+## Special routines for logical arrays
+%!assert (min (logical ([])), logical ([]))
+%!assert (min (logical ([0 0 1 0])), false)
+%!assert (min (logical ([0 0 1 0; 0 1 1 0])), logical ([0 0 1 0]))
+## Single values
+%!assert (min (single ([1, 4, 2, 3])), single (1))
+%!assert (min (single ([1; -10; 5; -2])), single (-10))
+%!assert (min (single ([4, 2i 4.999; -2, 2, 3+4i])), single ([-2, 2, 4.999]))
+## Integer values
+%!assert (min (uint8 ([1, 4, 2, 3])), uint8 (1))
+%!assert (min (uint8 ([1; -10; 5; -2])), uint8 (-10))
+%!assert (min (int8 ([1, 4, 2, 3])), int8 (1))
+%!assert (min (int8 ([1; -10; 5; -2])), int8 (-10))
+%!assert (min (uint16 ([1, 4, 2, 3])), uint16 (1))
+%!assert (min (uint16 ([1; -10; 5; -2])), uint16 (-10))
+%!assert (min (int16 ([1, 4, 2, 3])), int16 (1))
+%!assert (min (int16 ([1; -10; 5; -2])), int16 (-10))
+%!assert (min (uint32 ([1, 4, 2, 3])), uint32 (1))
+%!assert (min (uint32 ([1; -10; 5; -2])), uint32 (-10))
+%!assert (min (int32 ([1, 4, 2, 3])), int32 (1))
+%!assert (min (int32 ([1; -10; 5; -2])), int32 (-10))
+%!assert (min (uint64 ([1, 4, 2, 3])), uint64 (1))
+%!assert (min (uint64 ([1; -10; 5; -2])), uint64 (-10))
+%!assert (min (int64 ([1, 4, 2, 3])), int64 (1))
+%!assert (min (int64 ([1; -10; 5; -2])), int64 (-10))
+## Sparse double values
+%!assert (min (sparse ([1, 4, 2, 3])), sparse (1))
+%!assert (min (sparse ([1; -10; 5; -2])), sparse(-10))
+## FIXME: sparse doesn't order complex values by phase angle
+%!xtest
+%! assert (min (sparse ([4, 2i 4.999; -2, 2, 3+4i])), sparse ([-2, 2, 4.999]));
 
+## Test dimension argument
 %!test
 %! x = reshape (1:8, [2,2,2]);
-%! assert (max (x, [], 1), reshape ([2, 4, 6, 8], [1,2,2]));
-%! assert (max (x, [], 2), reshape ([3, 4, 7, 8], [2,1,2]));
-%! [y, i] = max (x, [], 3);
+%! assert (min (x, [], 1), reshape ([1, 3, 5, 7], [1,2,2]));
+%! assert (min (x, [], 2), reshape ([1, 2, 5, 6], [2,1,2]));
+%! [y, i] = min (x, [], 3);
 %! assert (ndims (y), 2);
-%! assert (y, [5, 7; 6, 8]);
+%! assert (y, [1, 3; 2, 4]);
 %! assert (ndims (i), 2);
-%! assert (i, [2, 2; 2, 2]);
+%! assert (i, [1, 1; 1, 1]);
+
+## Test 2-output forms for various arg types
+## Special routines for char arrays
+%!test
+%! [y, i] = min (["abc", "ABC"]);
+%! assert (y, 65);
+%! assert (i, 4);
+## Special routines for logical arrays
+%!test
+%! x = logical ([0 0 1 0]);
+%! [y, i] = min (x);
+%! assert (y, false);
+%! assert (i, 1);
+## Special handling of ranges
+%!test
+%! rng = 1:2:10;
+%! [y, i] = min (rng);
+%! assert (y, 1);
+%! assert (i, 1);
+%! rng = 10:-2:1;
+%! [y, i] = min (rng);
+%! assert (y, 2);
+%! assert (i, 5);
+
+## Test 2-input calling form for various arg types
+## Test generic double class
+%!test
+%! x = [1, 2, 3, 4];  y = fliplr (x);
+%! assert (min (x, y), [1 2 2 1]);
+%! assert (min (x, 3), [1 2 3 3]);
+%! assert (min (2, x), [1 2 2 2]);
+%! assert (min (x, 2.1i), [1 2 2.1i 2.1i]);
+## FIXME: Ordering of complex results with equal magnitude is not by phase
+##        angle in the 2-input form.  Instead, it is in the order in which it
+##        appears in the argument list.
+%!xtest
+%! x = [1, 2, 3, 4];  y = fliplr (x);
+%! assert (min (x, 2i), [2i 2i 3 4]);
+## Special routines for char arrays
+%!assert (min ("abc", "b"), [97 98 98])
+%!assert (min ("b", "cba"), [98 98 97])
+## Special handling for logical arrays
+%!assert (min ([true false], false), [false false])
+%!assert (min (true, [true false]), [true false])
+## Single values
+%!test
+%! x = single ([1, 2, 3, 4]);  y = fliplr (x);
+%! assert (min (x, y), single ([1 2 2 1]));
+%! assert (min (x, 3), single ([1 2 3 3]));
+%! assert (min (2, x), single ([1 2 2 2]));
+%! assert (min (x, 2.1i), single ([1 2 2.1i 2.1i]));
+## Integer values
+%!test
+%! x = uint8 ([1, 2, 3, 4]);  y = fliplr (x);
+%! assert (min (x, y), uint8 ([1 2 2 1]));
+%! assert (min (x, 3), uint8 ([1 2 3 3]));
+%! assert (min (2, x), uint8 ([1 2 2 2]));
+%! x = int8 ([1, 2, 3, 4]);  y = fliplr (x);
+%! assert (min (x, y), int8 ([1 2 2 1]));
+%! assert (min (x, 3), int8 ([1 2 3 3]));
+%! assert (min (2, x), int8 ([1 2 2 2]));
+%! x = uint16 ([1, 2, 3, 4]);  y = fliplr (x);
+%! assert (min (x, y), uint16 ([1 2 2 1]));
+%! assert (min (x, 3), uint16 ([1 2 3 3]));
+%! assert (min (2, x), uint16 ([1 2 2 2]));
+%! x = int16 ([1, 2, 3, 4]);  y = fliplr (x);
+%! assert (min (x, y), int16 ([1 2 2 1]));
+%! assert (min (x, 3), int16 ([1 2 3 3]));
+%! assert (min (2, x), int16 ([1 2 2 2]));
+%! x = uint32 ([1, 2, 3, 4]);  y = fliplr (x);
+%! assert (min (x, y), uint32 ([1 2 2 1]));
+%! assert (min (x, 3), uint32 ([1 2 3 3]));
+%! assert (min (2, x), uint32 ([1 2 2 2]));
+%! x = int32 ([1, 2, 3, 4]);  y = fliplr (x);
+%! assert (min (x, y), int32 ([1 2 2 1]));
+%! assert (min (x, 3), int32 ([1 2 3 3]));
+%! assert (min (2, x), int32 ([1 2 2 2]));
+%! x = uint64 ([1, 2, 3, 4]);  y = fliplr (x);
+%! assert (min (x, y), uint64 ([1 2 2 1]));
+%! assert (min (x, 3), uint64 ([1 2 3 3]));
+%! assert (min (2, x), uint64 ([1 2 2 2]));
+%! x = int64 ([1, 2, 3, 4]);  y = fliplr (x);
+%! assert (min (x, y), int64 ([1 2 2 1]));
+%! assert (min (x, 3), int64 ([1 2 3 3]));
+%! assert (min (2, x), int64 ([1 2 2 2]));
+## Sparse double values
+%!test
+%! x = sparse ([1, 2, 3, 4]);  y = fliplr (x);
+%! assert (min (x, y), sparse ([1 2 2 1]));
+%! assert (min (x, 3), sparse ([1 2 3 3]));
+%! assert (min (2, x), sparse ([1 2 2 2]));
+%! assert (min (x, 2.1i), sparse ([1 2 2.1i 2.1i]));
 
 %!error min ()
 %!error min (1, 2, 3, 4)
+%!error <DIM must be a valid dimension> min ([1 2; 3 4], [], -3)
+%!warning <second argument is ignored> min ([1 2 3 4], 2, 2);
+%!error <wrong type argument 'cell'> min ({1 2 3 4})
+%!error <cannot compute min \(cell, scalar\)> min ({1, 2, 3}, 2)
 */
 
 DEFUN (max, args, nargout,
        "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {} max (@var{x})\n\
-@deftypefnx {Built-in Function} {} max (@var{x}, @var{y})\n\
 @deftypefnx {Built-in Function} {} max (@var{x}, [], @var{dim})\n\
-@deftypefnx {Built-in Function} {} max (@var{x}, @var{y}, @var{dim})\n\
 @deftypefnx {Built-in Function} {[@var{w}, @var{iw}] =} max (@var{x})\n\
-For a vector argument, return the maximum value.  For a matrix\n\
-argument, return the maximum value from each column, as a row\n\
-vector, or over the dimension @var{dim} if defined, in which case @var{y} \n\
-should be set to the empty matrix (it's ignored otherwise).  For two matrices\n\
-(or a matrix and scalar), return the pair-wise maximum.\n\
+@deftypefnx {Built-in Function} {} max (@var{x}, @var{y})\n\
+Find maximum values in the array @var{x}.\n\
+\n\
+For a vector argument, return the maximum value.\n\
+For a matrix argument, return a row vector with the maximum value of each\n\
+column.\n\
+For a multi-dimensional array, @code{max} operates along the first\n\
+non-singleton dimension.\n\
+\n\
+If the optional third argument @var{dim} is present then operate along\n\
+this dimension.  In this case the second argument is ignored and should be\n\
+set to the empty matrix.\n\
+\n\
+For two matrices (or a matrix and a scalar), return the pairwise maximum.\n\
+\n\
 Thus,\n\
 \n\
 @example\n\
@@ -512,7 +673,7 @@
 @end example\n\
 \n\
 @noindent\n\
-returns the largest element of the matrix @var{x}, and\n\
+returns the largest element of the 2-D matrix @var{x}, and\n\
 \n\
 @example\n\
 @group\n\
@@ -522,11 +683,23 @@
 @end example\n\
 \n\
 @noindent\n\
-compares each element of the range @code{2:5} with @code{pi}, and\n\
-returns a row vector of the maximum values.\n\
+compares each element of the range @code{2:5} with @code{pi}, and returns a\n\
+row vector of the maximum values.\n\
 \n\
 For complex arguments, the magnitude of the elements are used for\n\
-comparison.\n\
+comparison.  If the magnitudes are identical, then the results are ordered\n\
+by phase angle in the range (-pi, pi].  Hence,\n\
+\n\
+@example\n\
+@group\n\
+max ([-1 i 1 -i])\n\
+    @result{} -1\n\
+@end group\n\
+@end example\n\
+\n\
+@noindent\n\
+because all entries have magnitude 1, but -1 has the largest phase angle\n\
+with value pi.\n\
 \n\
 If called with one input and two output arguments,\n\
 @code{max} also returns the first index of the\n\
@@ -546,22 +719,157 @@
 }
 
 /*
+## Test generic double class
 %!assert (max ([1, 4, 2, 3]), 4)
 %!assert (max ([1; -10; 5; -2]), 5)
-%!assert (max ([4, i 4.999; -2, 2, 3+4i]), [4, 2, 3+4i])
+%!assert (max ([4, 2i 4.999; -2, 2, 3+4i]), [4, 2i, 3+4i])
+## Special routines for char arrays
+%!assert (max (["abc", "ABC"]), 99)
+%!assert (max (["abc"; "CBA"]), [97 98 99])
+## Special routines for logical arrays
+%!assert (max (logical ([])), logical ([]))
+%!assert (max (logical ([0 0 1 0])), true)
+%!assert (max (logical ([0 0 1 0; 0 1 0 0])), logical ([0 1 1 0]))
+## Single values
+%!assert (max (single ([1, 4, 2, 3])), single (4))
+%!assert (max (single ([1; -10; 5; -2])), single (5))
+%!assert (max (single ([4, 2i 4.999; -2, 2, 3+4i])), single ([4, 2i, 3+4i]))
+## Integer values
+%!assert (max (uint8 ([1, 4, 2, 3])), uint8 (4))
+%!assert (max (uint8 ([1; -10; 5; -2])), uint8 (5))
+%!assert (max (int8 ([1, 4, 2, 3])), int8 (4))
+%!assert (max (int8 ([1; -10; 5; -2])), int8 (5))
+%!assert (max (uint16 ([1, 4, 2, 3])), uint16 (4))
+%!assert (max (uint16 ([1; -10; 5; -2])), uint16 (5))
+%!assert (max (int16 ([1, 4, 2, 3])), int16 (4))
+%!assert (max (int16 ([1; -10; 5; -2])), int16 (5))
+%!assert (max (uint32 ([1, 4, 2, 3])), uint32 (4))
+%!assert (max (uint32 ([1; -10; 5; -2])), uint32 (5))
+%!assert (max (int32 ([1, 4, 2, 3])), int32 (4))
+%!assert (max (int32 ([1; -10; 5; -2])), int32 (5))
+%!assert (max (uint64 ([1, 4, 2, 3])), uint64 (4))
+%!assert (max (uint64 ([1; -10; 5; -2])), uint64 (5))
+%!assert (max (int64 ([1, 4, 2, 3])), int64 (4))
+%!assert (max (int64 ([1; -10; 5; -2])), int64 (5))
+## Sparse double values
+%!assert (max (sparse ([1, 4, 2, 3])), sparse (4))
+%!assert (max (sparse ([1; -10; 5; -2])), sparse(5))
+%!assert (max (sparse ([4, 2i 4.999; -2, 2, 3+4i])), sparse ([4, 2i, 3+4i]))
 
+## Test dimension argument
 %!test
 %! x = reshape (1:8, [2,2,2]);
 %! assert (min (x, [], 1), reshape ([1, 3, 5, 7], [1,2,2]));
 %! assert (min (x, [], 2), reshape ([1, 2, 5, 6], [2,1,2]));
 %! [y, i] = min (x, [], 3);
-%! assert (ndims(y), 2);
+%! assert (ndims (y), 2);
 %! assert (y, [1, 3; 2, 4]);
-%! assert (ndims(i), 2);
+%! assert (ndims (i), 2);
 %! assert (i, [1, 1; 1, 1]);
 
+## Test 2-output forms for various arg types
+## Special routines for char arrays
+%!test
+%! [y, i] = max (["abc", "ABC"]);
+%! assert (y, 99);
+%! assert (i, 3);
+## Special routines for logical arrays
+%!test
+%! x = logical ([0 0 1 0]);
+%! [y, i] = max (x);
+%! assert (y, true);
+%! assert (i, 3);
+## Special handling of ranges
+%!test
+%! rng = 1:2:10;
+%! [y, i] = max (rng);
+%! assert (y, 9);
+%! assert (i, 5);
+%! rng = 10:-2:1;
+%! [y, i] = max (rng);
+%! assert (y, 10);
+%! assert (i, 1);
+
+## Test 2-input calling form for various arg types
+## Test generic double class
+%!test
+%! x = [1, 2, 3, 4];  y = fliplr (x);
+%! assert (max (x, y), [4 3 3 4]);
+%! assert (max (x, 3), [3 3 3 4]);
+%! assert (max (2, x), [2 2 3 4]);
+%! assert (max (x, 2.1i), [2.1i 2.1i 3 4]);
+## FIXME: Ordering of complex results with equal magnitude is not by phase
+##        angle in the 2-input form.  Instead, it is in the order in which it
+##        appears in the argument list.
+%!xtest
+%! x = [1, 2, 3, 4];  y = fliplr (x);
+%! assert (max (x, 2i), [2i 2i 3 4]);
+## Special routines for char arrays
+%!assert (max ("abc", "b"), [98 98 99])
+%!assert (max ("b", "cba"), [99 98 98])
+## Special handling for logical arrays
+%!assert (max ([true false], false), [true false])
+%!assert (max (true, [false false]), [true true])
+## Single values
+%!test
+%! x = single ([1, 2, 3, 4]);  y = fliplr (x);
+%! assert (max (x, y), single ([4 3 3 4]));
+%! assert (max (x, 3), single ([3 3 3 4]));
+%! assert (max (2, x), single ([2 2 3 4]));
+%! assert (max (x, 2.1i), single ([2.1i 2.1i 3 4]));
+## Integer values
+%!test
+%! x = uint8 ([1, 2, 3, 4]);  y = fliplr (x);
+%! assert (max (x, y), uint8 ([4 3 3 4]));
+%! assert (max (x, 3), uint8 ([3 3 3 4]));
+%! assert (max (2, x), uint8 ([2 2 3 4]));
+%! x = int8 ([1, 2, 3, 4]);  y = fliplr (x);
+%! assert (max (x, y), int8 ([4 3 3 4]));
+%! assert (max (x, 3), int8 ([3 3 3 4]));
+%! assert (max (2, x), int8 ([2 2 3 4]));
+%! x = uint16 ([1, 2, 3, 4]);  y = fliplr (x);
+%! assert (max (x, y), uint16 ([4 3 3 4]));
+%! assert (max (x, 3), uint16 ([3 3 3 4]));
+%! assert (max (2, x), uint16 ([2 2 3 4]));
+%! x = int16 ([1, 2, 3, 4]);  y = fliplr (x);
+%! assert (max (x, y), int16 ([4 3 3 4]));
+%! assert (max (x, 3), int16 ([3 3 3 4]));
+%! assert (max (2, x), int16 ([2 2 3 4]));
+%! x = uint32 ([1, 2, 3, 4]);  y = fliplr (x);
+%! assert (max (x, y), uint32 ([4 3 3 4]));
+%! assert (max (x, 3), uint32 ([3 3 3 4]));
+%! assert (max (2, x), uint32 ([2 2 3 4]));
+%! x = int32 ([1, 2, 3, 4]);  y = fliplr (x);
+%! assert (max (x, y), int32 ([4 3 3 4]));
+%! assert (max (x, 3), int32 ([3 3 3 4]));
+%! assert (max (2, x), int32 ([2 2 3 4]));
+%! x = uint64 ([1, 2, 3, 4]);  y = fliplr (x);
+%! assert (max (x, y), uint64 ([4 3 3 4]));
+%! assert (max (x, 3), uint64 ([3 3 3 4]));
+%! assert (max (2, x), uint64 ([2 2 3 4]));
+%! x = int64 ([1, 2, 3, 4]);  y = fliplr (x);
+%! assert (max (x, y), int64 ([4 3 3 4]));
+%! assert (max (x, 3), int64 ([3 3 3 4]));
+%! assert (max (2, x), int64 ([2 2 3 4]));
+## Sparse double values
+%!test
+%! x = sparse ([1, 2, 3, 4]);  y = fliplr (x);
+%! assert (max (x, y), sparse ([4 3 3 4]));
+%! assert (max (x, 3), sparse ([3 3 3 4]));
+%! assert (max (2, x), sparse ([2 2 3 4]));
+%! assert (max (x, 2.1i), sparse ([2.1i 2.1i 3 4]));
+
+## 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)
+%!error <DIM must be a valid dimension> max ([1 2; 3 4], [], -3)
+%!warning <second argument is ignored> max ([1 2 3 4], 2, 2);
+%!error <wrong type argument 'cell'> max ({1 2 3 4})
+%!error <cannot compute max \(cell, scalar\)> max ({1, 2, 3}, 2)
+
 */
 
 template <class ArrayType>
--- a/libinterp/corefcn/md5sum.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/md5sum.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -31,10 +31,10 @@
 #include "defun.h"
 #include "file-stat.h"
 #include "file-ops.h"
-#include "gripes.h"
 #include "load-path.h"
 #include "oct-env.h"
 #include "oct-md5.h"
+#include "utils.h"
 
 DEFUN (md5sum, args, ,
        "-*- texinfo -*-\n\
@@ -64,22 +64,11 @@
             retval = oct_md5 (str);
           else
             {
-              file_stat fs (str);
-
-              if (! fs.exists ())
-                {
-                  std::string tmp
-                    = octave_env::make_absolute (load_path::find_file (str));
+              std::string fname = file_ops::tilde_expand (str);
 
-                  if (! tmp.empty ())
-                    {
-                      warning_with_id ("Octave:md5sum-file-in-path",
-                                       "md5sum: file found in load path");
-                      str = tmp;
-                    }
-                }
+              fname = find_data_file_in_load_path ("md5sum", fname);
 
-              retval = oct_md5_file (str);
+              retval = oct_md5_file (fname);
             }
         }
     }
@@ -91,11 +80,13 @@
 %!assert (md5sum ("abc\0", true), "147a664a2ca9410911e61986d3f0d52a");
 
 %!test
-%! tfile = tmpnam ();
+%! tfile = tempname ();
 %! fid = fopen (tfile, "wb");
 %! fwrite (fid, "abc\0");
 %! fclose (fid);
 %! assert (md5sum (tfile), "147a664a2ca9410911e61986d3f0d52a");
 %! unlink (tfile);
+
+%!error md5sum ();
 */
 
--- a/libinterp/corefcn/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -44,6 +44,7 @@
 COREFCN_INC = \
   corefcn/Cell.h \
   corefcn/c-file-ptr-stream.h \
+  corefcn/cdisplay.h \
   corefcn/comment-list.h \
   corefcn/cutils.h \
   corefcn/data.h \
@@ -90,6 +91,7 @@
   corefcn/oct-stream.h \
   corefcn/oct-strstrm.h \
   corefcn/oct.h \
+  corefcn/octave-default-image.h \
   corefcn/octave-link.h \
   corefcn/pager.h \
   corefcn/pr-output.h \
@@ -142,6 +144,7 @@
   corefcn/bitfcns.cc \
   corefcn/bsxfun.cc \
   corefcn/c-file-ptr-stream.cc \
+  corefcn/cdisplay.c \
   corefcn/cellfun.cc \
   corefcn/colloc.cc \
   corefcn/comment-list.cc \
@@ -240,7 +243,7 @@
   corefcn/strfns.cc \
   corefcn/sub2ind.cc \
   corefcn/svd.cc \
-  corefcn/syl.cc \
+  corefcn/sylvester.cc \
   corefcn/symtab.cc \
   corefcn/syscalls.cc \
   corefcn/sysdep.cc \
@@ -319,7 +322,7 @@
 	mv $@-t $@
 
 corefcn/oct-tex-symbols.cc: corefcn/oct-tex-symbols.in Makefile.am
-	$(AWK) 'BEGIN { print "// DO NOT EDIT. AUTOMATICALLY GENERATED FROM oct-tex-symbols.in."; print "static uint32_t symbol_codes[][2] = {"; count = 0; } END { print "};"; printf("static int num_symbol_codes = %d;\n", count); } /^#/ { } { if (NF == 3) { printf("  { %s, %s },\n", $$2, $$3); count++; } }' $< > $@-t
+	$(AWK) 'BEGIN { print "// DO NOT EDIT. AUTOMATICALLY GENERATED FROM oct-tex-symbols.in."; print "static uint32_t symbol_codes[][2] = {"; count = 0; } END { print "};"; printf("static int num_symbol_codes = %d;\n", count); } !/^#/ && (NF == 3) { printf("  { %s, %s },\n", $$2, $$3); count++; }' $< > $@-t
 	mv $@-t $@
 
 corefcn/txt-eng.cc: corefcn/oct-tex-symbols.cc
@@ -337,7 +340,9 @@
                                  $(FONTCONFIG_CPPFLAGS) \
                                  $(FT2_CPPFLAGS) \
                                  $(HDF5_CPPFLAGS) \
-                                 $(LLVM_CPPFLAGS)
+                                 $(LLVM_CPPFLAGS) \
+                                 $(Z_CPPFLAGS)
+
 corefcn_libcorefcn_la_CXXFLAGS = $(AM_CXXFLAGS) $(LLVM_CXXFLAGS)
 
 corefcn_libtex_parser_la_SOURCES = $(TEX_PARSER_SRC)
--- a/libinterp/corefcn/nproc.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/nproc.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -87,4 +87,23 @@
 /*
 ## Must always report at least 1 cpu available
 %!assert (nproc () >= 1);
+%!assert (nproc ("all") >= 1);
+%!assert (nproc ("current") >= 1);
+
+%!test
+%! c = nproc ("current");
+%! unwind_protect
+%!   old_val = getenv ("OMP_NUM_THREADS");
+%!   new_val = c + 1;
+%!   setenv ("OMP_NUM_THREADS", num2str (new_val));
+%!   assert (nproc ("overridable"), new_val);
+%! unwind_protect_cleanup
+%!   if (! isempty (old_val))
+%!     setenv ("OMP_NUM_THREADS", old_val);
+%!   else
+%!     unsetenv ("OMP_NUM_THREADS");
+%!   endif
+%! end_unwind_protect
+
+%!error nproc ("no_valid_option");
 */
--- a/libinterp/corefcn/oct-fstrm.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/oct-fstrm.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -77,7 +77,7 @@
   return -1;
 }
 
-// Return non-zero if EOF has been reached on this stream.
+// Return nonzero if EOF has been reached on this stream.
 
 bool
 octave_fstream::eof (void) const
--- a/libinterp/corefcn/oct-fstrm.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/oct-fstrm.h	Mon Jan 12 09:17:35 2015 -0800
@@ -52,7 +52,7 @@
 
   off_t tell (void);
 
-  // Return non-zero if EOF has been reached on this stream.
+  // Return nonzero if EOF has been reached on this stream.
 
   bool eof (void) const;
 
--- a/libinterp/corefcn/oct-hdf5.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/oct-hdf5.h	Mon Jan 12 09:17:35 2015 -0800
@@ -23,7 +23,7 @@
 #if !defined (octave_oct_hdf5_h)
 #define octave_hdf5_h 1
 
-#if defined (HAVE_HDF5)
+#if defined (HAVE_HDF5_H)
 #include <hdf5.h>
 #endif
 
--- a/libinterp/corefcn/oct-iostrm.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/oct-iostrm.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -45,7 +45,7 @@
   return -1;
 }
 
-// Return non-zero if EOF has been reached on this stream.
+// Return nonzero if EOF has been reached on this stream.
 
 bool
 octave_base_iostream::eof (void) const
@@ -60,7 +60,7 @@
   ::error ("%s: invalid operation", stream_type ());
 }
 
-// Return non-zero if EOF has been reached on this stream.
+// Return nonzero if EOF has been reached on this stream.
 
 bool
 octave_istream::eof (void) const
@@ -74,7 +74,7 @@
   return octave_stream (new octave_istream (arg, n));
 }
 
-// Return non-zero if EOF has been reached on this stream.
+// Return nonzero if EOF has been reached on this stream.
 
 bool
 octave_ostream::eof (void) const
--- a/libinterp/corefcn/oct-iostrm.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/oct-iostrm.h	Mon Jan 12 09:17:35 2015 -0800
@@ -46,7 +46,7 @@
 
   off_t tell (void);
 
-  // Return non-zero if EOF has been reached on this stream.
+  // Return nonzero if EOF has been reached on this stream.
 
   bool eof (void) const;
 
@@ -87,7 +87,7 @@
   static octave_stream
   create (std::istream *arg = 0, const std::string& n = std::string ());
 
-  // Return non-zero if EOF has been reached on this stream.
+  // Return nonzero if EOF has been reached on this stream.
 
   bool eof (void) const;
 
@@ -126,7 +126,7 @@
   static octave_stream
   create (std::ostream *arg, const std::string& n = std::string ());
 
-  // Return non-zero if EOF has been reached on this stream.
+  // Return nonzero if EOF has been reached on this stream.
 
   bool eof (void) const;
 
--- a/libinterp/corefcn/oct-map.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/oct-map.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -25,7 +25,9 @@
 #include <config.h>
 #endif
 
+#include "Array-util.h"
 #include "error.h"
+#include "oct-locbuf.h"
 #include "str-vec.h"
 
 #include "oct-map.h"
@@ -117,7 +119,8 @@
 {
   bool retval = true;
 
-  iterator p = begin (), q = other.begin ();
+  iterator p = begin ();
+  iterator q = other.begin ();
   for (; p != end () && q != other.end (); p++, q++)
     {
       if (p->first == q->first)
@@ -251,15 +254,6 @@
     }
 }
 
-octave_map::octave_map (const Octave_map& m)
-  : xkeys (m.keys ()), xvals (m.nfields ()), dimensions (m.dims ())
-{
-  for (iterator p = begin (); p != end (); p++)
-    contents(p) = m.contents (key (p));
-
-  optimize_dimensions ();
-}
-
 Cell
 octave_map::getfield (const std::string& k) const
 {
@@ -819,9 +813,9 @@
 %! sr = [s,s];
 %! sc = [s;s];
 %! sm = [s,s;s,s];
-%! assert (nfields (sr), 0);
-%! assert (nfields (sc), 0);
-%! assert (nfields (sm), 0);
+%! assert (numfields (sr), 0);
+%! assert (numfields (sc), 0);
+%! assert (numfields (sm), 0);
 %! assert (size (sr), [1, 2]);
 %! assert (size (sc), [2, 1]);
 %! assert (size (sm), [2, 2]);
@@ -1314,470 +1308,3 @@
 
 }
 
-Octave_map::Octave_map (const dim_vector& dv, const Cell& key_vals)
-  : map (), key_list (), dimensions (dv)
-{
-  Cell c (dv);
-
-  if (key_vals.is_cellstr ())
-    {
-      for (octave_idx_type i = 0; i < key_vals.numel (); i++)
-        {
-          std::string k = key_vals(i).string_value ();
-          map[k] = c;
-          key_list.push_back (k);
-        }
-    }
-  else
-    error ("Octave_map: expecting keys to be cellstr");
-}
-
-Octave_map::Octave_map (const octave_map& m)
-  : map (), key_list (), dimensions (m.dims ())
-{
-  for (octave_map::const_iterator p = m.begin (); p != m.end (); p++)
-    map[m.key (p)] = m.contents (p);
-  const string_vector mkeys = m.fieldnames ();
-  for (octave_idx_type i = 0; i < mkeys.numel (); i++)
-    key_list.push_back (mkeys(i));
-}
-
-Octave_map
-Octave_map::squeeze (void) const
-{
-  Octave_map retval (dims ().squeeze ());
-
-  for (const_iterator pa = begin (); pa != end (); pa++)
-    {
-      Cell tmp = contents (pa).squeeze ();
-
-      if (error_state)
-        break;
-
-      retval.assign (key (pa), tmp);
-    }
-
-  // Preserve order of keys.
-  retval.key_list = key_list;
-
-  return retval;
-}
-
-Octave_map
-Octave_map::permute (const Array<int>& vec, bool inv) const
-{
-  Octave_map retval (dims ());
-
-  for (const_iterator pa = begin (); pa != end (); pa++)
-    {
-      Cell tmp = contents (pa).permute (vec, inv);
-
-      if (error_state)
-        break;
-
-      retval.assign (key (pa), tmp);
-    }
-
-  // Preserve order of keys.
-  retval.key_list = key_list;
-
-  return retval;
-}
-
-Cell&
-Octave_map::contents (const std::string& k)
-{
-  maybe_add_to_key_list (k);
-
-  return map[k];
-}
-
-Cell
-Octave_map::contents (const std::string& k) const
-{
-  const_iterator p = seek (k);
-
-  return p != end () ? p->second : Cell ();
-}
-
-int
-Octave_map::intfield (const std::string& k, int def_val) const
-{
-  int retval = def_val;
-
-  Cell c = contents (k);
-
-  if (! c.is_empty ())
-    retval = c(0).int_value ();
-
-  return retval;
-}
-
-std::string
-Octave_map::stringfield (const std::string& k,
-                         const std::string& def_val) const
-{
-  std::string retval = def_val;
-
-  Cell c = contents (k);
-
-  if (! c.is_empty ())
-    retval = c(0).string_value ();
-
-  return retval;
-}
-
-string_vector
-Octave_map::keys (void) const
-{
-  assert (static_cast<size_t>(nfields ()) == key_list.size ());
-
-  return string_vector (key_list);
-}
-
-Octave_map
-Octave_map::transpose (void) const
-{
-  assert (ndims () == 2);
-
-  dim_vector dv = dims ();
-
-  octave_idx_type nr = dv(0);
-  octave_idx_type nc = dv(1);
-
-  dim_vector new_dims (nc, nr);
-
-  Octave_map retval (new_dims);
-
-  for (const_iterator p = begin (); p != end (); p++)
-    retval.assign (key(p), Cell (contents(p).transpose ()));
-
-  // Preserve order of keys.
-  retval.key_list = key_list;
-
-  return retval;
-}
-
-Octave_map
-Octave_map::reshape (const dim_vector& new_dims) const
-{
-  Octave_map retval;
-
-  if (new_dims != dims ())
-    {
-      for (const_iterator p = begin (); p != end (); p++)
-        retval.assign (key(p), contents(p).reshape (new_dims));
-
-      retval.dimensions = new_dims;
-
-      // Preserve order of keys.
-      retval.key_list = key_list;
-    }
-  else
-    retval = *this;
-
-  return retval;
-}
-
-void
-Octave_map::resize (const dim_vector& dv, bool fill)
-{
-  if (dv != dims ())
-    {
-      if (nfields () == 0)
-        dimensions = dv;
-      else
-        {
-          for (const_iterator p = begin (); p != end (); p++)
-            {
-              Cell tmp = contents(p);
-
-              if (fill)
-                tmp.resize (dv, Matrix ());
-              else
-                tmp.resize (dv);
-
-              dimensions = dv;
-
-              assign (key(p), tmp);
-            }
-        }
-    }
-}
-
-Octave_map
-Octave_map::concat (const Octave_map& rb, const Array<octave_idx_type>& ra_idx)
-{
-  Octave_map retval;
-
-  if (nfields () == rb.nfields ())
-    {
-      for (const_iterator pa = begin (); pa != end (); pa++)
-        {
-          const_iterator pb = rb.seek (key(pa));
-
-          if (pb == rb.end ())
-            {
-              error ("field name mismatch in structure concatenation");
-              break;
-            }
-
-          retval.assign (key(pa),
-                         contents(pa).insert (rb.contents(pb), ra_idx));
-        }
-
-      // Preserve order of keys.
-      retval.key_list = key_list;
-    }
-  else
-    {
-      dim_vector dv = dims ();
-
-      if (dv.all_zero ())
-        retval = rb;
-      else
-        {
-          dv = rb.dims ();
-
-          if (dv.all_zero ())
-            retval = *this;
-          else
-            error ("invalid structure concatenation");
-        }
-    }
-
-  return retval;
-}
-
-static bool
-keys_ok (const Octave_map& a, const Octave_map& b, string_vector& keys)
-{
-  bool retval = false;
-
-  keys = string_vector ();
-
-  if (a.nfields () == 0)
-    {
-      keys = b.keys ();
-      retval = true;
-    }
-  else
-    {
-      string_vector a_keys = a.keys ().sort ();
-      string_vector b_keys = b.keys ().sort ();
-
-      octave_idx_type a_len = a_keys.length ();
-      octave_idx_type b_len = b_keys.length ();
-
-      if (a_len == b_len)
-        {
-          for (octave_idx_type i = 0; i < a_len; i++)
-            {
-              if (a_keys[i] != b_keys[i])
-                goto done;
-            }
-
-          keys = a_keys;
-          retval = true;
-        }
-    }
-
-done:
-  return retval;
-}
-
-Octave_map&
-Octave_map::maybe_delete_elements (const octave_value_list& idx)
-{
-  string_vector t_keys = keys ();
-  octave_idx_type len = t_keys.length ();
-
-  if (len > 0)
-    {
-      for (octave_idx_type i = 0; i < len; i++)
-        {
-          std::string k = t_keys[i];
-
-          contents(k).delete_elements (idx);
-
-          if (error_state)
-            break;
-        }
-
-      if (!error_state)
-        dimensions = contents(t_keys[0]).dims ();
-    }
-
-  return *this;
-}
-
-Octave_map&
-Octave_map::assign (const octave_value_list& idx, const Octave_map& rhs)
-{
-  string_vector t_keys;
-
-  if (keys_ok (*this, rhs, t_keys))
-    {
-      octave_idx_type len = t_keys.length ();
-
-      if (len == 0)
-        {
-          Cell tmp_lhs (dims ());
-          Cell tmp_rhs (rhs.dims ());
-
-          tmp_lhs.assign (idx, tmp_rhs, Matrix ());
-
-          if (! error_state)
-            resize (tmp_lhs.dims ());
-          else
-            error ("size mismatch in structure assignment");
-        }
-      else
-        {
-          for (octave_idx_type i = 0; i < len; i++)
-            {
-              std::string k = t_keys[i];
-
-              Cell t_rhs = rhs.contents (k);
-
-              assign (idx, k, t_rhs);
-
-              if (error_state)
-                break;
-            }
-        }
-    }
-  else
-    error ("field name mismatch in structure assignment");
-
-  return *this;
-}
-
-Octave_map&
-Octave_map::assign (const octave_value_list& idx, const std::string& k,
-                    const Cell& rhs)
-{
-  Cell tmp;
-
-  if (contains (k))
-    tmp = map[k];
-  else
-    tmp = Cell (dimensions);
-
-  tmp.assign (idx, rhs);
-
-  if (! error_state)
-    {
-      dim_vector tmp_dims = tmp.dims ();
-
-      if (tmp_dims != dimensions)
-        {
-          for (iterator p = begin (); p != end (); p++)
-            contents(p).resize (tmp_dims, Matrix ());
-
-          dimensions = tmp_dims;
-        }
-
-      maybe_add_to_key_list (k);
-
-      map[k] = tmp;
-    }
-
-  return *this;
-}
-
-Octave_map&
-Octave_map::assign (const std::string& k, const octave_value& rhs)
-{
-  if (nfields () == 0)
-    {
-      maybe_add_to_key_list (k);
-
-      map[k] = Cell (rhs);
-
-      dimensions = dim_vector (1, 1);
-    }
-  else
-    {
-      dim_vector dv = dims ();
-
-      if (dv.all_ones ())
-        {
-          maybe_add_to_key_list (k);
-
-          map[k] = Cell (rhs);
-        }
-      else
-        error ("invalid structure assignment");
-    }
-
-  return *this;
-}
-
-Octave_map&
-Octave_map::assign (const std::string& k, const Cell& rhs)
-{
-  if (nfields () == 0)
-    {
-      maybe_add_to_key_list (k);
-
-      map[k] = rhs;
-
-      dimensions = rhs.dims ();
-    }
-  else
-    {
-      if (dims () == rhs.dims ())
-        {
-          maybe_add_to_key_list (k);
-
-          map[k] = rhs;
-        }
-      else
-        error ("invalid structure assignment");
-    }
-
-  return *this;
-}
-
-Octave_map
-Octave_map::index (const octave_value_list& idx, bool resize_ok) const
-{
-  Octave_map retval;
-
-  octave_idx_type n_idx = idx.length ();
-
-  if (n_idx > 0)
-    {
-      Array<idx_vector> ra_idx (dim_vector (n_idx, 1));
-
-      for (octave_idx_type i = 0; i < n_idx; i++)
-        {
-          ra_idx(i) = idx(i).index_vector ();
-          if (error_state)
-            break;
-        }
-
-      if (! error_state)
-        {
-          for (const_iterator p = begin (); p != end (); p++)
-            {
-              Cell tmp = contents (p);
-
-              tmp = tmp.Array<octave_value>::index (ra_idx, resize_ok);
-
-              if (error_state)
-                break;
-
-              retval.assign (key(p), tmp);
-            }
-
-          // Preserve order of keys.
-          retval.key_list = key_list;
-        }
-    }
-  else
-    retval = *this;
-
-  return retval;
-}
--- a/libinterp/corefcn/oct-map.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/oct-map.h	Mon Jan 12 09:17:35 2015 -0800
@@ -287,8 +287,6 @@
 
   octave_map (const octave_scalar_map& m);
 
-  octave_map (const Octave_map& m);
-
   octave_map& operator = (const octave_map& m)
   {
     xkeys = m.xkeys;
@@ -475,189 +473,4 @@
 inline octave_map octave_value_extract<octave_map> (const octave_value& v)
 { return v.map_value (); }
 
-// The original Octave_map object which is now deprecated.
-// It was fully deprecated in version 3.8 and should be removed in 3.12.
-// Octave_map and octave_map are convertible to each other.
-
-class
-OCTINTERP_API
-Octave_map
-{
-public:
-
-  typedef std::map<std::string, Cell>::iterator iterator;
-  typedef std::map<std::string, Cell>::const_iterator const_iterator;
-
-  typedef std::list<std::string>::iterator key_list_iterator;
-  typedef std::list<std::string>::const_iterator const_key_list_iterator;
-
-  // Warning!  You should always use at least two dimensions.
-
-  Octave_map (const dim_vector& dv = dim_vector (0, 0),
-              const Cell& key_vals = Cell ());
-
-  Octave_map (const std::string& k, const octave_value& value)
-    : map (), key_list (), dimensions (1, 1)
-  {
-    map[k] = value;
-    key_list.push_back (k);
-  }
-
-  Octave_map (const string_vector& sv,
-              const dim_vector& dv = dim_vector (0, 0))
-    : map (), key_list (), dimensions (dv)
-  {
-    for (octave_idx_type i = 0; i < sv.length (); i++)
-      {
-        std::string k = sv[i];
-        map[k] = Cell (dv);
-        key_list.push_back (k);
-      }
-  }
-
-  Octave_map (const std::string& k, const Cell& vals)
-    : map (), key_list (), dimensions (vals.dims ())
-  {
-    map[k] = vals;
-    key_list.push_back (k);
-  }
-
-  Octave_map (const std::string& k, const octave_value_list& val_list)
-    : map (), key_list (), dimensions (1, val_list.length ())
-  {
-    map[k] = val_list;
-    key_list.push_back (k);
-  }
-
-  Octave_map (const Octave_map& m)
-    : map (m.map), key_list (m.key_list), dimensions (m.dimensions) { }
-
-  Octave_map (const octave_map& m);
-
-  Octave_map& operator = (const Octave_map& m)
-  {
-    if (this != &m)
-      {
-        map = m.map;
-        key_list = m.key_list;
-        dimensions = m.dimensions;
-      }
-
-    return *this;
-  }
-
-  ~Octave_map (void) { }
-
-  Octave_map squeeze (void) const;
-
-  Octave_map permute (const Array<int>& vec, bool inv = false) const;
-
-  // This is the number of keys.
-  octave_idx_type nfields (void) const { return map.size (); }
-
-  void del (const std::string& k)
-  {
-    iterator p = map.find (k);
-
-    if (p != map.end ())
-      {
-        map.erase (p);
-
-        key_list_iterator q
-          = std::find (key_list.begin (), key_list.end (), k);
-
-        assert (q != key_list.end ());
-
-        key_list.erase (q);
-      }
-  }
-
-  iterator begin (void) { return iterator (map.begin ()); }
-  const_iterator begin (void) const { return const_iterator (map.begin ()); }
-
-  iterator end (void) { return iterator (map.end ()); }
-  const_iterator end (void) const { return const_iterator (map.end ()); }
-
-  std::string key (const_iterator p) const { return p->first; }
-
-  Cell& contents (const std::string& k);
-  Cell contents (const std::string& k) const;
-
-  Cell& contents (iterator p)
-  { return p->second; }
-
-  Cell contents (const_iterator p) const
-  { return p->second; }
-
-  int intfield (const std::string& k, int def_val = 0) const;
-
-  std::string stringfield (const std::string& k,
-                           const std::string& def_val = std::string ()) const;
-
-  iterator seek (const std::string& k) { return map.find (k); }
-  const_iterator seek (const std::string& k) const { return map.find (k); }
-
-  bool contains (const std::string& k) const
-  { return (seek (k) != map.end ()); }
-
-  void clear (void)
-  {
-    map.clear ();
-    key_list.clear ();
-  }
-
-  string_vector keys (void) const;
-
-  octave_idx_type rows (void) const { return dimensions(0); }
-
-  octave_idx_type columns (void) const { return dimensions(1); }
-
-  dim_vector dims (void) const { return dimensions; }
-
-  int ndims (void) const { return dimensions.length (); }
-
-  Octave_map transpose (void) const;
-
-  Octave_map reshape (const dim_vector& new_dims) const;
-
-  void resize (const dim_vector& dv, bool fill = false);
-
-  octave_idx_type numel (void) const { return dimensions.numel (); }
-
-  Octave_map concat (const Octave_map& rb,
-                     const Array<octave_idx_type>& ra_idx);
-
-  Octave_map& maybe_delete_elements (const octave_value_list& idx);
-
-  Octave_map& assign (const octave_value_list& idx, const Octave_map& rhs);
-
-  Octave_map& assign (const octave_value_list& idx, const std::string& k,
-                      const Cell& rhs);
-
-  Octave_map& assign (const std::string& k, const octave_value& rhs);
-
-  Octave_map& assign (const std::string& k, const Cell& rhs);
-
-  Octave_map index (const octave_value_list& idx,
-                    bool resize_ok = false) const;
-
-private:
-
-  // The map of names to values.
-  std::map<std::string, Cell> map;
-
-  // An extra list of keys, so we can keep track of the order the keys
-  // are added for compatibility with you know what.
-  std::list<std::string> key_list;
-
-  // The current size.
-  mutable dim_vector dimensions;
-
-  void maybe_add_to_key_list (const std::string& k)
-  {
-    if (! contains (k))
-      key_list.push_back (k);
-  }
-} GCC_ATTR_DEPRECATED;
-
 #endif
--- a/libinterp/corefcn/oct-obj.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/oct-obj.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -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 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/oct-obj.h	Mon Jan 12 09:17:35 2015 -0800
@@ -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-stdstrm.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/oct-stdstrm.h	Mon Jan 12 09:17:35 2015 -0800
@@ -50,7 +50,7 @@
 
   off_t tell (void) { return s ? s->tell () : -1; }
 
-  // Return non-zero if EOF has been reached on this stream.
+  // Return nonzero if EOF has been reached on this stream.
 
   bool eof (void) const { return s ? s->eof () : true; }
 
--- a/libinterp/corefcn/oct-stream.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/oct-stream.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -34,12 +34,12 @@
 #include <sstream>
 #include <string>
 
-#include <Array.h>
-
+#include "Array.h"
 #include "byte-swap.h"
 #include "lo-ieee.h"
 #include "lo-mappers.h"
 #include "lo-utils.h"
+#include "oct-locbuf.h"
 #include "quit.h"
 #include "singleton-cleanup.h"
 #include "str-vec.h"
@@ -785,11 +785,14 @@
 
   if (i < n)
     {
+      // Accept and record modifier, but don't place it in the format
+      // item text.  All integer conversions are handled as 64-bit
+      // integers.
+
       switch (s[i])
         {
         case 'h': case 'l': case 'L':
-          modifier = s[i];
-          *buf << s[i++];
+          modifier = s[i++];
           break;
 
         default:
@@ -1053,7 +1056,8 @@
     {
       std::istream& is = *isp;
 
-      int c = 0, lastc = -1;
+      int c = 0;
+      int lastc = -1;
       cnt = 0;
 
       while (is && (c = is.get ()) != EOF)
@@ -2159,7 +2163,7 @@
 
   printf_value_cache (const octave_value_list& args, const std::string& who)
     : values (args), val_idx (0), elt_idx (0),
-      n_vals (values.length ()), n_elts (0), data (0),
+      n_vals (values.length ()), n_elts (0), have_data (false),
       curr_state (ok)
   {
     for (octave_idx_type i = 0; i < values.length (); i++)
@@ -2177,7 +2181,7 @@
   ~printf_value_cache (void) { }
 
   // Get the current value as a double and advance the internal pointer.
-  double double_value (void);
+  octave_value get_next_value (void);
 
   // Get the current value as an int and advance the internal pointer.
   int int_value (void);
@@ -2196,8 +2200,8 @@
   int elt_idx;
   int n_vals;
   int n_elts;
-  const double *data;
-  NDArray curr_val;
+  bool have_data;
+  octave_value curr_val;
   state curr_state;
 
   // Must create value cache with values!
@@ -2211,29 +2215,27 @@
   printf_value_cache& operator = (const printf_value_cache&);
 };
 
-double
-printf_value_cache::double_value (void)
+octave_value
+printf_value_cache::get_next_value (void)
 {
-  double retval = 0.0;
+  octave_value retval;
 
   if (exhausted ())
     curr_state = conversion_error;
 
   while (! exhausted ())
     {
-      if (! data)
+      if (! have_data)
         {
-          octave_value tmp_val = values (val_idx);
+          curr_val = values (val_idx);
 
           // Force string conversion here for compatibility.
 
-          curr_val = tmp_val.array_value (true);
-
           if (! error_state)
             {
               elt_idx = 0;
-              n_elts = curr_val.length ();
-              data = curr_val.data ();
+              n_elts = curr_val.numel ();
+              have_data = true;
             }
           else
             {
@@ -2244,13 +2246,13 @@
 
       if (elt_idx < n_elts)
         {
-          retval = data[elt_idx++];
+          retval = curr_val.fast_elem_extract (elt_idx++);
 
           if (elt_idx >= n_elts)
             {
               elt_idx = 0;
               val_idx++;
-              data = 0;
+              have_data = false;
             }
 
           break;
@@ -2258,7 +2260,7 @@
       else
         {
           val_idx++;
-          data = 0;
+          have_data = false;
 
           if (n_elts == 0 && exhausted ())
             curr_state = conversion_error;
@@ -2275,14 +2277,19 @@
 {
   int retval = 0;
 
-  double dval = double_value ();
+  octave_value val = get_next_value ();
 
   if (! error_state)
     {
-      if (D_NINT (dval) == dval)
-        retval = NINT (dval);
-      else
-        curr_state = conversion_error;
+      double dval = val.double_value ();
+
+      if (! error_state)
+        {
+          if (D_NINT (dval) == dval)
+            retval = NINT (dval);
+          else
+            curr_state = conversion_error;
+        }
     }
 
   return retval;
@@ -2357,27 +2364,202 @@
   return retval;
 }
 
-#define DO_DOUBLE_CONV(TQUAL) \
-  do \
-    { \
-      if (val > std::numeric_limits<TQUAL long>::max () \
-          || val < std::numeric_limits<TQUAL long>::min ()) \
-        { \
-          std::string tfmt = fmt; \
- \
-          tfmt.replace (tfmt.rfind (elt->type), 1, ".f"); \
- \
-          if (elt->modifier == 'l') \
-            tfmt.replace (tfmt.rfind (elt->modifier), 1, ""); \
- \
-          retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2, \
-                                    val, who); \
-        } \
-      else \
-        retval += do_printf_conv (os, fmt, nsa, sa_1, sa_2, \
-                                  static_cast<TQUAL long> (val), who); \
-    } \
-  while (0)
+static bool
+is_nan_or_inf (const octave_value& val)
+{
+  octave_value ov_isnan = val.isnan ();
+  octave_value ov_isinf = val.isinf ();
+
+  return (ov_isnan.is_true () || ov_isinf.is_true ());
+}
+
+static bool
+ok_for_signed_int_conv (const octave_value& val)
+{
+  uint64_t limit = std::numeric_limits<int64_t>::max ();
+
+  if (val.is_integer_type ())
+    {
+      if (val.is_uint64_type ())
+        {
+          octave_uint64 ival = val.uint64_scalar_value ();
+
+          if (ival.value () <= limit)
+            return true;
+        }
+      else
+        return true;
+    }
+  else
+    {
+      double dval = val.double_value ();
+
+      if (dval == xround (dval) && dval <= limit)
+        return true;
+    }
+
+  return false;
+}
+
+static bool
+ok_for_unsigned_int_conv (const octave_value& val)
+{
+  if (val.is_integer_type ())
+    {
+      // Easier than dispatching here...
+
+      octave_value ov_is_ge_zero
+        = do_binary_op (octave_value::op_ge, val, octave_value (0.0));
+
+      return ov_is_ge_zero.is_true ();
+    }
+  else
+    {
+      double dval = val.double_value ();
+
+      uint64_t limit = std::numeric_limits<uint64_t>::max ();
+
+      if (dval == xround (dval) && dval >= 0 && dval <= limit)
+        return true;
+    }
+
+  return false;
+}
+
+static std::string
+switch_to_g_format (const printf_format_elt *elt)
+{
+  std::string tfmt = elt->text;
+
+  tfmt.replace (tfmt.rfind (elt->type), 1, "g");
+
+  return tfmt;
+}
+
+int
+octave_base_stream::do_numeric_printf_conv (std::ostream& os,
+                                            const printf_format_elt *elt,
+                                            int nsa, int sa_1, int sa_2,
+                                            const octave_value& val,
+                                            const std::string& who)
+{
+  int retval = 0;
+
+  const char *fmt = elt->text;
+
+  if (is_nan_or_inf (val))
+    {
+      double dval = val.double_value ();
+
+      std::string tfmt = fmt;
+      std::string::size_type i1, i2;
+
+      tfmt.replace ((i1 = tfmt.rfind (elt->type)),
+                   1, 1, 's');
+
+      if ((i2 = tfmt.rfind ('.')) != std::string::npos
+          && i2 < i1)
+        {
+          tfmt.erase (i2, i1-i2);
+          if (elt->prec < 0)
+            nsa--;
+        }
+
+      const char *tval;
+      if (lo_ieee_isinf (dval))
+        {
+          if (elt->flags.find ('+') != std::string::npos)
+            tval = (dval < 0 ? "-Inf" : "+Inf");
+          else
+            tval = (dval < 0 ? "-Inf" : "Inf");
+        }
+      else
+        {
+          if (elt->flags.find ('+') != std::string::npos)
+            tval = (lo_ieee_is_NA (dval) ? "+NA" : "+NaN");
+          else
+            tval = (lo_ieee_is_NA (dval) ? "NA" : "NaN");
+        }
+
+      retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2, tval, who);
+    }
+  else
+    {
+      static std::string llmod
+        = sizeof (long) == sizeof (int64_t) ? "l" : "ll";
+
+      char type = elt->type;
+
+      switch (type)
+        {
+        case 'd': case 'i': case 'c':
+          if (ok_for_signed_int_conv (val))
+            {
+              octave_int64 tval = val.int64_scalar_value ();
+
+              // Insert "long" modifier.
+              std::string tfmt = fmt;
+              tfmt.replace (tfmt.rfind (type), 1, llmod + type);
+
+              retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2,
+                                        tval.value (), who);
+            }
+          else
+            {
+              std::string tfmt = switch_to_g_format (elt);
+
+              double dval = val.double_value ();
+
+              if (! error_state)
+                retval += do_printf_conv (os, tfmt.c_str (), nsa,
+                                          sa_1, sa_2, dval, who);
+            }
+          break;
+
+        case 'o': case 'x': case 'X': case 'u':
+          if (ok_for_unsigned_int_conv (val))
+            {
+              octave_uint64 tval = val.uint64_scalar_value ();
+
+              // Insert "long" modifier.
+              std::string tfmt = fmt;
+              tfmt.replace (tfmt.rfind (type), 1, llmod + type);
+
+              retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2,
+                                        tval.value (), who);
+            }
+          else
+            {
+              std::string tfmt = switch_to_g_format (elt);
+
+              double dval = val.double_value ();
+
+              if (! error_state)
+                retval += do_printf_conv (os, tfmt.c_str (), nsa,
+                                          sa_1, sa_2, dval, who);
+            }
+          break;
+
+        case 'f': case 'e': case 'E':
+        case 'g': case 'G':
+          {
+            double dval = val.double_value ();
+
+            if (! error_state)
+              retval += do_printf_conv (os, fmt, nsa, sa_1, sa_2, dval, who);
+          }
+          break;
+
+        default:
+          error ("%s: invalid format specifier",
+                 who.c_str ());
+          return -1;
+          break;
+        }
+    }
+
+  return retval;
+}
 
 int
 octave_base_stream::do_printf (printf_format_list& fmt_list,
@@ -2432,8 +2614,6 @@
                     }
                 }
 
-              const char *fmt = elt->text;
-
               if (elt->type == '%')
                 {
                   os << "%";
@@ -2449,77 +2629,18 @@
                   std::string val = val_cache.string_value ();
 
                   if (val_cache)
-                    retval += do_printf_conv (os, fmt, nsa, sa_1,
+                    retval += do_printf_conv (os, elt->text, nsa, sa_1,
                                               sa_2, val.c_str (), who);
                   else
                     break;
                 }
               else
                 {
-                  double val = val_cache.double_value ();
+                  octave_value val = val_cache.get_next_value ();
 
                   if (val_cache)
-                    {
-                      if (lo_ieee_isnan (val) || xisinf (val))
-                        {
-                          std::string tfmt = fmt;
-                          std::string::size_type i1, i2;
-
-                          tfmt.replace ((i1 = tfmt.rfind (elt->type)),
-                                        1, 1, 's');
-
-                          if ((i2 = tfmt.rfind ('.')) != std::string::npos
-                              && i2 < i1)
-                            {
-                              tfmt.erase (i2, i1-i2);
-                              if (elt->prec < 0)
-                                nsa--;
-                            }
-
-                          const char *tval;
-                          if (xisinf (val))
-                            if (elt->flags.find ('+') != std::string::npos)
-                              tval = (val < 0 ? "-Inf" : "+Inf");
-                            else
-                              tval = (val < 0 ? "-Inf" : "Inf");
-                          else
-                            if (elt->flags.find ('+') != std::string::npos)
-                              tval = (lo_ieee_is_NA (val) ? "+NA" : "+NaN");
-                            else
-                              tval = (lo_ieee_is_NA (val) ? "NA" : "NaN");
-
-                          retval += do_printf_conv (os, tfmt.c_str (),
-                                                    nsa, sa_1, sa_2,
-                                                    tval, who);
-                        }
-                      else
-                        {
-                          char type = elt->type;
-
-                          switch (type)
-                            {
-                            case 'd': case 'i': case 'c':
-                              DO_DOUBLE_CONV (OCTAVE_EMPTY_CPP_ARG);
-                              break;
-
-                            case 'o': case 'x': case 'X': case 'u':
-                              DO_DOUBLE_CONV (unsigned);
-                              break;
-
-                            case 'f': case 'e': case 'E':
-                            case 'g': case 'G':
-                              retval += do_printf_conv (os, fmt, nsa,
-                                                        sa_1, sa_2, val, who);
-                              break;
-
-                            default:
-                              error ("%s: invalid format specifier",
-                                     who.c_str ());
-                              return -1;
-                              break;
-                            }
-                        }
-                    }
+                    retval += do_numeric_printf_conv (os, elt, nsa, sa_1,
+                                                      sa_2, val, who);
                   else
                     break;
                 }
@@ -3191,8 +3312,7 @@
       if (! error_state)
         {
 
-          octave_idx_type elts_to_read
-            = std::numeric_limits<octave_idx_type>::max ();
+          octave_idx_type elts_to_read;
 
           if (one_elt_size_spec)
             {
@@ -3221,7 +3341,9 @@
                 nr = nc = 0;
             }
 
-          // FIXME: ensure that this does not overflow.
+          // FIXME: Ensure that this does not overflow.
+          //        Maybe try comparing nr * nc computed in double with
+          //        std::numeric_limits<octave_idx_type>::max ();
 
           elts_to_read = nr * nc;
 
@@ -4248,6 +4370,8 @@
       buf << "  "
           << std::setiosflags (std::ios::right)
           << std::setw (4) << p->first << "     "
+          // reset necessary in addition to setiosflags since this is one stmt.
+          << std::resetiosflags (std::ios::adjustfield)
           << std::setiosflags (std::ios::left)
           << std::setw (3)
           << octave_stream::mode_as_string (os.mode ())
--- a/libinterp/corefcn/oct-stream.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/oct-stream.h	Mon Jan 12 09:17:35 2015 -0800
@@ -38,7 +38,6 @@
 #include "data-conv.h"
 #include "lo-utils.h"
 #include "mach-info.h"
-#include "oct-locbuf.h"
 #include "oct-refcount.h"
 
 class
@@ -479,6 +478,11 @@
 
   int flush (void);
 
+  int do_numeric_printf_conv (std::ostream& os, const printf_format_elt *elt,
+                              int nsa, int sa_1, int sa_2,
+                              const octave_value& val,
+                              const std::string& who);
+
   int do_printf (printf_format_list& fmt_list, const octave_value_list& args,
                  const std::string& who /* = "printf" */);
 
--- a/libinterp/corefcn/oct-strstrm.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/oct-strstrm.h	Mon Jan 12 09:17:35 2015 -0800
@@ -96,7 +96,7 @@
           oct_mach_info::float_format ff
             = oct_mach_info::native_float_format ());
 
-  // Return non-zero if EOF has been reached on this stream.
+  // Return nonzero if EOF has been reached on this stream.
 
   bool eof (void) const { return is.eof (); }
 
@@ -142,7 +142,7 @@
           oct_mach_info::float_format ff
             = oct_mach_info::native_float_format ());
 
-  // Return non-zero if EOF has been reached on this stream.
+  // Return nonzero if EOF has been reached on this stream.
 
   bool eof (void) const { return os.eof (); }
 
--- a/libinterp/corefcn/oct-tex-symbols.in	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/oct-tex-symbols.in	Mon Jan 12 09:17:35 2015 -0800
@@ -1,12 +1,14 @@
 # List of supported symbols for the TeX interpreter
-# (http://www.mathworks.com/help/matlab/ref/text_props.html):
-# - symbol name
-# - Unicode code
-# - MS symbol code (http://www.kostis.net/charsets/symbol.htm)
-# - Arranged by listings in The TeXbook, Appendix F 
-# - Lowercase Greek letters: Greek Upper case: Misc Symbols type Ord: "Large" operators:
-# - Binary operators: Relations: Negated relations: Arrows: Openings: Closings: Alternate names:
-# - Other (not in Appendix F Tables):
+# Reference: http://www.mathworks.com/help/matlab/ref/text_props.html
+#
+# Column 1 : symbol name
+# Column 2 : Unicode code
+# Column 3 : MS symbol code (http://www.kostis.net/charsets/symbol.htm)
+#
+# Arranged by listings in The TeXbook, Appendix F:
+# Greek lower case letters, Greek upper case, Misc Symbols type Ord,
+# "Large" operators, Binary operators, Relations, Negated relations, Arrows,
+# Openings, Closings, Alternate names, and Other (not in Appendix F Tables).
 
 alpha           0x03B1  0xF061
 beta            0x03B2  0xF062
@@ -108,6 +110,6 @@
 rceil           0x2309  0xF0F9
 neq             0x2260  0xF0B9
 ldots           0x2026  0xF0BC
-0               0x2298  0xF0C6
+0               0x2205  0xF0C6
 copyright       0x00A9  0xF0E3
 deg             0x00B0  0xF0B0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/corefcn/octave-default-image.h	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,281 @@
+/*
+
+Copyright (C) 2014 Pantxo Diribarne
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+static char default_im_data[] = {
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,20,20,20,20,20,20,21,21,21,21,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,20,20,20,20,20,20,20,20,20,20,20,21,21,
+  21,21,21,21,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,20,20,20,20,20,20,20,20,20,20,20,20,20,20,21,
+  21,21,21,21,21,21,21,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,20,
+  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
+  21,21,21,21,21,21,21,21,21,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,20,20,
+  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
+  20,21,21,21,21,21,21,21,21,21,21,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,20,20,20,20,
+  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
+  20,20,21,21,21,21,21,21,21,21,21,21,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,20,20,20,20,20,
+  20,20,20,20,20,20,20,20,20,20,20,20,31,31,31,31,
+  31,31,31,31,31,31,21,21,21,21,21,21,21,21,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,20,20,20,20,20,
+  20,20,20,20,20,20,20,20,20,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,21,21,21,21,21,21,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,20,20,20,20,20,20,
+  20,20,20,20,20,20,20,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,21,21,21,21,21,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,20,20,20,20,20,20,20,
+  20,20,20,20,20,20,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,21,21,21,
+  21,21,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,20,20,20,20,20,20,20,20,
+  20,20,20,20,20,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,63,
+  49,49,49,49,49,49,49,49,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,20,20,20,20,20,20,20,20,
+  20,20,20,20,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,49,
+  48,48,48,48,48,48,48,49,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,20,20,20,20,20,20,20,20,20,
+  20,20,20,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,49,
+  48,47,47,47,47,47,47,48,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,19,20,20,20,20,20,20,20,20,
+  20,20,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,49,
+  48,47,47,47,47,47,47,48,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,20,19,20,20,20,20,20,20,20,
+  20,20,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,49,
+  48,47,47,47,47,47,47,48,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,19,19,19,19,20,20,20,20,20,20,
+  20,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,49,
+  48,47,47,47,47,47,47,48,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,19,19,19,19,19,20,20,20,20,20,
+  20,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,49,
+  48,47,47,47,47,47,47,48,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,19,19,19,19,19,19,19,20,20,20,
+  19,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,49,
+  48,47,47,47,47,47,48,48,63,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,19,19,19,19,19,19,20,19,20,20,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,49,
+  49,48,48,48,48,48,48,48,21,31,31,31,31,31,31,31,
+  31,31,31,31,31,19,19,19,19,19,19,19,19,19,19,20,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,21,21,21,31,31,31,31,31,31,
+  31,31,31,31,31,20,20,20,20,20,20,20,20,20,20,20,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,21,21,31,31,31,31,31,31,
+  31,31,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
+  49,49,49,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,21,21,31,31,31,31,31,
+  31,49,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
+  48,48,48,49,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,21,21,21,31,31,31,31,
+  49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
+  47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,21,21,31,31,31,31,
+  49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
+  47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,21,21,31,31,31,31,
+  49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
+  47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,21,21,31,31,31,
+  49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
+  47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,21,21,31,31,31,
+  49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
+  47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,21,21,21,31,31,
+  49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
+  47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,21,21,31,31,
+  49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
+  47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,21,21,31,31,
+  49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
+  47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,21,21,21,31,
+  49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
+  47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,21,21,31,
+  49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
+  47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,21,21,31,
+  49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
+  47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,20,21,31,
+  49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
+  47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,21,21,21,
+  49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
+  47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,20,21,21,
+  49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
+  47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,20,20,21,
+  49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
+  47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,20,20,20,
+  49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
+  47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,20,20,20,
+  31,49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,
+  47,47,48,49,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,20,20,20,
+  31,49,49,48,48,48,48,48,48,48,48,48,48,48,48,48,
+  48,48,49,63,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,20,20,20,
+  31,31,31,49,49,49,49,49,49,47,63,63,63,63,63,63,
+  63,63,20,19,19,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,20,20,20,20,
+  31,31,31,31,31,31,31,31,31,31,19,19,19,19,19,19,
+  19,19,19,19,19,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,20,20,20,20,
+  31,31,31,31,31,31,31,31,31,31,31,19,19,19,19,19,
+  19,19,19,19,19,19,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,20,20,20,20,
+  31,31,31,31,31,31,31,31,31,31,31,19,19,19,19,19,
+  19,19,19,19,19,19,19,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,20,20,20,20,
+  31,31,31,31,31,31,31,31,31,31,31,31,19,19,19,19,
+  19,19,19,19,19,19,19,19,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,20,20,20,20,20,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,19,19,19,
+  19,19,19,19,19,19,19,19,19,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,49,49,49,49,49,47,63,63,63,21,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,19,19,19,
+  19,19,19,19,19,19,19,19,19,19,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,49,49,48,48,48,48,48,48,48,48,48,48,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,19,19,
+  19,19,19,19,19,19,19,19,19,19,19,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,49,48,47,47,47,47,47,47,47,47,47,48,49,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,19,
+  19,19,19,19,19,19,19,19,19,19,19,19,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,49,47,47,47,47,47,47,47,47,47,47,48,48,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  19,19,19,19,19,19,19,19,19,19,19,19,19,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,49,47,47,47,47,47,47,47,47,47,47,48,49,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,19,19,19,19,19,19,19,19,19,19,19,19,19,19,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,49,47,47,47,47,47,47,47,47,47,47,48,49,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,49,47,47,47,47,47,47,47,47,47,47,48,49,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,19,19,19,19,19,19,19,19,19,19,19,19,19,
+  19,19,19,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,49,47,47,47,47,47,47,47,47,47,47,48,49,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,19,19,19,19,19,19,19,19,19,19,19,19,
+  19,19,19,19,19,31,31,31,31,31,31,31,31,31,31,31,
+  31,19,20,49,47,47,47,47,47,47,47,47,47,47,48,49,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,19,19,19,19,19,19,19,19,19,19,19,
+  19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
+  19,20,20,49,47,47,47,47,47,47,47,47,47,47,48,49,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,18,19,19,19,19,19,19,19,19,19,
+  19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
+  19,19,20,49,47,47,47,47,47,47,47,47,47,47,48,48,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,19,19,19,19,19,19,19,19,19,
+  19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
+  19,20,20,49,48,47,47,47,47,47,47,47,47,47,48,49,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,19,19,19,19,19,19,19,
+  19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
+  19,19,20,63,48,48,48,48,48,48,48,48,48,48,49,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,19,19,19,19,19,19,
+  19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
+  19,19,19,20,21,63,63,63,48,49,49,49,49,49,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,19,19,19,19,
+  19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
+  19,19,19,19,19,20,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,19,19,
+  19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
+  19,19,19,19,19,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
+  19,19,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,19,19,19,19,19,19,19,19,19,19,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31
+};
+
--- a/libinterp/corefcn/octave-link.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/octave-link.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -225,7 +225,7 @@
       std::string multi_on = args(4).string_value (); // on, off, create
       std::string pathname = args(5).string_value ();
 
-      octave_idx_type nel = flist.numel ();
+      octave_idx_type nel;
       octave_link::filter_list filter_lst;
 
       for (octave_idx_type i = 0; i < flist.rows (); i++)
@@ -432,7 +432,7 @@
 
 DEFUN (__octave_link_show_doc__, args, ,
        "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {} __octave_link_show_doc__ ( @var{filename} )\n\
+@deftypefn {Built-in Function} {} __octave_link_show_doc__ (@var{filename})\n\
 Undocumented internal function.\n\
 @end deftypefn")
 {
--- a/libinterp/corefcn/octave-link.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/octave-link.h	Mon Jan 12 09:17:35 2015 -0800
@@ -110,14 +110,6 @@
       instance->do_post_event (obj, method, arg);
   }
 
-  template <class T, class A, class B>
-  static void post_event (T *obj, void (T::*method) (const A&, const B&),
-                          const A& arg_a, const B& arg_b)
-  {
-    if (enabled ())
-      instance->do_post_event (obj, method, arg_a, arg_b);
-  }
-
   static void entered_readline_hook (void)
   {
     if (enabled ())
--- a/libinterp/corefcn/pager.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/pager.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -52,7 +52,7 @@
 static bool write_to_diary_file = false;
 
 // The name of the current diary file.
-static std::string diary_file;
+static std::string diary_file ("diary");
 
 // The diary file.
 static std::ofstream external_diary_file;
@@ -589,6 +589,24 @@
   return retval;
 }
 
+DEFUN (__diaryfile__, , ,
+       "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {@var{fname} =} __diaryfile__ ()\n\
+Undocumented internal function\n\
+@end deftypefn")
+{
+  return ovl (diary_file);
+}
+
+DEFUN (__diarystate__, , ,
+       "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {@var{state} =} __diarystate__ ()\n\
+Undocumented internal function\n\
+@end deftypefn")
+{
+  return ovl (write_to_diary_file);
+}
+
 DEFUN (more, args, ,
        "-*- texinfo -*-\n\
 @deftypefn  {Command} {} more\n\
--- a/libinterp/corefcn/pinv.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/pinv.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -76,22 +76,45 @@
 
   if (arg.is_diag_matrix ())
     {
-      if (nargin == 2)
-        warning ("pinv: tol is ignored for diagonal matrices");
-
-      if (arg.is_complex_type ())
+      if (isfloat)
         {
-          if (isfloat)
-            retval = arg.float_complex_diag_matrix_value ().pseudo_inverse ();
+          float tol = 0.0;
+          if (nargin == 2)
+            tol = args(1).float_value ();
+
+          if (error_state)
+            return retval;
+
+          if (tol < 0.0)
+            {
+              error ("pinv: TOL must be greater than zero");
+              return retval;
+            }
+
+          if (arg.is_real_type ())
+            retval = arg.float_diag_matrix_value ().pseudo_inverse (tol);
           else
-            retval = arg.complex_diag_matrix_value ().pseudo_inverse ();
+            retval = arg.float_complex_diag_matrix_value ().pseudo_inverse (tol);
         }
       else
         {
-          if (isfloat)
-            retval = arg.float_diag_matrix_value ().pseudo_inverse ();
+          double tol = 0.0;
+          if (nargin == 2)
+            tol = args(1).double_value ();
+
+          if (error_state)
+            return retval;
+
+          if (tol < 0.0)
+            {
+              error ("pinv: TOL must be greater than zero");
+              return retval;
+            }
+
+          if (arg.is_real_type ())
+            retval = arg.diag_matrix_value ().pseudo_inverse (tol);
           else
-            retval = arg.diag_matrix_value ().pseudo_inverse ();
+            retval = arg.complex_diag_matrix_value ().pseudo_inverse (tol);
         }
     }
   else if (arg.is_perm_matrix ())
@@ -189,4 +212,20 @@
 %!assert (y*x*y, y, -hitol)
 %!assert ((x*y)', x*y, hitol)
 %!assert ((y*x)', y*x, hitol)
+
+## Clear shared variables
+%!shared
+
+## Test pinv for Diagonal matrices
+%!test
+%! x = diag ([3 2 1 0 -0.5]);
+%! y = pinv (x);
+%! assert (typeinfo (y)(1:8), "diagonal");
+%! assert (isa (y, "double"));
+%! assert (diag (y), [1/3, 1/2, 1, 0  1/-0.5]');
+%! y = pinv (x, 1);
+%! assert (diag (y), [1/3 1/2 1 0 0]');
+%! y = pinv (x, 2);
+%! assert (diag (y), [1/3 1/2 0 0 0]');
+
 */
--- a/libinterp/corefcn/pr-output.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/pr-output.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -596,13 +596,11 @@
         {
           ld = digits;
           rd = prec > digits ? prec - digits : prec;
-          digits++;
         }
       else
         {
           ld = 1;
           rd = prec > digits ? prec - digits : prec;
-          digits = -digits + 1;
         }
 
       fw = 1 + ld + 1 + rd;
@@ -2105,7 +2103,7 @@
     {
     case 1:
     case 2:
-      octave_print_internal (os, nda.matrix_value (),
+      octave_print_internal (os, Matrix (nda),
                              pr_as_read_syntax, extra_indent);
       break;
 
@@ -2502,11 +2500,10 @@
 
       if (pr_as_read_syntax)
         {
-          Array<octave_idx_type> pvec = m.pvec ();
-          bool colp = m.is_col_perm ();
+          Array<octave_idx_type> pvec = m.col_perm_vec ();
 
           os << "eye (";
-          if (colp) os << ":, ";
+          os << ":, ";
 
           octave_idx_type col = 0;
           while (col < nc)
@@ -2537,7 +2534,6 @@
               else
                 os << " ...\n";
             }
-          if (! colp) os << ", :";
           os << ")";
         }
       else
@@ -2584,7 +2580,7 @@
     {
     case 1:
     case 2:
-      octave_print_internal (os, nda.matrix_value (),
+      octave_print_internal (os, ComplexMatrix (nda),
                              pr_as_read_syntax, extra_indent);
       break;
 
@@ -2794,7 +2790,7 @@
     {
     case 1:
     case 2:
-      octave_print_internal (os, nda.matrix_value (),
+      octave_print_internal (os, boolMatrix (nda),
                              pr_as_read_syntax, extra_indent);
       break;
 
@@ -2861,7 +2857,7 @@
     {
     case 1:
     case 2:
-      octave_print_internal (os, nda.matrix_value (),
+      octave_print_internal (os, charMatrix (nda),
                              pr_as_read_syntax, extra_indent, pr_as_string);
       break;
 
@@ -3402,8 +3398,7 @@
 }
 
 void
-octave_print_internal (std::ostream&, const octave_value&,
-                       bool pr_as_read_syntax)
+octave_print_internal (std::ostream&, const octave_value&, bool)
 {
   panic_impossible ();
 }
@@ -3457,7 +3452,7 @@
               rat_format = true;
 
               std::ostringstream buf;
-              args(0).print (buf);
+              arg.print (buf);
               std::string s = buf.str ();
 
               std::list<std::string> lst;
@@ -3519,11 +3514,12 @@
 
   if (nargin == 1 && nargout < 2)
     {
+      octave_value arg = args(0);
+
       if (nargout == 0)
-        args(0).print (octave_stdout);
+        arg.print (octave_stdout);
       else
         {
-          octave_value arg = args(0);
           std::ostringstream buf;
           arg.print (buf);
           retval = octave_value (buf.str (), arg.is_dq_string () ? '"' : '\'');
@@ -3560,7 +3556,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");
 
@@ -3568,8 +3564,10 @@
         {
           std::ostream *osp = os.output_stream ();
 
+          octave_value arg = args(1);
+
           if (osp)
-            args(1).print (*osp);
+            arg.print (*osp);
           else
             error ("fdisp: stream FID not open for writing");
         }
@@ -3630,20 +3628,25 @@
   Voutput_max_field_width = fw;
 }
 
+static std::string format_string ("short");
+
 static void
 set_format_style (int argc, const string_vector& argv)
 {
   int idx = 1;
+  std::string format;
 
   if (--argc > 0)
     {
       std::string arg = argv[idx++];
+      format = arg;
 
       if (arg == "short")
         {
           if (--argc > 0)
             {
               arg = argv[idx++];
+              format.append (arg);
 
               if (arg == "e")
                 {
@@ -3684,11 +3687,44 @@
 
           set_output_prec_and_fw (5, 10);
         }
+      else if (arg == "shorte")
+        {
+          init_format_state ();
+          print_e = true;
+          set_output_prec_and_fw (5, 10);
+        }
+      else if (arg == "shortE")
+        {
+          init_format_state ();
+          print_e = true;
+          print_big_e = true;
+          set_output_prec_and_fw (5, 10);
+        }
+      else if (arg == "shortg")
+        {
+          init_format_state ();
+          print_g = true;
+          set_output_prec_and_fw (5, 10);
+        }
+      else if (arg == "shortG")
+        {
+          init_format_state ();
+          print_g = true;
+          print_big_e = true;
+          set_output_prec_and_fw (5, 10);
+        }
+      else if (arg == "shortEng")
+        {
+          init_format_state ();
+          print_eng = true;
+          set_output_prec_and_fw (5, 10);
+        }
       else if (arg == "long")
         {
           if (--argc > 0)
             {
               arg = argv[idx++];
+              format.append (arg);
 
               if (arg == "e")
                 {
@@ -3729,6 +3765,38 @@
 
           set_output_prec_and_fw (15, 20);
         }
+      else if (arg == "longe")
+        {
+          init_format_state ();
+          print_e = true;
+          set_output_prec_and_fw (15, 20);
+        }
+      else if (arg == "longE")
+        {
+          init_format_state ();
+          print_e = true;
+          print_big_e = true;
+          set_output_prec_and_fw (15, 20);
+        }
+      else if (arg == "longg")
+        {
+          init_format_state ();
+          print_g = true;
+          set_output_prec_and_fw (15, 20);
+        }
+      else if (arg == "longG")
+        {
+          init_format_state ();
+          print_g = true;
+          print_big_e = true;
+          set_output_prec_and_fw (15, 20);
+        }
+      else if (arg == "longEng")
+        {
+          init_format_state ();
+          print_eng = true;
+          set_output_prec_and_fw (15, 20);
+        }
       else if (arg == "hex")
         {
           init_format_state ();
@@ -3754,6 +3822,7 @@
           if (--argc > 0)
             {
               arg = argv[idx++];
+              format.append (arg);
 
               if (arg.length () == 3)
                 plus_format_chars = arg;
@@ -3792,21 +3861,30 @@
       else if (arg == "compact")
         {
           Vcompact_format = true;
+          return;
         }
       else if (arg == "loose")
         {
           Vcompact_format = false;
+          return;
         }
       else
-        error ("format: unrecognized format state '%s'", arg.c_str ());
+        {
+          error ("format: unrecognized format state '%s'", arg.c_str ());
+          return;
+        }  
     }
   else
     {
       init_format_state ();
       set_output_prec_and_fw (5, 10);
+      format = std::string ("short");
     }
+
+  format_string = format;
 }
 
+
 DEFUN (format, args, ,
        "-*- texinfo -*-\n\
 @deftypefn  {Command} {} format\n\
@@ -3900,8 +3978,8 @@
 integer types).\n\
 \n\
 @table @code\n\
-@item  +\n\
-@itemx + @var{chars}\n\
+@item  \"+\"\n\
+@itemx \"+\" @var{chars}\n\
 @itemx plus\n\
 @itemx plus @var{chars}\n\
 Print a @samp{+} symbol for matrix elements greater than zero, a\n\
@@ -3911,8 +3989,8 @@
 \n\
 The optional argument @var{chars} specifies a list of 3 characters to use\n\
 for printing values greater than zero, less than zero and equal to zero.\n\
-For example, with the @samp{\"+\" \"+-.\"} format, @code{[1, 0, -1; -1, 0, 1]}\n\
-is displayed as\n\
+For example, with the @samp{\"+\" \"+-.\"} format,\n\
+@code{[1, 0, -1; -1, 0, 1]} is displayed as\n\
 \n\
 @example\n\
 @group\n\
@@ -3992,6 +4070,25 @@
   return retval;
 }
 
+DEFUN (__compactformat__, args, nargout,
+       "-*- texinfo -*-\n\
+@deftypefn  {Built-in Function} {@var{val} =} __compactformat__ ()\n\
+@deftypefnx {Built-in Function} {} __compactformat__ (@var{TRUE|FALSE})\n\
+Undocumented internal function\n\
+@end deftypefn")
+{
+  return SET_INTERNAL_VARIABLE (compact_format);
+}
+
+DEFUN (__formatstring__, , ,
+       "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {@var{val} =} __formatstring__ ()\n\
+Undocumented internal function\n\
+@end deftypefn")
+{
+  return ovl (format_string);
+}
+
 DEFUN (fixed_point_format, args, nargout,
        "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {@var{val} =} fixed_point_format ()\n\
@@ -4021,7 +4118,7 @@
 \n\
 @noindent\n\
 Notice that the first value appears to be 0 when it is actually 1.  Because\n\
-of the possibilty for confusion you should be careful about enabling\n\
+of the possibility for confusion you should be careful about enabling\n\
 @code{fixed_point_format}.\n\
 \n\
 When called from inside a function with the @qcode{\"local\"} option, the\n\
--- a/libinterp/corefcn/profiler.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/profiler.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -84,7 +84,7 @@
 }
 
 profile_data_accumulator::tree_node*
-profile_data_accumulator::tree_node::exit (octave_idx_type fcn)
+profile_data_accumulator::tree_node::exit (octave_idx_type /* fcn */)
 {
   // FIXME: These assert statements don't make sense if profile() is called
   //        from within a function hierarchy to begin with.  See bug #39587.
@@ -397,7 +397,7 @@
 // Enable or disable the profiler data collection.
 DEFUN (__profiler_enable__, args, ,
        "-*- texinfo -*-\n\
-@deftypefn {Function File} __profiler_enable__ ()\n\
+@deftypefn {Function File} {} __profiler_enable__ ()\n\
 Undocumented internal function.\n\
 @end deftypefn")
 {
@@ -423,7 +423,7 @@
 // Clear all collected profiling data.
 DEFUN (__profiler_reset__, args, ,
        "-*- texinfo -*-\n\
-@deftypefn {Function File} __profiler_reset__ ()\n\
+@deftypefn {Function File} {} __profiler_reset__ ()\n\
 Undocumented internal function.\n\
 @end deftypefn")
 {
@@ -441,7 +441,7 @@
 // Query the timings collected by the profiler.
 DEFUN (__profiler_data__, args, nargout,
        "-*- texinfo -*-\n\
-@deftypefn {Function File} __profiler_data__ ()\n\
+@deftypefn {Function File} {} __profiler_data__ ()\n\
 Undocumented internal function.\n\
 @end deftypefn")
 {
--- a/libinterp/corefcn/pt-jit.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/pt-jit.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -46,13 +46,26 @@
 
 static int Vjit_startcnt = 1000;
 
+static int Vjit_failure_count = 0;
+
 #include <llvm/Analysis/CallGraph.h>
 #include <llvm/Analysis/Passes.h>
+
+#ifdef HAVE_LLVM_IR_VERIFIER_H
+#include <llvm/IR/Verifier.h>
+#else
 #include <llvm/Analysis/Verifier.h>
+#endif
+
 #include <llvm/Bitcode/ReaderWriter.h>
 #include <llvm/ExecutionEngine/ExecutionEngine.h>
 #include <llvm/ExecutionEngine/JIT.h>
+
+#ifdef LEGACY_PASSMANAGER
+#include <llvm/IR/LegacyPassManager.h>
+#else
 #include <llvm/PassManager.h>
+#endif
 
 #ifdef HAVE_LLVM_IR_FUNCTION_H
 #include <llvm/IR/LLVMContext.h>
@@ -164,7 +177,7 @@
       if (expr)
         {
           jit_variable *retvar = get_variable ("#return");
-          jit_value *retval;
+          jit_value *retval = 0;
           try
             {
               retval = visit (expr);
@@ -230,13 +243,13 @@
 void
 jit_convert::visit_anon_fcn_handle (tree_anon_fcn_handle&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_anon_fcn_handle implementation");
 }
 
 void
 jit_convert::visit_argument_list (tree_argument_list&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_argument_list implementation");
 }
 
 void
@@ -337,25 +350,25 @@
 void
 jit_convert::visit_global_command (tree_global_command&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_global_command implemenation");
 }
 
 void
 jit_convert::visit_persistent_command (tree_persistent_command&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_persistent_command implementation");
 }
 
 void
 jit_convert::visit_decl_elt (tree_decl_elt&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_decl_elt implementation");
 }
 
 void
 jit_convert::visit_decl_init_list (tree_decl_init_list&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_decl_init_list implementation");
 }
 
 void
@@ -464,37 +477,37 @@
 void
 jit_convert::visit_complex_for_command (tree_complex_for_command&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_complex_for_command implementation");
 }
 
 void
 jit_convert::visit_octave_user_script (octave_user_script&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_octave_user_script implementation");
 }
 
 void
 jit_convert::visit_octave_user_function (octave_user_function&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_octave_user_function implementation");
 }
 
 void
 jit_convert::visit_octave_user_function_header (octave_user_function&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_octave_user_function_header implementation");
 }
 
 void
 jit_convert::visit_octave_user_function_trailer (octave_user_function&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_octave_user_function_trailer implementation");
 }
 
 void
 jit_convert::visit_function_def (tree_function_def&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_function_def implementation");
 }
 
 void
@@ -518,7 +531,7 @@
 void
 jit_convert::visit_if_clause (tree_if_clause&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_if_clause implementation");
 }
 
 void
@@ -539,7 +552,6 @@
   // the condition check for the ith clause. For the else, it is simple the
   // else body. If there is no else body, then it is padded with the tail
   std::vector<jit_block *> entry_blocks (lst.size () + 1 - last_else);
-  std::vector<jit_block *> branch_blocks (lst.size (), 0); // final blocks
   entry_blocks[0] = block;
 
   // we need to construct blocks first, because they have jumps to eachother
@@ -630,25 +642,25 @@
 void
 jit_convert::visit_matrix (tree_matrix&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_matrix implementation");
 }
 
 void
 jit_convert::visit_cell (tree_cell&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_cell implementation");
 }
 
 void
 jit_convert::visit_multi_assignment (tree_multi_assignment&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_multi_assignment implementation");
 }
 
 void
 jit_convert::visit_no_op_command (tree_no_op_command&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_no_op_command implementation");
 }
 
 void
@@ -679,13 +691,19 @@
 void
 jit_convert::visit_fcn_handle (tree_fcn_handle&)
 {
+  throw jit_fail_exception ("No visit_fcn_handle implementation");
+}
+
+void
+jit_convert::visit_funcall (tree_funcall&)
+{
   throw jit_fail_exception ();
 }
 
 void
 jit_convert::visit_parameter_list (tree_parameter_list&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_parameter_list implementation");
 }
 
 void
@@ -721,13 +739,13 @@
 void
 jit_convert::visit_return_command (tree_return_command&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_return_command implementation");
 }
 
 void
 jit_convert::visit_return_list (tree_return_list&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_return_list implementation");
 }
 
 void
@@ -805,31 +823,132 @@
 void
 jit_convert::visit_switch_case (tree_switch_case&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_switch_case implementation");
 }
 
 void
 jit_convert::visit_switch_case_list (tree_switch_case_list&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_switch_case_list implementation");
 }
 
 void
-jit_convert::visit_switch_command (tree_switch_command&)
+jit_convert::visit_switch_command (tree_switch_command& cmd)
 {
-  throw jit_fail_exception ();
+  tree_switch_case_list *lst = cmd.case_list ();
+
+  // always visit switch expression
+  tree_expression *expr = cmd.switch_value ();
+  assert (expr && "Switch value can not be null");
+  jit_value *value = visit (expr);
+  assert (value);
+
+  size_t case_blocks_num = lst->size ();
+
+  if (! case_blocks_num)  // there's nothing to do
+    return;
+
+  // check for otherwise, it's interpreted as last 'else' condition
+  size_t has_otherwise = 0;
+  tree_switch_case *last = lst->back ();
+  if (last->is_default_case ())
+    has_otherwise = 1;
+
+  std::vector<jit_block *> entry_blocks (case_blocks_num + 1 - has_otherwise);
+
+  // the first entry point is always the actual block. afterward new blocks
+  // are created for every case and the otherwise branch
+  entry_blocks[0] = block;
+  for (size_t i = 1; i < case_blocks_num; ++i)
+    entry_blocks[i] = factory.create<jit_block> ("case_cond");
+
+  jit_block *tail = factory.create<jit_block> ("switch_tail");
+
+  // if there's no otherwise branch, the the 'else' of the last branch
+  // has to point to the tail
+  if (! has_otherwise)
+    entry_blocks[entry_blocks.size()-1] = tail;
+
+  // each branch in the case statement will have different breaks/continues
+  block_list current_breaks = breaks;
+  block_list current_continues = continues;
+  breaks.clear ();
+  continues.clear ();
+
+  size_t num_incomming = 0; // number of incomming blocks to our tail
+
+  tree_switch_case_list::iterator iter = lst->begin ();
+  for (size_t i = 0; i < case_blocks_num; ++iter, ++i)
+    {
+      tree_switch_case *twc = *iter;
+      block = entry_blocks[i]; // case_cond
+      assert (block);
+
+      if (i)
+        blocks.push_back (entry_blocks[i]);  // first block already pushed
+
+      if (! twc->is_default_case ())
+        {
+          // compare result of switch expression with actual case label
+          tree_expression *te = twc->case_label ();
+          jit_value *label = visit (te);
+          assert(label);
+
+          const jit_operation& fn = jit_typeinfo::binary_op (octave_value::op_eq);
+          jit_value *cond = create_checked (fn, value, label);
+          assert(cond);
+
+          jit_call *check = create_checked (&jit_typeinfo::logically_true,
+                                            cond);
+
+          jit_block *body = factory.create<jit_block> ("case_body");
+          blocks.push_back (body);
+
+          block->append (factory.create<jit_cond_branch> (check, body,
+                                                          entry_blocks[i+1]));
+          block = body; // case_body
+        }
+
+      tree_statement_list *stmt_lst = twc->commands ();
+      assert(stmt_lst);
+
+      try
+        {
+          stmt_lst->accept (*this);
+          num_incomming++;
+          block->append (factory.create<jit_branch> (tail));
+        }
+      catch (const jit_break_exception&)
+        { }
+
+      // each branch in the case statement will have different breaks/continues
+      current_breaks.splice (current_breaks.end (), breaks);
+      current_continues.splice (current_continues.end (), continues);
+    }
+
+  // each branch in the case statement will have different breaks/continues
+  breaks.splice (breaks.end (), current_breaks);
+  continues.splice (continues.end (), current_continues);
+
+  if (num_incomming || ! has_otherwise)
+    {
+      blocks.push_back (tail);
+      block = tail; // switch_tail
+    }
+  else
+    throw jit_break_exception ();   // every branch broke
 }
 
 void
 jit_convert::visit_try_catch_command (tree_try_catch_command&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_try_catch_command implementation");
 }
 
 void
 jit_convert::visit_unwind_protect_command (tree_unwind_protect_command&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_unwind_protect_command implementation");
 }
 
 void
@@ -895,9 +1014,66 @@
 }
 
 void
-jit_convert::visit_do_until_command (tree_do_until_command&)
+jit_convert::visit_do_until_command (tree_do_until_command& duc)
 {
-  throw jit_fail_exception ();
+  unwind_protect prot;
+  prot.protect_var (breaks);
+  prot.protect_var (continues);
+  breaks.clear ();
+  continues.clear ();
+
+  jit_block *body = factory.create<jit_block> ("do_until_body");
+  jit_block *cond_check = factory.create<jit_block> ("do_until_cond_check");
+  jit_block *tail = factory.create<jit_block> ("do_until_tail");
+
+  block->append (factory.create<jit_branch> (body));
+  blocks.push_back (body);
+  block = body;
+
+  tree_statement_list *loop_body = duc.body ();
+  bool all_breaking = false;
+  if (loop_body)
+    {
+      try
+        {
+          loop_body->accept (*this);
+        }
+      catch (const jit_break_exception&)
+        {
+          all_breaking = true;
+        }
+    }
+
+  finish_breaks (tail, breaks);
+
+  if (! all_breaking || continues.size ())
+    {
+      jit_block *interrupt_check
+        = factory.create<jit_block> ("interrupt_check");
+      blocks.push_back (interrupt_check);
+      finish_breaks (interrupt_check, continues);
+      if (! all_breaking)
+        block->append (factory.create<jit_branch> (interrupt_check));
+
+      block = interrupt_check;
+      jit_error_check *ec
+        = factory.create<jit_error_check> (jit_error_check::var_interrupt,
+                                           cond_check, final_block);
+      block->append (ec);
+
+      blocks.push_back (cond_check);
+      block = cond_check;
+
+      tree_expression *expr = duc.condition ();
+      assert (expr && "Do-Until expression can not be null");
+      jit_value *check = visit (expr);
+      check = create_checked (&jit_typeinfo::logically_true, check);
+
+      block->append (factory.create<jit_cond_branch> (check, tail, body));
+    }
+
+  blocks.push_back (tail);
+  block = tail;
 }
 
 void
@@ -1888,10 +2064,15 @@
   if (! engine)
     return false;
 
+#ifdef LEGACY_PASSMANAGER
+  module_pass_manager = new llvm::legacy::PassManager ();
+  pass_manager = new llvm::legacy::FunctionPassManager (module); 
+#else
   module_pass_manager = new llvm::PassManager ();
+  pass_manager = new llvm::FunctionPassManager (module);
+#endif
   module_pass_manager->add (llvm::createAlwaysInlinerPass ());
 
-  pass_manager = new llvm::FunctionPassManager (module);
 #ifdef HAVE_LLVM_DATALAYOUT
   pass_manager->add (new llvm::DataLayout (*engine->getDataLayout ()));
 #else
@@ -2006,8 +2187,13 @@
   if (Vdebug_jit)
     {
       std::string error;
+#ifdef RAW_FD_OSTREAM_ARG_IS_LLVM_SYS_FS
+      llvm::raw_fd_ostream fout ("test.bc", error,
+                                 llvm::sys::fs::F_Binary);
+#else
       llvm::raw_fd_ostream fout ("test.bc", error,
                                  llvm::raw_fd_ostream::F_Binary);
+#endif
       llvm::WriteBitcodeToFile (module, fout);
     }
 }
@@ -2123,6 +2309,8 @@
             std::cout << "jit fail: " << e.what () << std::endl;
         }
 
+      Vjit_failure_count++;
+
       wrapper.erase ();
       raw_fn.erase ();
     }
@@ -2279,6 +2467,9 @@
           if (e.known ())
             std::cout << "jit fail: " << e.what () << std::endl;
         }
+
+      Vjit_failure_count++;
+
     }
 
   if (llvm_function)
@@ -2314,7 +2505,37 @@
 
 #endif
 
-DEFUN (debug_jit, args, nargout,
+#if defined (HAVE_LLVM)
+#define UNUSED_WITHOUT_LLVM(x) x
+#else
+#define UNUSED_WITHOUT_LLVM(x) x GCC_ATTR_UNUSED
+#endif
+
+DEFUN (jit_failure_count, UNUSED_WITHOUT_LLVM (args),
+       UNUSED_WITHOUT_LLVM (nargout),
+       "-*- texinfo -*-\n\
+@deftypefn  {Built-in Function} {@var{val} =} jit_failure_count ()\n\
+@deftypefnx {Built-in Function} {@var{old_val} =} jit_failure_count (@var{new_val})\n\
+@deftypefnx {Built-in Function} {} jit_failure_count (@var{new_val}, \"local\")\n\
+Query or set the internal variable that counts the number of\n\
+JIT fail exceptions for Octave's JIT compiler.\n\
+\n\
+When called from inside a function with the @qcode{\"local\"} option, the\n\
+variable is changed locally for the function and any subroutines it calls.  \n\
+The original variable value is restored when exiting the function.\n\
+@seealso{jit_enable, jit_startcnt, debug_jit}\n\
+@end deftypefn")
+{
+#if defined (HAVE_LLVM)
+  return SET_INTERNAL_VARIABLE (jit_failure_count);
+#else
+  warning ("jit_failure_count: JIT compiling not available in this version of Octave");
+  return octave_value ();
+#endif
+}
+
+DEFUN (debug_jit, UNUSED_WITHOUT_LLVM (args),
+       UNUSED_WITHOUT_LLVM (nargout),
        "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {@var{val} =} debug_jit ()\n\
 @deftypefnx {Built-in Function} {@var{old_val} =} debug_jit (@var{new_val})\n\
@@ -2336,7 +2557,8 @@
 #endif
 }
 
-DEFUN (jit_enable, args, nargout,
+DEFUN (jit_enable, UNUSED_WITHOUT_LLVM (args),
+       UNUSED_WITHOUT_LLVM (nargout),
        "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {@var{val} =} jit_enable ()\n\
 @deftypefnx {Built-in Function} {@var{old_val} =} jit_enable (@var{new_val})\n\
@@ -2357,7 +2579,8 @@
 #endif
 }
 
-DEFUN (jit_startcnt, args, nargout,
+DEFUN (jit_startcnt, UNUSED_WITHOUT_LLVM (args),
+       UNUSED_WITHOUT_LLVM (nargout),
        "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {@var{val} =} jit_startcnt ()\n\
 @deftypefnx {Built-in Function} {@var{old_val} =} jit_startcnt (@var{new_val})\n\
--- a/libinterp/corefcn/pt-jit.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/pt-jit.h	Mon Jan 12 09:17:35 2015 -0800
@@ -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&);
@@ -384,8 +386,13 @@
   size_t trip_count (const octave_value& bounds) const;
 
   llvm::Module *module;
+#ifdef LEGACY_PASSMANAGER
+  llvm::legacy::PassManager *module_pass_manager;
+  llvm::legacy::FunctionPassManager *pass_manager;
+#else
   llvm::PassManager *module_pass_manager;
   llvm::FunctionPassManager *pass_manager;
+#endif
   llvm::ExecutionEngine *engine;
 };
 
--- a/libinterp/corefcn/quad.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/quad.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -235,7 +235,7 @@
         quad_fcn = args(0).function_value ();
       else
         {
-          fcn_name = unique_symbol_name ("__quad_fcn_");
+          fcn_name = unique_symbol_name ("__quad_fcn__");
           std::string fname = "function y = ";
           fname.append (fcn_name);
           fname.append ("(x) y = ");
--- a/libinterp/corefcn/quadcc.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/quadcc.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -25,14 +25,14 @@
 #endif
 
 #include "lo-ieee.h"
-#include "parse.h"
-#include "variables.h"
+#include "oct-locbuf.h"
 
 #include "defun.h"
 #include "error.h"
 #include "oct-obj.h"
+#include "parse.h"
 #include "utils.h"
-
+#include "variables.h"
 
 /* Extended debugging */
 #define DEBUG_QUADCC 0
@@ -1492,9 +1492,9 @@
 @deftypefnx {Function File} {@var{q} =} quadcc (@var{f}, @var{a}, @var{b}, @var{tol}, @var{sing})\n\
 @deftypefnx {Function File} {[@var{q}, @var{err}, @var{nr_points}] =} quadcc (@dots{})\n\
 Numerically evaluate the integral of @var{f} from @var{a} to @var{b}\n\
-using the doubly-adaptive Clenshaw-Curtis quadrature described by P. Gonnet\n\
-in @cite{Increasing the Reliability of Adaptive Quadrature Using Explicit\n\
-Interpolants}.\n\
+using the doubly-adaptive @nospell{Clenshaw-Curtis} quadrature described by\n\
+@nospell{P. Gonnet} in @cite{Increasing the Reliability of Adaptive\n\
+Quadrature Using Explicit Interpolants}.\n\
 @var{f} is a function handle, inline function, or string\n\
 containing the name of the function to evaluate.\n\
 The function @var{f} must be vectorized and must return a vector of output\n\
@@ -1540,14 +1540,14 @@
 and, as such, may be less efficient for a smooth or otherwise\n\
 well-behaved integrand than other methods such as @code{quadgk}.\n\
 \n\
-The algorithm uses Clenshaw-Curtis quadrature rules of increasing\n\
+The algorithm uses @nospell{Clenshaw-Curtis} quadrature rules of increasing\n\
 degree in each interval and bisects the interval if either the\n\
 function does not appear to be smooth or a rule of maximum\n\
 degree has been reached.  The error estimate is computed from the\n\
 L2-norm of the difference between two successive interpolations\n\
 of the integrand over the nodes of the respective quadrature rules.\n\
 \n\
-Reference: P. Gonnet, @cite{Increasing the Reliability of Adaptive\n\
+Reference: @nospell{P. Gonnet}, @cite{Increasing the Reliability of Adaptive\n\
 Quadrature Using Explicit Interpolants}, ACM Transactions on\n\
 Mathematical Software, Vol. 37, Issue 3, Article No. 3, 2010.\n\
 @seealso{quad, quadv, quadl, quadgk, trapz, dblquad, triplequad}\n\
--- a/libinterp/corefcn/qz.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/qz.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -402,7 +402,7 @@
 
   if (nargin == 2)
     ord_job = 'N';
-  else if (!args(2).is_string ())
+  else if (! args(2).is_string ())
     {
       error ("qz: OPT must be a string");
       return retval;
@@ -928,7 +928,7 @@
                   std::cout << "  single gen eig:" << std::endl;
                   std::cout << "  alphar(" << jj << ") = " << aa(jj,jj)
                             << std::endl;
-                  std::cout << "  betar( " << jj << ") = " << bb(jj,jj)
+                  std::cout << "  betar(" << jj << ") = " << bb(jj,jj)
                             << std::endl;
                   std::cout << "  alphai(" << jj << ") = 0" << std::endl;
 #endif
@@ -1277,9 +1277,9 @@
 %! [aa, bb, q, z, v, w, lambda] = qz (a, b);
 %! sz = length (lambda);
 %! observed = (b * v * diag ([lambda;0])) (:, 1:sz);
-%! assert ( (a*v) (:, 1:sz), observed, norm (observed) * 1e-14);
+%! assert ((a*v)(:, 1:sz), observed, norm (observed) * 1e-14);
 %! observed = (diag ([lambda;0]) * w' * b) (1:sz, :);
-%! assert ( (w'*a) (1:sz, :) , observed, norm (observed) * 1e-13);
+%! assert ((w'*a)(1:sz, :) , observed, norm (observed) * 1e-13);
 %! assert (q * a * z, aa, norm (aa) * 1e-14);
 %! assert (q * b * z, bb, norm (bb) * 1e-14);
 
--- a/libinterp/corefcn/rand.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/rand.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -408,8 +408,8 @@
 vector in Octave's startup files (@pxref{Startup Files}).\n\
 \n\
 To compute the pseudo-random sequence, @code{rand} uses the Mersenne\n\
-Twister with a period of @math{2^{19937}-1} (See M. Matsumoto and\n\
-T. Nishimura,\n\
+Twister with a period of @math{2^{19937}-1} (See\n\
+@nospell{M. Matsumoto and T. Nishimura},\n\
 @cite{Mersenne Twister: A 623-dimensionally equidistributed uniform\n\
 pseudorandom number generator}, ACM Trans. on\n\
 Modeling and Computer Simulation Vol. 8, No. 1, pp. 3-30, January 1998,\n\
@@ -567,17 +567,17 @@
 elements having zero mean and variance one.  The arguments are\n\
 handled the same as the arguments for @code{rand}.\n\
 \n\
-By default, @code{randn} uses the Marsaglia and Tsang ``Ziggurat technique''\n\
-to transform from a uniform to a normal distribution.\n\
+By default, @code{randn} uses the @nospell{Marsaglia and Tsang}\n\
+``Ziggurat technique'' to transform from a uniform to a normal distribution.\n\
 \n\
 The class of the value returned can be controlled by a trailing\n\
 @qcode{\"double\"} or @qcode{\"single\"} argument.  These are the only valid\n\
 classes.\n\
 \n\
-Reference: G. Marsaglia and W.W. Tsang,\n\
+Reference: @nospell{G. Marsaglia and W.W. Tsang},\n\
 @cite{Ziggurat Method for Generating Random Variables},\n\
 J. Statistical Software, vol 5, 2000,\n\
-@url{http://www.jstatsoft.org/v05/i08/})\n\
+@url{http://www.jstatsoft.org/v05/i08/}\n\
 \n\
 @seealso{rand, rande, randg, randp}\n\
 @end deftypefn")
@@ -638,17 +638,17 @@
 Return a matrix with exponentially distributed random elements.  The\n\
 arguments are handled the same as the arguments for @code{rand}.\n\
 \n\
-By default, @code{randn} uses the Marsaglia and Tsang ``Ziggurat technique''\n\
-to transform from a uniform to an exponential distribution.\n\
+By default, @code{randn} uses the @nospell{Marsaglia and Tsang}\n\
+``Ziggurat technique'' to transform from a uniform to a normal distribution.\n\
 \n\
 The class of the value returned can be controlled by a trailing\n\
 @qcode{\"double\"} or @qcode{\"single\"} argument.  These are the only valid\n\
 classes.\n\
 \n\
-Reference: G. Marsaglia and W.W. Tsang,\n\
+Reference: @nospell{G. Marsaglia and W.W. Tsang},\n\
 @cite{Ziggurat Method for Generating Random Variables},\n\
 J. Statistical Software, vol 5, 2000,\n\
-@url{http://www.jstatsoft.org/v05/i08/})\n\
+@url{http://www.jstatsoft.org/v05/i08/}\n\
 \n\
 @seealso{rand, randn, randg, randp}\n\
 @end deftypefn")
@@ -1003,17 +1003,17 @@
 Cambridge University Press, 1992.\n\
 \n\
 @item For matrix @var{l} @leq{} 10, use inversion method.[2]\n\
-E. Stadlober, et al., WinRand source code, available via FTP.\n\
+@nospell{E. Stadlober, et al., WinRand source code}, available via FTP.\n\
 \n\
 @item For matrix @var{l} > 10, use patchwork rejection method.\n\
-E. Stadlober, et al., WinRand source code, available via FTP, or\n\
-H. Zechner, @cite{Efficient sampling from continuous and discrete\n\
+@nospell{E. Stadlober, et al., WinRand source code}, available via FTP, or\n\
+@nospell{H. Zechner}, @cite{Efficient sampling from continuous and discrete\n\
 unimodal distributions}, Doctoral Dissertation, 156pp., Technical\n\
-University Graz, Austria, 1994.\n\
+University @nospell{Graz}, Austria, 1994.\n\
 \n\
 @item For @var{l} > 1e8, use normal approximation.\n\
-L. Montanet, et al., @cite{Review of Particle Properties}, Physical Review\n\
-D 50 p1284, 1994.\n\
+@nospell{L. Montanet}, et al., @cite{Review of Particle Properties},\n\
+Physical Review D 50 p1284, 1994.\n\
 @end table\n\
 \n\
 The class of the value returned can be controlled by a trailing\n\
--- a/libinterp/corefcn/regexp.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/regexp.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -189,12 +189,13 @@
 
   for (int i = skip; i < nargin; i++)
     {
-      std::string str = args(i).string_value ();
+      std::string str;
 
-      if (error_state)
+      if (args(i).is_string ())
+        str = args(i).string_value ();
+      else
         {
-          error ("%s: optional arguments must be character strings",
-                 who.c_str ());
+          error ("%s: optional arguments must be strings", who.c_str ());
           break;
         }
 
--- a/libinterp/corefcn/schur.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/schur.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -63,7 +63,7 @@
 @deftypefnx {Built-in Function} {@var{S} =} schur (@var{A}, \"real\")\n\
 @deftypefnx {Built-in Function} {@var{S} =} schur (@var{A}, \"complex\")\n\
 @deftypefnx {Built-in Function} {@var{S} =} schur (@var{A}, @var{opt})\n\
-@deftypefnx {Built-in Function} {[@var{U}, @var{S}] =} schur (@var{A}, @dots{})\n\
+@deftypefnx {Built-in Function} {[@var{U}, @var{S}] =} schur (@dots{})\n\
 @cindex Schur decomposition\n\
 Compute the Schur@tie{}decomposition of @var{A}\n\
 @tex\n\
@@ -143,9 +143,9 @@
 
   if (nargin == 2)
     {
-      ord = args(1).string_value ();
-
-      if (error_state)
+      if (args(1).is_string ())
+        ord = args(1).string_value ();
+      else
         {
           error ("schur: second argument must be a string");
           return retval;
@@ -170,7 +170,7 @@
       if (ord_char != 'U' && ord_char != 'A' && ord_char != 'D'
           && ord_char != 'u' && ord_char != 'a' && ord_char != 'd')
         {
-          warning ("schur: incorrect ordered schur argument '%c'",
+          warning ("schur: incorrect ordered schur argument '%s'",
                    ord.c_str ());
           return retval;
         }
@@ -286,11 +286,13 @@
 %! [u, s] = schur (a);
 %! assert (u' * a * u, s, sqrt (eps ("single")));
 
-%!test
-%! fail ("schur ([1, 2; 3, 4], 2)", "warning");
+%!error schur ()
+%!error schur (1,2,3)
+%!error [a,b,c] = schur (1)
+%!error <argument must be a square matrix> schur ([1, 2, 3; 4, 5, 6])
+%!error <wrong type argument 'cell'> schur ({1})
+%!warning <incorrect ordered schur argument> schur ([1, 2; 3, 4], "bad_opt");
 
-%!error schur ()
-%!error <argument must be a square matrix> schur ([1, 2, 3; 4, 5, 6])
 */
 
 DEFUN (rsf2csf, args, nargout,
--- a/libinterp/corefcn/sparse-xdiv.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/sparse-xdiv.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -28,6 +28,7 @@
 #include <cassert>
 
 #include "Array-util.h"
+#include "lo-array-gripes.h"
 #include "oct-cmplx.h"
 #include "quit.h"
 #include "error.h"
@@ -43,8 +44,7 @@
 static void
 solve_singularity_warning (double rcond)
 {
-  warning ("matrix singular to machine precision, rcond = %g", rcond);
-  warning ("attempting to find minimum norm solution");
+  gripe_singular_matrix (rcond);
 }
 
 template <class T1, class T2>
@@ -302,7 +302,7 @@
   using std::min;
   const octave_idx_type nc = min (d_nr, a_nc);
 
-  if ( ! mx_div_conform (a, d))
+  if (! mx_div_conform (a, d))
     return RT ();
 
   const octave_idx_type nz = a.nnz ();
@@ -569,7 +569,7 @@
   using std::min;
   const octave_idx_type nr = min (d_nc, a_nr);
 
-  if ( ! mx_leftdiv_conform (d, a))
+  if (! mx_leftdiv_conform (d, a))
     return RT ();
 
   const octave_idx_type nz = a.nnz ();
--- a/libinterp/corefcn/sparse.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/sparse.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -135,7 +135,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 ())
@@ -178,7 +178,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/spparms.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/spparms.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -40,7 +40,7 @@
 @deftypefnx {Built-in Function} {[@var{keys}, @var{vals}] =} spparms ()\n\
 @deftypefnx {Built-in Function} {@var{val} =} spparms (@var{key})\n\
 @deftypefnx {Built-in Function} { } spparms (@var{vals})\n\
-@deftypefnx {Built-in Function} { } spparms (\"defaults\")\n\
+@deftypefnx {Built-in Function} { } spparms (\"default\")\n\
 @deftypefnx {Built-in Function} { } spparms (\"tight\")\n\
 @deftypefnx {Built-in Function} { } spparms (@var{key}, @var{val})\n\
 Query or set the parameters used by the sparse solvers and factorization\n\
@@ -86,7 +86,7 @@
 The pivot tolerance of the @sc{umfpack} symmetric solvers (default 0.001)\n\
 \n\
 @item bandden\n\
-The density of non-zero elements in a banded matrix before it is treated\n\
+The density of nonzero elements in a banded matrix before it is treated\n\
 by the @sc{lapack} banded solvers (default 0.5)\n\
 \n\
 @item umfpack\n\
@@ -97,7 +97,7 @@
 The value of individual keys can be set with\n\
 @code{spparms (@var{key}, @var{val})}.\n\
 The default values can be restored with the special keyword\n\
-@qcode{\"defaults\"}.  The special keyword @qcode{\"tight\"} can be used to\n\
+@qcode{\"default\"}.  The special keyword @qcode{\"tight\"} can be used to\n\
 set the mmd solvers to attempt a sparser solution at the potential cost of\n\
 longer running time.\n\
 @seealso{chol, colamd, lu, qr, symamd}\n\
@@ -129,8 +129,17 @@
           for (int i = 0; i < len; i++)
             str[i] = tolower (str[i]);
 
-          if (str == "defaults")
-            octave_sparse_params::defaults ();
+          if (str == "defaults" || str == "default")
+            {
+              // FIXME: deprecated in 4.2, remove "defaults" for 4.6 release
+              static bool warned = false;
+              if (! warned && str == "defaults")
+                {
+                  warning ("spparms: use \"default\" instead of \"defaults\"");
+                  warned = true;
+                }
+              octave_sparse_params::defaults ();
+            }
           else if (str == "tight")
             octave_sparse_params::tight ();
           else
@@ -181,7 +190,7 @@
 /*
 %!test
 %! old_vals = spparms ();  # save state
-%! spparms ("defaults");
+%! spparms ("default");
 %! vals = spparms ();
 %! assert (vals, [0 1 1 0 3 3 0.5 1.0 1.0 0.1 0.5 1.0 0.001]');
 %! [keys, vals] = spparms ();
--- a/libinterp/corefcn/sqrtm.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/sqrtm.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -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)
@@ -205,7 +206,7 @@
 @deftypefnx {Built-in Function} {[@var{s}, @var{error_estimate}] =} sqrtm (@var{A})\n\
 Compute the matrix square root of the square matrix @var{A}.\n\
 \n\
-Ref: N.J. Higham.  @cite{A New sqrtm for @sc{matlab}}.  Numerical\n\
+Ref: @nospell{N.J. Higham}.  @cite{A New sqrtm for @sc{matlab}}.  Numerical\n\
 Analysis Report No. 336, Manchester @nospell{Centre} for Computational\n\
 Mathematics, Manchester, England, January 1999.\n\
 @seealso{expm, logm}\n\
--- a/libinterp/corefcn/str2double.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/str2double.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -45,7 +45,7 @@
 static double
 single_num (std::istringstream& is)
 {
-  double num;
+  double num = 0.0;
 
   char c = is.peek ();
 
@@ -60,7 +60,8 @@
     {
       // It's infinity.
       is.get ();
-      char c1 = is.get (), c2 = is.get ();
+      char c1 = is.get ();
+      char c2 = is.get ();
       if (std::tolower (c1) == 'n' && std::tolower (c2) == 'f')
         {
           num = octave_Inf;
--- a/libinterp/corefcn/strfind.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/strfind.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -30,6 +30,8 @@
 #include <limits>
 #include <string>
 
+#include "oct-locbuf.h"
+
 #include "Cell.h"
 #include "ov.h"
 #include "defun.h"
@@ -155,7 +157,8 @@
 starting index of every such occurrence in the vector @var{idx}.\n\
 \n\
 If there is no such occurrence, or if @var{pattern} is longer\n\
-than @var{str}, then @var{idx} is the empty array @code{[]}.\n\
+than @var{str}, or if @var{pattern} itself is empty, then @var{idx} is the\n\
+empty array @code{[]}.\n\
 The optional argument @qcode{\"overlaps\"} determines whether the pattern\n\
 can match at every position in @var{str} (true), or only for unique\n\
 occurrences of the complete pattern (false).  The default is true.\n\
@@ -185,7 +188,7 @@
         @}\n\
 @end group\n\
 @end example\n\
-@seealso{findstr, strmatch, regexp, regexpi, find}\n\
+@seealso{findstr, regexp, regexpi, find}\n\
 @end deftypefn")
 {
   octave_value retval;
@@ -209,7 +212,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 ();
@@ -217,10 +221,14 @@
           qs_preprocess (needle, table);
 
           if (argstr.is_string ())
-            retval = octave_value (qs_search (needle,
-                                              argstr.char_array_value (),
-                                              table, overlaps),
-                                   true, true);
+            if (argpat.is_empty ())
+              // Return a null matrix for null pattern for MW compatibility
+              retval = Matrix ();
+            else
+              retval = octave_value (qs_search (needle,
+                                                argstr.char_array_value (),
+                                                table, overlaps),
+                                     true, true);
           else if (argstr.is_cell ())
             {
               const Cell argsc = argstr.cell_value ();
@@ -231,11 +239,15 @@
                 {
                   octave_value argse = argsc(i);
                   if (argse.is_string ())
-                    retc(i)
-                      = octave_value (qs_search (needle,
-                                                 argse.char_array_value (),
-                                                 table, overlaps),
-                                      true, true);
+                    {
+                      if (argpat.is_empty ())
+                        retc(i) = Matrix ();
+                      else
+                        retc(i) = octave_value (qs_search (needle,
+                                                     argse.char_array_value (),
+                                                     table, overlaps),
+                                                true, true);
+                    }
                   else
                     {
                       error ("strfind: each element of CELLSTR must be a string");
@@ -264,11 +276,16 @@
 %!assert (strfind ("abababa", "aba", "overlaps", false), [1, 5])
 %!assert (strfind ({"abababa", "bla", "bla"}, "a"), {[1, 3, 5, 7], 3, 3})
 %!assert (strfind ("Linux _is_ user-friendly. It just isn't ignorant-friendly or idiot-friendly.", "friendly"), [17, 50, 68])
+%!assert (strfind ("abc", ""), [])
+%!assert (strfind ("abc", {"", "b", ""}), {[], 2, []})
+%!assert (strfind ({"abc", "def"}, ""), {[], []})
 
 %!error strfind ()
 %!error strfind ("foo", "bar", 1)
+%!error <unknown option: foobar> strfind ("foo", 100, "foobar", 1)
+%!error <each element of CELLSTR must be a string> strfind ({"A", 1}, "foo")
+%!error <first argument must be a string> strfind (100, "foo")
 %!error <PATTERN must be a string> strfind ("foo", 100)
-%!error <first argument must be a string> strfind (100, "foo")
 */
 
 static Array<char>
@@ -279,7 +296,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)
     {
@@ -311,21 +330,27 @@
           else
             retsiz = siz + nidx * (rsiz - psiz);
 
-          ret.clear (dim_vector (1, retsiz));
-          const char *src = str.data (), *reps = rep.data ();
-          char *dest = ret.fortran_vec ();
-
-          octave_idx_type k = 0;
-          for (octave_idx_type i = 0; i < nidx; i++)
+          if (retsiz == 0)
+            ret.clear (dim_vector (0, 0));
+          else 
             {
-              octave_idx_type j = idx(i);
-              if (j >= k)
-                dest = std::copy (src + k, src + j, dest);
-              dest = std::copy (reps, reps + rsiz, dest);
-              k = j + psiz;
+              ret.clear (dim_vector (1, retsiz));
+              const char *src = str.data ();
+              const char *reps = rep.data ();
+              char *dest = ret.fortran_vec ();
+
+              octave_idx_type k = 0;
+              for (octave_idx_type i = 0; i < nidx; i++)
+                {
+                  octave_idx_type j = idx(i);
+                  if (j >= k)
+                    dest = std::copy (src + k, src + j, dest);
+                  dest = std::copy (reps, reps + rsiz, dest);
+                  k = j + psiz;
+                }
+
+              std::copy (src + k, src + siz, dest);
             }
-
-          std::copy (src + k, src + siz, dest);
         }
     }
 
@@ -380,7 +405,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 ();
@@ -433,6 +460,8 @@
 %!assert (strrep ("abababc", "abab", "xyz"), "xyzxyzc")
 %!assert (strrep ("abababc", "abab", "xyz", "overlaps", false), "xyzabc")
 
+%!assert (size (strrep ("a", "a", "")), [0 0])
+
 %!error strrep ()
 %!error strrep ("foo", "bar", 3, 4)
 */
--- a/libinterp/corefcn/strfns.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/strfns.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -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 ()));
@@ -912,7 +916,7 @@
 
   if (error_state)
     {
-      error ("list_in_columns: expecting cellstr or char array");
+      error ("list_in_columns: ARG must be a cellstr or char array");
       return retval;
     }
 
@@ -934,18 +938,10 @@
   if (nargin > 2)
     {
       if (args(2).is_string ())
-        {
-          prefix = args(2).string_value ();
-
-          if (error_state)
-            {
-              error ("list_in_columns: PREFIX must be a character string");
-              return retval;
-            }
-        }
+        prefix = args(2).string_value ();
       else
         {
-          error ("list_in_columns: PREFIX must be a character string");
+          error ("list_in_columns: PREFIX must be a string");
           return retval;
         }
     }
--- a/libinterp/corefcn/sub2ind.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/sub2ind.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -24,6 +24,8 @@
 #include <config.h>
 #endif
 
+#include "Array-util.h"
+#include "oct-locbuf.h"
 #include "quit.h"
 
 #include "defun.h"
--- a/libinterp/corefcn/syl.cc	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,218 +0,0 @@
-/*
-
-Copyright (C) 1996-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/>.
-
-*/
-
-// Author: A. S. Hodel <scotte@eng.auburn.edu>
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "defun.h"
-#include "error.h"
-#include "gripes.h"
-#include "oct-obj.h"
-#include "utils.h"
-
-DEFUN (syl, args, nargout,
-       "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {@var{x} =} syl (@var{A}, @var{B}, @var{C})\n\
-Solve the Sylvester equation\n\
-@tex\n\
-$$\n\
- A X + X B + C = 0\n\
-$$\n\
-@end tex\n\
-@ifnottex\n\
-\n\
-@example\n\
-A X + X B + C = 0\n\
-@end example\n\
-\n\
-@end ifnottex\n\
-using standard @sc{lapack} subroutines.  For example:\n\
-\n\
-@example\n\
-@group\n\
-syl ([1, 2; 3, 4], [5, 6; 7, 8], [9, 10; 11, 12])\n\
-   @result{} [ -0.50000, -0.66667; -0.66667, -0.50000 ]\n\
-@end group\n\
-@end example\n\
-@end deftypefn")
-{
-  octave_value retval;
-
-  int nargin = args.length ();
-
-  if (nargin != 3 || nargout > 1)
-    {
-      print_usage ();
-      return retval;
-    }
-
-  octave_value arg_a = args(0);
-  octave_value arg_b = args(1);
-  octave_value arg_c = args(2);
-
-  octave_idx_type a_nr = arg_a.rows ();
-  octave_idx_type a_nc = arg_a.columns ();
-
-  octave_idx_type b_nr = arg_b.rows ();
-  octave_idx_type b_nc = arg_b.columns ();
-
-  octave_idx_type c_nr = arg_c.rows ();
-  octave_idx_type c_nc = arg_c.columns ();
-
-  int arg_a_is_empty = empty_arg ("syl", a_nr, a_nc);
-  int arg_b_is_empty = empty_arg ("syl", b_nr, b_nc);
-  int arg_c_is_empty = empty_arg ("syl", c_nr, c_nc);
-
-  bool isfloat = arg_a.is_single_type () || arg_b.is_single_type ()
-                 || arg_c.is_single_type ();
-
-  if (arg_a_is_empty > 0 && arg_b_is_empty > 0 && arg_c_is_empty > 0)
-    if (isfloat)
-      return octave_value (FloatMatrix ());
-    else
-      return octave_value (Matrix ());
-  else if (arg_a_is_empty || arg_b_is_empty || arg_c_is_empty)
-    return retval;
-
-  // Arguments are not empty, so check for correct dimensions.
-
-  if (a_nr != a_nc || b_nr != b_nc)
-    {
-      gripe_square_matrix_required ("syl: first two parameters:");
-      return retval;
-    }
-  else if (a_nr != c_nr || b_nr != c_nc)
-    {
-      gripe_nonconformant ();
-      return retval;
-    }
-
-  // Dimensions look o.k., let's solve the problem.
-  if (isfloat)
-    {
-      if (arg_a.is_complex_type ()
-          || arg_b.is_complex_type ()
-          || arg_c.is_complex_type ())
-        {
-          // Do everything in complex arithmetic;
-
-          FloatComplexMatrix ca = arg_a.float_complex_matrix_value ();
-
-          if (error_state)
-            return retval;
-
-          FloatComplexMatrix cb = arg_b.float_complex_matrix_value ();
-
-          if (error_state)
-            return retval;
-
-          FloatComplexMatrix cc = arg_c.float_complex_matrix_value ();
-
-          if (error_state)
-            return retval;
-
-          retval = Sylvester (ca, cb, cc);
-        }
-      else
-        {
-          // Do everything in real arithmetic.
-
-          FloatMatrix ca = arg_a.float_matrix_value ();
-
-          if (error_state)
-            return retval;
-
-          FloatMatrix cb = arg_b.float_matrix_value ();
-
-          if (error_state)
-            return retval;
-
-          FloatMatrix cc = arg_c.float_matrix_value ();
-
-          if (error_state)
-            return retval;
-
-          retval = Sylvester (ca, cb, cc);
-        }
-    }
-  else
-    {
-      if (arg_a.is_complex_type ()
-          || arg_b.is_complex_type ()
-          || arg_c.is_complex_type ())
-        {
-          // Do everything in complex arithmetic;
-
-          ComplexMatrix ca = arg_a.complex_matrix_value ();
-
-          if (error_state)
-            return retval;
-
-          ComplexMatrix cb = arg_b.complex_matrix_value ();
-
-          if (error_state)
-            return retval;
-
-          ComplexMatrix cc = arg_c.complex_matrix_value ();
-
-          if (error_state)
-            return retval;
-
-          retval = Sylvester (ca, cb, cc);
-        }
-      else
-        {
-          // Do everything in real arithmetic.
-
-          Matrix ca = arg_a.matrix_value ();
-
-          if (error_state)
-            return retval;
-
-          Matrix cb = arg_b.matrix_value ();
-
-          if (error_state)
-            return retval;
-
-          Matrix cc = arg_c.matrix_value ();
-
-          if (error_state)
-            return retval;
-
-          retval = Sylvester (ca, cb, cc);
-        }
-    }
-
-  return retval;
-}
-
-/*
-%!assert (syl ([1, 2; 3, 4], [5, 6; 7, 8], [9, 10; 11, 12]), [-1/2, -2/3; -2/3, -1/2], sqrt (eps))
-%!assert (syl (single ([1, 2; 3, 4]), single ([5, 6; 7, 8]), single ([9, 10; 11, 12])), single ([-1/2, -2/3; -2/3, -1/2]), sqrt (eps ("single")))
-
-%!error syl ()
-%!error syl (1, 2, 3, 4)
-%!error <must be a square matrix> syl ([1, 2; 3, 4], [1, 2, 3; 4, 5, 6], [4, 3])
-*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/corefcn/sylvester.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,230 @@
+/*
+
+Copyright (C) 1996-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/>.
+
+*/
+
+// Author: A. S. Hodel <scotte@eng.auburn.edu>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "defun.h"
+#include "error.h"
+#include "gripes.h"
+#include "oct-obj.h"
+#include "utils.h"
+
+DEFUN (sylvester, args, nargout,
+       "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {@var{X} =} syl (@var{A}, @var{B}, @var{C})\n\
+Solve the Sylvester equation\n\
+@tex\n\
+$$\n\
+ A X + X B = C\n\
+$$\n\
+@end tex\n\
+@ifnottex\n\
+\n\
+@example\n\
+A X + X B = C\n\
+@end example\n\
+\n\
+@end ifnottex\n\
+using standard @sc{lapack} subroutines.\n\
+\n\
+For example:\n\
+\n\
+@example\n\
+@group\n\
+sylvester ([1, 2; 3, 4], [5, 6; 7, 8], [9, 10; 11, 12])\n\
+   @result{} [ 0.50000, 0.66667; 0.66667, 0.50000 ]\n\
+@end group\n\
+@end example\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+  int nargin = args.length ();
+
+  if (nargin != 3 || nargout > 1)
+    {
+      print_usage ();
+      return retval;
+    }
+
+  octave_value arg_a = args(0);
+  octave_value arg_b = args(1);
+  octave_value arg_c = args(2);
+
+  octave_idx_type a_nr = arg_a.rows ();
+  octave_idx_type a_nc = arg_a.columns ();
+
+  octave_idx_type b_nr = arg_b.rows ();
+  octave_idx_type b_nc = arg_b.columns ();
+
+  octave_idx_type c_nr = arg_c.rows ();
+  octave_idx_type c_nc = arg_c.columns ();
+
+  int arg_a_is_empty = empty_arg ("sylvester", a_nr, a_nc);
+  int arg_b_is_empty = empty_arg ("sylvester", b_nr, b_nc);
+  int arg_c_is_empty = empty_arg ("sylvester", c_nr, c_nc);
+
+  bool isfloat = arg_a.is_single_type ()
+                 || arg_b.is_single_type ()
+                 || arg_c.is_single_type ();
+
+  if (arg_a_is_empty > 0 && arg_b_is_empty > 0 && arg_c_is_empty > 0)
+    if (isfloat)
+      return octave_value (FloatMatrix ());
+    else
+      return octave_value (Matrix ());
+  else if (arg_a_is_empty || arg_b_is_empty || arg_c_is_empty)
+    return retval;
+
+  // Arguments are not empty, so check for correct dimensions.
+
+  if (a_nr != a_nc)
+    {
+      gripe_square_matrix_required ("sylvester: input A");
+      return retval;
+    }
+  else if (b_nr != b_nc)
+    {
+      gripe_square_matrix_required ("sylvester: input B");
+      return retval;
+    }
+  else if (a_nr != c_nr || b_nr != c_nc)
+    {
+      gripe_nonconformant ();
+      return retval;
+    }
+
+  if (isfloat)
+    {
+      if (arg_a.is_complex_type ()
+          || arg_b.is_complex_type ()
+          || arg_c.is_complex_type ())
+        {
+          // Do everything in complex arithmetic;
+
+          FloatComplexMatrix ca = arg_a.float_complex_matrix_value ();
+
+          if (error_state)
+            return retval;
+
+          FloatComplexMatrix cb = arg_b.float_complex_matrix_value ();
+
+          if (error_state)
+            return retval;
+
+          FloatComplexMatrix cc = arg_c.float_complex_matrix_value ();
+
+          if (error_state)
+            return retval;
+
+          retval = Sylvester (ca, cb, cc);
+        }
+      else
+        {
+          // Do everything in real arithmetic.
+
+          FloatMatrix ca = arg_a.float_matrix_value ();
+
+          if (error_state)
+            return retval;
+
+          FloatMatrix cb = arg_b.float_matrix_value ();
+
+          if (error_state)
+            return retval;
+
+          FloatMatrix cc = arg_c.float_matrix_value ();
+
+          if (error_state)
+            return retval;
+
+          retval = Sylvester (ca, cb, cc);
+        }
+    }
+  else
+    {
+      if (arg_a.is_complex_type ()
+          || arg_b.is_complex_type ()
+          || arg_c.is_complex_type ())
+        {
+          // Do everything in complex arithmetic;
+
+          ComplexMatrix ca = arg_a.complex_matrix_value ();
+
+          if (error_state)
+            return retval;
+
+          ComplexMatrix cb = arg_b.complex_matrix_value ();
+
+          if (error_state)
+            return retval;
+
+          ComplexMatrix cc = arg_c.complex_matrix_value ();
+
+          if (error_state)
+            return retval;
+
+          retval = Sylvester (ca, cb, cc);
+        }
+      else
+        {
+          // Do everything in real arithmetic.
+
+          Matrix ca = arg_a.matrix_value ();
+
+          if (error_state)
+            return retval;
+
+          Matrix cb = arg_b.matrix_value ();
+
+          if (error_state)
+            return retval;
+
+          Matrix cc = arg_c.matrix_value ();
+
+          if (error_state)
+            return retval;
+
+          retval = Sylvester (ca, cb, cc);
+        }
+    }
+
+  return retval;
+}
+
+/*
+%!assert (sylvester ([1, 2; 3, 4], [5, 6; 7, 8], [9, 10; 11, 12]), [1/2, 2/3; 2/3, 1/2], sqrt (eps))
+%!assert (sylvester (single ([1, 2; 3, 4]), single ([5, 6; 7, 8]), single ([9, 10; 11, 12])), single ([1/2, 2/3; 2/3, 1/2]), sqrt (eps ("single")))
+
+%% Test input validation
+%!error sylvester ()
+%!error sylvester (1)
+%!error sylvester (1,2)
+%!error sylvester (1, 2, 3, 4)
+%!error <input A: .* must be a square matrix> sylvester (ones (2,3), ones (2,2), ones (2,2))
+%!error <input B: .* must be a square matrix> sylvester (ones (2,2), ones (2,3), ones (2,2))
+%!error <nonconformant matrices> sylvester (ones (2,2), ones (2,2), ones (3,3))
+*/
--- a/libinterp/corefcn/symtab.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/symtab.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -38,6 +38,7 @@
 #include "dirfns.h"
 #include "input.h"
 #include "load-path.h"
+#include "ov-classdef.h"
 #include "ov-fcn.h"
 #include "ov-usr-fcn.h"
 #include "pager.h"
@@ -149,6 +150,24 @@
   return retval;
 }
 
+static void
+split_name_with_package (const std::string& name, std::string& fname,
+                         std::string& pname)
+{
+  size_t pos = name.rfind ('.');
+
+  fname.clear ();
+  pname.clear ();
+
+  if (pos != std::string::npos)
+    {
+      fname = name.substr (pos + 1);
+      pname = name.substr (0, pos);
+    }
+  else
+    fname = name;
+}
+
 // Check the load path to see if file that defined this is still
 // visible.  If the file is no longer visible, then erase the
 // definition and move on.  If the file is visible, then we also
@@ -165,11 +184,13 @@
 static inline bool
 load_out_of_date_fcn (const std::string& ff, const std::string& dir_name,
                       octave_value& function,
-                      const std::string& dispatch_type = std::string ())
+                      const std::string& dispatch_type = std::string (),
+                      const std::string& package_name = std::string ())
 {
   bool retval = false;
 
-  octave_function *fcn = load_fcn_from_file (ff, dir_name, dispatch_type);
+  octave_function *fcn = load_fcn_from_file (ff, dir_name, dispatch_type,
+                                             package_name);
 
   if (fcn)
     {
@@ -206,11 +227,13 @@
 
               bool relative = check_relative && fcn->is_relative ();
 
-              if (tc < Vlast_prompt_time
+              if (tc <= Vlast_prompt_time
                   || (relative && tc < Vlast_chdir_time))
                 {
                   bool clear_breakpoints = false;
                   std::string nm = fcn->name ();
+                  std::string pack = fcn->package_name ();
+                  std::string canonical_nm = fcn->canonical_name ();
 
                   bool is_same_file = false;
 
@@ -235,10 +258,13 @@
                           if (! dispatch_type.empty ())
                             {
                               file = load_path::find_method (dispatch_type, nm,
-                                                             dir_name);
+                                                             dir_name, pack);
 
                               if (file.empty ())
                                 {
+                                  std::string s_name;
+                                  std::string s_pack;
+
                                   const std::list<std::string>& plist
                                     = symbol_table::parent_classes (dispatch_type);
                                   std::list<std::string>::const_iterator it
@@ -246,10 +272,17 @@
 
                                   while (it != plist.end ())
                                     {
+                                      split_name_with_package (*it, s_name,
+                                                               s_pack);
+
                                       file = load_path::find_method (*it, nm,
-                                                                     dir_name);
+                                                                     dir_name,
+                                                                     s_pack);
                                       if (! file.empty ())
-                                        break;
+                                        {
+                                          pack = s_pack;
+                                          break;
+                                        }
 
                                       it++;
                                     }
@@ -261,7 +294,7 @@
                             file = lookup_autoload (nm);
 
                           if (file.empty ())
-                            file = load_path::find_fcn (nm, dir_name);
+                            file = load_path::find_fcn (nm, dir_name, pack);
                         }
 
                       if (! file.empty ())
@@ -303,7 +336,8 @@
                                 {
                                   retval = load_out_of_date_fcn (ff, dir_name,
                                                                  function,
-                                                                 dispatch_type);
+                                                                 dispatch_type,
+                                                                 pack);
 
                                   clear_breakpoints = true;
                                 }
@@ -322,7 +356,7 @@
                       // place of the old.
 
                       retval = load_out_of_date_fcn (file, dir_name, function,
-                                                     dispatch_type);
+                                                     dispatch_type, pack);
 
                       clear_breakpoints = true;
                     }
@@ -330,7 +364,8 @@
                   // If the function has been replaced then clear any
                   // breakpoints associated with it
                   if (clear_breakpoints)
-                    bp_table::remove_all_breakpoints_in_file (nm, true);
+                    bp_table::remove_all_breakpoints_in_file (canonical_nm,
+                                                              true);
                 }
             }
         }
@@ -383,11 +418,13 @@
 
   std::string dir_name;
 
-  std::string file_name = load_path::find_method (name, name, dir_name);
+  std::string file_name = load_path::find_method (name, name, dir_name,
+                                                  package_name);
 
   if (! file_name.empty ())
     {
-      octave_function *fcn = load_fcn_from_file (file_name, dir_name, name);
+      octave_function *fcn = load_fcn_from_file (file_name, dir_name, name,
+                                                 package_name);
 
       if (fcn)
         {
@@ -396,6 +433,31 @@
           class_constructors[name] = retval;
         }
     }
+  else
+    {
+      // Classdef constructors can be defined anywhere in the path, not
+      // necessarily in @-folders. Look for a normal function and load it.
+      // If the loaded function is a classdef constructor, store it as such
+      // and restore function_on_path to its previous value.
+
+      octave_value old_function_on_path = function_on_path;
+
+      octave_value maybe_cdef_ctor = find_user_function ();
+
+      if (maybe_cdef_ctor.is_defined ())
+        {
+          octave_function *fcn = maybe_cdef_ctor.function_value (true);
+
+          if (fcn && fcn->is_classdef_constructor ())
+            {
+              retval = maybe_cdef_ctor;
+
+              class_constructors[name] = retval;
+
+              function_on_path = old_function_on_path;
+            }
+        }
+    }
 
   return retval;
 }
@@ -406,47 +468,57 @@
 {
   octave_value retval;
 
-  if (name == dispatch_type)
+  if (full_name () == dispatch_type)
     retval = load_class_constructor ();
   else
     {
-      std::string dir_name;
+      octave_function *cm = cdef_manager::find_method_symbol (name,
+                                                              dispatch_type);
 
-      std::string file_name = load_path::find_method (dispatch_type, name,
-                                                      dir_name);
+      if (cm)
+        retval = octave_value (cm);
 
-      if (! file_name.empty ())
+      if (! retval.is_defined ())
         {
-          octave_function *fcn = load_fcn_from_file (file_name, dir_name,
-                                                     dispatch_type);
+          std::string dir_name;
 
-          if (fcn)
+          std::string file_name = load_path::find_method (dispatch_type, name,
+                                                          dir_name);
+
+          if (! file_name.empty ())
             {
-              retval = octave_value (fcn);
+              octave_function *fcn = load_fcn_from_file (file_name, dir_name,
+                                                         dispatch_type);
 
-              class_methods[dispatch_type] = retval;
-            }
-        }
+              if (fcn)
+                {
+                  retval = octave_value (fcn);
 
-      if (retval.is_undefined ())
-        {
-          // Search parent classes
+                  class_methods[dispatch_type] = retval;
+                }
+            }
 
-          const std::list<std::string>& plist = parent_classes (dispatch_type);
-
-          std::list<std::string>::const_iterator it = plist.begin ();
-
-          while (it != plist.end ())
+          if (retval.is_undefined ())
             {
-              retval = find_method (*it);
+              // Search parent classes
 
-              if (retval.is_defined ())
+              const std::list<std::string>& plist =
+                parent_classes (dispatch_type);
+
+              std::list<std::string>::const_iterator it = plist.begin ();
+
+              while (it != plist.end ())
                 {
-                  class_methods[dispatch_type] = retval;
-                  break;
+                  retval = find_method (*it);
+
+                  if (retval.is_defined ())
+                    {
+                      class_methods[dispatch_type] = retval;
+                      break;
+                    }
+
+                  it++;
                 }
-
-              it++;
             }
         }
     }
@@ -787,6 +859,13 @@
   if (fcn.is_defined ())
     return fcn;
 
+  // Package
+
+  fcn = find_package ();
+
+  if (fcn.is_defined ())
+    return fcn;
+
   // Built-in function (might be undefined).
 
   return built_in_function;
@@ -975,7 +1054,7 @@
 
           std::string dir_name = file_name.substr (0, pos);
 
-          octave_function *fcn = load_fcn_from_file (file_name, dir_name,
+          octave_function *fcn = load_fcn_from_file (file_name, dir_name, "",
                                                      "", name, true);
 
           if (fcn)
@@ -998,11 +1077,13 @@
     {
       std::string dir_name;
 
-      std::string file_name = load_path::find_fcn (name, dir_name);
+      std::string file_name = load_path::find_fcn (name, dir_name,
+                                                   package_name);
 
       if (! file_name.empty ())
         {
-          octave_function *fcn = load_fcn_from_file (file_name, dir_name);
+          octave_function *fcn = load_fcn_from_file (file_name, dir_name, "",
+                                                     package_name);
 
           if (fcn)
             function_on_path = octave_value (fcn);
@@ -1012,6 +1093,25 @@
   return function_on_path;
 }
 
+octave_value
+symbol_table::fcn_info::fcn_info_rep::find_package (void)
+{
+  // FIXME: implement correct way to check out of date package
+  //if (package.is_defined ())
+  //  out_of_date_check (package);
+
+  if (! (error_state || package.is_defined ()))
+    {
+      octave_function * fcn =
+        cdef_manager::find_package_symbol (full_name ());
+
+      if (fcn)
+        package = octave_value (fcn);
+    }
+
+  return package;
+}
+
 // Insert INF_CLASS in the set of class names that are considered
 // inferior to SUP_CLASS.  Return FALSE if INF_CLASS is currently
 // marked as superior to  SUP_CLASS.
@@ -1069,10 +1169,11 @@
 symbol_table::fcn_info::fcn_info_rep::dump (std::ostream& os,
                                             const std::string& prefix) const
 {
-  os << prefix << name
+  os << prefix << full_name ()
      << " ["
      << (cmdline_function.is_defined () ? "c" : "")
      << (built_in_function.is_defined () ? "b" : "")
+     << (package.is_defined () ? "p" : "")
      << "]\n";
 
   std::string tprefix = prefix + "  ";
@@ -1575,10 +1676,9 @@
 
   if (nargin == 1)
     {
-      std::string sval = args(0).string_value ();
-
-      if (! error_state)
+      if (args(0).is_string ())
         {
+          std::string sval = args(0).string_value ();
           if (sval == "all")
             Vignore_function_time_stamp = 2;
           else if (sval == "system")
@@ -1586,7 +1686,7 @@
           else if (sval == "none")
             Vignore_function_time_stamp = 0;
           else
-            error ("ignore_function_time_stamp: expecting argument to be \"all\", \"system\", or \"none\"");
+            error ("ignore_function_time_stamp: argument must be \"all\", \"system\", or \"none\"");
         }
       else
         error ("ignore_function_time_stamp: expecting argument to be character string");
--- a/libinterp/corefcn/symtab.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/symtab.h	Mon Jan 12 09:17:35 2015 -0800
@@ -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 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/syscalls.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -117,6 +117,7 @@
 If successful, @var{fid} is greater than zero and contains the new file\n\
 ID@.  Otherwise, @var{fid} is negative and @var{msg} contains a\n\
 system-dependent error message.\n\
+@seealso{fopen, fclose, fcntl}\n\
 @end deftypefn")
 {
   octave_value_list retval;
@@ -189,10 +190,10 @@
 
   if (nargin == 1 || nargin == 2)
     {
-      std::string exec_file = args(0).string_value ();
+      if (args(0).is_string ())
+        {
+          std::string exec_file = args(0).string_value ();
 
-      if (! error_state)
-        {
           string_vector exec_args;
 
           if (nargin == 2)
@@ -211,7 +212,7 @@
                     exec_args[i+1] = tmp[i];
                 }
               else
-                error ("exec: arguments must be character strings");
+                error ("exec: all arguments must be strings");
             }
           else
             {
@@ -299,10 +300,10 @@
 
   if (nargin >= 1 && nargin <= 3)
     {
-      std::string exec_file = args(0).string_value ();
+      if (args(0).is_string ())
+        {
+          std::string exec_file = args(0).string_value ();
 
-      if (! error_state)
-        {
           string_vector arg_list;
 
           if (nargin >= 2)
@@ -321,7 +322,7 @@
                     arg_list[i+1] = tmp[i];
                 }
               else
-                error ("popen2: arguments must be character strings");
+                error ("popen2: all arguments must be strings");
             }
           else
             {
@@ -366,7 +367,7 @@
                 }
             }
           else
-            error ("popen2: arguments must be character strings");
+            error ("popen2: all arguments must be strings");
         }
       else
         error ("popen2: COMMAND argument must be a string");
@@ -448,8 +449,9 @@
 DEFUNX ("fcntl", Ffcntl, args, ,
         "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {[@var{err}, @var{msg}] =} fcntl (@var{fid}, @var{request}, @var{arg})\n\
-Change the properties of the open file @var{fid}.  The following values\n\
-may be passed as @var{request}:\n\
+Change the properties of the open file @var{fid}.\n\
+\n\
+The following values may be passed as @var{request}:\n\
 \n\
 @vtable @code\n\
 @item F_DUPFD\n\
@@ -500,6 +502,7 @@
 If successful, @var{err} is 0 and @var{msg} is an empty string.\n\
 Otherwise, @var{err} is nonzero and @var{msg} contains a\n\
 system-dependent error message.\n\
+@seealso{fopen, dup2}\n\
 @end deftypefn")
 {
   octave_value_list retval;
@@ -511,7 +514,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)
         {
@@ -1622,10 +1625,9 @@
 
   if (args.length () == 1)
     {
-      std::string name = args(0).string_value ();
-
-      if (! error_state)
+      if (args(0).is_string ())
         {
+          std::string name = args(0).string_value ();
           std::string msg;
 
           std::string result = octave_canonicalize_file_name (name, msg);
@@ -1635,7 +1637,7 @@
           retval(0) = result;
         }
       else
-        error ("canonicalize_file_name: NAME must be a character string");
+        error ("canonicalize_file_name: NAME must be a string");
     }
   else
     print_usage ();
@@ -1878,7 +1880,7 @@
 
 DEFUNX ("O_TRUNC", FO_TRUNC, args, ,
         "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} O_TRUNC ()\n\
+@deftypefn {Built-in Function} {} O_TRUNC ()\n\
 Return the numerical value of the file status flag that may be\n\
 returned by @code{fcntl} to indicate that if file exists, it should\n\
 be truncated when writing.\n\
@@ -1959,3 +1961,4 @@
 {
   return const_value (args, WCONTINUE);
 }
+
--- a/libinterp/corefcn/sysdep.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/sysdep.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -106,6 +106,7 @@
 
 #define WIN32_LEAN_AND_MEAN
 #include <tlhelp32.h>
+#include <windows.h>
 
 static void
 w32_set_octave_home (void)
@@ -179,6 +180,36 @@
 }
 #endif
 
+DEFUN (__w32_shell_execute__, args, ,
+           "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {} __w32_shell_execute__ (@var{file})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  bool retval = false;
+
+#if defined (__WIN32__) && ! defined (_POSIX_VERSION)
+  if (args.length () == 1)
+    {
+      std::string file = args(0).string_value ();
+
+      if (! error_state)
+        {
+          HINSTANCE status = ShellExecute (0, 0, file.c_str (), 0, 0, SW_SHOWNORMAL);
+
+          // ShellExecute returns a value greater than 32 if successful.
+          retval = (reinterpret_cast<ptrdiff_t> (status) > 32);
+        }
+      else
+        error ("__w32_shell_execute__: expecting argument to be a file name");
+    }
+  else
+    print_usage ();
+#endif
+
+  return octave_value (retval);
+}
+
 #if defined (__MINGW32__)
 static void
 MINGW_init (void)
@@ -563,6 +594,7 @@
 \n\
 @noindent\n\
 returns a string containing the value of your path.\n\
+@seealso{setenv, unsetenv}\n\
 @end deftypefn")
 {
   octave_value retval;
@@ -582,11 +614,20 @@
   return retval;
 }
 
-DEFUN (putenv, args, ,
+/*
+%!assert (ischar (getenv ("OCTAVE_HOME")))
+*/
+
+DEFUN (setenv, args, ,
        "-*- texinfo -*-\n\
-@deftypefn  {Built-in Function} {} putenv (@var{var}, @var{value})\n\
-@deftypefnx {Built-in Function} {} setenv (@var{var}, @var{value})\n\
+@deftypefn  {Built-in Function} {} setenv (@var{var}, @var{value})\n\
+@deftypefnx {Built-in Function} {} setenv (@var{var})\n\
+@deftypefnx {Built-in Function} {} putenv (@dots{})\n\
 Set the value of the environment variable @var{var} to @var{value}.\n\
+\n\
+If no @var{value} is specified then the variable will be assigned the null\n\
+string.\n\
+@seealso{unsetenv, getenv}\n\
 @end deftypefn")
 {
   octave_value_list retval;
@@ -595,20 +636,20 @@
 
   if (nargin == 2 || nargin == 1)
     {
-      std::string var = args(0).string_value ();
+      if (args(0).is_string ())
+        {
+          std::string var = args(0).string_value ();
 
-      if (! error_state)
-        {
           std::string val = (nargin == 2
                              ? args(1).string_value () : std::string ());
 
           if (! error_state)
             octave_env::putenv (var, val);
           else
-            error ("putenv: VALUE must be a string");
+            error ("setenv: VALUE must be a string");
         }
       else
-        error ("putenv: VAR must be a string");
+        error ("setenv: VAR must be a string");
     }
   else
     print_usage ();
@@ -616,13 +657,48 @@
   return retval;
 }
 
-DEFALIAS (setenv, putenv);
+DEFALIAS (putenv, setenv);
 
 /*
-%!assert (ischar (getenv ("OCTAVE_HOME")))
 %!test
 %! setenv ("dummy_variable_that_cannot_matter", "foobar");
 %! assert (getenv ("dummy_variable_that_cannot_matter"), "foobar");
+%! unsetenv ("dummy_variable_that_cannot_matter");
+%! assert (getenv ("dummy_variable_that_cannot_matter"), "");
+*/
+
+DEFUN (unsetenv, args, ,
+       "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {@var{status} =} unsetenv (@var{var})\n\
+Delete the environment variable @var{var}.\n\
+\n\
+Return 0 if the variable was deleted, or did not exist, and -1 if an error\n\
+occurred.\n\
+@seealso{setenv, getenv}\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+  int nargin = args.length ();
+
+  if (nargin == 1)
+    {
+      std::string tmp = args(0).string_value ();
+
+      if (! error_state)
+        {
+          int status = gnulib::unsetenv (tmp.c_str ());
+          retval = status;
+        }
+    }
+  else
+    print_usage ();
+
+  return retval;
+}
+
+/*
+## Test for unsetenv is in setenv test
 */
 
 // FIXME: perhaps kbhit should also be able to print a prompt?
--- a/libinterp/corefcn/time.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/time.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -123,6 +123,8 @@
 
 /*
 %!assert (time () > 0)
+
+%!error time (1)
 */
 
 DEFUN (gmtime, args, ,
@@ -299,7 +301,9 @@
 %!assert (datestr (datenum (1795, 1, 1), 0), "01-Jan-1795 00:00:00")
 
 %!error mktime ()
+%!error mktime (1)
 %!error mktime (1, 2, 3)
+%!error mktime (struct ("year", "foo"))
 */
 
 DEFUN (strftime, args, ,
@@ -459,10 +463,10 @@
 
   if (args.length () == 2)
     {
-      std::string fmt = args(0).string_value ();
+      if (args(0).is_string ())
+        {
+          std::string fmt = args(0).string_value ();
 
-      if (! error_state)
-        {
           octave_scalar_map map = args(1).scalar_map_value ();
 
           if (! error_state)
@@ -494,6 +498,8 @@
 %!assert (ischar (strftime ("%m%U%w%W%x%y%Y", localtime (time ()))));
 
 %!error strftime ()
+%!error strftime ("foo", 1)
+%!error strftime ("foo", struct ("year", "foo"))
 %!error strftime ("foo", localtime (time ()), 1)
 */
 
@@ -513,14 +519,14 @@
 
   if (args.length () == 2)
     {
-      std::string str = args(0).string_value ();
-
-      if (! error_state)
+      if (args(0).is_string ())
         {
-          std::string fmt = args(1).string_value ();
+          std::string str = args(0).string_value ();
 
-          if (! error_state)
+          if (args(1).is_string ())
             {
+              std::string fmt = args(1).string_value ();
+
               octave_strptime t (str, fmt);
 
               retval(1) = t.characters_converted ();
@@ -537,3 +543,23 @@
 
   return retval;
 }
+
+/*
+%!test
+%! fmt = "%Y-%m-%d %H:%M:%S";
+%! s = strftime (fmt, localtime (time ()));
+%! ts = strptime  (s, fmt);
+%! assert (isstruct (ts));
+%! assert (isfield (ts, "usec"));
+%! assert (isfield (ts, "year"));
+%! assert (isfield (ts, "mon"));
+%! assert (isfield (ts, "mday"));
+%! assert (isfield (ts, "sec"));
+%! assert (isfield (ts, "min"));
+%! assert (isfield (ts, "wday"));
+%! assert (isfield (ts, "hour"));
+%! assert (isfield (ts, "isdst"));
+%! assert (isfield (ts, "yday"));
+
+%!error strptime ()
+*/
--- a/libinterp/corefcn/toplev.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/toplev.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -104,6 +104,32 @@
 
 octave_call_stack *octave_call_stack::instance = 0;
 
+std::string
+octave_call_stack::stack_frame::fcn_file_name (void) const
+{
+  return m_fcn ? m_fcn->fcn_file_name () : std::string ();
+}
+
+std::string
+octave_call_stack::stack_frame::fcn_name (bool print_subfn) const
+{
+  std::string retval;
+
+  if (m_fcn)
+    {
+      std::string parent_fcn_name = m_fcn->parent_fcn_name ();
+
+      if (print_subfn && ! parent_fcn_name.empty ())
+        retval = parent_fcn_name + Vfilemarker;
+
+      retval += m_fcn->name ();
+    }
+  else
+    retval = "<unknown>";
+  
+  return retval;
+}
+
 void
 octave_call_stack::create_instance (void)
 {
@@ -124,8 +150,8 @@
 
   if (! cs.empty ())
     {
-      const call_stack_elt& elt = cs[curr_frame];
-      retval = elt.line;
+      const stack_frame& elt = cs[curr_frame];
+      retval = elt.m_line;
     }
 
   return retval;
@@ -138,8 +164,8 @@
 
   if (! cs.empty ())
     {
-      const call_stack_elt& elt = cs[curr_frame];
-      retval = elt.column;
+      const stack_frame& elt = cs[curr_frame];
+      retval = elt.m_column;
     }
 
   return retval;
@@ -154,15 +180,15 @@
 
   while (p != cs.begin ())
     {
-      const call_stack_elt& elt = *(--p);
+      const stack_frame& elt = *(--p);
 
-      octave_function *f = elt.fcn;
+      octave_function *f = elt.m_fcn;
 
       if (f && f->is_user_code ())
         {
-          if (elt.line > 0)
+          if (elt.m_line > 0)
             {
-              retval = elt.line;
+              retval = elt.m_line;
               break;
             }
         }
@@ -180,15 +206,15 @@
 
   while (p != cs.begin ())
     {
-      const call_stack_elt& elt = *(--p);
+      const stack_frame& elt = *(--p);
 
-      octave_function *f = elt.fcn;
+      octave_function *f = elt.m_fcn;
 
       if (f && f->is_user_code ())
         {
-          if (elt.column)
+          if (elt.m_column)
             {
-              retval = elt.column;
+              retval = elt.m_column;
               break;
             }
         }
@@ -206,7 +232,7 @@
   curr_user_frame = 0;
 
   // Look for the caller of dbstack.
-  size_t frame = cs[curr_frame].prev;
+  size_t xframe = cs[curr_frame].m_prev;
 
   bool found = false;
 
@@ -214,9 +240,9 @@
 
   for (const_reverse_iterator p = cs.rbegin (); p != cs.rend (); p++)
     {
-      octave_function *f = (*p).fcn;
+      octave_function *f = (*p).m_fcn;
 
-      if (--k == frame)
+      if (--k == xframe)
         found = true;
 
       if (f && f->is_user_code ())
@@ -244,9 +270,9 @@
 
   while (p != cs.begin ())
     {
-      const call_stack_elt& elt = *(--p);
+      const stack_frame& elt = *(--p);
 
-      octave_function *f = elt.fcn;
+      octave_function *f = elt.m_fcn;
 
       if (f && f->is_user_code ())
         {
@@ -272,9 +298,9 @@
 
   while (p != cs.begin ())
     {
-      const call_stack_elt& elt = *(--p);
+      const stack_frame& elt = *(--p);
 
-      octave_function *f = elt.fcn;
+      octave_function *f = elt.m_fcn;
 
       if (f && ! f->is_user_script ())
         {
@@ -299,10 +325,12 @@
   return octave_map (dim_vector (0, 1), bt_fields);
 }
 
-octave_map
-octave_call_stack::do_backtrace (size_t nskip,
-                                 octave_idx_type& curr_user_frame) const
+std::list<octave_call_stack::stack_frame>
+octave_call_stack::do_backtrace_frames (size_t nskip,
+                                        octave_idx_type& curr_user_frame) const
 {
+  std::list<octave_call_stack::stack_frame> retval;
+
   size_t user_code_frames = do_num_user_code_frames (curr_user_frame);
 
   size_t nframes = nskip <= user_code_frames ? user_code_frames - nskip : 0;
@@ -310,6 +338,37 @@
   // Our list is reversed.
   curr_user_frame = nframes - curr_user_frame - 1;
 
+  if (nframes > 0)
+    {
+      for (const_reverse_iterator p = cs.rbegin (); p != cs.rend (); p++)
+        {
+          const stack_frame& elt = *p;
+
+          octave_function *f = elt.m_fcn;
+
+          if (f && f->is_user_code ())
+            {
+              if (nskip > 0)
+                nskip--;
+              else
+                retval.push_back (elt);
+            }
+        }
+    }
+
+  return retval;
+}
+
+octave_map
+octave_call_stack::do_backtrace (size_t nskip,
+                                 octave_idx_type& curr_user_frame,
+                                 bool print_subfn) const
+{
+  std::list<octave_call_stack::stack_frame> frames
+    = do_backtrace_frames (nskip, curr_user_frame);
+
+  size_t nframes = frames.size ();
+  
   octave_map retval (dim_vector (nframes, 1), bt_fields);
 
   Cell& file = retval.contents (0);
@@ -319,39 +378,21 @@
   Cell& scope = retval.contents (4);
   Cell& context = retval.contents (5);
 
-  if (nframes > 0)
-    {
-      int k = 0;
+  octave_idx_type k = 0;
 
-      for (const_reverse_iterator p = cs.rbegin (); p != cs.rend (); p++)
-        {
-          const call_stack_elt& elt = *p;
-
-          octave_function *f = elt.fcn;
+  for (std::list<octave_call_stack::stack_frame>::const_iterator p = frames.begin ();
+       p != frames.end (); p++)
+    {
+      const stack_frame& elt = *p;
 
-          if (f && f->is_user_code ())
-            {
-              if (nskip > 0)
-                nskip--;
-              else
-                {
-                  scope(k) = elt.scope;
-                  context(k) = elt.context;
+      scope(k) = elt.m_scope;
+      context(k) = elt.m_context;
+      file(k) = elt.fcn_file_name ();
+      name(k) = elt.fcn_name (print_subfn);
+      line(k) = elt.m_line;
+      column(k) = elt.m_column;
 
-                  file(k) = f->fcn_file_name ();
-                  std::string parent_fcn_name = f->parent_fcn_name ();
-                  if (parent_fcn_name == std::string ())
-                    name(k) = f->name ();
-                  else
-                    name(k) = f->parent_fcn_name () + Vfilemarker + f->name ();
-
-                  line(k) = elt.line;
-                  column(k) = elt.column;
-
-                  k++;
-                }
-            }
-        }
+      k++;
     }
 
   return retval;
@@ -368,21 +409,16 @@
 
       curr_frame = n;
 
-      const call_stack_elt& elt = cs[n];
+      const stack_frame& elt = cs[n];
 
-      symbol_table::set_scope_and_context (elt.scope, elt.context);
+      symbol_table::set_scope_and_context (elt.m_scope, elt.m_context);
 
       if (verbose)
-        {
-          octave_function *f = elt.fcn;
-          std::string nm = f ? f->name () : std::string ("<unknown>");
-
-          octave_stdout << "stopped in " << nm
-                        << " at line " << elt.line
-                        << " column " << elt.column
-                        << " (" << elt.scope << "[" << elt.context << "])"
-                        << std::endl;
-        }
+        octave_stdout << "stopped in " << elt.fcn_name ()
+                      << " at line " << elt.m_line
+                      << " column " << elt.m_column
+                      << " (" << elt.m_scope << "[" << elt.m_context << "])"
+                      << std::endl;
     }
 
   return retval;
@@ -401,20 +437,20 @@
     incr = 1;
 
   // Start looking with the caller of dbup/dbdown/keyboard.
-  size_t frame = cs[curr_frame].prev;
+  size_t xframe = cs[curr_frame].m_prev;
 
   while (true)
     {
-      if ((incr < 0 && frame == 0) || (incr > 0 && frame == cs.size () - 1))
+      if ((incr < 0 && xframe == 0) || (incr > 0 && xframe == cs.size () - 1))
         break;
 
-      frame += incr;
+      xframe += incr;
 
-      const call_stack_elt& elt = cs[frame];
+      const stack_frame& elt = cs[xframe];
 
-      octave_function *f = elt.fcn;
+      octave_function *f = elt.m_fcn;
 
-      if (frame == 0 || (f && f->is_user_code ()))
+      if (xframe == 0 || (f && f->is_user_code ()))
         {
           if (nskip > 0)
             nskip--;
@@ -423,10 +459,10 @@
 
           if (nskip == 0)
             {
-              curr_frame = frame;
-              cs[cs.size () - 1].prev = curr_frame;
+              curr_frame = xframe;
+              cs[cs.size () - 1].m_prev = curr_frame;
 
-              symbol_table::set_scope_and_context (elt.scope, elt.context);
+              symbol_table::set_scope_and_context (elt.m_scope, elt.m_context);
 
               if (verbose)
                 {
@@ -434,7 +470,7 @@
 
                   if (f)
                     buf << "stopped in " << f->name ()
-                        << " at line " << elt.line << std::endl;
+                        << " at line " << elt.m_line << std::endl;
                   else
                     buf << "at top level" << std::endl;
 
@@ -445,6 +481,8 @@
               break;
             }
         }
+      else if (incr == 0)  // Break out of infinite loop by choosing an incr. 
+        incr = -1;
 
       // There is no need to set scope and context here.  That will
       // happen when the dbup/dbdown/keyboard frame is popped and we
@@ -457,19 +495,19 @@
 void
 octave_call_stack::do_goto_caller_frame (void)
 {
-  size_t frame = curr_frame;
+  size_t xframe = curr_frame;
 
   bool skipped = false;
 
-  while (frame != 0)
+  while (xframe != 0)
     {
-      frame = cs[frame].prev;
+      xframe = cs[xframe].m_prev;
 
-      const call_stack_elt& elt = cs[frame];
+      const stack_frame& elt = cs[xframe];
 
-      octave_function *f = elt.fcn;
+      octave_function *f = elt.m_fcn;
 
-      if (elt.scope == cs[0].scope || (f && f->is_user_code ()))
+      if (elt.m_scope == cs[0].m_scope || (f && f->is_user_code ()))
         {
           if (! skipped)
             // We found the current user code frame, so skip it.
@@ -477,14 +515,14 @@
           else
             {
               // We found the caller user code frame.
-              call_stack_elt tmp (elt);
-              tmp.prev = curr_frame;
+              stack_frame tmp (elt);
+              tmp.m_prev = curr_frame;
 
               curr_frame = cs.size ();
 
               cs.push_back (tmp);
 
-              symbol_table::set_scope_and_context (tmp.scope, tmp.context);
+              symbol_table::set_scope_and_context (tmp.m_scope, tmp.m_context);
 
               break;
             }
@@ -495,45 +533,14 @@
 void
 octave_call_stack::do_goto_base_frame (void)
 {
-  call_stack_elt tmp (cs[0]);
-  tmp.prev = curr_frame;
+  stack_frame tmp (cs[0]);
+  tmp.m_prev = curr_frame;
 
   curr_frame = cs.size ();
 
   cs.push_back (tmp);
 
-  symbol_table::set_scope_and_context (tmp.scope, tmp.context);
-}
-
-void
-octave_call_stack::do_backtrace_error_message (void) const
-{
-  if (error_state > 0)
-    {
-      error_state = -1;
-
-      error ("called from:");
-    }
-
-  if (! cs.empty ())
-    {
-      const call_stack_elt& elt = cs.back ();
-
-      octave_function *fcn = elt.fcn;
-
-      std::string fcn_name = "?unknown?";
-
-      if (fcn)
-        {
-          fcn_name = fcn->fcn_file_name ();
-
-          if (fcn_name.empty ())
-            fcn_name = fcn->name ();
-        }
-
-      error ("  %s at line %d, column %d",
-             fcn_name.c_str (), elt.line, elt.column);
-    }
+  symbol_table::set_scope_and_context (tmp.m_scope, tmp.m_context);
 }
 
 void
@@ -612,7 +619,7 @@
                     {
                       if (! (interactive || forced_interactive))
                         {
-                          // We should exit with a non-zero status.
+                          // We should exit with a nonzero status.
                           retval = 1;
                           break;
                         }
@@ -651,6 +658,8 @@
     }
   while (retval == 0);
 
+  octave_stdout << "\n";
+
   if (retval == EOF)
     retval = 0;
 
@@ -779,11 +788,20 @@
 
 DEFUN (quit, args, ,
        "-*- texinfo -*-\n\
-@deftypefn  {Built-in Function} {} exit (@var{status})\n\
+@deftypefn  {Built-in Function} {} exit\n\
+@deftypefnx {Built-in Function} {} exit (@var{status})\n\
+@deftypefnx {Built-in Function} {} quit\n\
 @deftypefnx {Built-in Function} {} quit (@var{status})\n\
-Exit the current Octave session.  If the optional integer value\n\
-@var{status} is supplied, pass that value to the operating system as the\n\
-Octave's exit status.  The default value is zero.\n\
+Exit the current Octave session.\n\
+\n\
+If the optional integer value @var{status} is supplied, pass that value to\n\
+the operating system as Octave's exit status.  The default value is zero.\n\
+\n\
+When exiting, Octave will attempt to run the m-file @file{finish.m} if it\n\
+exists.  User commands to save the workspace or clean up temporary files\n\
+may be placed in that file.  Alternatively, another m-file may be scheduled\n\
+to run using @code{atexit}.\n\
+@seealso{atexit}\n\
 @end deftypefn")
 {
   octave_value_list retval;
@@ -992,10 +1010,10 @@
 
       if (nargin == 3)
         {
-          std::string type_str = args(2).string_value ();
+          if (args(2).is_string ())
+            {
+              std::string type_str = args(2).string_value ();
 
-          if (! error_state)
-            {
               if (type_str == "sync")
                 type = et_sync;
               else if (type_str == "async")
@@ -1008,7 +1026,7 @@
             }
           else
             {
-              error ("system: TYPE must be a character string");
+              error ("system: TYPE must be a string");
               return retval;
             }
         }
@@ -1148,7 +1166,9 @@
        "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {} atexit (@var{fcn})\n\
 @deftypefnx {Built-in Function} {} atexit (@var{fcn}, @var{flag})\n\
-Register a function to be called when Octave exits.  For example,\n\
+Register a function to be called when Octave exits.\n\
+\n\
+For example,\n\
 \n\
 @example\n\
 @group\n\
@@ -1180,6 +1200,7 @@
 from the list, so if a function was placed in the list multiple\n\
 times with @code{atexit}, it must also be removed from the list\n\
 multiple times.\n\
+@seealso{quit}\n\
 @end deftypefn")
 {
   octave_value_list retval;
@@ -1188,10 +1209,10 @@
 
   if (nargin == 1 || nargin == 2)
     {
-      std::string arg = args(0).string_value ();
+      if (args(0).is_string ())
+        {
+          std::string arg = args(0).string_value ();
 
-      if (! error_state)
-        {
           bool add_mode = true;
 
           if (nargin == 2)
@@ -1228,12 +1249,13 @@
        "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {} octave_config_info ()\n\
 @deftypefnx {Built-in Function} {} octave_config_info (@var{option})\n\
-Return a structure containing configuration and installation\n\
-information for Octave.\n\
+Return a structure containing configuration and installation information for\n\
+Octave.\n\
 \n\
 If @var{option} is a string, return the configuration information for the\n\
 specified option.\n\
 \n\
+@seealso{computer}\n\
 @end deftypefn")
 {
   octave_value retval;
@@ -1274,8 +1296,6 @@
     { false, "CAMD_LIBS", OCTAVE_CONF_CAMD_LIBS },
     { false, "CARBON_LIBS", OCTAVE_CONF_CARBON_LIBS },
     { false, "CC", OCTAVE_CONF_CC },
-    // FIXME: CC_VERSION is deprecated.  Remove in version 3.12
-    { false, "CC_VERSION", OCTAVE_CONF_CC_VERSION },
     { false, "CCOLAMD_CPPFLAGS", OCTAVE_CONF_CCOLAMD_CPPFLAGS },
     { false, "CCOLAMD_LDFLAGS", OCTAVE_CONF_CCOLAMD_LDFLAGS },
     { false, "CCOLAMD_LIBS", OCTAVE_CONF_CCOLAMD_LIBS },
@@ -1298,8 +1318,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 },
@@ -1426,6 +1444,7 @@
     { true, "man1dir", OCTAVE_MAN1DIR },
     { false, "man1ext", OCTAVE_MAN1EXT },
     { true, "mandir", OCTAVE_MANDIR },
+    { true, "octdatadir", OCTAVE_OCTDATADIR },
     { true, "octfiledir", OCTAVE_OCTFILEDIR },
     { true, "octetcdir", OCTAVE_OCTETCDIR },
     { true, "octincludedir", OCTAVE_OCTINCLUDEDIR },
--- a/libinterp/corefcn/toplev.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/toplev.h	Mon Jan 12 09:17:35 2015 -0800
@@ -76,41 +76,52 @@
 OCTINTERP_API
 octave_call_stack
 {
-private:
-
-  struct call_stack_elt
-  {
-    call_stack_elt (octave_function *f, symbol_table::scope_id s,
-                    symbol_table::context_id c, size_t p = 0)
-      : fcn (f), line (-1), column (-1), scope (s), context (c), prev (p)
-    { }
-
-    call_stack_elt (const call_stack_elt& elt)
-      : fcn (elt.fcn), line (elt.line), column (elt.column),
-        scope (elt.scope), context (elt.context), prev (elt.prev)
-    { }
-
-    octave_function *fcn;
-    int line;
-    int column;
-    symbol_table::scope_id scope;
-    symbol_table::context_id context;
-    size_t prev;
-  };
-
 protected:
 
   octave_call_stack (void) : cs (), curr_frame (0) { }
 
 public:
 
-  typedef std::deque<call_stack_elt>::iterator iterator;
-  typedef std::deque<call_stack_elt>::const_iterator const_iterator;
+  class stack_frame
+  {
+  public:
+
+    friend class octave_call_stack;
+
+    stack_frame (octave_function *fcn = 0, symbol_table::scope_id scope = 0,
+                 symbol_table::context_id context = 0, size_t prev = 0)
+      : m_fcn (fcn), m_line (-1), m_column (-1), m_scope (scope),
+        m_context (context), m_prev (prev)
+    { }
+
+    stack_frame (const stack_frame& elt)
+      : m_fcn (elt.m_fcn), m_line (elt.m_line), m_column (elt.m_column),
+        m_scope (elt.m_scope), m_context (elt.m_context), m_prev (elt.m_prev)
+    { }
+
+    int line (void) const { return m_line; }
 
-  typedef std::deque<call_stack_elt>::reverse_iterator
-    reverse_iterator;
-  typedef std::deque<call_stack_elt>::const_reverse_iterator
-    const_reverse_iterator;
+    int column (void) const { return m_column; }
+
+    std::string fcn_file_name (void) const;
+
+    std::string fcn_name (bool print_subfn = true) const;
+
+  private:
+
+    octave_function *m_fcn;
+    int m_line;
+    int m_column;
+    symbol_table::scope_id m_scope;
+    symbol_table::context_id m_context;
+    size_t m_prev;
+  };
+
+  typedef std::deque<stack_frame>::iterator iterator;
+  typedef std::deque<stack_frame>::const_iterator const_iterator;
+
+  typedef std::deque<stack_frame>::reverse_iterator reverse_iterator;
+  typedef std::deque<stack_frame>::const_reverse_iterator const_reverse_iterator;
 
   static void create_instance (void);
 
@@ -193,6 +204,12 @@
     return instance_ok () ? instance->do_current_context () : 0;
   }
 
+  /*
+  static stack_frame frame (size_t idx)
+  {
+    return instance_ok () ? instance->do_frame (idx) : stack_frame ();
+  }
+  */
   // Function at location N on the call stack (N == 0 is current), may
   // be built-in.
   static octave_function *element (size_t n)
@@ -275,10 +292,39 @@
       instance->do_goto_base_frame ();
   }
 
-  static octave_map backtrace (size_t nskip, octave_idx_type& curr_user_frame)
+  static octave_map backtrace (size_t nskip = 0)
+  {
+    octave_idx_type curr_user_frame = -1;
+
+    return instance_ok ()
+           ? instance->do_backtrace (nskip, curr_user_frame, true)
+           : octave_map ();
+  }
+  
+  static octave_map backtrace (size_t nskip, octave_idx_type& curr_user_frame,
+                               bool print_subfn = true)
   {
     return instance_ok ()
-           ? instance->do_backtrace (nskip, curr_user_frame) : octave_map ();
+           ? instance->do_backtrace (nskip, curr_user_frame, print_subfn)
+           : octave_map ();
+  }
+
+  static std::list<octave_call_stack::stack_frame>
+  backtrace_frames (size_t nskip = 0)
+  {
+    octave_idx_type curr_user_frame = -1;
+
+    return instance_ok ()
+           ? instance->do_backtrace_frames (nskip, curr_user_frame)
+           : std::list<octave_call_stack::stack_frame> ();
+  }
+  
+  static std::list<octave_call_stack::stack_frame>
+  backtrace_frames (size_t nskip, octave_idx_type& curr_user_frame)
+  {
+    return instance_ok ()
+           ? instance->do_backtrace_frames (nskip, curr_user_frame)
+           : std::list<octave_call_stack::stack_frame> ();
   }
 
   static octave_map empty_backtrace (void);
@@ -295,16 +341,10 @@
       instance->do_clear ();
   }
 
-  static void backtrace_error_message (void)
-  {
-    if (instance_ok ())
-      instance->do_backtrace_error_message ();
-  }
-
 private:
 
   // The current call stack.
-  std::deque<call_stack_elt> cs;
+  std::deque<stack_frame> cs;
 
   size_t curr_frame;
 
@@ -322,7 +362,7 @@
 
   octave_function *do_caller (void) const
   {
-    return curr_frame > 1 ? cs[curr_frame-1].fcn : cs[0].fcn;
+    return curr_frame > 1 ? cs[curr_frame-1].m_fcn : cs[0].m_fcn;
   }
 
   size_t do_current_frame (void) { return curr_frame; }
@@ -334,23 +374,30 @@
   symbol_table::scope_id do_current_scope (void) const
   {
     return curr_frame > 0 && curr_frame < cs.size ()
-           ? cs[curr_frame].scope : 0;
+           ? cs[curr_frame].m_scope : 0;
   }
 
   symbol_table::context_id do_current_context (void) const
   {
     return curr_frame > 0 && curr_frame < cs.size ()
-           ? cs[curr_frame].context : 0;
+           ? cs[curr_frame].m_context : 0;
   }
 
+  /*  const stack_frame& do_frame (size_t idx)
+  {
+    static stack_frame foobar;
+
+    return idx < cs.size () ? cs[idx] : foobar;
+  }
+  */
   octave_function *do_element (size_t n)
   {
     octave_function *retval = 0;
 
     if (cs.size () > n)
       {
-        call_stack_elt& elt = cs[n];
-        retval = elt.fcn;
+        stack_frame& elt = cs[n];
+        retval = elt.m_fcn;
       }
 
     return retval;
@@ -360,12 +407,12 @@
 
   bool do_all_scripts (void) const;
 
-  void do_push (octave_function *f, symbol_table::scope_id scope,
+  void do_push (octave_function *fcn, symbol_table::scope_id scope,
                 symbol_table::context_id context)
   {
     size_t prev_frame = curr_frame;
     curr_frame = cs.size ();
-    cs.push_back (call_stack_elt (f, scope, context, prev_frame));
+    cs.push_back (stack_frame (fcn, scope, context, prev_frame));
     symbol_table::set_scope_and_context (scope, context);
   }
 
@@ -375,8 +422,8 @@
 
     if (! cs.empty ())
       {
-        const call_stack_elt& elt = cs[curr_frame];
-        retval = elt.fcn;
+        const stack_frame& elt = cs[curr_frame];
+        retval = elt.m_fcn;
       }
 
     return retval;
@@ -386,10 +433,10 @@
   {
     if (! cs.empty ())
       {
-        call_stack_elt& elt = cs.back ();
+        stack_frame& elt = cs.back ();
 
-        elt.line = l;
-        elt.column = c;
+        elt.m_line = l;
+        elt.m_column = c;
       }
   }
 
@@ -397,9 +444,9 @@
   {
     if (! cs.empty ())
       {
-        call_stack_elt& elt = cs.back ();
+        stack_frame& elt = cs.back ();
 
-        elt.line = l;
+        elt.m_line = l;
       }
   }
 
@@ -407,14 +454,18 @@
   {
     if (! cs.empty ())
       {
-        call_stack_elt& elt = cs.back ();
+        stack_frame& elt = cs.back ();
 
-        elt.column = c;
+        elt.m_column = c;
       }
   }
 
+  std::list<octave_call_stack::stack_frame>
+  do_backtrace_frames (size_t nskip, octave_idx_type& curr_user_frame) const;
+
   octave_map do_backtrace (size_t nskip,
-                           octave_idx_type& curr_user_frame) const;
+                           octave_idx_type& curr_user_frame,
+                           bool print_subfn) const;
 
   bool do_goto_frame (size_t n, bool verbose);
 
@@ -428,17 +479,15 @@
   {
     if (cs.size () > 1)
       {
-        const call_stack_elt& elt = cs.back ();
-        curr_frame = elt.prev;
+        const stack_frame& elt = cs.back ();
+        curr_frame = elt.m_prev;
         cs.pop_back ();
-        const call_stack_elt& new_elt = cs[curr_frame];
-        symbol_table::set_scope_and_context (new_elt.scope, new_elt.context);
+        const stack_frame& new_elt = cs[curr_frame];
+        symbol_table::set_scope_and_context (new_elt.m_scope, new_elt.m_context);
       }
   }
 
   void do_clear (void) { cs.clear (); }
-
-  void do_backtrace_error_message (void) const;
 };
 
 // Call a function with exceptions handled to avoid problems with
--- a/libinterp/corefcn/tril.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/tril.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -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
@@ -364,7 +367,7 @@
 diagonal; above for positive @var{k} and below for negative @var{k}.\n\
 \n\
 The absolute value of @var{k} must not be greater than the number of\n\
-sub-diagonals or super-diagonals.\n\
+subdiagonals or superdiagonals.\n\
 \n\
 For example:\n\
 \n\
--- a/libinterp/corefcn/txt-eng-ft.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/txt-eng-ft.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -121,7 +121,7 @@
   typedef std::pair<std::string, double> ft_key;
   typedef std::map<ft_key, FT_Face> ft_cache;
 
-  // Cache the fonts loaded by freetype. This cache only contains
+  // Cache the fonts loaded by FreeType. This cache only contains
   // weak references to the fonts, strong references are only present
   // in class ft_render.
   ft_cache cache;
@@ -138,7 +138,7 @@
     : library (), freetype_initialized (false), fontconfig_initialized (false)
   {
     if (FT_Init_FreeType (&library))
-      ::error ("unable to initialize freetype library");
+      ::error ("unable to initialize FreeType library");
     else
       freetype_initialized = true;
 
@@ -635,7 +635,8 @@
       FT_UInt glyph_index, previous = 0;
 
       std::string str = e.string_value ();
-      size_t n = str.length (), curr = 0;
+      size_t n = str.length ();
+      size_t curr = 0;
       mbstate_t ps;
       memset (&ps, 0, sizeof (ps));  // Initialize state to 0.
       wchar_t wc;
--- a/libinterp/corefcn/txt-eng-ft.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/txt-eng-ft.h	Mon Jan 12 09:17:35 2015 -0800
@@ -114,7 +114,7 @@
   ft_render& operator = (const ft_render&);
 
   // Class to hold information about fonts and a strong
-  // reference to the font objects loaded by freetype.
+  // reference to the font objects loaded by FreeType.
   class ft_font
   {
   public:
--- a/libinterp/corefcn/typecast.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/typecast.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -90,10 +90,12 @@
 
 DEFUN (typecast, args, ,
        "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {} typecast (@var{x}, @var{class})\n\
+@deftypefn {Built-in Function} {@var{y} =} typecast (@var{x}, \"@var{class}\")\n\
 Return a new array @var{y} resulting from interpreting the data of\n\
-@var{x} in memory as data of the numeric class @var{class}.  Both the class\n\
-of @var{x} and @var{class} must be one of the built-in numeric classes:\n\
+@var{x} in memory as data of the numeric class @var{class}.\n\
+\n\
+Both the class of @var{x} and @var{class} must be one of the built-in\n\
+numeric classes:\n\
 \n\
 @example\n\
 @group\n\
@@ -120,7 +122,7 @@
 consecutive pairs of real numbers.  The sizes of integer types are given by\n\
 their bit counts.  Both logical and char are typically one byte wide;\n\
 however, this is not guaranteed by C++.  If your system is IEEE conformant,\n\
-single and double should be 4 bytes and 8 bytes wide, respectively.\n\
+single and double will be 4 bytes and 8 bytes wide, respectively.\n\
 @qcode{\"logical\"} is not allowed for @var{class}.  If the input is a row\n\
 vector, the return value is a row vector, otherwise it is a column vector.  \n\
 If the bit length of @var{x} is not divisible by that of @var{class}, an\n\
@@ -135,7 +137,7 @@
 @result{} [   1,   0, 255, 255]\n\
 @end group\n\
 @end example\n\
-@seealso{cast, bitunpack, bitpack, swapbytes}\n\
+@seealso{cast, bitpack, bitunpack, swapbytes}\n\
 @end deftypefn")
 {
   octave_value retval;
@@ -297,12 +299,17 @@
 DEFUN (bitpack, args, ,
        "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {@var{y} =} bitpack (@var{x}, @var{class})\n\
-Return a new array @var{y} resulting from interpreting an array\n\
+Return a new array @var{y} resulting from interpreting the logical array\n\
 @var{x} as raw bit patterns for data of the numeric class @var{class}.\n\
+\n\
 @var{class} must be one of the built-in numeric classes:\n\
 \n\
 @example\n\
 @group\n\
+\"double\"\n\
+\"single\"\n\
+\"double complex\"\n\
+\"single complex\"\n\
 \"char\"\n\
 \"int8\"\n\
 \"int16\"\n\
@@ -312,8 +319,6 @@
 \"uint16\"\n\
 \"uint32\"\n\
 \"uint64\"\n\
-\"double\"\n\
-\"single\"\n\
 @end group\n\
 @end example\n\
 \n\
@@ -327,7 +332,11 @@
 {
   octave_value retval;
 
-  if (args.length () == 2 && args(0).is_bool_type ())
+  if (args.length () != 2)
+    print_usage ();
+  else if (! args(0).is_bool_type ())
+    error ("bitpack: X must be a logical array");
+  else
     {
       boolNDArray bitp = args(0).bool_array_value ();
 
@@ -371,8 +380,6 @@
       if (! error_state && retval.is_undefined ())
         error ("bitpack: cannot pack to %s class", numclass.c_str ());
     }
-  else
-    print_usage ();
 
   return retval;
 }
@@ -407,11 +414,15 @@
 DEFUN (bitunpack, args, ,
        "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {@var{y} =} bitunpack (@var{x})\n\
-Return an array @var{y} corresponding to the raw bit patterns of\n\
-@var{x}.  @var{x} must belong to one of the built-in numeric classes:\n\
+Return a logical array @var{y} corresponding to the raw bit patterns of\n\
+@var{x}.\n\
+\n\
+@var{x} must belong to one of the built-in numeric classes:\n\
 \n\
 @example\n\
 @group\n\
+\"double\"\n\
+\"single\"\n\
 \"char\"\n\
 \"int8\"\n\
 \"int16\"\n\
@@ -421,8 +432,6 @@
 \"uint16\"\n\
 \"uint32\"\n\
 \"uint64\"\n\
-\"double\"\n\
-\"single\"\n\
 @end group\n\
 @end example\n\
 \n\
--- a/libinterp/corefcn/urlwrite.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/urlwrite.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -346,36 +346,36 @@
       return retval;
     }
 
+  if (! args(0).is_string ()) 
+    {
+      error ("urlwrite: URL must be a string");
+      return retval;
+    }
+
   std::string url = args(0).string_value ();
 
-  if (error_state)
+  if (! args(1).is_string ()) 
     {
-      error ("urlwrite: URL must be a character string");
+      error ("urlwrite: LOCALFILE must be a string");
       return retval;
     }
 
   // name to store the file if download is succesful
   std::string filename = args(1).string_value ();
 
-  if (error_state)
-    {
-      error ("urlwrite: LOCALFILE must be a character string");
-      return retval;
-    }
-
   std::string method;
   Array<std::string> param;
 
   if (nargin == 4)
     {
-      method = args(2).string_value ();
-
-      if (error_state)
+      if (! args(2).is_string ()) 
         {
-          error ("urlwrite: METHOD must be \"get\" or \"post\"");
+          error ("urlwrite: METHOD must be a string");
           return retval;
         }
 
+      method = args(2).string_value ();
+
       if (method != "get" && method != "post")
         {
           error ("urlwrite: METHOD must be \"get\" or \"post\"");
@@ -386,12 +386,11 @@
 
       if (error_state)
         {
-          error ("urlwrite: parameters (PARAM) for get and post requests must be given as a cell array of character strings");
+          error ("urlwrite: parameters (PARAM) for get and post requests must be given as a cell array of strings");
           return retval;
         }
 
-
-      if (param.numel () % 2 == 1 )
+      if (param.numel () % 2 == 1)
         {
           error ("urlwrite: number of elements in PARAM must be even");
           return retval;
@@ -498,33 +497,33 @@
   int nargin = args.length ();
 
   // verify arguments
-  if (nargin != 1  && nargin != 3)
+  if (nargin != 1 && nargin != 3)
     {
       print_usage ();
       return retval;
     }
 
-  std::string url = args(0).string_value ();
-
-  if (error_state)
+  if (! args(0).is_string ()) 
     {
-      error ("urlread: URL must be a character string");
+      error ("urlread: URL must be a string");
       return retval;
     }
 
+  std::string url = args(0).string_value ();
+
   std::string method;
   Array<std::string> param;
 
   if (nargin == 3)
     {
-      method = args(1).string_value ();
-
-      if (error_state)
+      if (! args(1).is_string ()) 
         {
-          error ("urlread: METHOD must be \"get\" or \"post\"");
+          error ("urlread: METHOD must be a string");
           return retval;
         }
 
+      method = args(1).string_value ();
+
       if (method != "get" && method != "post")
         {
           error ("urlread: METHOD must be \"get\" or \"post\"");
@@ -535,11 +534,11 @@
 
       if (error_state)
         {
-          error ("urlread: parameters (PARAM) for get and post requests must be given as a cell array of character strings");
+          error ("urlread: parameters (PARAM) for get and post requests must be given as a cell array of strings");
           return retval;
         }
 
-      if (param.numel () % 2 == 1 )
+      if (param.numel () % 2 == 1)
         {
           error ("urlread: number of elements in PARAM must be even");
           return retval;
--- a/libinterp/corefcn/utils.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/utils.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -38,8 +38,6 @@
 
 #include "vasnprintf.h"
 
-#include "quit.h"
-
 #include "dir-ops.h"
 #include "file-ops.h"
 #include "file-stat.h"
@@ -47,7 +45,9 @@
 #include "lo-utils.h"
 #include "oct-cmplx.h"
 #include "oct-env.h"
+#include "oct-locbuf.h"
 #include "pathsearch.h"
+#include "quit.h"
 #include "str-vec.h"
 
 #include "Cell.h"
@@ -121,6 +121,7 @@
 %!assert (isvarname ("1foo"), false)
 %!assert (isvarname (""), false)
 %!assert (isvarname (12), false)
+%!assert (isvarname ("foo+bar"), false)
 
 %!error isvarname ()
 %!error isvarname ("foo", "bar");
@@ -238,7 +239,7 @@
   return status;
 }
 
-// Return non-zero if either NR or NC is zero.  Return -1 if this
+// Return nonzero if either NR or NC is zero.  Return -1 if this
 // should be considered fatal; return 1 if this is ok.
 
 int
@@ -303,7 +304,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;
@@ -355,6 +356,8 @@
 
 %!error file_in_loadpath ()
 %!error file_in_loadpath ("foo", "bar", 1)
+%!error file_in_loadpath ([])
+%!error file_in_loadpath ("plot.m", "bar")
 */
 
 DEFUN (file_in_path, args, ,
@@ -380,7 +383,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;
@@ -389,10 +392,10 @@
 
   if (nargin == 2 || nargin == 3)
     {
-      std::string path = args(0).string_value ();
+      if (args(0).is_string ())
+        {
+          std::string path = args(0).string_value ();
 
-      if (! error_state)
-        {
           string_vector names = args(1).all_strings ();
 
           if (! error_state && names.length () > 0)
@@ -439,6 +442,9 @@
 %!error file_in_path ()
 %!error file_in_path ("foo")
 %!error file_in_path ("foo", "bar", "baz", 1)
+%!error file_in_path ([])
+%!error file_in_path (path (), [])
+%!error file_in_path (path (), "plot.m", "bar")
 */
 
 std::string
@@ -452,6 +458,44 @@
   return octave_env::make_absolute (load_path::find_file (nm));
 }
 
+std::string
+find_data_file_in_load_path  (const std::string& fcn,
+                              const std::string& file,
+                              bool require_regular_file)
+{
+  std::string fname = file;
+
+  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);
+
+      bool local_file_ok
+        = fs.exists () && (fs.is_reg () || ! require_regular_file);
+
+      if (! local_file_ok)
+        {
+          // Not directly found; search load path.
+
+          std::string tmp
+            = octave_env::make_absolute (load_path::find_file (fname));
+
+          if (! tmp.empty ())
+            {
+              gripe_data_file_in_path (fcn, tmp);
+
+              fname = tmp;
+            }
+        }
+    }
+
+  return fname;
+}
+
 // See if there is an function file in the path.  If so, return the
 // full path to the file.
 
@@ -680,14 +724,24 @@
 %!assert (do_string_escapes ("foo\\nbar"), ["foo", char(10), "bar"])
 %!assert ("foo\nbar", ["foo", char(10), "bar"])
 
-%!assert (do_string_escapes ('\a\b\f\n\r\t\v'), "\a\b\f\n\r\t\v")
-%!assert (do_string_escapes ("\\a\\b\\f\\n\\r\\t\\v"), "\a\b\f\n\r\t\v")
-%!assert (do_string_escapes ("\\a\\b\\f\\n\\r\\t\\v"),
-%!        char ([7, 8, 12, 10, 13, 9, 11]))
-%!assert ("\a\b\f\n\r\t\v", char ([7, 8, 12, 10, 13, 9, 11]))
+%!assert (do_string_escapes ('\0\a\b\f\n\r\t\v'), "\0\a\b\f\n\r\t\v")
+%!assert (do_string_escapes ("\\0\\a\\b\\f\\n\\r\\t\\v"), "\0\a\b\f\n\r\t\v")
+%!assert (do_string_escapes ("\\0\\a\\b\\f\\n\\r\\t\\v"),
+%!        char ([0, 7, 8, 12, 10, 13, 9, 11]))
+%!assert ("\0\a\b\f\n\r\t\v", char ([0, 7, 8, 12, 10, 13, 9, 11]))
+
+%!assert (do_string_escapes ('\\'), "\\")
+%!assert (do_string_escapes ("\\\\"), "\\")
+%!assert (do_string_escapes ("\\\\"), char (92))
+
+%!assert (do_string_escapes ('\''single-quoted\'''), "'single-quoted'")
+%!assert (do_string_escapes ("\\'single-quoted\\'"), "'single-quoted'")
+%!assert (do_string_escapes ('\"double-quoted\"'), "\"double-quoted\"")
+%!assert (do_string_escapes ("\\\"double-quoted\\\""), "\"double-quoted\"")
 
 %!error do_string_escapes ()
 %!error do_string_escapes ("foo", "bar")
+%!error do_string_escapes (3)
 */
 
 const char *
@@ -806,8 +860,16 @@
 %!assert (undo_string_escapes (char ([7, 8, 12, 10, 13, 9, 11])),
 %!        "\\a\\b\\f\\n\\r\\t\\v")
 
+%!assert (undo_string_escapes ("\\"), '\\')
+%!assert (undo_string_escapes ("\\"), "\\\\")
+%!assert (undo_string_escapes (char (92)), "\\\\")
+
+%!assert (undo_string_escapes ("\"double-quoted\""), '\"double-quoted\"')
+%!assert (undo_string_escapes ("\"double-quoted\""), "\\\"double-quoted\\\"")
+
 %!error undo_string_escapes ()
 %!error undo_string_escapes ("foo", "bar")
+%!error undo_string_escapes (3)
 */
 
 DEFUN (is_absolute_filename, args, ,
@@ -892,10 +954,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 +988,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 ();
@@ -935,10 +997,21 @@
 }
 
 /*
-## FIXME: We need system-dependent tests here.
+%!test
+%! f = dir_in_loadpath ("plot");
+%! assert (ischar (f));
+%! assert (! isempty (f));
 
-%!error find_dir_in_path ()
-%!error find_dir_in_path ("foo", "bar", 1)
+%!test
+%! f = dir_in_loadpath ("$$probably_!!_not_&&_a_!!_dir$$");
+%! assert (f, "");
+
+%!test
+%! lst = dir_in_loadpath ("$$probably_!!_not_&&_a_!!_dir$$", "all");
+%! assert (lst, {});
+
+%!error dir_in_loadpath ()
+%!error dir_in_loadpath ("foo", "bar", 1)
 */
 
 DEFUNX ("errno", Ferrno, args, ,
@@ -965,7 +1038,7 @@
           if (! error_state)
             retval = octave_errno::lookup (nm);
           else
-            error ("errno: expecting character string argument");
+            error ("errno: expecting string argument");
         }
       else
         {
@@ -1337,9 +1410,11 @@
 /*
 %!assert (isindex ([1, 2, 3]))
 %!assert (isindex (1:3))
+%!assert (isindex (1:3, 2), false)
 %!assert (isindex ([1, 2, -3]), false)
 
 %!error isindex ()
+%!error isindex (1:3, 2, 3)
 */
 
 octave_value_list
@@ -1441,3 +1516,25 @@
   stream.width (owidth);
   stream.fill (ofill);
 }
+
+DEFUN (isstudent, args, ,
+       "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {} isstudent ()\n\
+Return true if running in the student edition of @sc{matlab}.\n\
+\n\
+@code{isstudent} always returns false in Octave.\n\
+\n\
+@seealso{false}\n\
+@end deftypefn")
+{
+  if (args.length () != 0)
+    print_usage ();
+
+  return octave_value (false);
+}
+
+/*
+%!assert (isstudent (), false)
+
+%!error isstudent (1)
+*/
--- a/libinterp/corefcn/utils.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/utils.h	Mon Jan 12 09:17:35 2015 -0800
@@ -66,6 +66,11 @@
 extern OCTINTERP_API std::string
 file_in_path (const std::string&, const std::string&);
 
+extern OCTINTERP_API std::string
+find_data_file_in_load_path  (const std::string& fcn,
+                              const std::string& file,
+                              bool require_regular_file = false);
+
 extern OCTINTERP_API std::string contents_file_in_path (const std::string&);
 
 extern OCTINTERP_API std::string fcn_file_in_path (const std::string&);
--- a/libinterp/corefcn/variables.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/variables.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -150,14 +150,14 @@
 
   if (! retval)
     {
-      std::string s = arg.string_value ();
-
-      std::string cmd = header;
-      cmd.append (s);
-      cmd.append (trailer);
-
-      if (! error_state)
+      if (arg.is_string ())
         {
+          std::string s = arg.string_value ();
+
+          std::string cmd = header;
+          cmd.append (s);
+          cmd.append (trailer);
+
           int parse_status;
 
           eval_string (cmd, true, parse_status, 0);
@@ -283,7 +283,8 @@
 
           frame.run ();
 
-          if (tmp.is_defined () && (tmp.is_map () || tmp.is_java ()))
+          if (tmp.is_defined () &&
+              (tmp.is_map () || tmp.is_java () || tmp.is_classdef_object ()))
             names = tmp.map_keys ();
         }
     }
@@ -340,14 +341,14 @@
       return retval;
     }
 
-  std::string name = args(0).string_value ();
-
-  if (error_state)
+  if (! args(0).is_string ())
     {
       error ("isglobal: NAME must be a string");
       return retval;
     }
 
+  std::string name = args(0).string_value ();
+
   return symbol_table::is_global (name);
 }
 
@@ -388,17 +389,7 @@
 int
 symbol_exist (const std::string& name, const std::string& type)
 {
-  std::string struct_elts;
-  std::string symbol_name = name;
-
-  size_t pos = name.find ('.');
-
-  if (pos != std::string::npos && pos > 0)
-    {
-      struct_elts = name.substr (pos+1);
-      symbol_name = name.substr (0, pos);
-    }
-  else if (is_keyword (symbol_name))
+  if (is_keyword (name))
     return 0;
 
   bool search_any = type == "any";
@@ -409,21 +400,38 @@
 
   if (search_any || search_var)
     {
-      bool not_a_struct = struct_elts.empty ();
-      bool var_ok = not_a_struct; // || val.is_map_element (struct_elts)
-
       octave_value val = symbol_table::varval (name);
 
-      if (var_ok && (val.is_constant () || val.is_object ()
-                     || val.is_function_handle ()
-                     || val.is_anonymous_function ()
-                     || val.is_inline_function ()))
+      if (val.is_constant () || val.is_object ()
+          || val.is_function_handle ()
+          || val.is_anonymous_function ()
+          || val.is_inline_function ())
         return 1;
 
       if (search_var)
         return 0;
     }
 
+  // We shouldn't need to look in the global symbol table, since any name
+  // that is visible in the current scope will be in the local symbol table.
+
+  octave_value val;
+
+  if (search_any || search_builtin)
+    {
+      // FIXME: safe_symbol_lookup will attempt unsafe load of .oct/.mex file.
+      // This can cause a segfault.  To catch this would require temporarily
+      // diverting the SIGSEGV exception handler and then restoring it.
+      // See bug #36067.
+      val = safe_symbol_lookup (name);
+
+      if (val.is_defined () && val.is_builtin_function ())
+        return 5;
+
+      if (search_builtin)
+        return 0;
+    }
+
   if (search_any || search_file || search_dir)
     {
       std::string file_name = lookup_autoload (name);
@@ -455,7 +463,18 @@
       if (fs)
         {
           if (search_any || search_file)
-            return fs.is_dir () ? 7 : 2;
+          {
+            if (fs.is_dir ())
+              return 7;
+
+            len = file_name.length ();
+
+            if (len > 4 && (file_name.substr (len-4) == ".oct"
+                            || file_name.substr (len-4) == ".mex"))
+              return 3;
+            else
+              return 2;
+          }
           else if (search_dir && fs.is_dir ())
             return 7;
         }
@@ -464,27 +483,9 @@
         return 0;
     }
 
-  // We shouldn't need to look in the global symbol table, since any
-  // name that is visible in the current scope will be in the local
-  // symbol table.
-
-  octave_value val = safe_symbol_lookup (symbol_name);
-
-  if (val.is_defined () && struct_elts.empty ())
-    {
-      if ((search_any || search_builtin)
-          && val.is_builtin_function ())
-        return 5;
-
-      if ((search_any || search_file)
-          && (val.is_user_function () || val.is_dld_function ()))
-        {
-          octave_function *f = val.function_value (true);
-          std::string s = f ? f->fcn_file_name () : std::string ();
-
-          return s.empty () ? 103 : (val.is_user_function () ? 2 : 3);
-        }
-    }
+  // Command line function which Matlab does not support
+  if (search_any && val.is_defined () && val.is_user_function ())
+    return 103;
 
   return 0;
 }
@@ -515,21 +516,38 @@
 
 DEFUN (exist, args, ,
        "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {} exist (@var{name}, @var{type})\n\
-Return 1 if the name exists as a variable, 2 if the name is an\n\
-absolute file name, an ordinary file in Octave's @code{path}, or (after\n\
-appending @samp{.m}) a function file in Octave's @code{path}, 3 if the\n\
-name is a @samp{.oct} or @samp{.mex} file in Octave's @code{path},\n\
-5 if the name is a built-in function, 7 if the name is a directory, or 103\n\
-if the name is a function not associated with a file (entered on\n\
-the command line).\n\
+@deftypefn  {Built-in Function} {@var{c} =} exist (@var{name})\n\
+@deftypefnx {Built-in Function} {@var{c} =} exist (@var{name}, @var{type})\n\
+Check for the existence of @var{name} as a variable, function, file,\n\
+directory, or class.\n\
+\n\
+The return code @var{c} is one of\n\
+\n\
+@table @asis\n\
+@item 1\n\
+@var{name} is a variable.\n\
+\n\
+@item 2\n\
+@var{name} is an absolute file name, an ordinary file in Octave's\n\
+@code{path}, or (after appending @samp{.m}) a function file in Octave's\n\
+@code{path}.\n\
 \n\
-Otherwise, return 0.\n\
+@item 3\n\
+@var{name} is a @samp{.oct} or @samp{.mex} file in Octave's @code{path}.\n\
+\n\
+@item 5\n\
+@var{name} is a built-in function.\n\
 \n\
-This function also returns 2 if a regular file called @var{name}\n\
-exists in Octave's search path.  If you want information about\n\
-other types of files, you should use some combination of the functions\n\
-@code{file_in_path} and @code{stat} instead.\n\
+@item 7\n\
+@var{name} is a directory.\n\
+\n\
+@item 103\n\
+@var{name} is a function not associated with a file (entered on the command\n\
+line).\n\
+\n\
+@item 0\n\
+@var{name} does not exist.\n\
+@end table\n\
 \n\
 If the optional argument @var{type} is supplied, check only for\n\
 symbols of the specified type.  Valid types are\n\
@@ -541,14 +559,27 @@
 @item @qcode{\"builtin\"}\n\
 Check only for built-in functions.\n\
 \n\
+@item @qcode{\"dir\"}\n\
+Check only for directories.\n\
+\n\
 @item @qcode{\"file\"}\n\
 Check only for files and directories.\n\
 \n\
-@item @qcode{\"dir\"}\n\
-Check only for directories.\n\
+@item @qcode{\"class\"}\n\
+Check only for classes.  (Note: This option is accepted, but not currently\n\
+implemented)\n\
 @end table\n\
 \n\
-@seealso{file_in_loadpath, file_in_path, find_dir_in_path, stat}\n\
+If no type is given, and there are multiple possible matches for name,\n\
+@code{exist} will return a code according to the following priority list:\n\
+variable, built-in function, oct-file, directory, file, class. \n\
+\n\
+@code{exist} returns 2 if a regular file called @var{name} is present in\n\
+Octave's search path.  If you want information about other types of files\n\
+not on the search path you should use some combination of the functions\n\
+@code{file_in_path} and @code{stat} instead.\n\
+\n\
+@seealso{file_in_loadpath, file_in_path, dir_in_loadpath, stat}\n\
 @end deftypefn")
 {
   octave_value retval = false;
@@ -557,16 +588,21 @@
 
   if (nargin == 1 || nargin == 2)
     {
-      std::string name = args(0).string_value ();
-
-      if (! error_state)
+      if (args(0).is_string ())
         {
+          std::string name = args(0).string_value ();
+
           if (nargin == 2)
             {
-              std::string type = args(1).string_value ();
-
-              if (! error_state)
-                retval = symbol_exist (name, type);
+              if (args(1).is_string ())
+                {
+                  std::string type = args(1).string_value ();
+
+                  if (type == "class")
+                    warning ("exist: \"class\" type argument is not implemented");
+
+                  retval = symbol_exist (name, type);
+                }
               else
                 error ("exist: TYPE must be a string");
             }
@@ -583,18 +619,62 @@
 }
 
 /*
+%!shared dirtmp, __var1
+%! dirtmp = P_tmpdir ();
+%! __var1 = 1;
+
+%!assert (exist ("__%Highly_unlikely_name%__"), 0)
+%!assert (exist ("__var1"), 1)
+%!assert (exist ("__var1", "var"), 1)
+%!assert (exist ("__var1", "builtin"), 0)
+%!assert (exist ("__var1", "dir"), 0)
+%!assert (exist ("__var1", "file"), 0)
+
 %!test
 %! if (isunix ())
-%!   assert (exist ("/tmp") == 7);
-%!   assert (exist ("/tmp", "file") == 7);
-%!   assert (exist ("/tmp", "dir") == 7);
-%!   assert (exist ("/bin/sh") == 2);
-%!   assert (exist ("/bin/sh", "file") == 2);
-%!   assert (exist ("/bin/sh", "dir") == 0);
-%!   assert (exist ("/dev/null") == 2);
-%!   assert (exist ("/dev/null", "file") == 2);
-%!   assert (exist ("/dev/null", "dir") == 0);
+%!   assert (exist ("/bin/sh"), 2);
+%!   assert (exist ("/bin/sh", "file"), 2);
+%!   assert (exist ("/bin/sh", "dir"), 0);
+%!   assert (exist ("/dev/null"), 2);
+%!   assert (exist ("/dev/null", "file"), 2);
+%!   assert (exist ("/dev/null", "dir"), 0);
 %! endif
+
+%!assert (exist ("colon"), 2)
+%!assert (exist ("colon.m"), 2)
+%!assert (exist ("colon", "file"), 2)
+%!assert (exist ("colon", "dir"), 0)
+
+%!testif HAVE_CHOLMOD
+%! assert (exist ("chol"), 3);
+%! assert (exist ("chol.oct"), 3);
+%! assert (exist ("chol", "file"), 3);
+%! assert (exist ("chol", "builtin"), 0);
+
+%!assert (exist ("sin"), 5)
+%!assert (exist ("sin", "builtin"), 5)
+%!assert (exist ("sin", "file"), 0)
+
+%!assert (exist (dirtmp), 7)
+%!assert (exist (dirtmp, "dir"), 7)
+%!assert (exist (dirtmp, "file"), 7)
+
+%!error exist ()
+%!error exist (1,2,3)
+%!warning <"class" type argument is not implemented> exist ("a", "class");
+%!error <TYPE must be a string> exist ("a", 1)
+%!error <NAME must be a string> exist (1)
+
+%!test
+%! flist = dir ();
+%! fname = flist(3).name;  ## skip . and ..
+%! assert (exist (fullfile (pwd (), fname), "file"), 2)
+%! assert (exist (fullfile (pwd (), "nonexistentfile"), "file"), 0)
+
+%!assert (exist ("plot.m", "file"), 2);
+%!assert (exist ("./plot.m", "file"), 0);
+%!assert (exist ("./nonexistentfile", "file"), 0);
+%!assert (exist ("nonexistentfile", "file"), 0);
 */
 
 octave_value
@@ -856,17 +936,17 @@
 
   if (nargin == 1)
     {
-      std::string sval = args(0).string_value ();
-
-      if (! error_state)
+      if (args(0).is_string ()) 
         {
+          std::string sval = args(0).string_value ();
+
           if (empty_ok || ! sval.empty ())
             var = sval;
           else
             error ("%s: value must not be empty", nm);
         }
       else
-        error ("%s: expecting arg to be a character string", nm);
+        error ("%s: first argument must be a string", nm);
     }
   else if (nargin > 1)
     print_usage ();
@@ -897,10 +977,10 @@
 
   if (nargin == 1)
     {
-      std::string sval = args(0).string_value ();
-
-      if (! error_state)
+      if (args(0).is_string ()) 
         {
+          std::string sval = args(0).string_value ();
+
           int i = 0;
           for (; i < nchoices; i++)
             {
@@ -914,7 +994,7 @@
             error ("%s: value not allowed (\"%s\")", nm, sval.c_str ());
         }
       else
-        error ("%s: expecting arg to be a character string", nm);
+        error ("%s: first argument must be a string", nm);
     }
   else if (nargin > 1)
     print_usage ();
@@ -1405,7 +1485,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;
@@ -1994,10 +2076,11 @@
 
   if (args.length () == 1)
     {
-      std::string name = args(0).string_value ();
-
-      if (! error_state)
-        munlock (name);
+      if (args(0).is_string ())
+        {
+          std::string name = args(0).string_value ();
+          munlock (name);
+        }
       else
         error ("munlock: FCN must be a string");
     }
@@ -2030,10 +2113,11 @@
 
   if (args.length () == 1)
     {
-      std::string name = args(0).string_value ();
-
-      if (! error_state)
-        retval = mislocked (name);
+      if (args(0).is_string ())
+        {
+          std::string name = args(0).string_value ();
+          retval = mislocked (name);
+        }
       else
         error ("mislocked: FCN must be a string");
     }
@@ -2255,6 +2339,7 @@
         {
           symbol_table::clear_objects ();
           octave_class::clear_exemplar_map ();
+          symbol_table::clear_all ();
         }
       else
         {
@@ -2464,6 +2549,7 @@
                     {
                       symbol_table::clear_objects ();
                       octave_class::clear_exemplar_map ();
+                      symbol_table::clear_all ();
                     }
                   else
                     {
--- a/libinterp/corefcn/xdiv.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/xdiv.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -42,6 +42,7 @@
 #include "fDiagMatrix.h"
 #include "CDiagMatrix.h"
 #include "fCDiagMatrix.h"
+#include "lo-array-gripes.h"
 #include "quit.h"
 
 #include "error.h"
@@ -58,8 +59,7 @@
 static void
 solve_singularity_warning (double rcond)
 {
-  warning_with_id ("Octave:singular-matrix-div",
-                   "matrix singular to machine precision, rcond = %g", rcond);
+  gripe_singular_matrix (rcond);
 }
 
 template <class T1, class T2>
@@ -405,8 +405,7 @@
 static void
 solve_singularity_warning (float rcond)
 {
-  warning ("matrix singular to machine precision, rcond = %g", rcond);
-  warning ("attempting to find minimum norm solution");
+  gripe_singular_matrix (rcond);
 }
 
 INSTANTIATE_MX_LEFTDIV_CONFORM (FloatMatrix, FloatMatrix);
@@ -713,7 +712,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 +795,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 +875,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 +950,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/corefcn/xpow.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/corefcn/xpow.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -33,6 +33,7 @@
 #include "CColVector.h"
 #include "CDiagMatrix.h"
 #include "fCDiagMatrix.h"
+#include "fCMatrix.h"
 #include "CMatrix.h"
 #include "EIG.h"
 #include "fEIG.h"
@@ -41,6 +42,7 @@
 #include "dMatrix.h"
 #include "PermMatrix.h"
 #include "mx-cm-cdm.h"
+#include "mx-fcm-fcdm.h"
 #include "oct-cmplx.h"
 #include "Range.h"
 #include "quit.h"
@@ -52,10 +54,6 @@
 
 #include "bsxfun.h"
 
-#ifdef _OPENMP
-#include <omp.h>
-#endif
-
 static inline int
 xisint (double x)
 {
--- a/libinterp/dldfcn/__delaunayn__.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/dldfcn/__delaunayn__.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -45,6 +45,8 @@
 #include <iostream>
 #include <string>
 
+#include "oct-locbuf.h"
+
 #include "Cell.h"
 #include "defun-dld.h"
 #include "error.h"
@@ -175,7 +177,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/__eigs__.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/dldfcn/__eigs__.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -211,7 +211,7 @@
         {
           std::string name = args(0).string_value ();
           std::string fname = "function y = ";
-          fcn_name = unique_symbol_name ("__eigs_fcn_");
+          fcn_name = unique_symbol_name ("__eigs_fcn__");
           fname.append (fcn_name);
           fname.append ("(x) y = ");
           eigs_fcn = extract_function (args(0), "eigs", fcn_name, fname,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/dldfcn/__ichol__.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,516 @@
+/*
+
+Copyright (C) 2014 Eduardo Ramos Fernández <eduradical951@gmail.com>
+Copyright (C) 2013 Kai T. Ohlhus <k.ohlhus@gmail.com>
+
+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 "oct-locbuf.h"
+
+#include "defun-dld.h"
+#include "parse.h"
+
+// Secondary functions for complex and real case used in ichol algorithms.
+Complex ichol_mult_complex (Complex a, Complex b)
+{
+#if defined (HAVE_CXX_COMPLEX_SETTERS)
+  b.imag (-std::imag (b));
+#elif defined (HAVE_CXX_COMPLEX_REFERENCE_ACCESSORS)
+  b.imag () = -std::imag (b);
+#else
+  b = std::conj (b);
+#endif
+  return a * b;
+}
+
+double ichol_mult_real (double a, double b)
+{
+  return a * b;
+}
+
+bool ichol_checkpivot_complex (Complex pivot)
+{
+  if (pivot.imag () != 0)
+    {
+      error ("ichol: non-real pivot encountered.  The matrix must be hermitian.");
+      return false;
+    }
+  else if (pivot.real () < 0)
+    {
+      error ("ichol: negative pivot encountered");
+      return false;
+    }
+  return true;
+}
+
+bool ichol_checkpivot_real (double pivot)
+{
+  if (pivot < 0)
+    {
+      error ("ichol: negative pivot encountered");
+      return false;
+    }
+  return true;
+}
+
+template <typename octave_matrix_t, typename T, T (*ichol_mult) (T, T),
+          bool (*ichol_checkpivot) (T)>
+void ichol_0 (octave_matrix_t& sm, const std::string michol = "off")
+{
+
+  const octave_idx_type n = sm.cols ();
+  octave_idx_type j1, jend, j2, jrow, jjrow, j, jw, i, k, jj, r;
+  T tl;
+  char opt;
+  enum {OFF, ON};
+  if (michol == "on")
+    opt = ON;
+  else
+    opt = OFF;
+
+  // Input matrix pointers
+  octave_idx_type* cidx = sm.cidx ();
+  octave_idx_type* ridx = sm.ridx ();
+  T* data = sm.data ();
+
+  // Working arrays
+  OCTAVE_LOCAL_BUFFER (octave_idx_type, Lfirst, n);
+  OCTAVE_LOCAL_BUFFER (octave_idx_type, Llist, n);
+  OCTAVE_LOCAL_BUFFER (octave_idx_type, iw, n);
+  OCTAVE_LOCAL_BUFFER (T, dropsums, n);
+
+  // Initialize working arrays
+  for (i = 0; i < n; i++)
+    {
+      iw[i] = -1;
+      Llist[i] = -1;
+      Lfirst[i] = -1;
+      dropsums[i] = 0;
+    }
+
+  // Main loop
+  for (k = 0; k < n; k++)
+    {
+      j1 = cidx[k];
+      j2 = cidx[k+1];
+      for (j = j1; j < j2; j++)
+        iw[ridx[j]] = j;
+
+      jrow = Llist [k];
+      // Iterate over each non-zero element in the actual row.
+      while (jrow != -1)
+        {
+          jjrow = Lfirst[jrow];
+          jend = cidx[jrow+1];
+          for (jj = jjrow; jj < jend; jj++)
+            {
+              r = ridx[jj];
+              jw = iw[r];
+              tl = ichol_mult (data[jj], data[jjrow]);
+              if (jw != -1)
+                data[jw] -= tl;
+              else
+                // Because of the symmetry of the matrix, we know
+                // the drops in the column r are also in the column k.
+                if (opt == ON)
+                  {
+                    dropsums[r] -= tl;
+                    dropsums[k] -= tl;
+                  }
+            }
+          // Update the linked list and the first entry of the actual column.
+          if ((jjrow + 1) < jend)
+            {
+              Lfirst[jrow]++;
+              j = jrow;
+              jrow = Llist[jrow];
+              Llist[j] = Llist[ridx[Lfirst[j]]];
+              Llist[ridx[Lfirst[j]]] = j;
+            }
+          else
+            jrow = Llist[jrow];
+        }
+
+      if (opt == ON)
+        data[j1] += dropsums[k];
+
+      if (ridx[j1] != k)
+        {
+          error ("ichol: encountered a pivot equal to 0");
+          break;
+        }
+
+      if (! ichol_checkpivot (data[j1]))
+        break;
+
+      data[cidx[k]] = std::sqrt (data[j1]);
+
+      // Update Llist and Lfirst with the k-column information.  Also,
+      // scale the column elements by the pivot and reset the working array iw.
+      if (k < (n - 1))
+        {
+          iw[ridx[j1]] = -1;
+          for (i = j1 + 1; i < j2; i++)
+            {
+              iw[ridx[i]] = -1;
+              data[i] /= data[j1];
+            }
+          Lfirst[k] = j1;
+          if ((Lfirst[k] + 1) < j2)
+            {
+              Lfirst[k]++;
+              jjrow = ridx[Lfirst[k]];
+              Llist[k] = Llist[jjrow];
+              Llist[jjrow] = k;
+            }
+        }
+    }
+}
+
+DEFUN_DLD (__ichol0__, args, nargout, "-*- texinfo -*-\n\
+@deftypefn  {Loadable Function} {@var{L} =} __ichol0__ (@var{A})\n\
+@deftypefnx {Loadable Function} {@var{L} =} __ichol0__ (@var{A}, @var{michol})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+
+{
+  octave_value_list retval;
+
+  int nargin = args.length ();
+  std::string michol = "off";
+
+  if (nargout > 1 || nargin < 1 || nargin > 2)
+    {
+      print_usage ();
+      return retval;
+    }
+
+  if (nargin == 2)
+    michol = args(1).string_value ();
+
+  // In ICHOL0 algorithm the zero-pattern of the input matrix is preserved
+  // so it's structure does not change during the algorithm.  The same input
+  // matrix is used to build the output matrix due to that fact.
+  octave_value_list param_list;
+  if (!args(0).is_complex_type ())
+    {
+      SparseMatrix sm = args(0).sparse_matrix_value ();
+      param_list.append (sm);
+      sm = feval ("tril", param_list)(0).sparse_matrix_value ();
+      ichol_0 <SparseMatrix, double, ichol_mult_real,
+               ichol_checkpivot_real> (sm, michol);
+      if (! error_state)
+        retval(0) = sm;
+    }
+  else
+    {
+      SparseComplexMatrix sm = args(0).sparse_complex_matrix_value ();
+      param_list.append (sm);
+      sm = feval ("tril", param_list)(0).sparse_complex_matrix_value ();
+      ichol_0 <SparseComplexMatrix, Complex, ichol_mult_complex,
+               ichol_checkpivot_complex> (sm, michol);
+      if (! error_state)
+        retval(0) = sm;
+    }
+
+  return retval;
+}
+
+template <typename octave_matrix_t, typename T,  T (*ichol_mult) (T, T),
+          bool (*ichol_checkpivot) (T)>
+void ichol_t (const octave_matrix_t& sm, octave_matrix_t& L, const T* cols_norm,
+              const T droptol, const std::string michol = "off")
+
+{
+
+  const octave_idx_type n = sm.cols ();
+  octave_idx_type j, jrow, jend, jjrow, i, k, jj, total_len,
+                  w_len, max_len, ind;
+  char opt;
+  enum {OFF, ON};
+  if (michol == "on")
+    opt = ON;
+  else
+    opt = OFF;
+
+  // Input matrix pointers
+  octave_idx_type* cidx = sm.cidx ();
+  octave_idx_type* ridx = sm.ridx ();
+  T* data = sm.data ();
+
+  // Output matrix data structures.  Because the final zero pattern pattern of
+  // the output matrix is not known due to fill-in elements, a heuristic
+  // approach has been adopted for memory allocation.  The size of ridx_out_l
+  // and data_out_l is incremented 10% of their actual size (nnz (A) in the
+  // beginning).  If that amount is less than n, their size is just incremented
+  // in n elements.  This way the number of reallocations decreases throughout
+  // the process, obtaining a good performance.
+  max_len = sm.nnz ();
+  max_len += (0.1 * max_len) > n ? 0.1 * max_len : n;
+  Array <octave_idx_type> cidx_out_l (dim_vector (n + 1, 1));
+  octave_idx_type* cidx_l = cidx_out_l.fortran_vec ();
+  Array <octave_idx_type> ridx_out_l (dim_vector (max_len ,1));
+  octave_idx_type* ridx_l = ridx_out_l.fortran_vec ();
+  Array <T> data_out_l (dim_vector (max_len, 1));
+  T* data_l = data_out_l.fortran_vec ();
+
+  // Working arrays
+  OCTAVE_LOCAL_BUFFER (T, w_data, n);
+  OCTAVE_LOCAL_BUFFER (octave_idx_type, Lfirst, n);
+  OCTAVE_LOCAL_BUFFER (octave_idx_type, Llist, n);
+  OCTAVE_LOCAL_BUFFER (T, col_drops, n);
+  std::vector <octave_idx_type> vec;
+  vec.resize (n);
+
+  T zero = T (0);
+  cidx_l[0] = cidx[0];
+  for (i = 0; i < n; i++)
+    {
+      Llist[i] = -1;
+      Lfirst[i] = -1;
+      w_data[i] = 0;
+      col_drops[i] = zero;
+      vec[i] = 0;
+    }
+
+  total_len = 0;
+  for (k = 0; k < n; k++)
+    {
+      ind = 0;
+      for (j = cidx[k]; j < cidx[k+1]; j++)
+        {
+          w_data[ridx[j]] = data[j];
+          if (ridx[j] != k)
+            {
+              vec[ind] = ridx[j];
+              ind++;
+            }
+        }
+      jrow = Llist[k];
+      while (jrow != -1)
+        {
+          jjrow = Lfirst[jrow];
+          jend = cidx_l[jrow+1];
+          for (jj = jjrow; jj < jend; jj++)
+            {
+              j = ridx_l[jj];
+              // If the element in the j position of the row is zero,
+              // then it will become non-zero, so we add it to the
+              // vector that tracks non-zero elements in the working row.
+              if (w_data[j] == zero)
+                {
+                  vec[ind] = j;
+                  ind++;
+                }
+              w_data[j] -=  ichol_mult (data_l[jj], data_l[jjrow]);
+            }
+          // Update the actual column first element and
+          // update the linked list of the jrow row.
+          if ((jjrow + 1) < jend)
+            {
+              Lfirst[jrow]++;
+              j = jrow;
+              jrow = Llist[jrow];
+              Llist[j] = Llist[ridx_l[Lfirst[j]]];
+              Llist[ridx_l[Lfirst[j]]] = j;
+            }
+          else
+            jrow = Llist[jrow];
+        }
+
+      // Resizing output arrays
+      if ((max_len - total_len) < n)
+        {
+          max_len += (0.1 * max_len) > n ? 0.1 * max_len : n;
+          data_out_l.resize (dim_vector (max_len, 1));
+          data_l = data_out_l.fortran_vec ();
+          ridx_out_l.resize (dim_vector (max_len, 1));
+          ridx_l = ridx_out_l.fortran_vec ();
+        }
+
+      // The sorting of the non-zero elements of the working column can be
+      // handled in a couple of ways.  The most efficient two I found, are
+      // keeping the elements in an ordered binary search tree dynamically or
+      // keep them unsorted in a vector and at the end of the outer iteration
+      // order them.  The last approach exhibits lower execution times.
+      std::sort (vec.begin (), vec.begin () + ind);
+
+      data_l[total_len] = w_data[k];
+      ridx_l[total_len] = k;
+      w_len = 1;
+
+      // Extract the non-zero elements of working column and
+      // drop the elements that are lower than droptol * cols_norm[k].
+      for (i = 0; i < ind ; i++)
+        {
+          jrow = vec[i];
+          if (w_data[jrow] != zero)
+            {
+              if (std::abs (w_data[jrow]) < (droptol * cols_norm[k]))
+                {
+                  if (opt == ON)
+                    {
+                      col_drops[k] += w_data[jrow];
+                      col_drops[jrow] += w_data[jrow];
+                    }
+                }
+              else
+                {
+                  data_l[total_len + w_len] = w_data[jrow];
+                  ridx_l[total_len + w_len] = jrow;
+                  w_len++;
+                }
+              vec[i] = 0;
+            }
+          w_data[jrow] = zero;
+        }
+
+      // Compensate column sums --> michol option
+      if (opt == ON)
+        data_l[total_len] += col_drops[k];
+
+      if (data_l[total_len] == zero)
+        {
+          error ("ichol: encountered a pivot equal to 0");
+          break;
+        }
+      else if (! ichol_checkpivot (data_l[total_len]))
+        break;
+
+      // Once elements are dropped and compensation of column sums are done,
+      // scale the elements by the pivot.
+      data_l[total_len] = std::sqrt (data_l[total_len]);
+      for (jj = total_len + 1; jj < (total_len + w_len); jj++)
+        data_l[jj] /=  data_l[total_len];
+      total_len += w_len;
+      // Check if there are too many elements to be indexed with
+      // octave_idx_type type due to fill-in during the process.
+      if (total_len < 0)
+        {
+          error ("ichol: integer overflow.  Too many fill-in elements in L");
+          break;
+        }
+      cidx_l[k+1] = cidx_l[k] - cidx_l[0] + w_len;
+
+      // Update Llist and Lfirst with the k-column information.
+      if (k < (n - 1))
+        {
+          Lfirst[k] = cidx_l[k];
+          if ((Lfirst[k] + 1) < cidx_l[k+1])
+            {
+              Lfirst[k]++;
+              jjrow = ridx_l[Lfirst[k]];
+              Llist[k] = Llist[jjrow];
+              Llist[jjrow] = k;
+            }
+        }
+    }
+
+  if (! error_state)
+    {
+      // Build the output matrices
+      L = octave_matrix_t (n, n, total_len);
+      for (i = 0; i <= n; i++)
+        L.cidx (i) = cidx_l[i];
+      for (i = 0; i < total_len; i++)
+        {
+          L.ridx (i) = ridx_l[i];
+          L.data (i) = data_l[i];
+        }
+    }
+}
+
+DEFUN_DLD (__icholt__, args, nargout, "-*- texinfo -*-\n\
+@deftypefn  {Loadable Function} {@var{L} =} __icholt__ (@var{A})\n\
+@deftypefnx {Loadable Function} {@var{L} =} __icholt__ (@var{A}, @var{droptol})\n\
+@deftypefnx {Loadable Function} {@var{L} =} __icholt__ (@var{A}, @var{droptol}, @var{michol})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value_list retval;
+  int nargin = args.length ();
+  // Default values of parameters
+  std::string michol = "off";
+  double droptol = 0;
+
+  if (nargout > 1 || nargin < 1 || nargin > 3)
+    {
+      print_usage ();
+      return retval;
+    }
+
+  // Don't repeat input validation of arguments done in ichol.m
+
+  if (nargin >= 2)
+    droptol = args(1).double_value ();
+
+  if (nargin == 3)
+    michol = args(2).string_value ();
+
+  octave_value_list param_list;
+  if (! args(0).is_complex_type ())
+    {
+      Array <double> cols_norm;
+      SparseMatrix L;
+      param_list.append (args(0).sparse_matrix_value ());
+      SparseMatrix sm_l =
+        feval ("tril", param_list)(0).sparse_matrix_value ();
+      param_list(0) = sm_l;
+      param_list(1) = 1;
+      param_list(2) = "cols";
+      cols_norm = feval ("norm", param_list)(0).vector_value ();
+      param_list.clear ();
+      ichol_t <SparseMatrix,
+               double, ichol_mult_real, ichol_checkpivot_real>
+               (sm_l, L, cols_norm.fortran_vec (), droptol, michol);
+      if (! error_state)
+        retval(0) = L;
+    }
+  else
+    {
+      Array <Complex> cols_norm;
+      SparseComplexMatrix L;
+      param_list.append (args(0).sparse_complex_matrix_value ());
+      SparseComplexMatrix sm_l =
+        feval ("tril", param_list)(0).sparse_complex_matrix_value ();
+      param_list(0) = sm_l;
+      param_list(1) = 1;
+      param_list(2) = "cols";
+      cols_norm = feval ("norm", param_list)(0).complex_vector_value ();
+      param_list.clear ();
+      ichol_t <SparseComplexMatrix,
+               Complex, ichol_mult_complex, ichol_checkpivot_complex>
+               (sm_l, L, cols_norm.fortran_vec (),
+                Complex (droptol), michol);
+      if (! error_state)
+        retval(0) = L;
+    }
+
+  return retval;
+}
+
+/*
+## No test needed for internal helper function.
+%!assert (1)
+*/
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/dldfcn/__ilu__.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,1103 @@
+/*
+
+Copyright (C) 2014 Eduardo Ramos Fernández <eduradical951@gmail.com>
+Copyright (C) 2013 Kai T. Ohlhus <k.ohlhus@gmail.com>
+
+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 "oct-locbuf.h"
+
+#include "defun-dld.h"
+#include "parse.h"
+
+// That function implements the IKJ and JKI variants of Gaussian elimination to
+// perform the ILUTP decomposition.  The behaviour is controlled by milu
+// parameter.  If milu = ['off'|'col'] the JKI version is performed taking
+// advantage of CCS format of the input matrix.  If milu = 'row' the input
+// matrix has to be transposed to obtain the equivalent CRS structure so we can
+// work efficiently with rows.  In this case IKJ version is used.
+template <typename octave_matrix_t, typename T>
+void ilu_0 (octave_matrix_t& sm, const std::string milu = "off")
+{
+
+  const octave_idx_type n = sm.cols ();
+  OCTAVE_LOCAL_BUFFER (octave_idx_type, iw, n);
+  OCTAVE_LOCAL_BUFFER (octave_idx_type, uptr, n);
+  octave_idx_type j1, j2, jrow, jw, i, k, jj;
+  T tl, r;
+
+  enum {OFF, ROW, COL};
+  char opt;
+  if (milu == "row")
+    {
+      opt = ROW;
+      sm = sm.transpose ();
+    }
+  else if (milu == "col")
+    opt = COL;
+  else
+    opt = OFF;
+
+  octave_idx_type* cidx = sm.cidx ();
+  octave_idx_type* ridx = sm.ridx ();
+  T* data = sm.data ();
+  for (i = 0; i < n; i++)
+    iw[i] = -1;
+  for (k = 0; k < n; k++)
+    {
+      j1 = cidx[k];
+      j2 = cidx[k+1] - 1;
+      octave_idx_type j;
+      for (j = j1; j <= j2; j++)
+        {
+          iw[ridx[j]] = j;
+        }
+      r = 0;
+      j = j1;
+      jrow = ridx[j];
+      while ((jrow < k) && (j <= j2))
+        {
+          if (opt == ROW)
+            {
+              tl = data[j] / data[uptr[jrow]];
+              data[j] = tl;
+            }
+          for (jj = uptr[jrow] + 1; jj < cidx[jrow+1]; jj++)
+            {
+              jw = iw[ridx[jj]];
+              if (jw != -1)
+                if (opt == ROW)
+                  data[jw] -= tl * data[jj];
+                else
+                  data[jw] -= data[j] * data[jj];
+
+              else
+                // That is for the milu='row'
+                if (opt == ROW)
+                  r += tl * data[jj];
+                else if (opt == COL)
+                  r += data[j] * data[jj];
+            }
+          j++;
+          jrow = ridx[j];
+        }
+      uptr[k] = j;
+      if (opt != OFF)
+        data[uptr[k]] -= r;
+      if (opt != ROW)
+        for (jj = uptr[k] + 1; jj < cidx[k+1]; jj++)
+          data[jj] /=  data[uptr[k]];
+      if (k != jrow)
+        {
+          error ("ilu: A has a zero on the diagonal");
+          break;
+        }
+
+      if (data[j] == T(0))
+        {
+          error ("ilu: encountered a pivot equal to 0");
+          break;
+        }
+      for (i = j1; i <= j2; i++)
+        iw[ridx[i]] = -1;
+    }
+  if (opt == ROW)
+    sm = sm.transpose ();
+}
+
+DEFUN_DLD (__ilu0__, args, nargout, "-*- texinfo -*-\n\
+@deftypefn   {Loadable Function} {[@var{L}, @var{U}] =} __ilu0__ (@var{A})\n\
+@deftypefnx  {Loadable Function} {[@var{L}, @var{U}] =} __ilu0__ (@var{A}, @var{milu})\n\
+@deftypefnx  {Loadable Function} {[@var{L}, @var{U}, @var{P}] =} __ilu0__ (@var{A}, @dots{})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value_list retval;
+
+  int nargin = args.length ();
+  std::string milu;
+
+  if (nargout > 2 || nargin < 1 || nargin > 2)
+    {
+      print_usage ();
+      return retval;
+    }
+
+  // In ILU0 algorithm the zero-pattern of the input matrix is preserved so
+  // it's structure does not change during the algorithm.  The same input
+  // matrix is used to build the output matrix due to that fact.
+  octave_value_list param_list;
+  if (! args(0).is_complex_type ())
+    {
+      SparseMatrix sm = args(0).sparse_matrix_value ();
+      ilu_0 <SparseMatrix, double> (sm, milu);
+      if (!error_state)
+        {
+          param_list.append (sm);
+          retval(1) = feval ("triu", param_list)(0).sparse_matrix_value ();
+          SparseMatrix eye =
+            feval ("speye", octave_value_list (
+                     octave_value (sm.cols ())))(0).sparse_matrix_value ();
+          param_list.append (-1);
+          retval(0) = eye +
+                      feval ("tril", param_list)(0).sparse_matrix_value ();
+        }
+    }
+  else
+    {
+      SparseComplexMatrix sm = args(0).sparse_complex_matrix_value ();
+      ilu_0 <SparseComplexMatrix, Complex> (sm, milu);
+      if (! error_state)
+        {
+          param_list.append (sm);
+          retval(1) =
+            feval ("triu", param_list)(0).sparse_complex_matrix_value ();
+          SparseComplexMatrix eye =
+            feval ("speye", octave_value_list (
+                     octave_value (sm.cols ())))(0).sparse_complex_matrix_value ();
+          param_list.append (-1);
+          retval(0) =
+            eye + feval ("tril", param_list)(0).sparse_complex_matrix_value ();
+        }
+    }
+
+  return retval;
+}
+
+template <typename octave_matrix_t, typename T>
+void ilu_crout (octave_matrix_t& sm_l, octave_matrix_t& sm_u,
+                octave_matrix_t& L, octave_matrix_t& U, T* cols_norm,
+                T* rows_norm, const T droptol = 0,
+                const std::string milu = "off")
+{
+
+  // Map the strings into chars for faster comparing inside loops
+  char opt;
+  enum {OFF, ROW, COL};
+  if (milu == "row")
+    opt = ROW;
+  else if (milu == "col")
+    opt = COL;
+  else
+    opt = OFF;
+
+  octave_idx_type jrow, i, j, k, jj, total_len_l, total_len_u, max_len_u,
+                  max_len_l, w_len_u, w_len_l, cols_list_len, rows_list_len;
+
+  const octave_idx_type n = sm_u.cols ();
+  sm_u = sm_u.transpose ();
+
+  max_len_u = sm_u.nnz ();
+  max_len_u += (0.1 * max_len_u) > n ? 0.1 * max_len_u : n;
+  max_len_l = sm_l.nnz ();
+  max_len_l += (0.1 * max_len_l) > n ? 0.1 * max_len_l : n;
+  // Extract pointers to the arrays for faster access inside loops
+  octave_idx_type* cidx_in_u = sm_u.cidx ();
+  octave_idx_type* ridx_in_u = sm_u.ridx ();
+  T* data_in_u = sm_u.data ();
+  octave_idx_type* cidx_in_l = sm_l.cidx ();
+  octave_idx_type* ridx_in_l = sm_l.ridx ();
+  T* data_in_l = sm_l.data ();
+
+  // L output arrays
+  Array <octave_idx_type> ridx_out_l (dim_vector (max_len_l, 1));
+  octave_idx_type* ridx_l = ridx_out_l.fortran_vec ();
+  Array <T> data_out_l (dim_vector (max_len_l, 1));
+  T* data_l = data_out_l.fortran_vec ();
+
+  // U output arrays
+  Array <octave_idx_type> ridx_out_u (dim_vector (max_len_u, 1));
+  octave_idx_type* ridx_u = ridx_out_u.fortran_vec ();
+  Array <T> data_out_u (dim_vector (max_len_u, 1));
+  T* data_u = data_out_u.fortran_vec ();
+
+  // Working arrays
+  OCTAVE_LOCAL_BUFFER (octave_idx_type, cidx_l, n + 1);
+  OCTAVE_LOCAL_BUFFER (octave_idx_type, cidx_u, n + 1);
+  OCTAVE_LOCAL_BUFFER (octave_idx_type, cols_list, n);
+  OCTAVE_LOCAL_BUFFER (octave_idx_type, rows_list, n);
+  OCTAVE_LOCAL_BUFFER (T, w_data_l, n);
+  OCTAVE_LOCAL_BUFFER (T, w_data_u, n);
+  OCTAVE_LOCAL_BUFFER (octave_idx_type, Ufirst, n);
+  OCTAVE_LOCAL_BUFFER (octave_idx_type, Lfirst, n);
+  OCTAVE_LOCAL_BUFFER (T, cr_sum, n);
+
+  T zero = T (0);
+
+  cidx_u[0] = cidx_in_u[0];
+  cidx_l[0] = cidx_in_l[0];
+  for (i = 0; i < n; i++)
+    {
+      w_data_u[i] = zero;
+      w_data_l[i] = zero;
+      cr_sum[i] = zero;
+    }
+
+  total_len_u = 0;
+  total_len_l = 0;
+  cols_list_len = 0;
+  rows_list_len = 0;
+
+  for (k = 0; k < n; k++)
+    {
+      // Load the working column and working row
+      for (i = cidx_in_l[k]; i < cidx_in_l[k+1]; i++)
+        w_data_l[ridx_in_l[i]] = data_in_l[i];
+
+      for (i = cidx_in_u[k]; i < cidx_in_u[k+1]; i++)
+        w_data_u[ridx_in_u[i]] = data_in_u[i];
+
+      // Update U working row
+      for (j = 0; j < rows_list_len; j++)
+        {
+          if ((Ufirst[rows_list[j]] != -1))
+            for (jj = Ufirst[rows_list[j]]; jj < cidx_u[rows_list[j]+1]; jj++)
+              {
+                jrow = ridx_u[jj];
+                w_data_u[jrow] -= data_u[jj] * data_l[Lfirst[rows_list[j]]];
+              }
+        }
+      // Update L working column
+      for (j = 0; j < cols_list_len; j++)
+        {
+          if (Lfirst[cols_list[j]] != -1)
+            for (jj = Lfirst[cols_list[j]]; jj < cidx_l[cols_list[j]+1]; jj++)
+              {
+                jrow = ridx_l[jj];
+                w_data_l[jrow] -= data_l[jj] * data_u[Ufirst[cols_list[j]]];
+              }
+        }
+
+      if ((max_len_u - total_len_u) < n)
+        {
+          max_len_u += (0.1 * max_len_u) > n ? 0.1 * max_len_u : n;
+          data_out_u.resize (dim_vector (max_len_u, 1));
+          data_u = data_out_u.fortran_vec ();
+          ridx_out_u.resize (dim_vector (max_len_u, 1));
+          ridx_u = ridx_out_u.fortran_vec ();
+        }
+
+      if ((max_len_l - total_len_l) < n)
+        {
+          max_len_l += (0.1 * max_len_l) > n ? 0.1 * max_len_l : n;
+          data_out_l.resize (dim_vector (max_len_l, 1));
+          data_l = data_out_l.fortran_vec ();
+          ridx_out_l.resize (dim_vector (max_len_l, 1));
+          ridx_l = ridx_out_l.fortran_vec ();
+        }
+
+      // Expand the working row into the U output data structures
+      w_len_l = 0;
+      data_u[total_len_u] = w_data_u[k];
+      ridx_u[total_len_u] = k;
+      w_len_u = 1;
+      for (i = k + 1; i < n; i++)
+        {
+          if (w_data_u[i] != zero)
+            {
+              if (std::abs (w_data_u[i]) < (droptol * rows_norm[k]))
+                {
+                  if (opt == ROW)
+                    cr_sum[k] += w_data_u[i];
+                  else if (opt == COL)
+                    cr_sum[i] += w_data_u[i];
+                }
+              else
+                {
+                  data_u[total_len_u + w_len_u] = w_data_u[i];
+                  ridx_u[total_len_u + w_len_u] = i;
+                  w_len_u++;
+                }
+            }
+
+          // Expand the working column into the L output data structures
+          if (w_data_l[i] != zero)
+            {
+              if (std::abs (w_data_l[i]) < (droptol * cols_norm[k]))
+                {
+                  if (opt == COL)
+                    cr_sum[k] += w_data_l[i];
+                  else if (opt == ROW)
+                    cr_sum[i] += w_data_l[i];
+                }
+              else
+                {
+                  data_l[total_len_l + w_len_l] = w_data_l[i];
+                  ridx_l[total_len_l + w_len_l] = i;
+                  w_len_l++;
+                }
+            }
+          w_data_u[i] = zero;
+          w_data_l[i] = zero;
+        }
+
+      // Compensate row and column sums --> milu option
+      if (opt == COL || opt == ROW)
+        data_u[total_len_u] += cr_sum[k];
+
+      // Check if the pivot is zero
+      if (data_u[total_len_u] == zero)
+        {
+          error ("ilu: encountered a pivot equal to 0");
+          break;
+        }
+
+      // Scale the elements in L by the pivot
+      for (i = total_len_l ; i < (total_len_l + w_len_l); i++)
+        data_l[i] /= data_u[total_len_u];
+
+
+      total_len_u += w_len_u;
+      total_len_l += w_len_l;
+      // Check if there are too many elements to be indexed with
+      // octave_idx_type type due to fill-in during the process.
+      if (total_len_l < 0 || total_len_u < 0)
+        {
+          error ("ilu: integer overflow.  Too many fill-in elements in L or U");
+          break;
+        }
+      cidx_u[k+1] = cidx_u[k] - cidx_u[0] + w_len_u;
+      cidx_l[k+1] = cidx_l[k] - cidx_l[0] + w_len_l;
+
+      // The tricky part of the algorithm.  The arrays pointing to the first
+      // working element of each column in the next iteration (Lfirst) or
+      // the first working element of each row (Ufirst) are updated.  Also the
+      // arrays working as lists cols_list and rows_list are filled with
+      // indices pointing to Ufirst and Lfirst respectively.
+      // TODO: Maybe the -1 indicating in Ufirst and Lfirst, that no elements
+      // have to be considered in a certain column or row in next iteration,
+      // can be removed.  It feels safer to me using such an indicator.
+      if (k < (n - 1))
+        {
+          if (w_len_u > 0)
+            Ufirst[k] = cidx_u[k];
+          else
+            Ufirst[k] = -1;
+          if (w_len_l > 0)
+            Lfirst[k] = cidx_l[k];
+          else
+            Lfirst[k] = -1;
+          cols_list_len = 0;
+          rows_list_len = 0;
+          for (i = 0; i <= k; i++)
+            {
+              if (Ufirst[i] != -1)
+                {
+                  jj = ridx_u[Ufirst[i]];
+                  if (jj < (k + 1))
+                    {
+                      if (Ufirst[i] < (cidx_u[i+1]))
+                        {
+                          Ufirst[i]++;
+                          if (Ufirst[i] == cidx_u[i+1])
+                            Ufirst[i] = -1;
+                          else
+                            jj = ridx_u[Ufirst[i]];
+                        }
+                    }
+                  if (jj == (k + 1))
+                    {
+                      cols_list[cols_list_len] = i;
+                      cols_list_len++;
+                    }
+                }
+
+              if (Lfirst[i] != -1)
+                {
+                  jj = ridx_l[Lfirst[i]];
+                  if (jj < (k + 1))
+                    if (Lfirst[i] < (cidx_l[i+1]))
+                      {
+                        Lfirst[i]++;
+                        if (Lfirst[i] == cidx_l[i+1])
+                          Lfirst[i] = -1;
+                        else
+                          jj = ridx_l[Lfirst[i]];
+                      }
+                  if (jj == (k + 1))
+                    {
+                      rows_list[rows_list_len] = i;
+                      rows_list_len++;
+                    }
+                }
+            }
+        }
+    }
+
+  if (! error_state)
+    {
+      // Build the output matrices
+      L = octave_matrix_t (n, n, total_len_l);
+      U = octave_matrix_t (n, n, total_len_u);
+      for (i = 0; i <= n; i++)
+        L.cidx (i) = cidx_l[i];
+      for (i = 0; i < total_len_l; i++)
+        {
+          L.ridx (i) = ridx_l[i];
+          L.data (i) = data_l[i];
+        }
+      for (i = 0; i <= n; i++)
+        U.cidx (i) = cidx_u[i];
+      for (i = 0; i < total_len_u; i++)
+        {
+          U.ridx (i) = ridx_u[i];
+          U.data (i) = data_u[i];
+        }
+      U = U.transpose ();
+    }
+}
+
+DEFUN_DLD (__iluc__, args, nargout, "-*- texinfo -*-\n\
+@deftypefn  {Loadable Function} {[@var{L}, @var{U}] =} __iluc__ (@var{A})\n\
+@deftypefnx {Loadable Function} {[@var{L}, @var{U}] =} __iluc__ (@var{A}, @var{droptol}) \n\
+@deftypefnx {Loadable Function} {[@var{L}, @var{U}] =} __iluc__ (@var{A}, @var{droptol}, @var{milu})\n\
+@deftypefnx {Loadable Function} {[@var{L}, @var{U}, @var{P}] =} __iluc__ (@var{A}, @dots{})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value_list retval;
+  int nargin = args.length ();
+  std::string milu = "off";
+  double droptol = 0;
+
+  if (nargout != 2 || nargin < 1 || nargin > 3)
+    {
+      print_usage ();
+      return retval;
+    }
+
+  // Don't repeat input validation of arguments done in ilu.m
+  if (nargin >= 2)
+    droptol = args(1).double_value ();
+
+  if (nargin == 3)
+    milu = args(2).string_value ();
+
+  octave_value_list param_list;
+  if (! args(0).is_complex_type ())
+    {
+      Array<double> cols_norm, rows_norm;
+      param_list.append (args(0).sparse_matrix_value ());
+      SparseMatrix sm_u = feval ("triu", param_list)(0).sparse_matrix_value ();
+      param_list.append (-1);
+      SparseMatrix sm_l = feval ("tril", param_list)(0).sparse_matrix_value ();
+      param_list(1) = "rows";
+      rows_norm = feval ("norm", param_list)(0).vector_value ();
+      param_list(1) = "cols";
+      cols_norm = feval ("norm", param_list)(0).vector_value ();
+      param_list.clear ();
+      SparseMatrix U;
+      SparseMatrix L;
+      ilu_crout <SparseMatrix, double> (sm_l, sm_u, L, U,
+                                        cols_norm.fortran_vec (),
+                                        rows_norm.fortran_vec (),
+                                        droptol, milu);
+      if (! error_state)
+        {
+          param_list.append (octave_value (L.cols ()));
+          SparseMatrix eye =
+            feval ("speye", param_list)(0).sparse_matrix_value ();
+          retval(1) = U;
+          retval(0) = L + eye;
+        }
+    }
+  else
+    {
+      Array<Complex> cols_norm, rows_norm;
+      param_list.append (args(0).sparse_complex_matrix_value ());
+      SparseComplexMatrix sm_u =
+        feval("triu", param_list)(0).sparse_complex_matrix_value ();
+      param_list.append (-1);
+      SparseComplexMatrix sm_l =
+        feval("tril", param_list)(0).sparse_complex_matrix_value ();
+      param_list(1) = "rows";
+      rows_norm = feval ("norm", param_list)(0).complex_vector_value ();
+      param_list(1) = "cols";
+      cols_norm = feval ("norm", param_list)(0).complex_vector_value ();
+      param_list.clear ();
+      SparseComplexMatrix U;
+      SparseComplexMatrix L;
+      ilu_crout < SparseComplexMatrix, Complex >
+                (sm_l, sm_u, L, U, cols_norm.fortran_vec () ,
+                 rows_norm.fortran_vec (), Complex (droptol), milu);
+      if (! error_state)
+        {
+          param_list.append (octave_value (L.cols ()));
+          SparseComplexMatrix eye =
+            feval ("speye", param_list)(0).sparse_complex_matrix_value ();
+          retval(1) = U;
+          retval(0) = L + eye;
+        }
+    }
+
+  return retval;
+}
+
+// That function implements the IKJ and JKI variants of gaussian elimination
+// to perform the ILUTP decomposition.  The behaviour is controlled by milu
+// parameter.  If milu = ['off'|'col'] the JKI version is performed taking
+// advantage of CCS format of the input matrix.  Row pivoting is performed.
+// If milu = 'row' the input matrix has to be transposed to obtain the
+// equivalent CRS structure so we can work efficiently with rows.  In that
+// case IKJ version is used and column pivoting is performed.
+
+template <typename octave_matrix_t, typename T>
+void ilu_tp (octave_matrix_t& sm, octave_matrix_t& L, octave_matrix_t& U,
+             octave_idx_type nnz_u, octave_idx_type nnz_l, T* cols_norm,
+             Array <octave_idx_type>& perm_vec, const T droptol = T(0),
+             const T thresh = T(0), const  std::string milu = "off",
+             const double udiag = 0)
+{
+  char opt;
+  enum {OFF, ROW, COL};
+  if (milu == "row")
+    opt = ROW;
+  else if (milu == "col")
+    opt = COL;
+  else
+    opt = OFF;
+
+  const octave_idx_type n = sm.cols ();
+
+  // That is necessary for the JKI (milu = "row") variant.
+  if (opt == ROW)
+    sm = sm.transpose();
+
+  // Extract pointers to the arrays for faster access inside loops
+  octave_idx_type* cidx_in = sm.cidx ();
+  octave_idx_type* ridx_in = sm.ridx ();
+  T* data_in = sm.data ();
+  octave_idx_type jrow, i, j, k, jj, c, total_len_l, total_len_u, p_perm,
+                  max_ind, max_len_l, max_len_u;
+  T tl, aux, maximum;
+
+  max_len_u = nnz_u;
+  max_len_u += (0.1 * max_len_u) > n ? 0.1 * max_len_u : n;
+  max_len_l = nnz_l;
+  max_len_l += (0.1 * max_len_l) > n ? 0.1 * max_len_l : n;
+
+  Array <octave_idx_type> cidx_out_l (dim_vector (n + 1, 1));
+  octave_idx_type* cidx_l = cidx_out_l.fortran_vec ();
+  Array <octave_idx_type> ridx_out_l (dim_vector (max_len_l, 1));
+  octave_idx_type* ridx_l = ridx_out_l.fortran_vec ();
+  Array <T> data_out_l (dim_vector (max_len_l ,1));
+  T* data_l = data_out_l.fortran_vec ();
+  // Data for U
+  Array <octave_idx_type> cidx_out_u (dim_vector (n + 1, 1));
+  octave_idx_type* cidx_u = cidx_out_u.fortran_vec ();
+  Array <octave_idx_type> ridx_out_u (dim_vector (max_len_u, 1));
+  octave_idx_type* ridx_u = ridx_out_u.fortran_vec ();
+  Array <T> data_out_u (dim_vector (max_len_u, 1));
+  T* data_u = data_out_u.fortran_vec();
+
+  // Working arrays and permutation arrays
+  octave_idx_type w_len_u, w_len_l;
+  T total_sum, partial_col_sum, partial_row_sum;
+  std::set <octave_idx_type> iw_l;
+  std::set <octave_idx_type> iw_u;
+  std::set <octave_idx_type>::iterator it, it2;
+  OCTAVE_LOCAL_BUFFER (T, w_data, n);
+  OCTAVE_LOCAL_BUFFER (octave_idx_type, iperm, n);
+  octave_idx_type* perm = perm_vec.fortran_vec ();
+  OCTAVE_LOCAL_BUFFER (octave_idx_type, uptr, n);
+
+
+  T zero = T(0);
+  cidx_l[0] = cidx_in[0];
+  cidx_u[0] = cidx_in[0];
+  for (i = 0; i < n; i++)
+    {
+      w_data[i] = 0;
+      perm[i] = i;
+      iperm[i] = i;
+    }
+  total_len_u = 0;
+  total_len_l = 0;
+
+  for (k = 0; k < n; k++)
+    {
+
+      for (j = cidx_in[k]; j < cidx_in[k+1]; j++)
+        {
+          p_perm = iperm[ridx_in[j]];
+          w_data[iperm[ridx_in[j]]] = data_in[j];
+          if (p_perm > k)
+            iw_l.insert (ridx_in[j]);
+          else
+            iw_u.insert (p_perm);
+        }
+
+      it = iw_u.begin ();
+      jrow = *it;
+      total_sum = zero;
+      while ((jrow < k) && (it != iw_u.end ()))
+        {
+          if (opt == COL)
+            partial_col_sum = w_data[jrow];
+          if (w_data[jrow] != zero)
+            {
+              if (opt == ROW)
+                {
+                  partial_row_sum = w_data[jrow];
+                  tl = w_data[jrow] / data_u[uptr[jrow]];
+                }
+              for (jj = cidx_l[jrow]; jj < cidx_l[jrow+1]; jj++)
+                {
+                  p_perm = iperm[ridx_l[jj]];
+                  aux = w_data[p_perm];
+                  if (opt == ROW)
+                    {
+                      w_data[p_perm] -= tl * data_l[jj];
+                      partial_row_sum += tl * data_l[jj];
+                    }
+                  else
+                    {
+                      tl = data_l[jj] * w_data[jrow];
+                      w_data[p_perm] -= tl;
+                      if (opt == COL)
+                        partial_col_sum += tl;
+                    }
+
+                  if ((aux == zero) && (w_data[p_perm] != zero))
+                    {
+                      if (p_perm > k)
+                        iw_l.insert (ridx_l[jj]);
+                      else
+                        iw_u.insert (p_perm);
+                    }
+                }
+
+              // Drop element from the U part in IKJ and L part in JKI
+              // variant (milu = [col|off])
+              if ((std::abs (w_data[jrow]) < (droptol * cols_norm[k]))
+                  && (w_data[jrow] != zero))
+                {
+                  if (opt == COL)
+                    total_sum += partial_col_sum;
+                  else if (opt == ROW)
+                    total_sum += partial_row_sum;
+                  w_data[jrow] = zero;
+                  it2 = it;
+                  it++;
+                  iw_u.erase (it2);
+                  jrow = *it;
+                  continue;
+                }
+              else
+                // This is the element scaled by the pivot
+                // in the actual iteration
+                if (opt == ROW)
+                  w_data[jrow] = tl;
+            }
+          jrow = *(++it);
+        }
+
+      // Search for the pivot and update iw_l and iw_u if the pivot is not the
+      // diagonal element
+      if ((thresh > zero) && (k < (n - 1)))
+        {
+          maximum = std::abs (w_data[k]) / thresh;
+          max_ind = perm[k];
+          for (it = iw_l.begin (); it != iw_l.end (); ++it)
+            {
+              p_perm = iperm[*it];
+              if (std::abs (w_data[p_perm]) > maximum)
+                {
+                  maximum = std::abs (w_data[p_perm]);
+                  max_ind = *it;
+                  it2 = it;
+                }
+            }
+          // If the pivot is not the diagonal element update all.
+          p_perm = iperm[max_ind];
+          if (max_ind != perm[k])
+            {
+              iw_l.erase (it2);
+              if (w_data[k] != zero)
+                iw_l.insert (perm[k]);
+              else
+                iw_u.insert (k);
+              // Swap data and update permutation vectors
+              aux = w_data[k];
+              iperm[perm[p_perm]] = k;
+              iperm[perm[k]] = p_perm;
+              c = perm[k];
+              perm[k] = perm[p_perm];
+              perm[p_perm] = c;
+              w_data[k] = w_data[p_perm];
+              w_data[p_perm] = aux;
+            }
+
+        }
+
+      // Drop elements in the L part in the IKJ and from the U part in the JKI
+      // version.
+      it = iw_l.begin ();
+      while (it != iw_l.end ())
+        {
+          p_perm = iperm[*it];
+          if (droptol > zero)
+            if (std::abs (w_data[p_perm]) < (droptol * cols_norm[k]))
+              {
+                if (opt != OFF)
+                  total_sum += w_data[p_perm];
+                w_data[p_perm] = zero;
+                it2 = it;
+                it++;
+                iw_l.erase (it2);
+                continue;
+              }
+
+          it++;
+        }
+
+      // If milu == [row|col] summation is preserved.
+      // Compensate diagonal element.
+      if (opt != OFF)
+        {
+          if ((total_sum > zero) && (w_data[k] == zero))
+            iw_u.insert (k);
+          w_data[k] += total_sum;
+        }
+
+
+
+      // Check if the pivot is zero and if udiag is active.
+      // NOTE: If the pivot == 0 and udiag is active, then if milu = [col|row]
+      //       will not preserve the row sum for that column/row.
+      if (w_data[k] == zero)
+        {
+          if (udiag == 1)
+            {
+              w_data[k] = droptol;
+              iw_u.insert (k);
+            }
+          else
+            {
+              error ("ilu: encountered a pivot equal to 0");
+              break;
+            }
+        }
+
+      // Scale the elements on the L part for IKJ version (milu = [col|off])
+      if (opt != ROW)
+        for (it = iw_l.begin (); it != iw_l.end (); ++it)
+          {
+            p_perm = iperm[*it];
+            w_data[p_perm] = w_data[p_perm] / w_data[k];
+          }
+
+
+      if ((max_len_u - total_len_u) < n)
+        {
+          max_len_u += (0.1 * max_len_u) > n ? 0.1 * max_len_u : n;
+          data_out_u.resize (dim_vector (max_len_u, 1));
+          data_u = data_out_u.fortran_vec ();
+          ridx_out_u.resize (dim_vector (max_len_u, 1));
+          ridx_u = ridx_out_u.fortran_vec ();
+        }
+
+      if ((max_len_l - total_len_l) < n)
+        {
+          max_len_l += (0.1 * max_len_l) > n ? 0.1 * max_len_l : n;
+          data_out_l.resize (dim_vector (max_len_l, 1));
+          data_l = data_out_l.fortran_vec ();
+          ridx_out_l.resize (dim_vector (max_len_l, 1));
+          ridx_l = ridx_out_l.fortran_vec ();
+        }
+
+      // Expand working vector into U.
+      w_len_u = 0;
+      for (it = iw_u.begin (); it != iw_u.end (); ++it)
+        {
+          if (w_data[*it] != zero)
+            {
+              data_u[total_len_u + w_len_u] = w_data[*it];
+              ridx_u[total_len_u + w_len_u] = *it;
+              w_len_u++;
+            }
+          w_data[*it] = 0;
+        }
+      // Expand working vector into L.
+      w_len_l = 0;
+      for (it = iw_l.begin (); it != iw_l.end (); ++it)
+        {
+          p_perm = iperm[*it];
+          if (w_data[p_perm] != zero)
+            {
+              data_l[total_len_l + w_len_l] = w_data[p_perm];
+              ridx_l[total_len_l + w_len_l] = *it;
+              w_len_l++;
+            }
+          w_data[p_perm] = 0;
+        }
+      total_len_u += w_len_u;
+      total_len_l += w_len_l;
+      // Check if there are too many elements to be indexed with
+      // octave_idx_type type due to fill-in during the process.
+      if (total_len_l < 0 || total_len_u < 0)
+        {
+          error ("ilu: Integer overflow.  Too many fill-in elements in L or U");
+          break;
+        }
+      if (opt == ROW)
+        uptr[k] = total_len_u - 1;
+      cidx_u[k+1] = cidx_u[k] - cidx_u[0] + w_len_u;
+      cidx_l[k+1] = cidx_l[k] - cidx_l[0] + w_len_l;
+
+      iw_l.clear ();
+      iw_u.clear ();
+    }
+
+  if (! error_state)
+    {
+      octave_matrix_t *L_ptr;
+      octave_matrix_t *U_ptr;
+      octave_matrix_t diag (n, n, n);
+
+      // L and U are interchanged if milu = 'row'.  It is a matter
+      // of nomenclature to re-use code with both IKJ and JKI
+      // versions of the algorithm.
+      if (opt == ROW)
+        {
+          L_ptr = &U;
+          U_ptr = &L;
+          L = octave_matrix_t (n, n, total_len_u - n);
+          U = octave_matrix_t (n, n, total_len_l);
+        }
+      else
+        {
+          L_ptr = &L;
+          U_ptr = &U;
+          L = octave_matrix_t (n, n, total_len_l);
+          U = octave_matrix_t (n, n, total_len_u);
+        }
+
+      for (i = 0; i <= n; i++)
+        {
+          L_ptr->cidx (i) = cidx_l[i];
+          U_ptr->cidx (i) = cidx_u[i];
+          if (opt == ROW)
+            U_ptr->cidx (i) -= i;
+        }
+
+      for (i = 0; i < n; i++)
+        {
+          if (opt == ROW)
+            diag.elem (i,i) = data_u[uptr[i]];
+          j = cidx_l[i];
+
+          while (j < cidx_l[i+1])
+            {
+              L_ptr->ridx (j) = ridx_l[j];
+              L_ptr->data (j) = data_l[j];
+              j++;
+            }
+          j = cidx_u[i];
+
+          while (j < cidx_u[i+1])
+            {
+              c = j;
+              if (opt == ROW)
+                {
+                  // The diagonal is removed from L if milu = 'row'.
+                  // That is because is convenient to have it inside
+                  // the L part to carry out the process.
+                  if (ridx_u[j] == i)
+                    {
+                      j++;
+                      continue;
+                    }
+                  else
+                    c -= i;
+                }
+              U_ptr->data (c) = data_u[j];
+              U_ptr->ridx (c) = ridx_u[j];
+              j++;
+            }
+        }
+
+      if (opt == ROW)
+        {
+          U = U.transpose ();
+          // The diagonal, conveniently permuted is added to U
+          U += diag.index (idx_vector::colon, perm_vec);
+          L = L.transpose ();
+        }
+    }
+}
+
+DEFUN_DLD (__ilutp__, args, nargout, "-*- texinfo -*-\n\
+@deftypefn  {Loadable Function} {[@var{L}, @var{U}] =} __ilutp__ (@var{A})\n\
+@deftypefnx {Loadable Function} {[@var{L}, @var{U}] =} __ilutp__ (@var{A}, @var{droptol})\n\
+@deftypefnx {Loadable Function} {[@var{L}, @var{U}] =} __ilutp__ (@var{A}, @var{droptol}, @var{thresh})\n\
+@deftypefnx {Loadable Function} {[@var{L}, @var{U}] =} __ilutp__ (@var{A}, @var{droptol}, @var{thresh}, @var{milu})\n\
+@deftypefnx {Loadable Function} {[@var{L}, @var{U}] =} __ilutp__ (@var{A}, @var{droptol}, @var{thresh}, @var{milu}, @var{udiag})\n\
+@deftypefnx {Loadable Function} {[@var{L}, @var{U}, @var{P}] =} __ilutp__ (@var{A}, @dots{})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value_list retval;
+
+  int nargin = args.length ();
+  std::string milu = "";
+  double droptol = 0, thresh = 1;
+  double udiag = 0;
+
+  if (nargout < 2 || nargout > 3 || nargin < 1 || nargin > 5)
+    {
+      print_usage ();
+      return retval;
+    }
+
+  // Don't repeat input validation of arguments done in ilu.m
+  if (nargin >= 2)
+    droptol = args(1).double_value ();
+
+  if (nargin >= 3)
+    thresh = args(2).double_value ();
+
+  if (nargin >= 4)
+    milu = args(3).string_value ();
+
+  if (nargin == 5)
+    udiag = args(4).double_value ();
+
+  octave_value_list param_list;
+  octave_idx_type nnz_u, nnz_l;
+  if (! args(0).is_complex_type ())
+    {
+      Array <double> rc_norm;
+      SparseMatrix sm = args(0).sparse_matrix_value ();
+      param_list.append (sm);
+      nnz_u =  (feval ("triu", param_list)(0).sparse_matrix_value ()).nnz ();
+      param_list.append (-1);
+      nnz_l =  (feval ("tril", param_list)(0).sparse_matrix_value ()).nnz ();
+      if (milu == "row")
+        param_list (1) = "rows";
+      else
+        param_list (1) = "cols";
+      rc_norm = feval ("norm", param_list)(0).vector_value ();
+      param_list.clear ();
+      Array <octave_idx_type> perm (dim_vector (sm.cols (), 1));
+      SparseMatrix U;
+      SparseMatrix L;
+      ilu_tp <SparseMatrix, double> (sm, L, U, nnz_u, nnz_l,
+                                     rc_norm.fortran_vec (),
+                                     perm, droptol, thresh, milu, udiag);
+      if (! error_state)
+        {
+          param_list.append (octave_value (L.cols ()));
+          SparseMatrix eye =
+            feval ("speye", param_list)(0).sparse_matrix_value ();
+          if (milu == "row")
+            {
+              if (nargout == 3)
+                {
+                  retval(2) = eye.index (idx_vector::colon, perm);
+                  retval(1) = U.index (idx_vector::colon, perm);
+                }
+              else if (nargout == 2)
+                retval(1) = U;
+              retval(0) = L + eye;
+            }
+          else
+            {
+              if (nargout == 3)
+                {
+                  retval(2) = eye.index (perm, idx_vector::colon);
+                  retval(1) = U;
+                  retval(0) = L.index (perm, idx_vector::colon) + eye;
+                }
+              else
+                {
+                  retval(1) = U;
+                  retval(0) = L + eye.index (perm, idx_vector::colon);
+                }
+            }
+        }
+    }
+  else
+    {
+      Array <Complex> rc_norm;
+      SparseComplexMatrix sm = args(0).sparse_complex_matrix_value ();
+      param_list.append (sm);
+      nnz_u =
+        feval ("triu", param_list)(0).sparse_complex_matrix_value ().nnz ();
+      param_list.append (-1);
+      nnz_l =
+        feval ("tril", param_list)(0).sparse_complex_matrix_value ().nnz ();
+      if (milu == "row")
+        param_list(1) = "rows";
+      else
+        param_list(1) = "cols";
+      rc_norm = feval ("norm", param_list)(0).complex_vector_value ();
+      Array <octave_idx_type> perm (dim_vector (sm.cols (), 1));
+      param_list.clear ();
+      SparseComplexMatrix U;
+      SparseComplexMatrix L;
+      ilu_tp < SparseComplexMatrix, Complex>
+              (sm, L, U, nnz_u, nnz_l, rc_norm.fortran_vec (), perm,
+               Complex (droptol), Complex (thresh), milu, udiag);
+
+      if (! error_state)
+        {
+          param_list.append (octave_value (L.cols ()));
+          SparseComplexMatrix eye =
+            feval ("speye", param_list)(0).sparse_complex_matrix_value ();
+          if (milu == "row")
+            {
+              if (nargout == 3)
+                {
+                  retval(2) = eye.index (idx_vector::colon, perm);
+                  retval(1) = U.index (idx_vector::colon, perm);
+                }
+              else if (nargout == 2)
+                retval(1) = U;
+              retval(0) = L + eye;
+            }
+          else
+            {
+              if (nargout == 3)
+                {
+                  retval(2) = eye.index (perm, idx_vector::colon);
+                  retval(1) = U;
+                  retval(0) = L.index (perm, idx_vector::colon) + eye;
+                }
+              else
+                {
+                  retval(1) = U;
+                  retval(0) = L + eye.index (perm, idx_vector::colon);
+                }
+            }
+        }
+    }
+
+  return retval;
+}
+
+/*
+## No test needed for internal helper function.
+%!assert (1)
+*/
+
--- a/libinterp/dldfcn/__init_fltk__.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/dldfcn/__init_fltk__.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -1,6 +1,7 @@
 /*
 
 Copyright (C) 2007-2013 Shai Ayal
+Copyright (C) 2014 Andreas Weber
 
 This file is part of Octave.
 
@@ -61,6 +62,7 @@
 #include <FL/Fl_Choice.H>
 #include <FL/Fl_File_Chooser.H>
 #include <FL/Fl_Gl_Window.H>
+#include <FL/names.h>
 #include <FL/Fl_Menu_Bar.H>
 #include <FL/Fl_Menu_Button.H>
 #include <FL/Fl_Output.H>
@@ -91,9 +93,6 @@
 
 #define FLTK_GRAPHICS_TOOLKIT_NAME "fltk"
 
-// Give FLTK no more than 0.01 sec to do its stuff.
-static double fltk_maxtime = 1e-2;
-
 const char* help_text = "\
 Keyboard Shortcuts\n\
 a - autoscale\n\
@@ -113,7 +112,7 @@
 public:
   OpenGL_fltk (int xx, int yy, int ww, int hh, double num)
     : Fl_Gl_Window (xx, yy, ww, hh, 0), number (num), renderer (),
-      in_zoom (false), zoom_box (),  print_mode (false)
+      in_zoom (false), zoom_box ()
   {
     // Ask for double buffering and a depth buffer.
     mode (FL_DEPTH | FL_DOUBLE | FL_MULTISAMPLE);
@@ -133,16 +132,21 @@
 
   void print (const std::string& cmd, const std::string& term)
   {
-    print_mode  = true;
-    print_cmd = cmd;
-    print_term  = term;
+    //std::cout << "OpenGL_fltk::print(cmd=" << cmd << ", term=" << term << ") canvas size = " << w () << "x" << h () << std::endl;
+#ifdef HAVE_GL2PS_H
+    FILE *fp;
+    fp = octave_popen (cmd.c_str (), "w");
+    glps_renderer rend (fp, term);
+    rend.draw (gh_manager::get_object (number), cmd);
+    octave_pclose (fp);
+#else
+    error ("fltk: printing not available without gl2ps library");
+#endif
   }
 
   void resize (int xx, int yy, int ww, int hh)
   {
     Fl_Gl_Window::resize (xx, yy, ww, hh);
-    setup_viewport (ww, hh);
-    redraw ();
   }
 
   bool renumber (double new_number)
@@ -165,48 +169,19 @@
   // (x1,y1,x2,y2)
   Matrix zoom_box;
 
-  bool print_mode;
-  std::string print_cmd;
-  std::string print_term;
-
-  void setup_viewport (int ww, int hh)
-  {
-    glMatrixMode (GL_PROJECTION);
-    glLoadIdentity ();
-    glViewport (0, 0, ww, hh);
-  }
-
   void draw (void)
   {
     if (! valid ())
       {
-        valid (1);
-        setup_viewport (w (), h ());
+        glMatrixMode (GL_PROJECTION);
+        glLoadIdentity ();
+        glViewport (0, 0, w (), h ());
       }
 
-    if (print_mode)
-      {
-#ifdef HAVE_GL2PS_H
-        FILE *fp = octave_popen (print_cmd.c_str (), "w");
-        glps_renderer rend (fp, print_term);
-
-        rend.draw (gh_manager::get_object (number), print_cmd);
+    renderer.draw (gh_manager::get_object (number));
 
-        octave_pclose (fp);
-        print_mode = false;
-#else
-        print_mode = false;
-        error ("fltk: printing not available without gl2ps library");
-        return;
-#endif
-      }
-    else
-      {
-        renderer.draw (gh_manager::get_object (number));
-
-        if (zoom ())
-          overlay ();
-      }
+    if (zoom ())
+      overlay ();
   }
 
   void zoom_box_vertex (void)
@@ -249,28 +224,20 @@
 
   int handle (int event)
   {
-    int retval = Fl_Gl_Window::handle (event);
-
     switch (event)
       {
       case FL_ENTER:
-        window ()->cursor (FL_CURSOR_CROSS);
+        cursor (FL_CURSOR_CROSS);
         return 1;
 
       case FL_LEAVE:
-        window ()->cursor (FL_CURSOR_DEFAULT);
+        cursor (FL_CURSOR_DEFAULT);
         return 1;
       }
-
-    return retval;
+    return Fl_Gl_Window::handle (event);
   }
 };
 
-// Parameter controlling how fast we zoom when using the scrool wheel.
-static double Vwheel_zoom_speed = 0.05;
-// Parameter controlling the GUI mode.
-static enum { pan_zoom, rotate_zoom, none } gui_mode;
-
 void script_cb (Fl_Widget*, void* data)
 {
   static_cast<uimenu::properties*> (data)->execute_callback ();
@@ -282,8 +249,7 @@
 public:
   fltk_uimenu (int xx, int yy, int ww, int hh)
   {
-    menubar = new
-    Fl_Menu_Bar (xx, yy, ww, hh);
+    menubar = new Fl_Menu_Bar (xx, yy, ww, hh);
   }
 
   int items_to_show (void)
@@ -291,7 +257,7 @@
     //returns the number of visible menu items
     int len = menubar->size ();
     int n = 0;
-    for (int t = 0; t < len; t++ )
+    for (int t = 0; t < len; t++)
       {
         const Fl_Menu_Item *m = static_cast<const Fl_Menu_Item*> (&
                                 (menubar->menu ()[t]));
@@ -305,11 +271,13 @@
   void show (void)
   {
     menubar->show ();
+    menubar->redraw ();
   }
 
   void hide (void)
   {
     menubar->hide ();
+    menubar->redraw ();
   }
 
   bool is_visible (void)
@@ -326,7 +294,7 @@
     // Kai Habel (14.10.2010)
 
     std::string menupath;
-    for (int t = 0; t < menubar->size (); t++ )
+    for (int t = 0; t < menubar->size (); t++)
       {
         Fl_Menu_Item *m = const_cast<Fl_Menu_Item*> (&(menubar->menu ()[t]));
         if (m->submenu ())
@@ -336,7 +304,7 @@
               menupath += "/";
             menupath += m->label ();
 
-            if (menupath.compare (findname) == 0 )
+            if (menupath.compare (findname) == 0)
               return (t);
           }
         else
@@ -691,14 +659,20 @@
 {
   friend class fltk_uimenu;
 public:
-  plot_window (int xx, int yy, int ww, int hh, figure::properties& xfp)
-    : Fl_Window (xx, yy - menu_h, ww, hh + menu_h + status_h, "octave"),
-      window_label (), shift (0), ndim (2), fp (xfp), canvas (0),
+  plot_window (int xx, int yy, int ww, int hh, figure::properties& xfp, bool internal)
+    : Fl_Window (xx, yy, ww, hh + menu_h + status_h + 2, "octave"),
+      window_label (), fp (xfp), canvas (0),
       autoscale (0), togglegrid (0), panzoom (0), rotate (0), help (0),
-      status (0), ax_obj (), pos_x (0), pos_y (0)
+      status (0), resize_dummy (0), ax_obj (), pos_x (0), pos_y (0)
   {
     callback (window_close, static_cast<void*> (this));
-    size_range (4*status_h, 2*status_h);
+
+    // The size of the resize_dummy box also determines the minimum window size
+    resize_dummy = new Fl_Box (5 * status_h + 1, menu_h + 1,
+                               ww - 5 * status_h - 1, hh);
+    // See http://fltk.org/articles.php?L415+I0+T+M1000+P1
+    // for how resizable works
+    resizable (resize_dummy);
 
     // FIXME: The function below is only available in FLTK >= 1.3
     // At some point support for FLTK 1.1 will be dropped in Octave.
@@ -708,115 +682,84 @@
     // windows.  Otherwise, the class is just "FLTK"
     //default_xclass ("Octave");
 
-    begin ();
-    {
-      // bbox of plot canvas = [xx, yy, ww, hh];
-      // (xx, yy) = UL coordinate relative to UL window.
+    uimenu = new fltk_uimenu (0, 0, ww, menu_h);
+    canvas = new OpenGL_fltk (0, menu_h, ww, hh, number ());
 
-      canvas = new OpenGL_fltk (0, menu_h, ww, hh, number ());
+    // The bottom toolbar is a composite of "autoscale", "togglegrid",
+    // "panzoom", "rotate", "help", and "status".
+    // Only "status" should be resized.
 
-      uimenu = new fltk_uimenu (0, 0, ww, menu_h);
-      uimenu->hide ();
-
-      // Toolbar is a composite of "bottom", "autoscale", "togglegrid",
-      // "panzoom", "rotate", "help", and "status".
+    int toolbar_y = menu_h + hh + 1;
+    status = new Fl_Output (5 * status_h + 1, toolbar_y,
+                            ww - 5 * status_h - 1, status_h, "");
 
-      yy = hh + menu_h;
-      bottom = new Fl_Box (0, yy, ww, status_h);
-      bottom->box (FL_FLAT_BOX);
-
-      ndim = calc_dimensions (gh_manager::get_object (fp.get___myhandle__ ()));
-
-      autoscale = new Fl_Button (0, yy, status_h, status_h, "A");
-      autoscale->callback (button_callback, static_cast<void*> (this));
-      autoscale->tooltip ("Autoscale");
+    status->textcolor (FL_BLACK);
+    status->color (FL_GRAY);
+    status->textfont (FL_COURIER);
+    status->textsize (10);
+    status->box (FL_ENGRAVED_BOX);
 
-      togglegrid = new Fl_Button (status_h, yy, status_h,
-                                  status_h, "G");
-      togglegrid->callback (button_callback, static_cast<void*> (this));
-      togglegrid->tooltip ("Toggle Grid");
+    autoscale = new Fl_Button (0, toolbar_y, status_h, status_h, "A");
+    autoscale->callback (button_callback, static_cast<void*> (this));
+    autoscale->tooltip ("Autoscale");
 
-      panzoom = new Fl_Button (2 * status_h, yy, status_h,
-                               status_h, "P");
-      panzoom->callback (button_callback, static_cast<void*> (this));
-      panzoom->tooltip ("Mouse Pan/Zoom");
+    togglegrid = new Fl_Button (status_h, toolbar_y, status_h, status_h, "G");
+    togglegrid->callback (button_callback, static_cast<void*> (this));
+    togglegrid->tooltip ("Toggle Grid");
+
+    panzoom = new Fl_Button (2* status_h, toolbar_y, status_h, status_h, "P");
+    panzoom->callback (button_callback, static_cast<void*> (this));
+    panzoom->tooltip ("Mouse Pan/Zoom");
 
-      rotate = new Fl_Button (3 * status_h, yy, status_h,
-                              status_h, "R");
-      rotate->callback (button_callback, static_cast<void*> (this));
-      rotate->tooltip ("Mouse Rotate");
-
-      if (ndim == 2)
-        rotate->deactivate ();
+    rotate = new Fl_Button (3 * status_h, toolbar_y, status_h, status_h, "R");
+    rotate->callback (button_callback, static_cast<void*> (this));
+    rotate->tooltip ("Mouse Rotate");
 
-      help = new Fl_Button (4 * status_h, yy, status_h,
-                            status_h, "?");
-      help->callback (button_callback, static_cast<void*> (this));
-      help->tooltip ("Help");
+    help = new Fl_Button (4 * status_h, toolbar_y, status_h, status_h, "?");
+    help->callback (button_callback, static_cast<void*> (this));
+    help->tooltip ("Help");
 
-      status = new Fl_Output (5 * status_h, yy,
-                              ww > 2*status_h ? ww - status_h : 0,
-                              status_h, "");
+    end ();
 
-      status->textcolor (FL_BLACK);
-      status->color (FL_GRAY);
-      status->textfont (FL_COURIER);
-      status->textsize (10);
-      status->box (FL_ENGRAVED_BOX);
+    set_name ();
+    uimenu->add_to_menu (fp);
+    if (fp.menubar_is ("none") || !uimenu->items_to_show ())
+      hide_menubar ();
+
+    update_boundingbox (internal);
 
-      // This allows us to have a valid OpenGL context right away.
-      canvas->mode (FL_DEPTH | FL_DOUBLE | FL_MULTISAMPLE);
-      if (fp.is_visible ())
-        {
-          // FIXME: This code should be removed when Octave drops support
-          // for FLTK 1.1.  Search for default_xclass in this file to find
-          // code that should be uncommented to take its place.
-          //
-          // Set WM_CLASS which allows window managers to properly group
-          // related windows.  Otherwise, the class is just "FLTK"
-          xclass ("Octave");
+    if (fp.is_visible ())
+      {
+        // FIXME: This code should be removed when Octave drops support
+        // for FLTK 1.1.  Search for default_xclass in this file to find
+        // code that should be uncommented to take its place.
+        //
+        // Set WM_CLASS which allows window managers to properly group
+        // related windows.  Otherwise, the class is just "FLTK"
+        xclass ("Octave");
 
-          show ();
+        show ();
 
 #if defined (HAVE_X_WINDOWS)
-          std::string show_gui_msgs
-            = octave_env::getenv ("OCTAVE_SHOW_GUI_MESSAGES");
+        std::string show_gui_msgs
+          = octave_env::getenv ("OCTAVE_SHOW_GUI_MESSAGES");
 
-          // Installing our handler suppresses the messages.
-          if (show_gui_msgs.empty ())
-            XSetErrorHandler (xerror_handler);
+        // Installing our handler suppresses the messages.
+        if (show_gui_msgs.empty ())
+          XSetErrorHandler (xerror_handler);
 #endif
 
-          if (fp.get_currentaxes ().ok ())
-            show_canvas ();
-          else
-            hide_canvas ();
-        }
-    }
-    end ();
-
-    status->show ();
-    autoscale->show ();
-    togglegrid->show ();
-    panzoom->show ();
-    rotate->show ();
-
-    set_name ();
-    resizable (canvas);
-    gui_mode = (ndim == 3 ? rotate_zoom : pan_zoom);
-    uimenu->add_to_menu (fp);
-    if (uimenu->items_to_show ())
-      show_menubar ();
-    else
-      hide_menubar ();
+        if (fp.get_currentaxes ().ok ())
+          show_canvas ();
+        else
+          hide_canvas ();
+      }
   }
 
   ~plot_window (void)
   {
-    canvas->hide ();
-    status->hide ();
-    uimenu->hide ();
     this->hide ();
+    Fl::check ();
   }
 
   double number (void) { return fp.get___myhandle__ ().value (); }
@@ -835,31 +778,18 @@
   void print (const std::string& cmd, const std::string& term)
   {
     canvas->print (cmd, term);
-
-    // Print immediately so the output file will exist when the drawnow
-    // command is done.
-    mark_modified ();
-    Fl::wait (fltk_maxtime);
   }
 
   void show_menubar (void)
   {
-    if (!uimenu->is_visible ())
-      {
-        // FIXME: Toolbar and menubar do not update
-        uimenu->show ();
-        mark_modified ();
-      }
+    uimenu->show ();
+    update_toolbar_position ();
   }
 
   void hide_menubar (void)
   {
-    if (uimenu->is_visible ())
-      {
-        // FIXME: Toolbar and menubar do not update
-        uimenu->hide ();
-        mark_modified ();
-      }
+    uimenu->hide ();
+    update_toolbar_position ();
   }
 
   void uimenu_update (const graphics_handle& gh, int id)
@@ -922,8 +852,6 @@
           show_menubar ();
         else
           hide_menubar ();
-
-        mark_modified ();
       }
   }
 
@@ -943,19 +871,63 @@
     canvas->hide ();
   }
 
+  // Move the toolbar at the bottom of the plot_window.
+  // The only reason for moving the toolbar is hiding and
+  // showing the menubar. All other resizing is done by fltk.
+
+  void update_toolbar_position ()
+  {
+    int old_canvas_h = canvas->h ();
+
+    // keep position fix, change outerposition accordingly
+    update_boundingbox (true);
+    canvas->resize (0, menu_dy (), w (), old_canvas_h);
+
+    int toolbar_y = canvas->h () + menu_dy () + 1;
+    autoscale->position (0, toolbar_y);
+    togglegrid->position (status_h, toolbar_y);
+    panzoom->position (2 * status_h, toolbar_y);
+    rotate->position (3 * status_h, toolbar_y);
+    help->position (4 * status_h, toolbar_y);
+    status->resize (5 * status_h + 1, toolbar_y,
+                    w () - 5 * status_h - 1, status_h);
+
+    init_sizes ();
+    redraw ();
+  }
+
+  Matrix outerposition2position (const Matrix& outerpos)
+    {
+      Matrix pos = outerpos;
+      pos(1) += menu_dy ();
+      pos(3) -= menu_dy () + status_h + 2;
+      return pos;
+    }
+
+  Matrix position2outerposition (const Matrix& pos)
+    {
+      Matrix outerpos = pos;
+      outerpos(1) -= menu_dy ();
+      outerpos(3) += menu_dy () + status_h + 2;
+      return outerpos;
+    }
+
+  // Called from figure::properties::ID_POSITION if internal = true
+  // or ID_OUTERPOSITION if false.
+  // (someone has requested a position change with set (h, "position", [...])
+  // or set (h, "outerposition", [...])
+
+  void update_boundingbox (bool internal)
+  {
+    Matrix bb = fp.get_boundingbox (internal);
+    if (internal)
+      bb = position2outerposition (bb);
+    resize (bb(0), bb(1), bb(2), bb(3));
+  }
+
   void mark_modified (void)
   {
-    damage (FL_DAMAGE_ALL);
-    canvas->damage (FL_DAMAGE_ALL);
-    ndim = calc_dimensions (gh_manager::get_object (fp.get___myhandle__ ()));
-
-    if (ndim == 3)
-      rotate->activate ();
-    else if (ndim == 2 && gui_mode == rotate_zoom)
-      {
-        rotate->deactivate ();
-        gui_mode = pan_zoom;
-      }
+    canvas->redraw ();
   }
 
   void set_name (void)
@@ -976,12 +948,6 @@
   // life
   std::string window_label;
 
-  // Mod keys status
-  int shift;
-
-  // Number of dimensions, 2 or 3.
-  int ndim;
-
   // Figure properties.
   figure::properties& fp;
 
@@ -989,7 +955,7 @@
   static const int status_h = 20;
 
   // Menu height
-  static const int menu_h = 20;
+  static const int menu_h = 25;
 
   // Window callback.
   static void window_close (Fl_Widget*, void* data)
@@ -1009,40 +975,62 @@
   {
     if (widg == autoscale)
       axis_auto ();
-
-    if (widg == togglegrid)
+    else if (widg == togglegrid)
       toggle_grid ();
+    else if (widg == panzoom)
+      set_on_ax_obj ("pan", "on");
+    else if (widg == rotate)
+      set_on_ax_obj ("rotate3d", "on");
+    else if (widg == help)
+      fl_message ("%s", help_text);
+  }
 
-    if (widg == panzoom)
-      gui_mode = pan_zoom;
-
-    if (widg == rotate && ndim == 3)
-      gui_mode = rotate_zoom;
-
-    if (widg == help)
-      fl_message ("%s", help_text);
+  void set_on_ax_obj (const std::string& name, const std::string& value)
+  {
+    // ax_obj is the last clicked axes object
+    if (ax_obj && ax_obj.isa ("axes"))
+      {
+        axes::properties& ap =
+          dynamic_cast<axes::properties&>(ax_obj.get_properties ());
+        ap.set (name, value);
+      }
+    else // no axes object clicked so far, take currentaxes
+      {
+        graphics_handle gh = fp.get_currentaxes ();
+        if (gh.ok ())
+          {
+            graphics_object go = gh_manager::get_object (gh);
+            axes::properties& ap =
+              dynamic_cast<axes::properties&>(go.get_properties ());
+            ap.set (name, value);
+          }
+      }
   }
 
   fltk_uimenu* uimenu;
   OpenGL_fltk* canvas;
-  Fl_Box*    bottom;
   Fl_Button* autoscale;
   Fl_Button* togglegrid;
   Fl_Button* panzoom;
   Fl_Button* rotate;
   Fl_Button* help;
   Fl_Output* status;
+  Fl_Box* resize_dummy;
   graphics_object ax_obj;
   int pos_x;
   int pos_y;
 
+
   void axis_auto (void)
   {
     octave_value_list args;
-    args(0) = fp.get_currentaxes ().as_octave_value ();
-    args(1) = "auto";
-    feval ("axis", args);
-    mark_modified ();
+    if (fp.get_currentaxes ().ok ())
+      {
+        args(0) = fp.get_currentaxes ().as_octave_value ();
+        args(1) = "auto";
+        feval ("axis", args);
+        mark_modified ();
+      }
   }
 
   void toggle_grid (void)
@@ -1058,7 +1046,7 @@
   void pixel2pos (const graphics_handle& ax, int px, int py, double& xx,
                   double& yy) const
   {
-    pixel2pos ( gh_manager::get_object (ax), px, py, xx, yy);
+    pixel2pos (gh_manager::get_object (ax), px, py, xx, yy);
   }
 
   void pixel2pos (graphics_object ax, int px, int py, double& xx,
@@ -1074,7 +1062,7 @@
       }
   }
 
-  graphics_handle pixel2axes_or_ca (int px, int py )
+  graphics_handle pixel2axes_or_ca (int px, int py)
   {
     Matrix kids = fp.get_children ();
     int len = kids.length ();
@@ -1089,7 +1077,7 @@
 
             if (kid.valid_object () && kid.isa ("axes"))
               {
-                Matrix bb = kid.get_properties ().get_boundingbox (true);
+                Matrix bb = kid.get_properties ().get_boundingbox (false);
 
                 if (bb(0) <= px && px < (bb(0)+bb(2))
                     && bb(1) <= py && py < (bb(1)+bb(3)))
@@ -1125,7 +1113,6 @@
       }
 
     status->value (cbuf.str ().c_str ());
-    status->redraw ();
   }
 
   void view2status (graphics_object ax)
@@ -1142,7 +1129,6 @@
         cbuf << "[azimuth: " << v(0) << ", elevation: " << v(1) << "]";
 
         status->value (cbuf.str ().c_str ());
-        status->redraw ();
       }
   }
 
@@ -1150,9 +1136,7 @@
   {
     if (!fp.is_beingdeleted ())
       {
-        Matrix pos (1,2,0);
-        pos(0) = px;
-        pos(1) = h () - (py + status_h + menu_dy ());
+        Matrix pos = fp.map_from_boundingbox (px, py);
         fp.set_currentpoint (pos);
         graphics_object robj = gh_manager::get_object (fp.get_parent ());
         root_figure::properties& rp =
@@ -1163,19 +1147,25 @@
 
   void set_axes_currentpoint (graphics_object ax, int px, int py)
   {
-    if (ax.valid_object ())
+    if (ax.valid_object () && ax.isa ("axes"))
       {
         axes::properties& ap =
           dynamic_cast<axes::properties&> (ax.get_properties ());
 
-        double xx, yy;
-        pixel2pos (ax, px, py, xx, yy);
+        Matrix x_zlim = ap.get_transform_zlim ();
+        Matrix pos (2, 3, 0.0);
 
-        Matrix pos (2,3,0);
-        pos(0,0) = xx;
-        pos(1,0) = yy;
-        pos(0,1) = xx;
-        pos(1,1) = yy;
+        // front point (nearest to the viewer)
+        ColumnVector tmp = ap.get_transform ().untransform (px, py, x_zlim(0));
+        pos(0,0) = tmp(0);
+        pos(0,1) = tmp(1);
+        pos(0,2) = tmp(2);
+
+        // back point (furthest from the viewer)
+        tmp = ap.get_transform ().untransform (px, py, x_zlim(1));
+        pos(1,0) = tmp(0);
+        pos(1,1) = tmp(1);
+        pos(1,2) = tmp(2);
 
         ap.set_currentpoint (pos);
         fp.set_currentaxes (ap.get___myhandle__ ().value ());
@@ -1190,169 +1180,271 @@
       return 0;
   }
 
-  int key2shift (int key)
+  octave_scalar_map format_key_event (int e_key, const char* e_text, int e_state)
   {
-    if (key == FL_Shift_L || key == FL_Shift_R)
-      return FL_SHIFT;
+    octave_scalar_map evt;
 
-    if (key == FL_Control_L || key == FL_Control_R)
-      return FL_CTRL;
+    evt.assign ("Character", octave_value (e_text));
+    evt.assign ("Modifier", octave_value (modifier2cell (e_state)));
+
+    std::string key_str;
+    std::ostringstream tmp_str;
 
-    if (key == FL_Alt_L || key == FL_Alt_R)
-      return FL_ALT;
+    if (e_key == FL_Escape)
+      key_str = "escape";
+    else if (e_key == FL_Tab)
+      key_str = "tab";
+    else if (e_key == FL_Caps_Lock)
+      key_str = "capslock";
+    else if (e_key == FL_Shift_L || e_key == FL_Shift_R)
+      key_str = "shift";
+    else if (e_key == FL_Control_L || e_key == FL_Control_R)
+      key_str = "control";
+    else if (e_key == FL_Meta_L || e_key == FL_Meta_R)
+      key_str = "windows";
+    else if (e_key == FL_Alt_L || e_key == FL_Alt_R)
+      key_str = "alt";
+    else if (e_key == 32)
+      key_str = "space";
+    else if (e_key == FL_Enter)
+      key_str = "return";
+    else if (e_key == FL_BackSpace)
+      key_str = "backspace";
+    else if (e_key == FL_Print)
+      key_str = "printscreen";
+    else if (e_key == FL_Pause)
+      key_str = "pause";
+    else if (e_key == FL_Home)
+      key_str = "home";
+    else if (e_key == FL_End)
+      key_str = "end";
+    else if (e_key == FL_Insert)
+      key_str = "insert";
+    else if (e_key == FL_Page_Up)
+      key_str = "pageup";
+    else if (e_key == FL_Delete)
+      key_str = "delete";
+    else if (e_key == FL_Page_Down)
+      key_str = "pagedown";
+    else if (e_key == FL_Left)
+      key_str = "leftarrow";
+    else if (e_key == FL_Up)
+      key_str = "uparrow";
+    else if (e_key == FL_Right)
+      key_str = "rightarrow";
+    else if (e_key == FL_Down)
+      key_str = "downarrow";
+    else if (e_key == FL_Num_Lock)
+      key_str = "numlock";
+    else if (e_key == 0xffaf)
+      key_str = "divide";
+    else if (e_key == 0xffaa)
+      key_str = "multiply";
+    else if (e_key == 0xffad)
+      key_str = "subtract";
+    else if (e_key == 0xffab)
+      key_str = "add";
+    else if (e_key == 0xff8d)
+      key_str = "return";
+    else if (e_key == 0xffac)
+      key_str = "separator";
+    else if (e_key >= 0xffb0 && e_key <= 0xffb9)
+      {
+        tmp_str << "numpad" << (e_key - 0xffb0);
+        key_str = tmp_str.str ();
+      }
+    else if (e_key >= (FL_F + 1) && e_key <= (FL_F + 12))
+      {
+        tmp_str << "f" << (e_key - FL_F);
+        key_str = tmp_str.str ();
+      }
+    else if (e_key == ',')
+      key_str = "comma";
+    else if (e_key == '.')
+      key_str = "period";
+    else if (e_key == '-')
+      key_str = "hyphen";
+    else if (e_key == '^' || e_key == '+' || e_key == '#'
+             || e_key == '<' || e_key == 0xfe03 /*AltGr*/)
+      key_str = "0";
+    else if (isalnum (e_key))
+      key_str = std::tolower (e_key);
+    else if (isprint (e_text[0]))
+      key_str = "0";
 
-    if (key == FL_Meta_L || key == FL_Meta_R)
-      return FL_META;
-
-    return 0;
+    evt.assign ("Key", octave_value (key_str));
+    return evt;
   }
 
-  int key2ascii (int key)
-  {
-    if (key < 256) return key;
-    if (key == FL_Tab) return '\t';
-    if (key == FL_Enter) return 0x0a;
-    if (key == FL_BackSpace) return 0x08;
-    if (key == FL_Escape) return 0x1b;
-
-    return 0;
-  }
-
-  Cell modifier2cell ()
+  Cell modifier2cell (int e_state)
   {
     string_vector mod;
 
-    if (shift & FL_SHIFT)
+    if (e_state & FL_SHIFT)
       mod.append (std::string ("shift"));
-    if (shift & FL_CTRL)
+    if (e_state & FL_CTRL)
       mod.append (std::string ("control"));
-    if (shift & FL_ALT || shift & FL_META)
+    if (e_state & FL_ALT)
       mod.append (std::string ("alt"));
-
+    if (e_state & FL_COMMAND)
+      mod.append (std::string ("command"));
     return Cell (mod);
   }
 
-  void resize (int xx,int yy,int ww,int hh)
+  void resize (int xx, int yy, int ww, int hh)
   {
     Fl_Window::resize (xx, yy, ww, hh);
 
-    Matrix pos (1,4,0);
-    pos(0) = xx;
-    pos(1) = yy + menu_dy ();
-    pos(2) = ww;
-    pos(3) = hh - menu_dy () - status_h;
-
-    fp.set_boundingbox (pos, true);
-  }
+    Matrix bb (1, 4);
+    bb(0) = xx;
+    bb(1) = yy;
+    bb(2) = ww;
+    bb(3) = hh;
 
-  void draw (void)
-  {
-    // FIXME: Toolbar and menubar do not update properly
-    Matrix pos = fp.get_boundingbox (true);
-    int canvas_h = pos(3);
-    int canvas_w = pos(2);
-    int canvas_y = menu_dy ();
-    int toolbar_y = menu_dy () + canvas_h;
-    pos(1) = pos(1) - menu_dy ();
-    pos(3) = pos(3) + menu_dy () + status_h;
+    // update outerposition
+    fp.set_boundingbox (bb, false, false);
 
-    Fl_Window::resize (pos(0), pos(1), pos(2), pos(3));
-
-    bottom->resize (0, toolbar_y, status_h, status_h);
-    autoscale->resize (0, toolbar_y, status_h, status_h);
-    togglegrid->resize (status_h, toolbar_y, status_h, status_h);
-    panzoom->resize (2 * status_h, toolbar_y, status_h, status_h);
-    rotate->resize (3 * status_h, toolbar_y, status_h, status_h);
-    help->resize (4 * status_h, toolbar_y, status_h, status_h);
-    status->resize (5 * status_h, toolbar_y, pos(2) - 4 * status_h, status_h);
-    if (canvas->valid ())
-      canvas->resize (0, canvas_y, canvas_w, canvas_h);
-
-    return Fl_Window::draw ();
+    // update position
+    fp.set_boundingbox (outerposition2position (bb), true, false);
   }
 
   int handle (int event)
   {
-    graphics_handle gh;
+    if (event == FL_FOCUS)
+      return 1;
 
-    graphics_object fig = gh_manager::get_object (fp.get___myhandle__ ());
-    int retval = Fl_Window::handle (event);
-
-    // We only handle events which are in the canvas area.
-    if (!Fl::event_inside (canvas))
-      return retval;
+    graphics_handle gh;
 
     if (!fp.is_beingdeleted ())
       {
+        //std::cout << "plot_window::handle event = " <<  fl_eventnames[event] << std::endl;
+
+        // FLTK resends keyboard events with flipped case if all
+        // widgets rejects the event.
+        // See Event Propagation http://www.fltk.org/doc-1.3/events.html
+        static bool key_resent_detected = false;
+
         switch (event)
           {
+          case FL_SHORTCUT:
+            {
+              // check if it a resent event with switched case
+              static int last_event_key = 0;
+              static char last_event_text = 0;
+
+              int e_key = Fl::event_key ();
+              char e_text = Fl::event_text ()[0];
+              key_resent_detected = (e_key == last_event_key
+                  && std::tolower (last_event_text) == std::tolower (e_text)
+                  && ((islower (last_event_text) && isupper (e_text))
+                      || (isupper (last_event_text) && islower (e_text))));
+
+              last_event_key = e_key;
+              last_event_text = e_text;
+            }
+            break;
+
           case FL_KEYDOWN:
             {
-              int key = Fl::event_key ();
+              int e_key = Fl::event_key ();
+              const char *e_text = Fl::event_text ();
+              int e_state = Fl::event_state ();
+              octave_scalar_map evt =
+                format_key_event (e_key, e_text, e_state);
 
-              shift |= key2shift (key);
-              int key_a = key2ascii (key);
-              if (key_a && fp.get_keypressfcn ().is_defined ())
-                {
-                  octave_scalar_map evt;
-                  evt.assign ("Character", octave_value (key_a));
-                  evt.assign ("Key", octave_value (std::tolower (key_a)));
-                  evt.assign ("Modifier", octave_value (modifier2cell ()));
-                  fp.execute_keypressfcn (evt);
-                }
-              switch (key)
+              fp.set_currentcharacter (std::string (e_text));
+              if (fp.get_keypressfcn ().is_defined ()
+                  && (evt.contents ("Key").length () > 0))
+                fp.execute_keypressfcn (evt);
+
+              switch (e_key)
                 {
                 case 'a':
                 case 'A':
                   axis_auto ();
-                  break;
+                  return 1;
 
                 case 'g':
                 case 'G':
                   toggle_grid ();
-                  break;
+                  return 1;
 
                 case 'p':
                 case 'P':
-                  gui_mode = pan_zoom;
-                  break;
+                  set_on_ax_obj ("pan", "on");
+                  return 1;
 
                 case 'r':
                 case 'R':
-                  gui_mode = rotate_zoom;
-                  break;
+                  set_on_ax_obj ("rotate3d", "on");
+                  return 1;
                 }
             }
             break;
 
           case FL_KEYUP:
             {
-              int key = Fl::event_key ();
-
-              shift &= (~key2shift (key));
-              int key_a = key2ascii (key);
-              if (key_a && fp.get_keyreleasefcn ().is_defined ())
+              int e_key = Fl::event_key ();
+              int e_state = Fl::event_state ();
+              octave_scalar_map evt;
+              if (key_resent_detected && Fl::event_length () == 1)
                 {
-                  octave_scalar_map evt;
-                  evt.assign ("Character", octave_value (key_a));
-                  evt.assign ("Key", octave_value (std::tolower (key_a)));
-                  evt.assign ("Modifier", octave_value (modifier2cell ()));
-                  fp.execute_keyreleasefcn (evt);
+                  // FLTK flipped the case of Fl::event_text because no
+                  // widget wanted the FL_KEYDOWN event.
+                  char tmp_e_text[2];
+                  tmp_e_text[0] = Fl::event_text ()[0];
+                  tmp_e_text[1] = 0;
+                  // Undo the case flip
+                  if (std::islower (tmp_e_text[0]))
+                    tmp_e_text[0] = std::toupper (tmp_e_text[0]);
+                  else
+                    tmp_e_text[0] = std::tolower (tmp_e_text[0]);
+                  evt = format_key_event (e_key, tmp_e_text, e_state);
                 }
+              else
+                {
+                  const char *e_text = Fl::event_text ();
+                  evt = format_key_event (e_key, e_text, e_state);
+                }
+
+              if (fp.get_keyreleasefcn ().is_defined ()
+                  && (evt.contents ("Key").length () > 0))
+                fp.execute_keyreleasefcn (evt);
+              return 1;
             }
             break;
+          }
 
+      // Events we only handle if they are in the canvas area.
+      if (Fl::event_inside (canvas))
+        switch (event)
+          {
           case FL_MOVE:
             pixel2status (pixel2axes_or_ca (Fl::event_x (),
                                             Fl::event_y () - menu_dy ()),
                           Fl::event_x (), Fl::event_y () - menu_dy ());
-            break;
+            return 1;
 
           case FL_PUSH:
             pos_x = Fl::event_x ();
             pos_y = Fl::event_y () - menu_dy ();
 
-            set_currentpoint (Fl::event_x (), Fl::event_y () - menu_dy ());
+            set_currentpoint (pos_x, pos_y);
+
+            if (Fl::event_button () == FL_LEFT_MOUSE
+                && Fl::event_shift ())
+              fp.set_selectiontype ("extend");
+            else if ((Fl::event_button () == FL_LEFT_MOUSE
+                      && Fl::event_ctrl ())
+                      || Fl::event_button () == FL_RIGHT_MOUSE)
+              fp.set_selectiontype ("alternate");
+            else if (Fl::event_clicks ())
+              fp.set_selectiontype ("open");
+            else
+              fp.set_selectiontype ("normal");
+
+            if (fp.get_windowbuttondownfcn ().is_defined ())
+              fp.execute_windowbuttondownfcn (Fl::event_button ());
 
             gh = pixel2axes_or_ca (pos_x, pos_y);
 
@@ -1360,12 +1452,24 @@
               {
                 ax_obj = gh_manager::get_object (gh);
                 set_axes_currentpoint (ax_obj, pos_x, pos_y);
-              }
+
+                int ndim = calc_dimensions (ax_obj);
+
+                if (ndim == 3)
+                  rotate->activate ();
+                else // ndim == 2
+                  rotate->deactivate ();
 
-            fp.execute_windowbuttondownfcn (Fl::event_button());
+                fp.set_currentobject (ax_obj.get_handle ().value ());
 
-            if (Fl::event_button () == 1 || Fl::event_button () == 3)
-              return 1;
+                base_properties& props = ax_obj.get_properties ();
+                if (props.get_buttondownfcn ().is_defined ())
+                  props.execute_buttondownfcn (Fl::event_button ());
+
+                return 1;
+              }
+            else if (fp.get_buttondownfcn ().is_defined ())
+              fp.execute_buttondownfcn (Fl::event_button ());
 
             break;
 
@@ -1380,32 +1484,50 @@
               {
                 if (ax_obj && ax_obj.isa ("axes"))
                   {
-                    if (gui_mode == pan_zoom)
-                      pixel2status (ax_obj, pos_x, pos_y,
-                                    Fl::event_x (),
-                                    Fl::event_y () - menu_dy ());
-                    else
-                      view2status (ax_obj);
                     axes::properties& ap =
                       dynamic_cast<axes::properties&>
                       (ax_obj.get_properties ());
 
-                    double x0, y0, x1, y1;
-                    Matrix pos = fp.get_boundingbox (true);
-                    pixel2pos (ax_obj, pos_x, pos_y, x0, y0);
-                    pixel2pos (ax_obj, Fl::event_x (),
-                                       Fl::event_y () - menu_dy (),
-                                       x1, y1);
+                    // Don't pan or rotate legend
+                    if (ap.get_tag ().compare ("legend") < 0)
+                      {
+                        if (ap.rotate3d_is ("on"))
+                          view2status (ax_obj);
+                        else
+                          pixel2status (ax_obj, pos_x, pos_y,
+                                        Fl::event_x (),
+                                        Fl::event_y () - menu_dy ());
+
+                        double x0, y0, x1, y1;
+                        Matrix pos = fp.get_boundingbox (true);
+                        pixel2pos (ax_obj, pos_x, pos_y, x0, y0);
+                        pixel2pos (ax_obj, Fl::event_x (),
+                                           Fl::event_y () - menu_dy (),
+                                           x1, y1);
 
-                    if (gui_mode == pan_zoom)
-                      ap.translate_view (x0, x1, y0, y1);
-                    else if (gui_mode == rotate_zoom)
-                      {
-                        double daz, del;
-                        daz = (Fl::event_x () - pos_x) / pos(2) * 360;
-                        del = (Fl::event_y () - menu_dy () - pos_y)
-                              / pos(3) * 360;
-                        ap.rotate_view (del, daz);
+                        if (ap.pan_is ("on"))
+                          ap.translate_view (x0, x1, y0, y1);
+                        else if (ap.pan_is ("xon"))
+                          ap.translate_view (x0, x1, y1, y1);
+                        else if (ap.pan_is ("yon"))
+                          ap.translate_view (x1, x1, y0, y1);
+                        else if (ap.rotate3d_is ("on"))
+                          {
+                            double daz, del;
+                            daz = (Fl::event_x () - pos_x) / pos(2) * 360;
+                            del = (Fl::event_y () - menu_dy () - pos_y)
+                                  / pos(3) * 360;
+                            ap.rotate_view (del, daz);
+                          }
+                      }
+                    else
+                      {  // move the position of the legend
+                        Matrix pos = ap.get_position ().matrix_value ();
+                        pos(0) += double (Fl::event_x () - pos_x)
+                                  / canvas->w ();
+                        pos(1) -= double (Fl::event_y () - menu_dy () - pos_y)
+                                  / canvas->h ();
+                        ap.set_position (pos);
                       }
 
                     pos_x = Fl::event_x ();
@@ -1425,7 +1547,8 @@
                 zoom_box (3) =  Fl::event_y () - menu_dy ();
                 canvas->set_zoom_box (zoom_box);
                 canvas->zoom (true);
-                canvas->redraw ();
+                mark_modified ();
+                return 1;
               }
 
             break;
@@ -1441,6 +1564,9 @@
                   axes::properties& ap =
                     dynamic_cast<axes::properties&> (ax.get_properties ());
 
+                  // Control how fast to zoom when using scroll wheel.
+                  double Vwheel_zoom_speed = ap.get_mouse_wheel_zoom ();
+
                   // Determine if we're zooming in or out.
                   const double factor =
                     (Fl::event_dy () > 0) ? 1 / (1.0 - Vwheel_zoom_speed)
@@ -1453,9 +1579,9 @@
 
                   ap.zoom_about_point (x1, y1, factor, false);
                   mark_modified ();
+                  return 1;
                 }
             }
-            return 1;
 
           case FL_RELEASE:
             if (fp.get_windowbuttonupfcn ().is_defined ())
@@ -1464,20 +1590,13 @@
                 fp.execute_windowbuttonupfcn ();
               }
 
-            if (Fl::event_button () == 1)
+            if ((Fl::event_button () == 1) && Fl::event_clicks ())
               {
-                if ( Fl::event_clicks () == 1)
-                  {
-                    if (ax_obj && ax_obj.isa ("axes"))
-                      {
-                        axes::properties& ap = dynamic_cast<axes::properties&>
-                                               (ax_obj.get_properties ());
-                        ap.set_xlimmode ("auto");
-                        ap.set_ylimmode ("auto");
-                        ap.set_zlimmode ("auto");
-                        mark_modified ();
-                      }
-                  }
+                // Double click
+                set_on_ax_obj ("xlimmode", "auto");
+                set_on_ax_obj ("ylimmode", "auto");
+                set_on_ax_obj ("zlimmode", "auto");
+                return 1;
               }
             if (Fl::event_button () == 3)
               {
@@ -1524,14 +1643,15 @@
                             ap.zoom (xl, yl);
                           }
                         mark_modified ();
+                        return 1;
                       }
                   }
               }
             break;
           }
       }
-
-    return retval;
+    //std::cout << "plot_window::handle wasn't interested in event " <<  fl_eventnames[event] << std::endl;
+    return Fl_Window::handle (event);
   }
 };
 
@@ -1655,16 +1775,19 @@
       instance->do_update_canvas (hnd2idx (gh), ca);
   }
 
-  static void toggle_menubar_visibility (int fig_idx, bool menubar_is_figure)
+  static void update_boundingbox (const std::string& fig_idx_str,
+                                  bool internal)
   {
     if (instance_ok ())
-      instance->do_toggle_menubar_visibility (fig_idx, menubar_is_figure);
+      instance->do_update_boundingbox (str2idx (fig_idx_str), internal);
   }
 
   static void toggle_menubar_visibility (const std::string& fig_idx_str,
                                          bool menubar_is_figure)
   {
-    toggle_menubar_visibility (str2idx (fig_idx_str), menubar_is_figure);
+    if (instance_ok ())
+      instance->do_toggle_menubar_visibility (str2idx (fig_idx_str),
+                                              menubar_is_figure);
   }
 
 private:
@@ -1700,16 +1823,23 @@
 
     if (idx >= 0 && windows.find (idx) == windows.end ())
       {
-        Matrix pos = fp.get_boundingbox (true);
-
-        int x = pos(0);
-        int y = pos(1);
-        int w = pos(2);
-        int h = pos(3);
+        Matrix pos = fp.get_outerposition ().matrix_value ();
+        bool internal = false;
+        // check if figure::properties::outerposition is default -1.0
+        if (pos(2) != -1.0 && pos(3) != -1.0)
+          {
+            pos = fp.get_boundingbox (internal);
+          }
+        else
+          {
+            // use position
+            internal = true;
+            pos = fp.get_boundingbox (internal);
+          }
 
         idx2figprops (curr_index, fp);
 
-        windows[curr_index++] = new plot_window (x, y, w, h, fp);
+        windows[curr_index++] = new plot_window (pos(0), pos(1), pos(2), pos(3), fp, internal);
       }
   }
 
@@ -1739,11 +1869,13 @@
     if (win != windows.end ())
       {
         if (is_visible)
-          win->second->show ();
+          {
+            win->second->show ();
+            win->second->show_canvas ();
+          }
         else
           win->second->hide ();
 
-        win->second->redraw ();
       }
   }
 
@@ -1767,7 +1899,9 @@
     wm_iterator win = windows.find (idx);
 
     if (win != windows.end ())
-      win->second->mark_modified ();
+      {
+        win->second->mark_modified ();
+      }
   }
 
   void do_set_name (int idx)
@@ -1822,6 +1956,14 @@
       }
   }
 
+  void do_update_boundingbox (int idx, bool internal)
+  {
+    wm_iterator win = windows.find (idx);
+
+    if (win != windows.end ())
+      win->second->update_boundingbox (internal);
+  }
+
   static int str2idx (const caseless_str& clstr)
   {
     int ind;
@@ -1882,47 +2024,15 @@
 
 static bool toolkit_loaded = false;
 
-static int
-__fltk_redraw__ (void)
-{
-  if (toolkit_loaded)
-    {
-      // We scan all figures and add those which use FLTK.
-      graphics_object obj = gh_manager::get_object (0);
-      if (obj && obj.isa ("root"))
-        {
-          base_properties& props = obj.get_properties ();
-          Matrix children = props.get_all_children ();
-
-          for (octave_idx_type n = 0; n < children.numel (); n++)
-            {
-              graphics_object fobj = gh_manager::get_object (children (n));
-              if (fobj && fobj.isa ("figure"))
-                {
-                  figure::properties& fp =
-                    dynamic_cast<figure::properties&> (fobj.get_properties ());
-                  if (fp.get___graphics_toolkit__ ()
-                      == FLTK_GRAPHICS_TOOLKIT_NAME)
-                    figure_manager::new_window (fp);
-                }
-            }
-        }
-
-      // it seems that we have to call Fl::check twice to get everything drawn
-      Fl::check ();
-      Fl::check ();
-    }
-
-  return 0;
-}
-
 class fltk_graphics_toolkit : public base_graphics_toolkit
 {
 public:
   fltk_graphics_toolkit (void)
     : base_graphics_toolkit (FLTK_GRAPHICS_TOOLKIT_NAME),
       input_event_hook_fcn_id ()
-  { }
+  {
+    Fl::visual (FL_RGB);
+  }
 
   ~fltk_graphics_toolkit (void) { }
 
@@ -2016,6 +2126,14 @@
                   figure_manager::set_name (tmp);
                 }
                 break;
+
+              case figure::properties::ID_POSITION:
+                figure_manager::update_boundingbox (ov.string_value (), true);
+                break;
+
+              case figure::properties::ID_OUTERPOSITION:
+                figure_manager::update_boundingbox (ov.string_value (), false);
+                break;
               }
           }
       }
@@ -2031,9 +2149,29 @@
 
   void redraw_figure (const graphics_object& go) const
   {
-    figure_manager::mark_modified (go.get_handle ());
+    // We scan all figures and add those which use FLTK.
+    graphics_object obj = gh_manager::get_object (0);
+    if (obj && obj.isa ("root"))
+      {
+        base_properties& props = obj.get_properties ();
+        Matrix children = props.get_all_children ();
 
-    __fltk_redraw__ ();
+        for (octave_idx_type n = 0; n < children.numel (); n++)
+          {
+            graphics_object fobj = gh_manager::get_object (children (n));
+            if (fobj && fobj.isa ("figure"))
+              {
+                figure::properties& fp =
+                  dynamic_cast<figure::properties&> (fobj.get_properties ());
+                if (fp.get___graphics_toolkit__ ()
+                    == FLTK_GRAPHICS_TOOLKIT_NAME)
+                  figure_manager::new_window (fp);
+              }
+          }
+      }
+
+    figure_manager::mark_modified (go.get_handle ());
+    Fl::check ();
   }
 
   void print_figure (const graphics_object& go,
@@ -2042,7 +2180,6 @@
                      const std::string& /*debug_file*/) const
   {
     figure_manager::print (go.get_handle (), file_cmd, term);
-    redraw_figure (go);
   }
 
   Matrix get_canvas_size (const graphics_handle& fh) const
@@ -2050,11 +2187,16 @@
     return figure_manager::get_size (fh);
   }
 
+/*
   double get_screen_resolution (void) const
   {
     // FLTK doesn't give this info.
     return 72.0;
+
+    // FIXME: FLTK >= 1.3.0 could do this with  Fl::screen_dpi (h, v, n)
+    // but do we need it?
   }
+*/
 
   Matrix get_screen_size (void) const
   {
@@ -2070,16 +2212,12 @@
       {
         munlock ("__init_fltk__");
 
-        figure_manager::close_all ();
-
         octave_value_list args = input_event_hook_fcn_id;
         args.append (false);
         Fremove_input_event_hook (args, 0);
-
         input_event_hook_fcn_id = octave_value_list ();
 
-        // FIXME: ???
-        Fl::wait (fltk_maxtime);
+        figure_manager::close_all ();
       }
   }
 
@@ -2094,16 +2232,16 @@
 
 #endif
 
-DEFUN_DLD (__fltk_redraw__, , ,
+DEFUN_DLD (__fltk_check__, , ,
            "-*- texinfo -*-\n\
-@deftypefn {Loadable Function} {} __fltk_redraw__ ()\n\
-Undocumented internal function.\n\
+@deftypefn {Loadable Function} {} __fltk_check__ ()\n\
+Undocumented internal function.  Calls Fl::check ()\n\
 @end deftypefn")
 {
 #ifdef HAVE_FLTK
-  __fltk_redraw__ ();
+  Fl::check ();
 #else
-  error ("__fltk_redraw__: not available without OpenGL and FLTK libraries");
+  error ("__fltk_check__: not available without OpenGL and FLTK libraries");
 #endif
 
   return octave_value ();
@@ -2129,8 +2267,8 @@
       gtk_manager::load_toolkit (tk);
       toolkit_loaded = true;
 
-      octave_value fcn (new octave_builtin (F__fltk_redraw__));
-      octave_value fcn_handle (new octave_fcn_handle (fcn, "@__fltk_redraw__"));
+      octave_value fcn (new octave_builtin (F__fltk_check__));
+      octave_value fcn_handle (new octave_fcn_handle (fcn, "@__fltk_check__"));
       octave_value_list id = Fadd_input_event_hook (fcn_handle, 1);
 
       fltk->set_input_event_hook_id (id);
@@ -2142,31 +2280,6 @@
   return octave_value ();
 }
 
-DEFUN_DLD (__fltk_maxtime__, args, ,
-           "-*- texinfo -*-\n\
-@deftypefn  {Loadable Function} {@var{maxtime} =} __fltk_maxtime__ ()\n\
-@deftypefnx {Loadable Function} {} __fltk_maxtime__ (@var{maxtime})\n\
-Undocumented internal function.\n\
-@end deftypefn")
-{
-#ifdef HAVE_FLTK
-  octave_value retval = fltk_maxtime;
-
-  if (args.length () == 1)
-    {
-      if (args(0).is_real_scalar ())
-        fltk_maxtime = args(0).double_value ();
-      else
-        error ("argument must be a real scalar");
-    }
-
-  return retval;
-#else
-  error ("__fltk_maxtime__: not available without OpenGL and FLTK libraries");
-  return octave_value ();
-#endif
-}
-
 DEFUN_DLD (__have_fltk__, , ,
            "-*- texinfo -*-\n\
 @deftypefn {Loadable Function} {@var{FLTK_available} =} __have_fltk__ ()\n\
@@ -2183,101 +2296,3 @@
 
   return retval;
 }
-
-// FIXME: This function should be abstracted and made potentially
-// available to all graphics toolkits.  This suggests putting it in
-// graphics.cc as is done for drawnow() and having the master
-// mouse_wheel_zoom function call fltk_mouse_wheel_zoom.  The same
-// should be done for gui_mode and fltk_gui_mode.  For now (2011.01.30),
-// just changing function names and docstrings.
-
-DEFUN_DLD (mouse_wheel_zoom, args, nargout,
-           "-*- texinfo -*-\n\
-@deftypefn  {Loadable Function} {@var{val} =} mouse_wheel_zoom ()\n\
-@deftypefnx {Loadable Function} {@var{old_val} =} mouse_wheel_zoom (@var{new_val})\n\
-@deftypefnx {Loadable Function} {} mouse_wheel_zoom (@var{new_val}, \"local\")\n\
-Query or set the mouse wheel zoom factor.\n\
-\n\
-The zoom factor is a number in the range (0,1) which is the percentage of the\n\
-current axis limits that will be used when zooming.  For example, if the\n\
-current x-axis limits are [0, 50] and @code{mouse_wheel_zoom} is 0.4 (40%),\n\
-then a zoom operation will change the limits by 20.\n\
-\n\
-When called from inside a function with the @qcode{\"local\"} option, the\n\
-variable is changed locally for the function and any subroutines it calls.  \n\
-The original variable value is restored when exiting the function.\n\
-\n\
-This function is currently implemented only for the FLTK graphics toolkit.\n\
-@seealso{gui_mode}\n\
-@end deftypefn")
-{
-#ifdef HAVE_FLTK
-  return SET_INTERNAL_VARIABLE_WITH_LIMITS(wheel_zoom_speed, 0.0001, 0.9999);
-#else
-  error ("mouse_wheel_zoom: not available without OpenGL and FLTK libraries");
-  return octave_value ();
-#endif
-}
-
-DEFUN_DLD (gui_mode, args, ,
-           "-*- texinfo -*-\n\
-@deftypefn  {Built-in Function} {@var{mode} =} gui_mode ()\n\
-@deftypefnx {Built-in Function} {} gui_mode (@var{mode})\n\
-Query or set the GUI mode for the current graphics toolkit.\n\
-The @var{mode} argument can be one of the following strings:\n\
-\n\
-@table @asis\n\
-@item @qcode{\"2d\"}\n\
-Allows panning and zooming of current axes.\n\
-\n\
-@item @qcode{\"3d\"}\n\
-Allows rotating and zooming of current axes.\n\
-\n\
-@item @qcode{\"none\"}\n\
-Mouse inputs have no effect.\n\
-@end table\n\
-\n\
-This function is currently implemented only for the FLTK graphics toolkit.\n\
-@seealso{mouse_wheel_zoom}\n\
-@end deftypefn")
-{
-#ifdef HAVE_FLTK
-  caseless_str mode_str;
-
-  if (gui_mode == pan_zoom)
-    mode_str = "2d";
-  else if (gui_mode == rotate_zoom)
-    mode_str = "3d";
-  else
-    mode_str = "none";
-
-  bool failed = false;
-
-  if (args.length () == 1)
-    {
-      if (args(0).is_string ())
-        {
-          mode_str = args(0).string_value ();
-
-          if (mode_str.compare ("2d"))
-            gui_mode = pan_zoom;
-          else if (mode_str.compare ("3d"))
-            gui_mode = rotate_zoom;
-          else if (mode_str.compare ("none"))
-            gui_mode = none;
-          else
-            failed = true;
-        }
-      else
-        failed = true;
-    }
-
-  if (failed)
-    error ("MODE must be one of the strings: \"2D\", \"3D\", or \"none\"");
-
-  return octave_value (mode_str);
-#else
-  error ("gui_mode: not available without OpenGL and FLTK libraries");
-  return octave_value ();
-#endif
-}
--- a/libinterp/dldfcn/__voronoi__.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/dldfcn/__voronoi__.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -38,6 +38,7 @@
 
 #include <list>
 
+#include "oct-locbuf.h"
 #include "lo-ieee.h"
 
 #include "Cell.h"
--- a/libinterp/dldfcn/amd.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/dldfcn/amd.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -67,8 +67,8 @@
 @table @asis\n\
 @item @var{opts}.dense\n\
 Determines what @code{amd} considers to be a dense row or column of the\n\
-input matrix.  Rows or columns with more than @code{max(16, (dense *\n\
-sqrt (@var{n})} entries, where @var{n} is the order of the matrix @var{S},\n\
+input matrix.  Rows or columns with more than @code{max (16, (dense *\n\
+sqrt (@var{n})))} entries, where @var{n} is the order of the matrix @var{S},\n\
 are ignored by @code{amd} during the calculation of the permutation\n\
 The value of dense must be a positive scalar and its default value is 10.0\n\
 \n\
@@ -164,11 +164,11 @@
 
               // FIXME: how can we manage the memory allocation of amd
               //        in a cleaner manner?
-              amd_malloc = malloc;
-              amd_free = free;
-              amd_calloc = calloc;
-              amd_realloc = realloc;
-              amd_printf = printf;
+              SUITESPARSE_ASSIGN_FPTR (malloc_func, amd_malloc, malloc);
+              SUITESPARSE_ASSIGN_FPTR (free_func, amd_free, free);
+              SUITESPARSE_ASSIGN_FPTR (calloc_func, amd_calloc, calloc);
+              SUITESPARSE_ASSIGN_FPTR (realloc_func, amd_realloc, realloc);
+              SUITESPARSE_ASSIGN_FPTR (printf_func, amd_printf, printf);
 
               octave_idx_type result = AMD_NAME (_order) (n_col, cidx, ridx, P,
                                                           Control, Info);
@@ -204,3 +204,19 @@
 
   return retval;
 }
+/*
+%!shared A, A2, opts
+%! A = ones (20, 30);
+%! A2 = ones (30, 30);
+%!
+%!testif HAVE_AMD
+%! assert(amd (A2), [1:30])
+%! opts.dense = 25;
+%! assert(amd (A2, opts), [1:30])
+%! opts.aggressive = 1;
+%! assert(amd (A2, opts), [1:30])
+
+%!error <matrix S must be square|not available in this version> amd (A)
+%!error amd (A2, 2)
+%!error <matrix S is corrupted|not available in this version> amd ([])
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/dldfcn/audiodevinfo.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,2910 @@
+/*
+
+Copyright (C) 2013 Vytautas Jančauskas
+
+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
+
+// <cstdint> requires c++11
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+#include "mach-info.h"
+
+#include "defun-dld.h"
+#include "error.h"
+#include "gripes.h"
+#include "oct-obj.h"
+#include "ov.h"
+#include "ov-int32.h"
+#include "ov-struct.h"
+#include "parse.h"
+
+#if defined (HAVE_PORTAUDIO)
+
+#include <portaudio.h>
+
+PaSampleFormat
+bits_to_format (int bits)
+{
+  if (bits == 8)
+    return paInt8;
+  else if (bits == 16)
+    return paInt16;
+  else if (bits == 24)
+    return paInt24;
+  else if (bits == 32)
+    return paInt32;
+  else if (bits == -1)
+    return paFloat32;
+  else
+    return 0;
+}
+
+#endif
+
+DEFUN_DLD (audiodevinfo, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {@var{devinfo} =} audiodevinfo ()\n\
+\n\
+@deftypefnx {Loadable Function} {@var{devs} =} audiodevinfo (@var{io})\n\
+@deftypefnx {Loadable Function} {@var{name} =} audiodevinfo (@var{io}, @var{id})\n\
+@deftypefnx {Loadable Function} {@var{id} =} audiodevinfo (@var{io}, @var{name})\n\
+@deftypefnx {Loadable Function} {@var{id} =} audiodevinfo (@var{io}, @var{rate}, @var{bits}, @var{chans})\n\
+\n\
+@deftypefnx {Loadable Function} {@var{supports} =} audiodevinfo (@var{io}, @var{id}, @var{rate}, @var{bits}, @var{chans})\n\
+\n\
+Return a structure with fields \"input\" and \"output\".\n\
+The value of each field is a structure array with fields\n\
+\"Name\", \"DriverVersion\" and \"ID\" describing an audio device.\n\
+\n\
+\n\
+If the optional argument @var{io} is 1, return information about input\n\
+devices only.  If it is 0, return information about output devices only.\n\
+\n\
+If the optional argument @var{id} is provided, return information about\n\
+corresponding device.\n\
+\n\
+If the optional argument @var{name} is provided, return the id of the\n\
+named device.\n\
+\n\
+Given a sampling rate, bits per sample, and number of channels for\n\
+an input or output device, return the ID of the first device that\n\
+supports playback or recording using the specified parameters.\n\
+\n\
+If also given a device ID, return true if the device supports playback\n\
+or recording using those parameters.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+#ifdef HAVE_PORTAUDIO
+
+  int nargin = args.length ();
+
+  octave_scalar_map devinfo;
+  octave_value_list input;
+  octave_value_list output;
+
+  PaError err = Pa_Initialize ();
+
+  if (err != paNoError)
+    {
+      error ("audiodevinfo: PortAudio initialization failed");
+      return retval;
+    }
+
+  int num_devices = Pa_GetDeviceCount ();
+
+  if (num_devices < 0)
+    {
+      error ("audiodevinfo: no audio device found");
+      return retval;
+    }
+
+  octave_idx_type numinput = 0, numoutput = 0;
+  for (int i = 0; i < num_devices; i++)
+    {
+      const PaDeviceInfo *device_info = Pa_GetDeviceInfo (i);
+
+      if (device_info->maxInputChannels != 0)
+        numinput++;
+
+      if (device_info->maxOutputChannels != 0)
+        numoutput++;
+    }
+
+  Cell input_name (dim_vector (1, numinput));
+  Cell input_driver_version (dim_vector (1, numinput));
+  Cell input_id (dim_vector (1, numinput));
+  Cell output_name (dim_vector (1, numoutput));
+  Cell output_driver_version (dim_vector (1, numoutput));
+  Cell output_id (dim_vector (1, numoutput));
+
+  octave_idx_type idx_i = 0, idx_o = 0;
+  for (int i = 0; i < num_devices; i++)
+    {
+      const PaDeviceInfo *device_info = Pa_GetDeviceInfo (i);
+      const char *driver;
+      char name[128];
+      driver = Pa_GetHostApiInfo (device_info->hostApi)->name;
+      sprintf (name, "%s (%s)", device_info->name, driver);
+
+      if (device_info->maxInputChannels != 0)
+        {
+          input_name(idx_i) = name;
+          input_driver_version(idx_i) = driver;
+          input_id(idx_i) = i;
+          idx_i++;
+        }
+
+      if (device_info->maxOutputChannels != 0)
+        {
+          output_name(idx_o) = name;
+          output_driver_version(idx_o) = driver;
+          output_id(idx_o) = i;
+          idx_o++;
+        }
+    }
+
+  octave_map inputdev, outputdev;
+  inputdev.setfield ("Name", input_name);
+  inputdev.setfield ("DriverVersion", input_driver_version);
+  inputdev.setfield ("ID", input_id);
+  outputdev.setfield ("Name", output_name);
+  outputdev.setfield ("DriverVersion", output_driver_version);
+  outputdev.setfield ("ID", output_id);
+  devinfo.setfield ("input", inputdev);
+  devinfo.setfield ("output", outputdev);
+
+  // Return information about input and output audio devices and
+  // their properties.
+  if (nargin == 0)
+    retval = devinfo;
+  // Return the number of input or output devices
+  else if (nargin == 1)
+    {
+      if (args(0).int_value () == 0)
+        retval = numoutput;
+      else if (args(0).int_value () == 1)
+        retval = numinput;
+      else
+        {
+          error ("audiodevinfo: please specify 0 for output and 1 for input devices");
+          return retval;
+        }
+    }
+  // Return device name when given id or id when given device name.
+  else if (nargin == 2)
+    {
+      bool found = false;
+      int outin = args(0).int_value ();
+      if (args(1).is_string ())
+        {
+          if (outin == 0)
+            {
+              for (int i = 0; i < numoutput; i++)
+                {
+                  if (output_name(i).string_value () == args(1).string_value ())
+                    {
+                      retval = output_id(i);
+                      found = true;
+                      break;
+                    }
+                }
+            }
+          else if (outin == 1)
+            {
+              for (int i = 0; i < numinput; i++)
+                {
+                  if (input_name(i).string_value () == args(1).string_value ())
+                    {
+                      retval = input_id(i);
+                      found = true;
+                      break;
+                    }
+                }
+            }
+          else
+            {
+              error ("audiodevinfo: please specify 0 for output and 1 for input devices");
+              return retval;
+            }
+        }
+      else
+        {
+          if (outin == 0)
+            {
+              for (int i = 0; i < numoutput; i++)
+                {
+                  if (output_id(i).int_value () == args(1).int_value ())
+                    {
+                      retval = output_name(i);
+                      found = true;
+                      break;
+                    }
+                }
+            }
+          else if (outin == 1)
+            {
+              for (int i = 0; i < numinput; i++)
+                {
+                  if (input_id(i).int_value () == args(1).int_value ())
+                    {
+                      retval = input_name(i);
+                      found = true;
+                      break;
+                    }
+                }
+            }
+          else
+            {
+              error ("audiodevinfo: please specify 0 for output and 1 for input devices");
+              return retval;
+            }
+        }
+      if (not found)
+        error ("audiodevinfo: no device meeting the specified criteria found");
+    }
+  else if (nargin == 3)
+    {
+      // FIXME: what was supposed to happen here?
+    }
+  // Return the id of the first device meeting specified criteria.
+  else if (nargin == 4)
+    {
+      int io = args(0).int_value ();
+      int rate = args(1).int_value ();
+      int bits = args(2).int_value ();
+      int chans = args(3).int_value ();
+
+      for (int i = 0; i < num_devices; i++)
+        {
+          PaStreamParameters stream_parameters;
+          stream_parameters.device = i;
+          stream_parameters.channelCount = chans;
+          PaSampleFormat format = bits_to_format (bits);
+
+          if (format != 0)
+            stream_parameters.sampleFormat = format;
+          else
+            {
+              error ("audiodevinfo: no such bits per sample format");
+              return retval;
+            }
+
+          stream_parameters.suggestedLatency
+            = Pa_GetDeviceInfo (i)->defaultLowInputLatency;
+          stream_parameters.hostApiSpecificStreamInfo = 0;
+
+          if (io == 0)
+            {
+              if (Pa_GetDeviceInfo (i)->maxOutputChannels < chans)
+                continue;
+
+              err = Pa_IsFormatSupported (0, &stream_parameters, rate);
+
+              if (err == paFormatIsSupported)
+                {
+                  retval = i;
+                  return retval;
+                }
+            }
+          else if (io == 1)
+            {
+              if (Pa_GetDeviceInfo (i)->maxInputChannels < chans)
+                continue;
+
+              err = Pa_IsFormatSupported (&stream_parameters, 0, rate);
+              if (err == paFormatIsSupported)
+                {
+                  retval = i;
+                  return retval;
+                }
+            }
+        }
+      retval = -1;
+    }
+  // Check if given device supports specified playback or recording modes.
+  else if (nargin == 5)
+    {
+      int io = args(0).int_value ();
+      int id = args(1).int_value ();
+      int rate = args(2).int_value ();
+      int bits = args(3).int_value ();
+      int chans = args(4).int_value ();
+      PaStreamParameters stream_parameters;
+      stream_parameters.device = id;
+      stream_parameters.channelCount = chans;
+      PaSampleFormat format = bits_to_format (bits);
+      if (format != 0)
+        stream_parameters.sampleFormat = format;
+      else
+        {
+          error ("audiodevinfo: no such bits per sample format");
+          return retval;
+        }
+      stream_parameters.suggestedLatency =
+        Pa_GetDeviceInfo (id)->defaultLowInputLatency;
+      stream_parameters.hostApiSpecificStreamInfo = 0;
+      if (io == 0)
+        {
+          if (Pa_GetDeviceInfo (id)->maxOutputChannels < chans)
+            {
+              retval = 0;
+              return retval;
+            }
+          err = Pa_IsFormatSupported (0, &stream_parameters, rate);
+          if (err == paFormatIsSupported)
+            {
+              retval = 1;
+              return retval;
+            }
+        }
+      else if (io == 1)
+        {
+          if (Pa_GetDeviceInfo (id)->maxInputChannels < chans)
+            {
+              retval = 0;
+              return retval;
+            }
+          err = Pa_IsFormatSupported (&stream_parameters, 0, rate);
+          if (err == paFormatIsSupported)
+            {
+              retval = 1;
+              return retval;
+            }
+        }
+      else
+        {
+          error ("audiodevinfo: please specify 0 for output and 1 for input devices");
+          return retval;
+        }
+      retval = 0;
+    }
+  else
+    {
+      error ("audiodevinfo: wrong number of arguments");
+      return retval;
+    }
+#else
+
+  error ("portaudio not found on your system and thus audio functionality is not present");
+
+#endif
+
+  return retval;
+}
+
+/*
+%!testif HAVE_PORTAUDIO
+%! devinfo = audiodevinfo;
+%! assert (rows (devinfo.input), 1);
+%! assert (rows (devinfo.output), 1);
+
+%!testif HAVE_PORTAUDIO
+%! devinfo = audiodevinfo;
+%! nout = audiodevinfo (0);
+%! nin = audiodevinfo (1);
+%! assert (columns (devinfo.output), nout);
+%! assert (columns (devinfo.input), nin);
+
+%!testif HAVE_PORTAUDIO
+%! devinfo = audiodevinfo;
+%! nout = audiodevinfo (0);
+%! nin = audiodevinfo (1);
+%! for i = 1:nout,
+%!   assert (devinfo.output(i).Name, audiodevinfo (0, devinfo.output(i).ID))
+%! endfor
+%! for i=1:nin,
+%!   assert (devinfo.input(i).Name, audiodevinfo (1, devinfo.input(i).ID))
+%! endfor
+
+%!testif HAVE_PORTAUDIO
+%! devinfo = audiodevinfo;
+%! nout = audiodevinfo (0);
+%! nin = audiodevinfo (1);
+%! for i = 1:nout,
+%!   assert (devinfo.output(i).ID, audiodevinfo (0, devinfo.output(i).Name))
+%! endfor
+%! for i = 1:nin,
+%!   assert (devinfo.input(i).ID, audiodevinfo (1, devinfo.input(i).Name))
+%! endfor
+*/
+
+#ifdef HAVE_PORTAUDIO
+
+enum audio_type { TYPE_INT8, TYPE_UINT8, TYPE_UINT16, TYPE_DOUBLE };
+
+class audioplayer : public octave_base_value
+{
+public:
+  audioplayer (void);
+  ~audioplayer (void) {};
+
+  // Overloaded base functions
+  double player_value (void) const { return 0; }
+  virtual double scalar_value (bool = false) const { return 0; }
+  void print (std::ostream& os, bool pr_as_read_syntax = false) const;
+  void print_raw (std::ostream& os, bool pr_as_read_syntax) const;
+
+  // Properties
+  bool is_constant (void) const { return true; }
+  bool is_defined (void) const { return true; }
+  bool print_as_scalar (void) const { return true; }
+
+  void init (void);
+  void init_fn (void);
+  void set_y (const octave_value& y);
+  void set_y (octave_function *fn);
+  void set_y (std::string fn);
+  Matrix& get_y (void);
+  RowVector get_left (void) const;
+  RowVector get_right (void) const;
+  void set_fs (int fs);
+  int get_fs (void);
+  void set_nbits (int nbits);
+  int get_nbits (void);
+  void set_id (int id);
+  int get_id (void);
+  int get_channels (void);
+  audio_type get_type (void);
+
+  void set_sample_number (unsigned int sample);
+  unsigned int get_sample_number (void);
+  unsigned int get_total_samples (void);
+  void set_end_sample (unsigned int sample);
+  unsigned int get_end_sample (void);
+  void reset_end_sample (void);
+  void set_tag (const charMatrix& tag);
+  charMatrix get_tag (void);
+  void set_userdata (const octave_value& userdata);
+  octave_value get_userdata (void);
+  PaStream *get_stream (void);
+
+  void playblocking (void);
+  void play (void);
+  void pause (void);
+  void resume (void);
+  void stop (void);
+  bool isplaying (void);
+
+  octave_function *octave_callback_function;
+
+private:
+  int id;
+  int fs;
+  int nbits;
+  int channels;
+  unsigned int sample_number;
+  unsigned int end_sample;
+  charMatrix tag;
+  Matrix y;
+  octave_value userdata;
+  RowVector left;
+  RowVector right;
+  PaStream *stream;
+  PaStreamParameters output_parameters;
+  audio_type type;
+
+  DECLARE_OCTAVE_ALLOCATOR
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+};
+
+static const unsigned int BUFFER_SIZE = 8192;
+
+DEFINE_OCTAVE_ALLOCATOR (audioplayer);
+DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (audioplayer, "audioplayer", "audioplayer");
+
+static int
+octave_play_callback (const void *, void *output, unsigned long frames,
+                      const PaStreamCallbackTimeInfo *,
+                      PaStreamCallbackFlags, void *data)
+{
+  audioplayer *player = static_cast<audioplayer *> (data);
+
+  if (! player)
+    {
+      error ("audio player callback function called without player");
+      return paAbort;
+    }
+
+  octave_value_list retval = feval (player->octave_callback_function,
+                                    ovl (static_cast<double> (frames)), 1);
+
+  if (error_state || retval.length () < 2)
+    {
+      error ("audio player callback function failed");
+      return paAbort;
+    }
+
+  const Matrix sound = retval(0).matrix_value ();
+  int return_status = retval(1).int_value ();
+
+  if (error_state || frames != sound.rows ()
+      || sound.columns () < 1 || sound.columns () > 2)
+    {
+      error ("audio player callback function failed");
+      return paAbort;
+    }
+
+  // Don't multiply the audio data by scale_factor here.  Although it
+  // does move the operation outside of the loops below, it also causes
+  // a second copy of the data array to be made.
+
+  const ColumnVector sound_l = sound.column (0);
+  const ColumnVector sound_r = (sound.columns () == 1)
+    ? sound_l : sound.column (1);
+
+  const double *p_l = sound_l.data ();
+  const double *p_r = sound_r.data ();
+
+  switch (player->get_nbits ())
+    {
+    case 8:
+      {
+        static double scale_factor = std::pow (2.0, 7) - 1.0;
+
+        int8_t *buffer = static_cast<int8_t *> (output);
+
+        for (unsigned long i = 0; i < frames; i++)
+          {
+            buffer[2*i] = p_l[i] * scale_factor;
+            buffer[2*i+1] = p_r[i] * scale_factor;
+          }
+      }
+      break;
+
+    case 16:
+      {
+        static double scale_factor = std::pow (2.0, 15) - 1.0;
+
+        int16_t *buffer = static_cast<int16_t *> (output);
+
+        for (unsigned long i = 0; i < frames; i++)
+          {
+            buffer[2*i] = p_l[i] * scale_factor;
+            buffer[2*i+1] = p_r[i] * scale_factor;
+          }
+      }
+      break;
+
+    case 24:
+      {
+        static double scale_factor = std::pow (2.0, 23) - 1.0;
+
+        static int big_endian = oct_mach_info::words_big_endian ();
+
+        uint8_t *buffer = static_cast<uint8_t *> (output);
+
+        for (unsigned long i = 0; i < frames; i++)
+          {
+            int32_t sample_l = p_l[i];
+            int32_t sample_r = p_r[i];
+
+            sample_l &= 0x00ffffff;
+            sample_r &= 0x00ffffff;
+
+            // FIXME: Would a mask work better?
+            uint8_t *_sample_l = reinterpret_cast<uint8_t *> (&sample_l);
+            uint8_t *_sample_r = reinterpret_cast<uint8_t *> (&sample_r);
+
+            unsigned long offset = i * 6;
+
+            buffer[offset+0] = _sample_l[0+big_endian] * scale_factor;
+            buffer[offset+1] = _sample_l[1+big_endian] * scale_factor;
+            buffer[offset+2] = _sample_l[2+big_endian] * scale_factor;
+
+            buffer[offset+3] = _sample_r[0+big_endian] * scale_factor;
+            buffer[offset+4] = _sample_r[1+big_endian] * scale_factor;
+            buffer[offset+5] = _sample_r[2+big_endian] * scale_factor;
+          }
+      }
+      break;
+
+    default:
+      error ("invalid player bit depth in callback function");
+      break;
+    }
+
+  return return_status;
+}
+
+static int
+portaudio_play_callback (const void *, void *output, unsigned long frames,
+                         const PaStreamCallbackTimeInfo*,
+                         PaStreamCallbackFlags, void *data)
+{
+  audioplayer *player = static_cast<audioplayer *> (data);
+
+  if (! player)
+    {
+      error ("audio player callback function called without player");
+      return paAbort;
+    }
+
+  // Don't multiply the audio data by scale_factor here.  Although it
+  // would move the operation outside of the loops below, it also causes
+  // a second copy of the *entire* data array to be made when only a
+  // small portion (BUFFER_SIZE elements) is usually needed for this
+  // callback.
+
+  const RowVector sound_l = player->get_left ();
+  const RowVector sound_r = player->get_right ();
+
+  const double *pl = sound_l.data ();
+  const double *pr = sound_r.data ();
+
+  if (player->get_type () == TYPE_DOUBLE)
+    {
+      switch (player->get_nbits ())
+        {
+        case 8:
+          {
+            static double scale_factor = std::pow (2.0, 7) - 1.0;
+
+            int8_t *buffer = static_cast<int8_t *> (output);
+
+            for (unsigned long j = 0; j < frames; j++)
+              {
+                unsigned int sample_number = player->get_sample_number ();
+
+                if (sample_number >= player->get_end_sample ())
+                  return paComplete;
+
+                unsigned long offset = j * 2;
+
+                buffer[offset+0] = pl[sample_number] * scale_factor;
+                buffer[offset+1] = pr[sample_number] * scale_factor;
+
+                player->set_sample_number (sample_number + 1);
+              }
+          }
+          break;
+
+        case 16:
+          {
+            static double scale_factor = std::pow (2.0, 15) - 1.0;
+
+            int16_t *buffer = static_cast<int16_t *> (output);
+
+            for (unsigned long j = 0; j < frames; j++)
+              {
+                unsigned int sample_number = player->get_sample_number ();
+
+                if (sample_number >= player->get_end_sample ())
+                  return paComplete;
+
+                unsigned long offset = j * 2;
+
+                buffer[offset+0] = pl[sample_number] * scale_factor;
+                buffer[offset+1] = pr[sample_number] * scale_factor;
+
+                player->set_sample_number (sample_number + 1);
+              }
+          }
+          break;
+
+        case 24:
+          {
+            static double scale_factor = std::pow (2.0, 23) - 1.0;
+
+            static int big_endian = oct_mach_info::words_big_endian ();
+
+            uint8_t *buffer = static_cast<uint8_t *> (output);
+
+            for (unsigned long j = 0; j < frames; j++)
+              {
+                unsigned int sample_number = player->get_sample_number ();
+
+                if (sample_number >= player->get_end_sample ())
+                  return paComplete;
+
+                int32_t sample_l = pl[sample_number] * scale_factor;
+                int32_t sample_r = pr[sample_number] * scale_factor;
+
+                sample_l &= 0x00ffffff;
+                sample_r &= 0x00ffffff;
+
+                // FIXME: Would a mask work better?
+                uint8_t *_sample_l = reinterpret_cast<uint8_t *> (&sample_l);
+                uint8_t *_sample_r = reinterpret_cast<uint8_t *> (&sample_r);
+
+                unsigned long offset = j * 6;
+
+                buffer[offset+0] = _sample_l[0+big_endian];
+                buffer[offset+1] = _sample_l[1+big_endian];
+                buffer[offset+2] = _sample_l[2+big_endian];
+
+                buffer[offset+3] = _sample_r[0+big_endian];
+                buffer[offset+4] = _sample_r[1+big_endian];
+                buffer[offset+5] = _sample_r[2+big_endian];
+
+                player->set_sample_number (sample_number + 1);
+              }
+          }
+          break;
+
+        default:
+          error ("invalid player bit depth in callback function");
+          break;
+        }
+    }
+  else if (player->get_type () == TYPE_INT8)
+    {
+      int8_t *buffer = static_cast<int8_t *> (output);
+
+      for (unsigned long j = 0; j < frames; j++)
+        {
+          unsigned int sample_number = player->get_sample_number ();
+
+          if (sample_number >= player->get_end_sample ())
+            return paComplete;
+
+          unsigned long offset = j * 2;
+
+          buffer[offset+0] = pl[sample_number];
+          buffer[offset+1] = pr[sample_number];
+
+          player->set_sample_number (sample_number + 1);
+        }
+    }
+  else if (player->get_type () == TYPE_UINT8)
+    {
+      uint8_t *buffer = static_cast<uint8_t *> (output);
+
+      for (unsigned long j = 0; j < frames; j++)
+        {
+          unsigned int sample_number = player->get_sample_number ();
+
+          if (sample_number >= player->get_end_sample ())
+            return paComplete;
+
+          unsigned long offset = j * 2;
+
+          buffer[offset+0] = pl[sample_number];
+          buffer[offset+1] = pr[sample_number];
+
+          player->set_sample_number (sample_number + 1);
+        }
+    }
+  else if (player->get_type () == TYPE_UINT16)
+    {
+      int16_t *buffer = static_cast<int16_t *> (output);
+
+      for (unsigned long j = 0; j < frames; j++)
+        {
+          unsigned int sample_number = player->get_sample_number ();
+
+          if (sample_number >= player->get_end_sample ())
+            return paComplete;
+
+          unsigned long offset = j * 2;
+
+          buffer[offset+0] = pl[sample_number];
+          buffer[offset+1] = pr[sample_number];
+
+          player->set_sample_number (sample_number + 1);
+        }
+    }
+
+  return paContinue;
+}
+
+audioplayer::audioplayer (void)
+  : octave_callback_function (0),
+    id (-1), fs (0), nbits (16), channels (0), sample_number (0),
+    end_sample (-1), tag (""), y (), userdata (Matrix ()),
+    left (), right (), stream (0), output_parameters (), type ()
+{ }
+
+void
+audioplayer::print (std::ostream& os, bool pr_as_read_syntax) const
+{
+  print_raw (os, pr_as_read_syntax);
+  newline (os);
+}
+
+void
+audioplayer::print_raw (std::ostream& os, bool) const
+{
+  os << 0;
+}
+
+void
+audioplayer::init_fn (void)
+{
+  if (Pa_Initialize () != paNoError)
+    {
+      error ("audioplayer: initialization error!");
+      return;
+    }
+
+  if (Pa_GetDeviceCount () < 1)
+    {
+      error ("audioplayer: no audio devices found or available!");
+      return;
+    }
+
+  int device = get_id ();
+
+  if (device == -1)
+    device = Pa_GetDefaultOutputDevice ();
+
+  output_parameters.device = device;
+  output_parameters.channelCount = 2;
+  output_parameters.sampleFormat = bits_to_format (get_nbits ());
+  output_parameters.suggestedLatency = Pa_GetDeviceInfo (device)->defaultHighOutputLatency;
+  output_parameters.hostApiSpecificStreamInfo = 0;
+}
+
+void
+audioplayer::init (void)
+{
+  // Both of these variables are unused.  Should they be
+  // eliminated or is something not yet implemented?
+  //
+  // int channels = y.rows ();
+  // RowVector *sound_l = get_left ();
+
+  if (Pa_Initialize () != paNoError)
+    {
+      error ("audioplayer: initialization error!");
+      return;
+    }
+
+  if (Pa_GetDeviceCount () < 1)
+    {
+      error ("audioplayer: no audio devices found or available!");
+      return;
+    }
+
+  int device = get_id ();
+
+  if (device == -1)
+    device = Pa_GetDefaultOutputDevice ();
+
+  output_parameters.device = device;
+  output_parameters.channelCount = 2;
+
+  if (type == TYPE_DOUBLE)
+    output_parameters.sampleFormat = bits_to_format (get_nbits ());
+  else if (type == TYPE_INT8)
+    output_parameters.sampleFormat = paInt8;
+  else if (type == TYPE_UINT8)
+    output_parameters.sampleFormat = paUInt8;
+  else if (type == TYPE_UINT16)
+    output_parameters.sampleFormat = paInt16;
+
+  output_parameters.suggestedLatency = Pa_GetDeviceInfo (device)->defaultHighOutputLatency;
+  output_parameters.hostApiSpecificStreamInfo = 0;
+}
+
+void
+audioplayer::set_y (const octave_value& y_arg)
+{
+  if (y_arg.is_int8_type ())
+    type = TYPE_INT8;
+  else if (y_arg.is_uint8_type ())
+    type = TYPE_UINT8;
+  else if (y_arg.is_int16_type ())
+    type = TYPE_UINT16;
+  else
+    type = TYPE_DOUBLE;
+
+  y = y_arg.matrix_value ();
+
+  if (y.rows () > 2)
+    y = y.transpose ();
+
+  channels = y.rows ();
+  left = y.row (0);
+
+  if (channels == 2)
+    right = y.row (1);
+
+  reset_end_sample ();
+}
+
+void
+audioplayer::set_y (octave_function *fn)
+{
+  octave_callback_function = fn;
+  channels = 2;
+  reset_end_sample ();
+}
+
+Matrix&
+audioplayer::get_y (void)
+{
+  return y;
+}
+
+RowVector
+audioplayer::get_left (void) const
+{
+  return left;
+}
+
+RowVector
+audioplayer::get_right (void) const
+{
+  return channels == 1 ? left : right;
+}
+
+void
+audioplayer::set_fs (int fs_arg)
+{
+  fs = fs_arg;
+}
+
+int
+audioplayer::get_fs (void)
+{
+  return fs;
+}
+
+void
+audioplayer::set_nbits (int nbits_arg)
+{
+  nbits = nbits_arg;
+}
+
+int
+audioplayer::get_nbits (void)
+{
+  return nbits;
+}
+
+void
+audioplayer::set_id (int id_arg)
+{
+  id = id_arg;
+}
+
+int
+audioplayer::get_id (void)
+{
+  return id;
+}
+
+int
+audioplayer::get_channels (void)
+{
+  return channels;
+}
+
+audio_type
+audioplayer::get_type (void)
+{
+  return type;
+}
+
+void
+audioplayer::set_sample_number (unsigned int sample_number_arg)
+{
+  sample_number = sample_number_arg;
+}
+
+unsigned int
+audioplayer::get_sample_number (void)
+{
+  return sample_number;
+}
+
+unsigned int
+audioplayer::get_total_samples (void)
+{
+  return left.length ();
+}
+
+void
+audioplayer::set_end_sample (unsigned int end_sample_arg)
+{
+  end_sample = end_sample_arg;
+}
+
+unsigned int
+audioplayer::get_end_sample (void)
+{
+  return end_sample;
+}
+
+void
+audioplayer::reset_end_sample (void)
+{
+  set_end_sample (left.length ());
+}
+
+void
+audioplayer::set_tag (const charMatrix& tag_arg)
+{
+  tag = tag_arg;
+}
+
+charMatrix
+audioplayer::get_tag (void)
+{
+  return tag;
+}
+
+void
+audioplayer::set_userdata (const octave_value& userdata_arg)
+{
+  userdata = userdata_arg;
+}
+
+octave_value
+audioplayer::get_userdata (void)
+{
+  return userdata;
+}
+
+void
+audioplayer::playblocking (void)
+{
+  if (get_stream ())
+    stop ();
+
+  PaError err;
+  uint32_t buffer[BUFFER_SIZE * 2];
+  err = Pa_OpenStream (&stream, 0, &(output_parameters), get_fs (),
+                               BUFFER_SIZE, paClipOff, 0, 0);
+  if (err != paNoError)
+    {
+      error ("audioplayer: unable to open audio playback stream");
+      return;
+    }
+
+  err = Pa_StartStream (stream);
+  if (err != paNoError)
+    {
+      error ("audioplayer: unable to start start audio playback stream");
+      return;
+    }
+
+  unsigned int start, end;
+  start = get_sample_number ();
+  end = get_end_sample ();
+  for (unsigned int i = start; i < end; i += BUFFER_SIZE)
+    {
+      if (octave_callback_function != 0)
+        octave_play_callback (0, buffer, BUFFER_SIZE, 0, 0, this);
+      else
+        portaudio_play_callback (0, buffer, BUFFER_SIZE, 0, 0, this);
+
+      err = Pa_WriteStream (stream, buffer, BUFFER_SIZE);
+    }
+
+  err = Pa_StopStream (stream);
+  if (err != paNoError)
+    {
+      error ("audioplayer: Error stoping audio playback stream");
+      return;
+    }
+
+  err = Pa_CloseStream (stream);
+  if (err != paNoError)
+    {
+      error ("audioplayer: Error closing audio playback stream");
+      return;
+    }
+
+  stream = 0;
+  set_sample_number (0);
+  reset_end_sample ();
+}
+
+void
+audioplayer::play (void)
+{
+  if (get_stream ())
+    stop ();
+
+  PaError err;
+  if (octave_callback_function != 0)
+    err = Pa_OpenStream (&stream, 0, &(output_parameters),
+                         get_fs (), BUFFER_SIZE, paClipOff,
+                         octave_play_callback, this);
+  else
+    err = Pa_OpenStream (&stream, 0, &(output_parameters),
+                         get_fs (), BUFFER_SIZE, paClipOff,
+                         portaudio_play_callback, this);
+
+  if (err != paNoError)
+    {
+      error ("audioplayer: Error opening audio playback stream");
+      return;
+    }
+
+  err = Pa_StartStream (stream);
+  if (err != paNoError)
+    {
+      error ("audioplayer: Error starting audio playback stream");
+      return;
+    }
+}
+
+void
+audioplayer::pause (void)
+{
+  if (get_stream () == 0)
+    return;
+
+  PaError err;
+  err = Pa_StopStream (stream);
+  if (err != paNoError)
+    {
+      error ("audiorecorder: Error stoping audio recording stream");
+      return;
+    }
+}
+
+void
+audioplayer::resume (void)
+{
+  if (get_stream () == 0)
+    return;
+
+  PaError err;
+  err = Pa_StartStream (stream);
+  if (err != paNoError)
+    {
+      error ("audiorecorder: Error starting audio recording stream");
+      return;
+    }
+}
+
+PaStream *
+audioplayer::get_stream (void)
+{
+  return stream;
+}
+
+void
+audioplayer::stop (void)
+{
+  if (get_stream () == 0)
+    return;
+
+  PaError err;
+  set_sample_number (0);
+  reset_end_sample ();
+  if (not Pa_IsStreamStopped (get_stream ()))
+    {
+      err = Pa_AbortStream (get_stream ());
+      if (err != paNoError)
+        {
+          error ("audioplayer: Error stopping audio playback stream");
+          return;
+        }
+    }
+
+  err = Pa_CloseStream (get_stream ());
+  if (err != paNoError)
+    {
+      error ("audioplayer: Error closing audio playback stream");
+      return;
+    }
+
+  stream = 0;
+}
+
+bool
+audioplayer::isplaying (void)
+{
+  if (get_stream () == 0)
+    return false;
+
+  PaError err;
+  err = Pa_IsStreamActive (stream);
+  if (err != 0 && err != 1)
+    {
+      error ("audiorecorder: Error checking stream activity status");
+      return false;
+    }
+
+  return (err == 1);
+}
+
+class audiorecorder : public octave_base_value
+{
+public:
+  audiorecorder (void);
+  ~audiorecorder (void) {};
+
+  // Overloaded base functions
+  double player_value (void) const { return 0; }
+  virtual double scalar_value (bool = false) const { return 0; }
+  void print (std::ostream& os, bool pr_as_read_syntax = false) const;
+  void print_raw (std::ostream& os, bool pr_as_read_syntax) const;
+
+  // Properties
+  bool is_constant (void) const { return true; }
+  bool is_defined (void) const { return true; }
+  bool print_as_scalar (void) const { return true; }
+
+  void init (void);
+  void set_fs (int fs);
+  int get_fs (void);
+  void set_nbits (int nbits);
+  int get_nbits (void);
+  void set_id (int id);
+  int get_id (void);
+  void set_channels (int channels);
+  int get_channels (void);
+  audio_type get_type (void);
+
+  void set_sample_number (unsigned int sample);
+  unsigned int get_sample_number (void);
+  unsigned int get_total_samples (void);
+  void set_end_sample (unsigned int sample);
+  unsigned int get_end_sample (void);
+  void reset_end_sample (void);
+  void set_tag (const charMatrix& tag);
+  charMatrix get_tag (void);
+  void set_userdata (const octave_value& userdata);
+  octave_value get_userdata (void);
+  PaStream *get_stream (void);
+
+  octave_value getaudiodata (void);
+  audioplayer *getplayer (void);
+  bool isrecording (void);
+  audioplayer play (void);
+  void record (void);
+  void recordblocking (float seconds);
+  void pause (void);
+  void resume (void);
+  void stop (void);
+  void append (float sample_l, float sample_r);
+
+  octave_function *octave_callback_function;
+
+private:
+  int id;
+  int fs;
+  int nbits;
+  int channels;
+  unsigned int sample_number;
+  unsigned int end_sample;
+  charMatrix tag;
+  Matrix y;
+  octave_value userdata;
+  std::vector<float> left;
+  std::vector<float> right;
+  PaStream *stream;
+  PaStreamParameters input_parameters;
+  audio_type type;
+
+  DECLARE_OCTAVE_ALLOCATOR
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+};
+
+DEFINE_OCTAVE_ALLOCATOR (audiorecorder);
+DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (audiorecorder, "audiorecorder", "audiorecorder");
+
+static int
+octave_record_callback (const void *input, void *, unsigned long frames,
+                        const PaStreamCallbackTimeInfo *,
+                        PaStreamCallbackFlags, void *data)
+{
+  audiorecorder *recorder = static_cast<audiorecorder *> (data);
+  int channels = recorder->get_channels ();
+
+  Matrix sound (frames, 2);
+  sound.resize (frames, 2);
+
+  if (recorder->get_nbits () == 8)
+    {
+      static double scale_factor = std::pow (2.0, 7) - 1.0;
+
+      const int8_t *input8 = static_cast<const int8_t *> (input);
+
+      for (unsigned long i = 0; i < frames; i++)
+        {
+          float sample_l = input8[i*channels] / scale_factor;
+          float sample_r = input8[i*channels + (channels - 1)] / scale_factor;
+
+          sound(i, 0) = sample_l;
+          sound(i, 1) = sample_r;
+        }
+      }
+  else if (recorder->get_nbits () == 16)
+    {
+      static double scale_factor = std::pow (2.0, 15) - 1.0;
+
+      const int16_t *input16 = static_cast<const int16_t *> (input);
+
+      for (unsigned long i = 0; i < frames; i++)
+        {
+          float sample_l = input16[i*channels] / scale_factor;
+          float sample_r = input16[i*channels + (channels - 1)] / scale_factor;
+
+          sound(i, 0) = sample_l;
+          sound(i, 1) = sample_r;
+        }
+    }
+  else if (recorder->get_nbits () == 24)
+    {
+      static double scale_factor = std::pow (2.0, 23);
+
+      // FIXME: Is there a better way?
+      const uint8_t *input24 = static_cast<const uint8_t *> (input);
+
+      int32_t sample_l32 = 0, sample_r32 = 0;
+
+      uint8_t *sample_l = reinterpret_cast<uint8_t *> (&sample_l32);
+      uint8_t *sample_r = reinterpret_cast<uint8_t *> (&sample_r32);
+
+      for (unsigned long i = 0; i < frames; i++)
+        {
+          for (int j = 0; j < 3; j++)
+            {
+              sample_l[j] = input24[i*channels*3 + j];
+              sample_r[j] = input24[i*channels*3 + (channels - 1)*3 + j];
+            }
+
+          if (sample_l32 & 0x00800000)
+            sample_l32 |= 0xff000000;
+
+          if (sample_r32 & 0x00800000)
+            sample_r32 |= 0xff000000;
+
+          sound(i, 0) = sample_l32 / scale_factor;
+          sound(i, 1) = sample_r32 / scale_factor;
+        }
+    }
+
+  octave_value_list retval
+    = feval (recorder->octave_callback_function, ovl (sound), 1);
+
+  return retval(0).int_value ();
+}
+
+static int
+portaudio_record_callback (const void *input, void *, unsigned long frames,
+                           const PaStreamCallbackTimeInfo *,
+                           PaStreamCallbackFlags, void *data)
+{
+  audiorecorder *recorder = static_cast<audiorecorder *> (data);
+
+  int channels = recorder->get_channels ();
+
+  if (recorder->get_nbits () == 8)
+    {
+      static float scale_factor = std::pow (2.0f, 7) - 1.0f;
+
+      const int8_t *input8 = static_cast<const int8_t *> (input);
+
+      for (unsigned long i = 0; i < frames; i++)
+        {
+          float sample_l = input8[i*channels] / scale_factor;
+          float sample_r = input8[i*channels + (channels - 1)] / scale_factor;
+
+          recorder->append (sample_l, sample_r);
+        }
+    }
+  else if (recorder->get_nbits () == 16)
+    {
+      static float scale_factor = std::pow (2.0f, 15) - 1.0f;
+
+      const int16_t *input16 = static_cast<const int16_t *> (input);
+
+      for (unsigned long i = 0; i < frames; i++)
+        {
+          float sample_l = input16[i*channels] / scale_factor;
+          float sample_r = input16[i*channels + (channels - 1)] / scale_factor;
+
+          recorder->append (sample_l, sample_r);
+        }
+    }
+  else if (recorder->get_nbits () == 24)
+    {
+      static float scale_factor = std::pow (2.0f, 23);
+
+      // FIXME: Is there a better way?
+      const uint8_t *input24 = static_cast<const uint8_t *> (input);
+
+      int32_t sample_l32 = 0, sample_r32 = 0;
+
+      uint8_t *sample_l = reinterpret_cast<uint8_t *> (&sample_l32);
+      uint8_t *sample_r = reinterpret_cast<uint8_t *> (&sample_r32);
+
+      for (unsigned long i = 0; i < frames; i++)
+        {
+          for (int j = 0; j < 3; j++)
+            {
+              sample_l[j] = input24[i*channels*3 + j];
+              sample_r[j] = input24[i*channels*3 + (channels - 1)*3 + j];
+            }
+
+          if (sample_l32 & 0x00800000)
+            sample_l32 |= 0xff000000;
+
+          if (sample_r32 & 0x00800000)
+            sample_r32 |= 0xff000000;
+
+          recorder->append (sample_l32 / scale_factor,
+                            sample_r32 / scale_factor);
+        }
+    }
+
+  if (recorder->get_sample_number () > recorder->get_end_sample ())
+    return paComplete;
+
+  return paContinue;
+}
+
+audiorecorder::audiorecorder (void)
+  : octave_callback_function (0),
+    id (-1), fs (44100), nbits (16), channels (2), sample_number (0),
+    end_sample (-1), tag (""), y (), userdata (Matrix ()),
+    left (), right (), stream (0), input_parameters (), type ()
+{ }
+
+void
+audiorecorder::print (std::ostream& os, bool pr_as_read_syntax) const
+{
+  print_raw (os, pr_as_read_syntax);
+  newline (os);
+}
+
+void
+audiorecorder::print_raw (std::ostream& os, bool) const
+{
+  os << 0;
+}
+
+void
+audiorecorder::init (void)
+{
+  if (Pa_Initialize () != paNoError)
+    {
+      error ("audiorecorder: initialization error!");
+      return;
+    }
+
+  if (Pa_GetDeviceCount () < 1)
+    {
+      error ("audiorecorder: no audio devices found or available!");
+      return;
+    }
+
+  int device = get_id ();
+
+  if (device == -1)
+    device = Pa_GetDefaultInputDevice ();
+
+  input_parameters.device = device;
+  input_parameters.channelCount = get_channels ();
+  input_parameters.sampleFormat = bits_to_format (get_nbits ());
+  input_parameters.suggestedLatency = Pa_GetDeviceInfo (device)->defaultHighInputLatency;
+  input_parameters.hostApiSpecificStreamInfo = 0;
+}
+
+void
+audiorecorder::set_fs (int fs_arg)
+{
+  fs = fs_arg;
+}
+
+int
+audiorecorder::get_fs (void)
+{
+  return fs;
+}
+
+void
+audiorecorder::set_nbits (int nbits_arg)
+{
+  nbits = nbits_arg;
+}
+
+int
+audiorecorder::get_nbits (void)
+{
+  return nbits;
+}
+
+void
+audiorecorder::set_id (int id_arg)
+{
+  id = id_arg;
+}
+
+int
+audiorecorder::get_id (void)
+{
+  return id;
+}
+
+void
+audiorecorder::set_channels (int channels_arg)
+{
+  assert (channels_arg == 1 || channels_arg == 2);
+  channels = channels_arg;
+}
+
+int
+audiorecorder::get_channels (void)
+{
+  return channels;
+}
+
+audio_type
+audiorecorder::get_type (void)
+{
+  return type;
+}
+
+void
+audiorecorder::set_sample_number (unsigned int sample_number_arg)
+{
+  sample_number = sample_number_arg;
+}
+
+unsigned int
+audiorecorder::get_sample_number (void)
+{
+  return sample_number;
+}
+
+unsigned int
+audiorecorder::get_total_samples (void)
+{
+  return left.size ();
+}
+
+void
+audiorecorder::set_end_sample (unsigned int end_sample_arg)
+{
+  end_sample = end_sample_arg;
+}
+
+unsigned int
+audiorecorder::get_end_sample (void)
+{
+  return end_sample;
+}
+
+void
+audiorecorder::reset_end_sample (void)
+{
+  set_end_sample (left.size ());
+}
+
+void
+audiorecorder::set_tag (const charMatrix& tag_arg)
+{
+  tag = tag_arg;
+}
+
+charMatrix
+audiorecorder::get_tag (void)
+{
+  return tag;
+}
+
+void
+audiorecorder::set_userdata (const octave_value& userdata_arg)
+{
+  userdata = userdata_arg;
+}
+
+octave_value
+audiorecorder::get_userdata (void)
+{
+  return userdata;
+}
+
+octave_value
+audiorecorder::getaudiodata (void)
+{
+  Matrix audio (2, left.size ());
+
+  for (unsigned int i = 0; i < left.size (); i++)
+    {
+      audio(0, i) = left[i];
+      audio(1, i) = right[i];
+    }
+
+  return audio;
+}
+
+audioplayer *
+audiorecorder::getplayer (void)
+{
+  audioplayer *player = new audioplayer ();
+
+  player->set_y (getaudiodata ());
+  player->set_fs (get_fs ());
+  player->set_nbits (get_nbits ());
+  player->init ();
+
+  return player;
+}
+
+bool
+audiorecorder::isrecording (void)
+{
+  if (get_stream () == 0)
+    return false;
+
+  PaError err;
+  err = Pa_IsStreamActive (stream);
+  if (err != 0 && err != 1)
+    {
+      error ("audiorecorder: unable to check stream activity status");
+      return false;
+    }
+
+  return (err == 1);
+}
+
+void
+audiorecorder::record (void)
+{
+  if (get_stream ())
+    stop ();
+
+  left.clear ();
+  right.clear ();
+  PaError err;
+  if (octave_callback_function != 0)
+    {
+      err = Pa_OpenStream (&stream, &(input_parameters), 0,
+                           get_fs (), BUFFER_SIZE, paClipOff,
+                           octave_record_callback, this);
+    }
+  else
+    {
+      err = Pa_OpenStream (&stream, &(input_parameters), 0,
+                           get_fs (), BUFFER_SIZE, paClipOff,
+                           portaudio_record_callback, this);
+    }
+  if (err != paNoError)
+    {
+      error ("audiorecorder: unable to open audio recording stream");
+      return;
+    }
+  err = Pa_StartStream (stream);
+  if (err != paNoError)
+    {
+      error ("audiorecorder: unable to start audio recording stream");
+      return;
+    }
+}
+
+void
+audiorecorder::recordblocking (float seconds)
+{
+  if (get_stream ())
+    stop ();
+
+  left.clear ();
+  right.clear ();
+
+  PaError err;
+  err = Pa_OpenStream (&stream, &(input_parameters), 0,
+                       get_fs (), BUFFER_SIZE, paClipOff, 0, this);
+  if (err != paNoError)
+    {
+      error ("audiorecorder: unable to open audio recording stream");
+      return;
+    }
+
+  err = Pa_StartStream (stream);
+  if (err != paNoError)
+    {
+      error ("audiorecorder: unable to start audio recording stream");
+      return;
+    }
+
+  unsigned int frames = seconds * get_fs ();
+  uint8_t buffer[BUFFER_SIZE * 2 * 3];
+  for (unsigned long i = 0; i < frames / BUFFER_SIZE; i++)
+    {
+      Pa_ReadStream (get_stream (), buffer, BUFFER_SIZE);
+      if (octave_callback_function != 0)
+        octave_record_callback (buffer, 0, BUFFER_SIZE, 0, 0, this);
+      else
+        portaudio_record_callback (buffer, 0, BUFFER_SIZE, 0, 0, this);
+    }
+}
+
+void
+audiorecorder::pause (void)
+{
+  if (get_stream () == 0)
+    return;
+
+  PaError err;
+  err = Pa_StopStream (stream);
+  if (err != paNoError)
+    {
+      error ("audiorecorder: unable to stop audio recording stream");
+      return;
+    }
+}
+
+void
+audiorecorder::resume (void)
+{
+  if (get_stream () == 0)
+    return;
+
+  PaError err;
+  err = Pa_StartStream (stream);
+  if (err != paNoError)
+    {
+      error ("audiorecorder: unable to start audio recording stream");
+      return;
+    }
+}
+
+void
+audiorecorder::stop (void)
+{
+  if (get_stream () == 0)
+    return;
+
+  PaError err;
+  if (not Pa_IsStreamStopped (get_stream ()))
+    {
+      err = Pa_AbortStream (get_stream ());
+      if (err != paNoError)
+        {
+          error ("audioplayer: unable to stop audio playback stream");
+          return;
+        }
+    }
+
+  err = Pa_CloseStream (stream);
+  if (err != paNoError)
+    {
+      error ("audiorecorder: unable to close audio recording stream");
+      return;
+    }
+
+  set_sample_number (0);
+  reset_end_sample ();
+  stream = 0;
+}
+
+void
+audiorecorder::append (float sample_l, float sample_r)
+{
+  left.push_back (sample_l);
+  right.push_back (sample_r);
+  set_sample_number (get_sample_number () + 1);
+}
+
+PaStream *
+audiorecorder::get_stream (void)
+{
+  return stream;
+}
+
+#endif
+
+DEFUN_DLD (__recorder_audiorecorder__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn  {Loadable Function} {@var{recorder} =} __recorder_audiorecorder__ (@var{fs}, @var{nbits}, @var{channels})\n\
+@deftypefnx {Loadable Function} {@var{recorder} =} __recorder_audiorecorder__ (@var{fs}, @var{nbits}, @var{channels}, @var{id})\n\
+@deftypefnx {Loadable Function} {@var{recorder} =} __recorder_audiorecorder__ (@var{fcn}, @dots{})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+#ifdef HAVE_PORTAUDIO
+
+  int nargin = args.length ();
+
+  audiorecorder* recorder = new audiorecorder ();
+
+  int offset = 0;
+
+  if (nargin > 0)
+    {
+      bool is_function = args(0).is_string () || args(0).is_function_handle () || args(0).is_inline_function ();
+
+      if (is_function)
+        {
+          error ("audioplayer: callbacks not yet implemented");
+          return retval;
+
+          // recorder->octave_callback_function = args(0).function_value ();
+          // offset = 1;
+        }
+    }
+
+  switch (nargin - offset)
+    {
+    case 3:
+      recorder->set_fs (args(0 + offset).int_value ());
+      recorder->set_nbits (args(1 + offset).int_value ());
+      recorder->set_channels (args(2 + offset).int_value ());
+      break;
+
+    case 4:
+      recorder->set_fs (args(0 + offset).int_value ());
+      recorder->set_nbits (args(1 + offset).int_value ());
+      recorder->set_channels (args(2 + offset).int_value ());
+      recorder->set_id (args(3 + offset).int_value ());
+      break;
+    }
+
+  recorder->init ();
+
+  retval = recorder;
+
+#else
+
+  error ("portaudio not found on your system and thus audio functionality is not present");
+
+#endif
+
+  return retval;
+}
+
+#ifdef HAVE_PORTAUDIO
+
+static audiorecorder *
+get_recorder (const octave_value& ov)
+{
+  const octave_base_value& rep = ov.get_rep ();
+
+  octave_base_value *ncrep = const_cast<octave_base_value *> (&rep);
+
+  return dynamic_cast<audiorecorder *> (ncrep);
+}
+
+#endif
+
+DEFUN_DLD (__recorder_getaudiodata__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {@var{data}} __recorder_getaudiodata__ (@var{recorder})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+#ifdef HAVE_PORTAUDIO
+
+  audiorecorder *recorder = get_recorder (args(0));
+  retval = recorder->getaudiodata ();
+
+#else
+
+  error ("portaudio not found on your system and thus audio functionality is not present");
+
+#endif
+
+  return retval;
+}
+
+DEFUN_DLD (__recorder_get_channels__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {@var{n} =} __recorder_get_channels__ (@var{recorder})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+#ifdef HAVE_PORTAUDIO
+
+  if (args.length () == 1)
+    {
+      audiorecorder *recorder = get_recorder (args(0));
+      retval = recorder->get_channels ();
+    }
+
+#else
+
+  error ("portaudio not found on your system and thus audio functionality is not present");
+
+#endif
+
+  return retval;
+}
+
+DEFUN_DLD (__recorder_get_fs__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {@var{fs} =} __recorder_get_fs__ (@var{recorder})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+#ifdef HAVE_PORTAUDIO
+
+  if (args.length () == 1)
+    {
+      audiorecorder *recorder = get_recorder (args(0));
+      retval = recorder->get_fs ();
+    }
+
+#else
+
+  error ("portaudio not found on your system and thus audio functionality is not present");
+
+#endif
+
+  return retval;
+}
+
+DEFUN_DLD (__recorder_get_id__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {@var{id} =} __recorder_get_id__ (@var{recorder})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+#ifdef HAVE_PORTAUDIO
+
+  if (args.length () == 1)
+    {
+      audiorecorder *recorder = get_recorder (args(0));
+      retval = recorder->get_id ();
+    }
+
+#else
+
+  error ("portaudio not found on your system and thus audio functionality is not present");
+
+#endif
+
+  return retval;
+}
+
+DEFUN_DLD (__recorder_get_nbits__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {@var{nbits} =} __recorder_get_nbits__ (@var{recorder})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+#ifdef HAVE_PORTAUDIO
+
+  if (args.length () == 1)
+    {
+      audiorecorder *recorder = get_recorder (args(0));
+      retval = recorder->get_nbits ();
+    }
+
+#else
+
+  error ("portaudio not found on your system and thus audio functionality is not present");
+
+#endif
+
+  return retval;
+}
+
+DEFUN_DLD (__recorder_get_sample_number__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {@var{n} =} __recorder_get_sample_number__ (@var{recorder})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+#ifdef HAVE_PORTAUDIO
+
+  if (args.length () == 1)
+    {
+      audiorecorder *recorder = get_recorder (args(0));
+      retval = recorder->get_sample_number ();
+    }
+
+#else
+
+  error ("portaudio not found on your system and thus audio functionality is not present");
+
+#endif
+
+  return retval;
+}
+
+DEFUN_DLD (__recorder_get_tag__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {@var{tag} =} __recorder_get_tag__ (@var{recorder})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+#ifdef HAVE_PORTAUDIO
+
+  if (args.length () == 1)
+    {
+      audiorecorder *recorder = get_recorder (args(0));
+      retval = recorder->get_tag ();
+    }
+
+#else
+
+  error ("portaudio not found on your system and thus audio functionality is not present");
+
+#endif
+
+  return retval;
+}
+
+DEFUN_DLD (__recorder_get_total_samples__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {@var{n} =} __recorder_get_total_samples__ (@var{recorder})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+#ifdef HAVE_PORTAUDIO
+
+  if (args.length () == 1)
+    {
+      audiorecorder *recorder = get_recorder (args(0));
+      retval = recorder->get_total_samples ();
+    }
+
+#else
+
+  error ("portaudio not found on your system and thus audio functionality is not present");
+
+#endif
+
+  return retval;
+}
+
+DEFUN_DLD (__recorder_get_userdata__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {@var{data} =} __recorder_get_userdata__ (@var{recorder})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+#ifdef HAVE_PORTAUDIO
+
+  if (args.length () == 1)
+    {
+      audiorecorder *recorder = get_recorder (args(0));
+      retval = recorder->get_userdata ();
+    }
+
+#else
+
+  error ("portaudio not found on your system and thus audio functionality is not present");
+
+#endif
+
+  return retval;
+}
+
+DEFUN_DLD (__recorder_isrecording__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {} __recorder_isrecording__ (@var{recorder})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+#ifdef HAVE_PORTAUDIO
+
+  if (args.length () == 1)
+    {
+      audiorecorder *recorder = get_recorder (args(0));
+      retval = recorder->isrecording () ? true : false;
+    }
+
+#else
+
+  error ("portaudio not found on your system and thus audio functionality is not present");
+
+#endif
+
+  return retval;
+}
+
+DEFUN_DLD (__recorder_pause__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {} __recorder_pause__ (@var{recorder})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+#ifdef HAVE_PORTAUDIO
+
+  if (args.length () == 1)
+    {
+      audiorecorder *recorder = get_recorder (args(0));
+      recorder->pause ();
+    }
+
+#else
+
+  error ("portaudio not found on your system and thus audio functionality is not present");
+
+#endif
+
+  return retval;
+}
+
+DEFUN_DLD (__recorder_recordblocking__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {} __recorder_recordblocking__ (@var{recorder}, @var{seconds})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+#ifdef HAVE_PORTAUDIO
+
+  audiorecorder *recorder = get_recorder (args(0));
+  recorder->recordblocking (args(1).float_value ());
+
+#else
+
+  error ("portaudio not found on your system and thus audio functionality is not present");
+
+#endif
+
+  return retval;
+}
+
+DEFUN_DLD (__recorder_record__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn  {Loadable Function} {} __recorder_record__ (@var{recorder})\n\
+@deftypefnx {Loadable Function} {} __recorder_record__ (@var{recorder}, @var{seconds})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+#ifdef HAVE_PORTAUDIO
+
+  audiorecorder *recorder = get_recorder (args(0));
+
+  if (args.length () == 1)
+    recorder->record ();
+  else if (args.length () == 2)
+    {
+      recorder->set_end_sample (args(1).int_value () * recorder->get_fs ());
+      recorder->record ();
+    }
+  else
+    error ("audiorecorder: wrong number of arguments passed to record");
+
+#else
+
+  error ("portaudio not found on your system and thus audio functionality is not present");
+
+#endif
+
+  return retval;
+}
+
+DEFUN_DLD (__recorder_resume__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {} __recorder_resume__ (@var{recorder})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+#ifdef HAVE_PORTAUDIO
+
+  if (args.length () == 1)
+    {
+      audiorecorder *recorder = get_recorder (args(0));
+      recorder->resume ();
+    }
+
+#else
+
+  error ("portaudio not found on your system and thus audio functionality is not present");
+
+#endif
+
+  return retval;
+}
+
+DEFUN_DLD (__recorder_set_fs__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {} __recorder_set_fs__ (@var{recorder}, @var{fs})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+#ifdef HAVE_PORTAUDIO
+
+  if (args.length () == 2)
+    {
+      audiorecorder *recorder = get_recorder (args(0));
+      recorder->set_fs (args(1).int_value ());
+    }
+
+#else
+
+  error ("portaudio not found on your system and thus audio functionality is not present");
+
+#endif
+
+  return retval;
+}
+
+DEFUN_DLD (__recorder_set_tag__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {} __recorder_set_tag__ (@var{recorder}, @var{tag})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+#ifdef HAVE_PORTAUDIO
+
+  if (args.length () == 2)
+    {
+      audiorecorder *recorder = get_recorder (args(0));
+      recorder->set_tag (args(1).char_matrix_value ());
+    }
+
+#else
+
+  error ("portaudio not found on your system and thus audio functionality is not present");
+
+#endif
+
+  return retval;
+}
+
+DEFUN_DLD (__recorder_set_userdata__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {} __recorder_set_userdata__ (@var{recorder}, @var{data})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+#ifdef HAVE_PORTAUDIO
+
+  if (args.length () == 2)
+    {
+      audiorecorder *recorder = get_recorder (args(0));
+      recorder->set_userdata (args(1));
+    }
+
+#else
+
+  error ("portaudio not found on your system and thus audio functionality is not present");
+
+#endif
+
+  return retval;
+}
+
+DEFUN_DLD (__recorder_stop__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {} __recorder_stop__ (@var{recorder})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+#ifdef HAVE_PORTAUDIO
+
+  audiorecorder *recorder = get_recorder (args(0));
+  recorder->stop ();
+
+#else
+
+  error ("portaudio not found on your system and thus audio functionality is not present");
+
+#endif
+
+  return retval;
+}
+
+DEFUN_DLD (__player_audioplayer__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn  {Loadable Function} {@var{player} =} __player_audioplayer__ (@var{y}, @var{fs})\n\
+@deftypefnx {Loadable Function} {@var{player} =} __player_audioplayer__ (@var{y}, @var{fs}, @var{nbits})\n\
+@deftypefnx {Loadable Function} {@var{player} =} __player_audioplayer__ (@var{y}, @var{fs}, @var{nbits}, @var{id})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+#ifdef HAVE_PORTAUDIO
+
+  int nargin = args.length ();
+
+  if (nargin < 2 || nargin > 4)
+    {
+      print_usage ();
+      return retval;
+    }
+
+  audioplayer* recorder = new audioplayer ();
+
+  bool is_function = args(0).is_string () || args(0).is_function_handle () || args(0).is_inline_function ();
+
+  if (is_function)
+    {
+      error ("audioplayer: callbacks not yet implemented");
+      return retval;
+
+      // recorder->set_y (args(0).function_value ());
+    }
+  else
+    recorder->set_y (args(0));
+
+  recorder->set_fs (args(1).int_value ());
+
+  switch (nargin)
+    {
+    case 3:
+      recorder->set_nbits (args(2).int_value ());
+      break;
+
+    case 4:
+      recorder->set_nbits (args(2).int_value ());
+      recorder->set_id (args(3).int_value ());
+      break;
+    }
+
+  if (is_function)
+    recorder->init_fn ();
+  else
+    recorder->init ();
+
+  retval = recorder;
+
+#else
+
+  error ("portaudio not found on your system and thus audio functionality is not present");
+
+#endif
+
+  return retval;
+}
+
+#ifdef HAVE_PORTAUDIO
+
+static audioplayer *
+get_player (const octave_value& ov)
+{
+  const octave_base_value& rep = ov.get_rep ();
+
+  octave_base_value *ncrep = const_cast<octave_base_value *> (&rep);
+
+  return dynamic_cast<audioplayer *> (ncrep);
+}
+
+#endif
+
+DEFUN_DLD (__player_get_channels__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {@var{n} =} __player_get_channels__ (@var{player})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+#ifdef HAVE_PORTAUDIO
+
+  if (args.length () == 1)
+    {
+      audioplayer *player = get_player (args(0));
+      retval = player->get_channels ();
+    }
+
+#else
+
+  error ("portaudio not found on your system and thus audio functionality is not present");
+
+#endif
+
+  return retval;
+}
+
+DEFUN_DLD (__player_get_fs__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {@var{fs} =} __player_get_fs__ (@var{player})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+#ifdef HAVE_PORTAUDIO
+
+  if (args.length () == 1)
+    {
+      audioplayer *player = get_player (args(0));
+      retval = player->get_fs ();
+    }
+
+#else
+
+  error ("portaudio not found on your system and thus audio functionality is not present");
+
+#endif
+
+  return retval;
+}
+
+DEFUN_DLD (__player_get_id__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {@var{id} =} __player_get_id__ (@var{player})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+#ifdef HAVE_PORTAUDIO
+
+  if (args.length () == 1)
+    {
+      audioplayer *player = get_player (args(0));
+      retval = player->get_id ();
+    }
+
+#else
+
+  error ("portaudio not found on your system and thus audio functionality is not present");
+
+#endif
+
+  return retval;
+}
+
+DEFUN_DLD (__player_get_nbits__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {@var{nbits} =} __player_get_nbits__ (@var{player})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+#ifdef HAVE_PORTAUDIO
+
+  if (args.length () == 1)
+    {
+      audioplayer *player = get_player (args(0));
+      retval = player->get_nbits ();
+    }
+
+#else
+
+  error ("portaudio not found on your system and thus audio functionality is not present");
+
+#endif
+
+  return retval;
+}
+
+DEFUN_DLD (__player_get_sample_number__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {@var{n} =} __player_get_sample_number__ (@var{player})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+#ifdef HAVE_PORTAUDIO
+
+  if (args.length () == 1)
+    {
+      audioplayer *player = get_player (args(0));
+      retval = player->get_sample_number ();
+    }
+
+#else
+
+  error ("portaudio not found on your system and thus audio functionality is not present");
+
+#endif
+
+  return retval;
+}
+
+DEFUN_DLD (__player_get_tag__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {@var{tag} =} __player_get_tag__ (@var{player})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+#ifdef HAVE_PORTAUDIO
+
+  if (args.length () == 1)
+    {
+      audioplayer *player = get_player (args(0));
+      retval = player->get_tag ();
+    }
+
+#else
+
+  error ("portaudio not found on your system and thus audio functionality is not present");
+
+#endif
+
+  return retval;
+}
+
+DEFUN_DLD (__player_get_total_samples__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {@var{n} =} __player_get_total_samples__ (@var{player})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+#ifdef HAVE_PORTAUDIO
+
+  if (args.length () == 1)
+    {
+      audioplayer *player = get_player (args(0));
+      retval = player->get_total_samples ();
+    }
+
+#else
+
+  error ("portaudio not found on your system and thus audio functionality is not present");
+
+#endif
+
+  return retval;
+}
+
+DEFUN_DLD (__player_get_userdata__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {@var{data} =} __player_get_userdata__ (@var{player})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+#ifdef HAVE_PORTAUDIO
+
+  if (args.length () == 1)
+    {
+      audioplayer *player = get_player (args(0));
+      retval = player->get_userdata ();
+    }
+
+#else
+
+  error ("portaudio not found on your system and thus audio functionality is not present");
+
+#endif
+
+  return retval;
+}
+
+DEFUN_DLD (__player_isplaying__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {} __player_isplaying__ (@var{player})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+#ifdef HAVE_PORTAUDIO
+
+  if (args.length () == 1)
+    {
+      audioplayer *player = get_player (args(0));
+      retval = player->isplaying () ? true : false;
+    }
+
+#else
+
+  error ("portaudio not found on your system and thus audio functionality is not present");
+
+#endif
+
+  return retval;
+}
+
+DEFUN_DLD (__player_pause__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {} __player_pause__ (@var{player})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+#ifdef HAVE_PORTAUDIO
+
+  if (args.length () == 1)
+    {
+      audioplayer *player = get_player (args(0));
+      player->pause ();
+    }
+
+#else
+
+  error ("portaudio not found on your system and thus audio functionality is not present");
+
+#endif
+
+  return retval;
+}
+
+DEFUN_DLD (__player_playblocking__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn  {Loadable Function} {} __player_playblocking__ (@var{player})\n\
+@deftypefnx {Loadable Function} {} __player_playblocking__ (@var{player}, @var{start})\n\
+@deftypefnx {Loadable Function} {} __player_playblocking__ (@var{player}, [@var{start}, @var{end}])\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+#ifdef HAVE_PORTAUDIO
+
+  if (args.length () == 1)
+    {
+      audioplayer *player = get_player (args(0));
+      player->playblocking ();
+    }
+  else
+    {
+      audioplayer *player = get_player (args(0));
+      if (args(1).is_matrix_type ())
+        {
+          RowVector range = args(1).row_vector_value ();
+
+          unsigned int start = range.elem (0) - 1;
+          unsigned int end = range.elem (1) - 1;
+
+          if (start > player->get_total_samples ()
+              || start > end || end > player->get_total_samples ())
+            {
+              error ("audioplayer: invalid range specified for playback");
+              return retval;
+            }
+
+          player->set_sample_number (start);
+          player->set_end_sample (end);
+        }
+      else
+        {
+          unsigned int start = args(1).int_value () - 1;
+
+          if (start > player->get_total_samples ())
+            {
+              error ("audioplayer: invalid range specified for playback");
+              return retval;
+            }
+
+          player->set_sample_number (start);
+        }
+
+      player->playblocking ();
+    }
+
+#else
+
+  error ("portaudio not found on your system and thus audio functionality is not present");
+
+#endif
+
+  return retval;
+}
+
+DEFUN_DLD (__player_play__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn  {Loadable Function} {} __player_play__ (@var{player})\n\
+@deftypefnx {Loadable Function} {} __player_play__ (@var{player}, @var{start})\n\
+@deftypefnx {Loadable Function} {} __player_play__ (@var{player}, [@var{start}, @var{end}])\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+#ifdef HAVE_PORTAUDIO
+
+  if (args.length () == 1)
+    {
+      audioplayer *player = get_player (args(0));
+      player->play ();
+    }
+  else
+    {
+      audioplayer *player = get_player (args(0));
+
+      if (args(1).is_matrix_type ())
+        {
+          RowVector range = args(1).row_vector_value ();
+
+          unsigned int start = range.elem (0) - 1;
+          unsigned int end = range.elem (1) - 1;
+
+          if (start > player->get_total_samples ()
+              || start > end || end > player->get_total_samples ())
+            {
+              error ("audioplayer: invalid range specified for playback");
+              return retval;
+            }
+
+          player->set_sample_number (start);
+          player->set_end_sample (end);
+        }
+      else
+        {
+          unsigned int start = args(1).int_value () - 1;
+
+          if (start > player->get_total_samples ())
+            {
+              error ("audioplayer: invalid range specified for playback");
+              return retval;
+            }
+
+          player->set_sample_number (start);
+        }
+
+      player->play ();
+    }
+
+#else
+
+  error ("portaudio not found on your system and thus audio functionality is not present");
+
+#endif
+
+  return retval;
+}
+
+DEFUN_DLD (__player_resume__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {} __player_resume__ (@var{player})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+#ifdef HAVE_PORTAUDIO
+
+  if (args.length () == 1)
+    {
+      audioplayer *player = get_player (args(0));
+      player->resume ();
+    }
+
+#else
+
+  error ("portaudio not found on your system and thus audio functionality is not present");
+
+#endif
+
+  return retval;
+}
+
+DEFUN_DLD (__player_set_fs__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {} __player_set_fs__ (@var{player}, @var{fs})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+#ifdef HAVE_PORTAUDIO
+
+  if (args.length () == 2)
+    {
+      audioplayer *player = get_player (args(0));
+      player->set_fs (args(1).int_value ());
+    }
+
+#else
+
+  error ("portaudio not found on your system and thus audio functionality is not present");
+
+#endif
+
+  return retval;
+}
+
+DEFUN_DLD (__player_set_tag__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {} __player_set_tag__ (@var{player}, @var{tag})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+#ifdef HAVE_PORTAUDIO
+
+  if (args.length () == 2)
+    {
+      audioplayer *player = get_player (args(0));
+      player->set_tag (args(1).char_matrix_value ());
+    }
+
+#else
+
+  error ("portaudio not found on your system and thus audio functionality is not present");
+
+#endif
+
+  return retval;
+}
+
+DEFUN_DLD (__player_set_userdata__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {} __player_set_userdata__ (@var{player}, @var{data})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+#ifdef HAVE_PORTAUDIO
+
+  if (args.length () == 2)
+    {
+      audioplayer *player = get_player (args(0));
+      player->set_userdata (args(1));
+    }
+
+#else
+
+  error ("portaudio not found on your system and thus audio functionality is not present");
+
+#endif
+
+  return retval;
+}
+
+DEFUN_DLD (__player_stop__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {} __player_stop__ (@var{player})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+#ifdef HAVE_PORTAUDIO
+
+  if (args.length () == 1)
+    {
+      audioplayer *player = get_player (args (0));
+      player->stop ();
+    }
+
+#else
+
+  error ("portaudio not found on your system and thus audio functionality is not present");
+
+#endif
+
+  return retval;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/dldfcn/audioread.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,515 @@
+/*
+
+Copyright (C) 2013 Vytautas Jančauskas
+
+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 <string>
+#include <map>
+
+#include "oct-locbuf.h"
+#include "unwind-prot.h"
+
+#include "defun-dld.h"
+#include "error.h"
+#include "gripes.h"
+#include "oct-obj.h"
+#include "ov.h"
+#include "ov-struct.h"
+
+#ifdef HAVE_SNDFILE
+#include <sndfile.h>
+#endif
+
+#ifdef HAVE_SNDFILE
+static void
+safe_close (SNDFILE *file)
+{
+  sf_close (file);
+}
+#endif
+
+DEFUN_DLD (audioread, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {[@var{y}, @var{fs}] =} audioread (@var{filename})\n\
+@deftypefnx {Loadable Function} {[@var{y}, @var{fs}] =} audioread (@var{filename}, @var{samples})\n\
+\n\
+@deftypefnx {Loadable Function} {[@var{y}, @var{fs}] =} audioread (@var{filename}, @var{datatype})\n\
+@deftypefnx {Loadable Function} {[@var{y}, @var{fs}] =} audioread (@var{filename}, @var{samples}, @var{datatype})\n\
+Read the audio file @var{filename} and return the audio data and sampling\n\
+rate.  The audio data is stored as matrix with rows corresponding\n\
+to audio frames and columns corresponding to channels.\n\
+\n\
+The optional two-element vector argument @var{samples} specifies starting\n\
+and ending frames.\n\
+\n\
+The optional argument @var{datatype} specifies the datatype to return.\n\
+If it is @qcode{\"native\"}, then the type of data depends on how the\n\
+data is stored in the audio file.\n\
+\n\
+Read a file and return a specified range of frames in an array of specified type.\n\
+\n\
+@end deftypefn")
+{
+  octave_value_list retval;
+
+#ifdef HAVE_SNDFILE
+
+  int nargin = args.length ();
+
+  if (nargin < 1 || nargin > 3)
+    {
+      print_usage ();
+      return retval;
+    }
+
+  std::string filename = args(0).string_value ();
+
+  if (error_state)
+    return retval;
+  
+  SF_INFO info;
+  info.format = 0;
+  SNDFILE *file = sf_open (filename.c_str (), SFM_READ, &info);
+
+  if (! file)
+    {
+      error ("audioread: failed to open input file %s", filename.c_str ());
+      return retval;
+    }
+
+  unwind_protect frame;
+
+  frame.add_fcn (safe_close, file);
+
+  OCTAVE_LOCAL_BUFFER (float, data, info.frames * info.channels);
+
+  sf_read_float (file, data, info.frames * info.channels);
+
+  sf_count_t start = 0;
+  sf_count_t end = info.frames;
+
+  if ((nargin == 2 && ! args(1).is_string ()) || nargin == 3)
+    {
+      RowVector range = args(1).row_vector_value ();
+
+      if (error_state)
+        return retval;
+
+      if (range.nelem () != 2)
+        {
+          error ("audioread: invalid specification for range of frames");
+          return retval;
+        }
+
+      double dstart = range(0);
+      double dend = range(1);
+
+      if (dstart < 0 || dstart > dend || D_NINT (dstart) != dstart
+          || D_NINT (dend) != dend)
+        {
+          error ("audioread: invalid specification for range of frames");
+          return retval;
+        }
+
+      start = dstart;
+      end = dend;
+    }
+
+  sf_count_t items = end - start;
+
+  Matrix audio (items, info.channels);
+
+  double *paudio = audio.fortran_vec ();
+
+  data += start * info.channels;
+
+  for (int i = 0; i < items; i++)
+    {
+      for (int channel = 0; channel < info.channels; channel++)
+        paudio[items*channel+i] = *data++;
+    }
+
+  octave_value ret_audio;
+
+  if ((nargin == 2 && args(1).is_string ()) || nargin == 3)
+    {
+      std::string type;
+      if (nargin == 3)
+        type = args(2).string_value ();
+      else
+        type = args(1).string_value ();
+
+      if (error_state)
+        return retval;
+
+      if (type == "native")
+        {
+          if (info.format & SF_FORMAT_PCM_S8)
+            ret_audio = int8NDArray (audio * 127);
+          else if (info.format & SF_FORMAT_PCM_U8)
+            ret_audio = uint8NDArray (audio * 127 + 127);
+          else if (info.format & SF_FORMAT_PCM_16)
+            ret_audio = int16NDArray (audio * 32767);
+          else if (info.format & SF_FORMAT_PCM_24)
+            ret_audio = int32NDArray (audio * 8388608);
+          else if (info.format & SF_FORMAT_PCM_32)
+            ret_audio = int32NDArray (audio * 2147483648);
+          else
+            ret_audio = audio;
+        }
+      else
+        ret_audio = audio;
+    }
+  else
+    ret_audio = audio;
+
+  retval(1) = info.samplerate;
+  retval(0) = ret_audio;
+
+#else
+
+  error ("sndfile not found on your system and thus audioread is not functional");
+
+#endif
+
+  return retval;
+}
+
+#ifdef HAVE_SNDFILE
+
+static int
+extension_to_format (const std::string& ext)
+{
+  static bool initialized = false;
+
+  static std::map<std::string, int> table;
+
+  if (! initialized)
+    {
+      table["wav"] = SF_FORMAT_WAV;
+      table["aiff"] = SF_FORMAT_AIFF;
+      table["au"] = SF_FORMAT_AU;
+      table["raw"] = SF_FORMAT_RAW;
+      table["paf"] = SF_FORMAT_PAF;
+      table["svx"] = SF_FORMAT_SVX;
+      table["nist"] = SF_FORMAT_NIST;
+      table["voc"] = SF_FORMAT_VOC;
+      table["ircam"] = SF_FORMAT_IRCAM;
+      table["w64"] = SF_FORMAT_W64;
+      table["mat4"] = SF_FORMAT_MAT4;
+      table["mat5"] = SF_FORMAT_MAT5;
+      table["pvf"] = SF_FORMAT_PVF;
+      table["xi"] = SF_FORMAT_XI;
+      table["htk"] = SF_FORMAT_HTK;
+      table["sds"] = SF_FORMAT_SDS;
+      table["avr"] = SF_FORMAT_AVR;
+      table["wavex"] = SF_FORMAT_WAVEX;
+      table["sd2"] = SF_FORMAT_SD2;
+      table["flac"] = SF_FORMAT_FLAC;
+      table["caf"] = SF_FORMAT_CAF;
+      table["wve"] = SF_FORMAT_WVE;
+      table["ogg"] = SF_FORMAT_OGG;
+      table["mpc2k"] = SF_FORMAT_MPC2K;
+      table["rf64"] = SF_FORMAT_RF64;
+
+      initialized = true;
+    }
+
+  std::map<std::string, int>::const_iterator it = table.find (ext);
+
+  return (it != table.end ()) ? it->second : 0;
+}
+
+#endif
+
+DEFUN_DLD (audiowrite, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {} audiowrite (@var{filename}, @var{y}, @var{fs})\n\
+@deftypefnx {Loadable Function} {} audiowrite (@var{filename}, @var{y}, @var{fs}, @var{name}, @var{value}, @dots{})\n\
+\n\
+Write audio data from the matrix @var{y} to @var{filename} with the file\n\
+format determined by the file extension.\n\
+\n\
+Additional name and value argument pairs may be used to specify the\n\
+following options:\n\
+\n\
+@table @samp\n\
+@item BitsPerSample\n\
+Number of bits per sample, valid values are 8, 16, 24 and 32. Default is 16.\n\
+@item BitRate\n\
+Valid argument name, but ignored. Left for compatibility with @sc{matlab}.\n\
+@item Quality\n\
+Quality setting for the Ogg Vorbis compressor. Values can range between 0 and 100 with 100 being the highest quality setting. Default is 75.\n\
+@item Title\n\
+Title for the audio file.\n\
+@item Artist\n\
+Artist name.\n\
+@item Comment\n\
+Comment.\n\
+@end table\n\
+@end deftypefn")
+{
+  // FIXME: shouldn't we return something to indicate whether the file
+  // was written successfully?
+
+  octave_value retval;
+
+#ifdef HAVE_SNDFILE
+
+  int nargin = args.length ();
+
+  if (nargin < 3)
+    {
+      print_usage ();
+      return retval;
+    }
+
+  std::string filename = args(0).string_value ();
+
+  if (error_state)
+    return retval;
+
+  const Matrix audio = args(1).matrix_value ();
+
+  if (error_state)
+    return retval;
+
+  int samplerate = args(2).int_value ();
+
+  if (error_state)
+    return retval;
+
+  std::string ext = filename.substr (filename.find_last_of (".") + 1);
+  std::transform (ext.begin (), ext.end (), ext.begin (), ::tolower);
+
+  sf_count_t items_to_write = audio.rows () * audio.columns ();
+
+  OCTAVE_LOCAL_BUFFER (float, data, items_to_write);
+
+  sf_count_t idx = 0;
+  for (int i = 0; i < audio.rows (); i++)
+    {
+      for (int j = 0; j < audio.columns (); j++)
+        data[idx++] = audio.xelem (i, j);
+    }
+
+  SF_INFO info;
+
+  memset (&info, 0, sizeof (info)) ;
+
+  sf_count_t chunk_size = 0;
+
+  if (ext == "ogg")
+    {
+      info.format = SF_FORMAT_VORBIS;
+
+      // FIXME: there seems to be a bug writing ogg files in one shot
+      // that causes a segfault.  Breaking it up into a series of
+      // smaller chunks seems to avoid the problem and produce valid
+      // files.
+      chunk_size = 0x1FFFFE;
+    }
+  else
+    info.format = SF_FORMAT_PCM_16;
+
+  info.channels = audio.columns ();
+  info.samplerate = samplerate;
+  info.channels = audio.cols ();
+  info.format |= extension_to_format (ext);
+
+  std::string title = "";
+  std::string artist = "";
+  std::string comment = "";
+  // Quality is currently unused?
+  //
+  // float quality = 0.75;
+  for (int i = 3; i < nargin; i += 2)
+    {
+      if (args(i).string_value () == "BitsPerSample")
+        {
+          int bits = args(i + 1).int_value ();
+          if (bits == 8)
+            info.format |= SF_FORMAT_PCM_S8;
+          else if (bits == 16)
+            info.format |= SF_FORMAT_PCM_16;
+          else if (bits == 24)
+            info.format |= SF_FORMAT_PCM_24;
+          else if (bits == 32)
+            info.format |= SF_FORMAT_PCM_32;
+          else
+            {
+              error ("audiowrite: wrong number of bits specified");
+              return retval;
+            }
+        }
+      else if (args(i).string_value () == "BitRate")
+        ;
+      // Quality is currently unused?
+      //
+      // else if (args(i).string_value () == "Quality")
+      //   quality = args(i + 1).int_value () * 0.01;
+      else if (args(i).string_value () == "Title")
+        title = args(i + 1).string_value ();
+      else if (args(i).string_value () == "Artist")
+        artist = args(i + 1).string_value ();
+      else if (args(i).string_value () == "Comment")
+        comment = args(i + 1).string_value ();
+      else
+        {
+          error ("audiowrite: wrong argument name");
+          return retval;
+        }
+    }
+
+  SNDFILE *file = sf_open (filename.c_str (), SFM_WRITE, &info);
+
+  if (! file)
+    {
+      error ("audiowrite: failed to open output file %s", filename.c_str ());
+      return retval;
+    }
+
+  unwind_protect frame;
+
+  frame.add_fcn (safe_close, file);
+
+  if (title != "")
+    sf_set_string (file, SF_STR_TITLE, title.c_str ());
+
+  if (artist != "")
+    sf_set_string (file, SF_STR_ARTIST, artist.c_str ());
+
+  if (comment != "")
+    sf_set_string (file, SF_STR_COMMENT, comment.c_str ());
+
+  sf_count_t total_items_written = 0;
+  sf_count_t offset = 0;
+
+  if (chunk_size == 0)
+    chunk_size = items_to_write;
+
+  while (total_items_written < items_to_write)
+    {
+      if (items_to_write - offset < chunk_size)
+        chunk_size = items_to_write - offset;
+
+      sf_count_t items_written = sf_write_float (file, data+offset, chunk_size);
+
+      if (items_written != chunk_size)
+        {
+          error ("audiowrite: write failed, wrote %ld of %ld items\n",
+                 items_written, chunk_size);
+          return retval;
+        }
+
+      total_items_written += items_written;
+      offset += chunk_size;
+    }
+
+#else
+
+  error ("sndfile not found on your system and thus audiowrite is not functional");
+
+#endif
+
+  return retval;
+}
+
+DEFUN_DLD (audioinfo, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {@var{info} =} audioinfo (@var{filename})\n\
+Return information about an audio file specified by @var{filename}.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+#ifdef HAVE_SNDFILE
+
+  if (args.length () != 1)
+    {
+      print_usage ();
+      return retval;
+    }
+
+  std::string filename = args(0).string_value ();
+
+  if (error_state)
+    return retval;
+
+  SF_INFO info;
+  info.format = 0;
+  SNDFILE *file = sf_open (filename.c_str (), SFM_READ, &info);
+
+  if (! file)
+    {
+      error ("audioinfo: failed to open file %s", filename.c_str ());
+      return retval;
+    }
+
+  unwind_protect frame;
+
+  frame.add_fcn (safe_close, file);
+
+  octave_scalar_map result;
+
+  result.assign ("Filename", filename);
+  result.assign ("CompressionMethod", "");
+  result.assign ("NumChannels", info.channels);
+  result.assign ("SampleRate", info.samplerate);
+  result.assign ("TotalSamples", info.frames);
+
+  double dframes = info.frames;
+  double drate = info.samplerate;
+  result.assign ("Duration", dframes / drate);
+
+  int bits;
+  if (info.format & SF_FORMAT_PCM_S8)
+    bits = 8;
+  else if (info.format & SF_FORMAT_PCM_U8)
+    bits = 8;
+  else if (info.format & SF_FORMAT_PCM_16)
+    bits = 16;
+  else if (info.format & SF_FORMAT_PCM_24)
+    bits = 24;
+  else if (info.format & SF_FORMAT_PCM_32)
+    bits = 32;
+  else
+    bits = -1;
+
+  result.assign ("BitsPerSample", bits);
+  result.assign ("BitRate", -1);
+  result.assign ("Title", sf_get_string (file, SF_STR_TITLE));
+  result.assign ("Artist", sf_get_string (file, SF_STR_ARTIST));
+  result.assign ("Comment", sf_get_string (file, SF_STR_COMMENT));
+
+  retval = result;
+
+#else
+
+  error ("sndfile not found on your system and thus audioinfo is not functional");
+
+#endif
+
+  return retval;
+}
--- a/libinterp/dldfcn/ccolamd.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/dldfcn/ccolamd.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -100,10 +100,9 @@
 @var{cmember} is an optional vector of length @math{n}.  It defines the\n\
 constraints on the column ordering.  If @code{@var{cmember}(j) = @var{c}},\n\
 then column @var{j} is in constraint set @var{c} (@var{c} must be in the\n\
-range 1 to\n\
-n).  In the output permutation @var{p}, all columns in set 1 appear\n\
-first, followed by all columns in set 2, and so on.  @code{@var{cmember} =\n\
-ones (1,n)} if not present or empty.\n\
+range 1 to n).  In the output permutation @var{p}, all columns in set 1\n\
+appear first, followed by all columns in set 2, and so on.\n\
+@code{@var{cmember} = ones (1,n)} if not present or empty.\n\
 @code{ccolamd (@var{S}, [], 1 : n)} returns @code{1 : n}\n\
 \n\
 @code{@var{p} = ccolamd (@var{S})} is about the same as\n\
@@ -133,11 +132,12 @@
 or out-of-order row indices.  @code{@var{stats}(8 : 20)} is always zero in\n\
 the current version of @sc{ccolamd} (reserved for future use).\n\
 \n\
-The authors of the code itself are S. Larimore, T. Davis (Univ. of Florida)\n\
-and S. Rajamanickam in collaboration with J. Bilbert and E. Ng.  Supported\n\
-by the National Science Foundation\n\
-@nospell{(DMS-9504974, DMS-9803599, CCR-0203270)}, and a grant from Sandia\n\
-National Lab.  See @url{http://www.cise.ufl.edu/research/sparse} for\n\
+The authors of the code itself are @nospell{S. Larimore, T. Davis}\n\
+(Univ. of Florida) and @nospell{S. Rajamanickam} in collaboration with\n\
+@nospell{J. Bilbert and E. Ng}.  Supported by the National Science Foundation\n\
+@nospell{(DMS-9504974, DMS-9803599, CCR-0203270)}, and a grant from\n\
+@nospell{Sandia} National Lab.\n\
+See @url{http://www.cise.ufl.edu/research/sparse} for\n\
 ccolamd, csymamd, amd, colamd, symamd, and other related orderings.\n\
 @seealso{colamd, csymamd}\n\
 @end deftypefn")
@@ -390,11 +390,12 @@
 or out-of-order row indices.  @code{@var{stats}(8:20)} is always zero in\n\
 the current version of @sc{ccolamd} (reserved for future use).\n\
 \n\
-The authors of the code itself are S. Larimore, T. Davis (Uni of Florida)\n\
-and S. Rajamanickam in collaboration with J. Bilbert and E. Ng.  Supported\n\
-by the National Science Foundation\n\
-@nospell{(DMS-9504974, DMS-9803599, CCR-0203270)}, and a grant from Sandia\n\
-National Lab.  See @url{http://www.cise.ufl.edu/research/sparse} for\n\
+The authors of the code itself are @nospell{S. Larimore, T. Davis}\n\
+(Univ. of Florida) and @nospell{S. Rajamanickam} in collaboration with\n\
+@nospell{J. Bilbert and E. Ng}.  Supported by the National Science Foundation\n\
+@nospell{(DMS-9504974, DMS-9803599, CCR-0203270)}, and a grant from\n\
+@nospell{Sandia} National Lab.\n\
+See @url{http://www.cise.ufl.edu/research/sparse} for\n\
 ccolamd, csymamd, amd, colamd, symamd, and other related orderings.\n\
 @seealso{symamd, ccolamd}\n\
 @end deftypefn")
--- a/libinterp/dldfcn/chol.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/dldfcn/chol.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -135,7 +135,7 @@
 \n\
 In general the lower triangular factorization is significantly faster for\n\
 sparse matrices.\n\
-@seealso{hess, lu, qr, qz, schur, svd, cholinv, chol2inv, cholupdate, cholinsert, choldelete, cholshift}\n\
+@seealso{hess, lu, qr, qz, schur, svd, ichol, cholinv, chol2inv, cholupdate, cholinsert, choldelete, cholshift}\n\
 @end deftypefn")
 {
   octave_value_list retval;
@@ -155,7 +155,7 @@
     {
       std::string tmp = args(n++).string_value ();
 
-      if (! error_state )
+      if (! error_state)
         {
           if (tmp.compare ("vector") == 0)
             vecout = true;
--- a/libinterp/dldfcn/colamd.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/dldfcn/colamd.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -270,10 +270,9 @@
 \n\
 The ordering is followed by a column elimination tree post-ordering.\n\
 \n\
-The authors of the code itself are Stefan I. Larimore and Timothy A.\n\
-Davis @email{davis@@cise.ufl.edu}, University of Florida.  The algorithm was\n\
-developed in collaboration with John Gilbert, Xerox PARC, and Esmond\n\
-Ng, Oak Ridge National Laboratory.  (see\n\
+The authors of the code itself are @nospell{Stefan I. Larimore} and\n\
+@nospell{Timothy A. Davis @email{davis@@cise.ufl.edu}}, University of Florida.  The algorithm was developed in collaboration with @nospell{John Gilbert},\n\
+Xerox PARC, and @nospell{Esmond Ng}, Oak Ridge National Laboratory.  (see\n\
 @url{http://www.cise.ufl.edu/research/sparse/colamd})\n\
 @seealso{colperm, symamd, ccolamd}\n\
 @end deftypefn")
@@ -506,10 +505,9 @@
 \n\
 The ordering is followed by a column elimination tree post-ordering.\n\
 \n\
-The authors of the code itself are Stefan I. Larimore and Timothy A.\n\
-Davis @email{davis@@cise.ufl.edu}, University of Florida.  The algorithm was\n\
-developed in collaboration with John Gilbert, Xerox PARC, and Esmond\n\
-Ng, Oak Ridge National Laboratory.  (see\n\
+The authors of the code itself are @nospell{Stefan I. Larimore} and\n\
+@nospell{Timothy A. Davis @email{davis@@cise.ufl.edu}}, University of Florida.  The algorithm was developed in collaboration with @nospell{John Gilbert},\n\
+Xerox PARC, and @nospell{Esmond Ng}, Oak Ridge National Laboratory.  (see\n\
 @url{http://www.cise.ufl.edu/research/sparse/colamd})\n\
 @seealso{colperm, colamd}\n\
 @end deftypefn")
--- a/libinterp/dldfcn/convhulln.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/dldfcn/convhulln.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -33,7 +33,7 @@
 #include <config.h>
 #endif
 
-#include <sstream>
+#include "oct-locbuf.h"
 
 #include "Cell.h"
 #include "defun-dld.h"
--- a/libinterp/dldfcn/dmperm.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/dldfcn/dmperm.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -136,8 +136,10 @@
 @deftypefn  {Loadable Function} {@var{p} =} dmperm (@var{S})\n\
 @deftypefnx {Loadable Function} {[@var{p}, @var{q}, @var{r}, @var{S}] =} dmperm (@var{S})\n\
 \n\
-@cindex Dulmage-Mendelsohn decomposition\n\
-Perform a Dulmage-Mendelsohn permutation of the sparse matrix @var{S}.\n\
+@cindex @nospell{Dulmage-Mendelsohn} decomposition\n\
+Perform a @nospell{Dulmage-Mendelsohn} permutation of the sparse matrix\n\
+@var{S}.\n\
+\n\
 With a single output argument @code{dmperm} performs the row permutations\n\
 @var{p} such that @code{@var{S}(@var{p},:)} has no zero elements on the\n\
 diagonal.\n\
@@ -147,9 +149,9 @@
 triangular form.  The values of @var{r} and @var{S} define the boundaries\n\
 of the blocks.  If @var{S} is square then @code{@var{r} == @var{S}}.\n\
 \n\
-The method used is described in: A. Pothen & C.-J. Fan. @cite{Computing the\n\
-Block Triangular Form of a Sparse Matrix}. ACM Trans. Math. Software,\n\
-16(4):303-324, 1990.\n\
+The method used is described in: @nospell{A. Pothen & C.-J. Fan.}\n\
+@cite{Computing the Block Triangular Form of a Sparse Matrix}.\n\
+ACM Trans. Math. Software, 16(4):303-324, 1990.\n\
 @seealso{colamd, ccolamd}\n\
 @end deftypefn")
 {
@@ -194,8 +196,8 @@
 \n\
 Calculate the structural rank of the sparse matrix @var{S}.  Note that\n\
 only the structure of the matrix is used in this calculation based on\n\
-a Dulmage-Mendelsohn permutation to block triangular form.  As such the\n\
-numerical rank of the matrix @var{S} is bounded by\n\
+a @nospell{Dulmage-Mendelsohn} permutation to block triangular form.  As\n\
+such the numerical rank of the matrix @var{S} is bounded by\n\
 @code{sprank (@var{S}) >= rank (@var{S})}.  Ignoring floating point errors\n\
 @code{sprank (@var{S}) == rank (@var{S})}.\n\
 @seealso{dmperm}\n\
--- a/libinterp/dldfcn/fftw.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/dldfcn/fftw.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -32,6 +32,8 @@
 #include "error.h"
 #include "ov.h"
 
+#include "gripes.h"
+
 DEFUN_DLD (fftw, args, ,
            "-*- texinfo -*-\n\
 @deftypefn  {Loadable Function} {@var{method} =} fftw (\"planner\")\n\
@@ -189,7 +191,7 @@
                               methf = octave_float_fftw_planner::HYBRID;
                             }
                           else
-                            error ("unrecognized planner METHOD");
+                            error ("fftw: unrecognized planner METHOD");
 
                           if (!error_state)
                             {
@@ -210,7 +212,7 @@
                         }
                     }
                   else
-                    error ("fftw planner expects a string value as METHOD");
+                    error ("fftw: planner expects a string value as METHOD");
                 }
               else //planner getter
                 {
@@ -246,7 +248,7 @@
                           if (arg1.length () < 1)
                             fftw_forget_wisdom ();
                           else if (! fftw_import_wisdom_from_string (arg1.c_str ()))
-                            error ("could not import supplied WISDOM");
+                            error ("fftw: could not import supplied WISDOM");
 
                           if (!error_state)
                             retval = octave_value (std::string (str));
@@ -280,7 +282,7 @@
                           if (arg1.length () < 1)
                             fftwf_forget_wisdom ();
                           else if (! fftwf_import_wisdom_from_string (arg1.c_str ()))
-                            error ("could not import supplied WISDOM");
+                            error ("fftw: could not import supplied WISDOM");
 
                           if (!error_state)
                             retval = octave_value (std::string (str));
@@ -303,24 +305,24 @@
                   if (args(1).is_real_scalar ())
                     {
                       int nthreads = args(1).int_value();
-                      if ( nthreads >= 1)
+                      if (nthreads >= 1)
                         {
 #if defined (HAVE_FFTW3_THREADS)
                           octave_fftw_planner::threads (nthreads);
 #else
-                          warning ("this copy of Octave was not configured to use the multithreaded fftw libraries.");
+                          gripe_disabled_feature ("fftw", "multithreaded FFTW");
 #endif
 #if defined (HAVE_FFTW3F_THREADS)
                           octave_float_fftw_planner::threads (nthreads);
 #else
-                          warning ("this copy of Octave was not configured to use the multithreaded fftwf libraries.");
+                          gripe_disabled_feature ("fftw", "multithreaded FFTW");
 #endif
                         }
                       else
-                        error ("number of threads must be >=1");
+                        error ("fftw: number of threads must be >=1");
                     }
                   else
-                    error ("setting threads needs one integer argument.");
+                    error ("fftw: setting threads needs one integer argument");
                 }
               else //threads getter
 #if defined (HAVE_FFTW3_THREADS)
@@ -330,14 +332,14 @@
 #endif
             }
           else
-            error ("unrecognized argument");
+            error ("fftw: unrecognized argument");
         }
     }
   else
-    error ("unrecognized argument");
+    error ("fftw: unrecognized argument");
 #else
 
-  warning ("fftw: this copy of Octave was not configured to use the FFTW3 planner");
+  gripe_disabled_feature ("fftw", "the FFTW3 planner");
 
 #endif
 
@@ -367,8 +369,22 @@
 %!   fftw ("planner", def_method);
 %! end_unwind_protect
 
-%!error <Invalid call to fftw> fftw ();
-%!error <Invalid call to fftw> fftw ("planner", "estimate", "measure");
+%!testif HAVE_FFTW
+%! def_dwisdom = fftw ("dwisdom");
+%! def_swisdom = fftw ("swisdom");
+%! unwind_protect
+%!   wisdom = fftw ("dwisdom");
+%!   assert (ischar (wisdom));
+%!   fftw ("dwisdom", wisdom);
+%!   assert (fftw ("dwisdom"), wisdom);
+%!   wisdom = fftw ("swisdom");
+%!   assert (ischar (wisdom));
+%!   fftw ("swisdom", wisdom);
+%!   assert (fftw ("swisdom"), wisdom);
+%! unwind_protect_cleanup
+%!   fftw ("dwisdom", def_dwisdom);
+%!   fftw ("swisdom", def_swisdom);
+%! end_unwind_protect
 
 %!testif HAVE_FFTW3_THREADS
 %! n = fftw ("threads");
@@ -378,4 +394,15 @@
 %! unwind_protect_cleanup
 %!   fftw ("threads", n);
 %! end_unwind_protect
+
+%!error <Invalid call to fftw> fftw ();
+%!error <Invalid call to fftw> fftw ("planner", "estimate", "measure");
+%!error fftw (3);
+%!error fftw ("invalid");
+%!error fftw ("planner", "invalid");
+%!error fftw ("planner", 2);
+%!error fftw ("dwisdom", "invalid");
+%!error fftw ("swisdom", "invalid");
+%!error fftw ("threads", "invalid");
+%!error fftw ("threads", -3);
  */
--- a/libinterp/dldfcn/module-files	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/dldfcn/module-files	Mon Jan 12 09:17:35 2015 -0800
@@ -4,6 +4,8 @@
 __eigs__.cc|$(ARPACK_CPPFLAGS) $(SPARSE_XCPPFLAGS)|$(ARPACK_LDFLAGS) $(SPARSE_XLDFLAGS)|$(ARPACK_LIBS) $(SPARSE_XLIBS) $(LAPACK_LIBS) $(BLAS_LIBS)
 __fltk_uigetfile__.cc|$(GRAPHICS_CFLAGS) $(FT2_CPPFLAGS)|$(GRAPHICS_LDFLAGS) $(FT2_LDFLAGS)|$(GRAPHICS_LIBS) $(FT2_LIBS)
 __glpk__.cc|$(GLPK_CPPFLAGS)|$(GLPK_LDFLAGS)|$(GLPK_LIBS)
+__ichol__.cc
+__ilu__.cc
 __init_fltk__.cc|$(GRAPHICS_CFLAGS) $(FT2_CPPFLAGS) $(FONTCONFIG_CPPFLAGS)|$(GRAPHICS_LDFLAGS) $(FT2_LDFLAGS)|$(GRAPHICS_LIBS) $(FT2_LIBS) $(OPENGL_LIBS)
 __init_gnuplot__.cc|$(FT2_CPPFLAGS) $(FONTCONFIG_CPPFLAGS)||
 __magick_read__.cc|$(MAGICK_CPPFLAGS)|$(MAGICK_LDFLAGS)|$(MAGICK_LIBS)
@@ -19,3 +21,5 @@
 symbfact.cc|$(SPARSE_XCPPFLAGS)|$(SPARSE_XLDFLAGS)|$(SPARSE_XLIBS)
 symrcm.cc|$(SPARSE_XCPPFLAGS)|$(SPARSE_XLDFLAGS)|$(SPARSE_XLIBS)
 tsearch.cc
+audioread.cc|$(SNDFILE_CPPFLAGS)|$(SNDFILE_LDFLAGS)|$(SNDFILE_LIBS)
+audiodevinfo.cc|$(PORTAUDIO_CPPFLAGS)|$(PORTAUDIO_LDFLAGS)|$(PORTAUDIO_LIBS)
--- a/libinterp/dldfcn/qr.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/dldfcn/qr.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -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/symbfact.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/dldfcn/symbfact.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -114,17 +114,17 @@
   if (spu == 0.)
     {
       cm->print = -1;
-      cm->print_function = 0;
+      SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, 0);
     }
   else
     {
       cm->print = static_cast<int> (spu) + 2;
-      cm->print_function =&SparseCholPrint;
+      SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, &SparseCholPrint);
     }
 
   cm->error_handler = &SparseCholError;
-  cm->complex_divide = CHOLMOD_NAME(divcomplex);
-  cm->hypotenuse = CHOLMOD_NAME(hypot);
+  SUITESPARSE_ASSIGN_FPTR2 (divcomplex_func, cm->complex_divide, divcomplex);
+  SUITESPARSE_ASSIGN_FPTR2 (hypot_func, cm->hypotenuse, hypot);
 
   double dummy;
   cholmod_sparse Astore;
--- a/libinterp/dldfcn/symrcm.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/dldfcn/symrcm.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -322,7 +322,7 @@
   return x.id;
 }
 
-// Calculates the node's degrees. This means counting the non-zero elements
+// Calculates the node's degrees. This means counting the nonzero elements
 // in the symmetric matrix' rows. This works for non-symmetric matrices
 // as well.
 
@@ -341,7 +341,7 @@
         {
           OCTAVE_QUIT;
           octave_idx_type k = ridx[i];
-          // there is a non-zero element (k,j)
+          // there is a nonzero element (k,j)
           D[k]++;
           if (D[k] > max_deg)
             max_deg = D[k];
@@ -414,7 +414,7 @@
 DEFUN_DLD (symrcm, args, ,
            "-*- texinfo -*-\n\
 @deftypefn {Loadable Function} {@var{p} =} symrcm (@var{S})\n\
-Return the symmetric reverse Cuthill-McKee permutation of @var{S}.\n\
+Return the symmetric reverse @nospell{Cuthill-McKee} permutation of @var{S}.\n\
 @var{p} is a permutation vector such that\n\
 @code{@var{S}(@var{p}, @var{p})} tends to have its diagonal elements\n\
 closer to the diagonal than @var{S}.  This is a good preordering for LU\n\
@@ -425,11 +425,11 @@
 bandwidth minimization problem.  The implementation is based in the\n\
 descriptions found in\n\
 \n\
-E. Cuthill, J. McKee. @cite{Reducing the Bandwidth of Sparse Symmetric\n\
-Matrices}. Proceedings of the 24th ACM National Conference, 157--172\n\
-1969, Brandon Press, New Jersey.\n\
+@nospell{E. Cuthill, J. McKee}. @cite{Reducing the Bandwidth of Sparse\n\
+Symmetric Matrices}. Proceedings of the 24th ACM National Conference,\n\
+157--172 1969, Brandon Press, New Jersey.\n\
 \n\
-A. George, J.W.H. Liu. @cite{Computer Solution of Large Sparse\n\
+@nospell{A. George, J.W.H. Liu}. @cite{Computer Solution of Large Sparse\n\
 Positive Definite Systems}, Prentice Hall Series in Computational\n\
 Mathematics, ISBN 0-13-165274-5, 1981.\n\
 \n\
@@ -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 12 09:13:19 2015 -0800
+++ b/libinterp/dldfcn/tsearch.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -110,8 +110,10 @@
   const octave_idx_type np = xi.length ();
   ColumnVector values (np);
 
-  double x0 = 0.0, y0 = 0.0;
-  double a11 = 0.0, a12 = 0.0, a21 = 0.0, a22 = 0.0, det = 0.0;
+  double x0, y0, a11, a12, a21, a22, det;
+  x0 = y0 = 0.0;
+  a11 = a12 = a21 = a22 = 0.0;
+  det = 0.0;
 
   octave_idx_type k = nelem; // k is a counter of elements
   for (octave_idx_type kp = 0; kp < np; kp++)
--- a/libinterp/genprops.awk	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/genprops.awk	Mon Jan 12 09:17:35 2015 -0800
@@ -290,7 +290,7 @@
   if (class_name && ! base)
     emit_common_declarations();
 
-  printf ("public:\n\n\n  static std::set<std::string> core_property_names (void);\n\n  static bool has_core_property (const caseless_str& pname);\n\n  std::set<std::string> all_property_names (void) const;\n\n");
+  printf ("public:\n\n\n  static std::set<std::string> core_property_names (void);\n\n  static std::set<std::string> readonly_property_names (void);\n\n  static bool has_core_property (const caseless_str& pname);\n\n  static bool has_readonly_property (const caseless_str& pname);\n\n  std::set<std::string> all_property_names (void) const;\n\n");
 
   if (! base)
     printf ("  bool has_property (const caseless_str& pname) const;\n\n");
@@ -470,7 +470,7 @@
               class_name);
 
     if (! base)
-      printf ("  const std::set<std::string>& pnames = all_property_names ();\n\n  caseless_str pname = validate_property_name (\"get\", go_name, pnames, pname_arg);\n\n  if (error_state)\n    return;\n\n");
+        printf ("  const std::set<std::string>& pnames = all_property_names ();\n\n  caseless_str pname = validate_property_name (\"set\", go_name, pnames, pname_arg);\n\n  if (error_state)\n    return;\n  else if (has_readonly_property (pname))\n    {\n      error (\"set: \\\"%%s\\\" is read-only\", pname.c_str ());\n      return;\n    }\n\n");
 
     first = 1;
 
@@ -611,6 +611,7 @@
       printf ("std::string %s::properties::go_name (\"%s\");\n\n",
               class_name, object_name);
 
+    ## core_property_names
     printf ("std::set<std::string>\n");
     if (base)
       printf ("base_properties");
@@ -622,7 +623,7 @@
     if (! base)
       printf ("\n      std::set<std::string> base_pnames = base_properties::core_property_names ();\n      all_pnames.insert (base_pnames.begin (), base_pnames.end ());\n");
     printf ("\n      initialized = true;\n    }\n\n  return all_pnames;\n}\n\n");
-
+    ## has_core_property
     printf ("bool\n");
     if (base)
       printf ("base_properties");
@@ -630,6 +631,30 @@
       printf ("%s::properties", class_name);
     printf ("::has_core_property (const caseless_str& pname)\n{\n  std::set<std::string> pnames = core_property_names ();\n\n  return pnames.find (pname) != pnames.end ();\n}\n\n", class_name);
 
+    ## readonly_property_names
+    printf ("std::set<std::string>\n");
+    if (base)
+      printf ("base_properties");
+    else
+      printf ("%s::properties", class_name);
+    printf ("::readonly_property_names (void)\n{\n  static std::set<std::string> all_pnames;\n\n  static bool initialized = false;\n\n  if (! initialized)\n    {\n");
+    for (i = 1; i <= idx; i++)
+        if (readonly[i])
+        {
+            printf ("      all_pnames.insert (\"%s\");\n", name[i]);
+        }
+    if (! base)
+      printf ("\n      std::set<std::string> base_pnames = base_properties::readonly_property_names ();\n      all_pnames.insert (base_pnames.begin (), base_pnames.end ());\n");
+    printf ("\n      initialized = true;\n    }\n\n  return all_pnames;\n}\n\n");
+    ## has_readonly_property
+    printf ("bool\n");
+    if (base)
+      printf ("base_properties");
+    else
+      printf ("%s::properties", class_name);
+    printf ("::has_readonly_property (const caseless_str& pname)\n{\n  std::set<std::string> pnames = readonly_property_names ();\n\n  return pnames.find (pname) != pnames.end ();\n}\n\n", class_name);
+
+    ## all_property_names
     printf ("std::set<std::string>\n");
     if (base)
         printf ("base_properties");
--- a/libinterp/octave-value/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -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 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-base-diag.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -100,7 +100,6 @@
                                         bool resize_ok)
 {
   octave_value retval;
-  typedef typename DMT::element_type el_type;
 
   if (idx.length () == 2 && ! resize_ok)
     {
@@ -441,7 +440,8 @@
 bool
 octave_base_diag<DMT, MT>::load_ascii (std::istream& is)
 {
-  octave_idx_type r = 0, c = 0;
+  octave_idx_type r = 0;
+  octave_idx_type c = 0;
   bool success = true;
 
   if (extract_keyword (is, "rows", r, true)
@@ -505,8 +505,7 @@
 
 template <class DMT, class MT>
 void
-octave_base_diag<DMT, MT>::print (std::ostream& os,
-                                  bool pr_as_read_syntax) const
+octave_base_diag<DMT, MT>::print (std::ostream& os, bool pr_as_read_syntax)
 {
   print_raw (os, pr_as_read_syntax);
   newline (os);
@@ -531,6 +530,23 @@
 
 template <class DMT, class MT>
 octave_value
+octave_base_diag<DMT, MT>::fast_elem_extract (octave_idx_type n) const
+{
+  if (n < matrix.numel ())
+    {
+      octave_idx_type nr = matrix.rows ();
+
+      octave_idx_type r = n % nr;
+      octave_idx_type c = n / nr;
+
+      return octave_value (matrix.elem (r, c));
+    }
+  else
+    return octave_value ();
+}
+
+template <class DMT, class MT>
+octave_value
 octave_base_diag<DMT, MT>::to_dense (void) const
 {
   if (! dense_cache.is_defined ())
--- a/libinterp/octave-value/ov-base-diag.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-base-diag.h	Mon Jan 12 09:17:35 2015 -0800
@@ -203,10 +203,12 @@
 
   bool print_as_scalar (void) const;
 
-  void print (std::ostream& os, bool pr_as_read_syntax = false) const;
+  void print (std::ostream& os, bool pr_as_read_syntax = false);
 
   void print_info (std::ostream& os, const std::string& prefix) const;
 
+  octave_value fast_elem_extract (octave_idx_type n) const;
+
 protected:
 
   DMT matrix;
--- a/libinterp/octave-value/ov-base-int.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-base-int.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -266,7 +266,7 @@
 template <class T>
 bool
 octave_base_int_matrix<T>::load_binary (std::istream& is, bool swap,
-                                        oct_mach_info::float_format )
+                                        oct_mach_info::float_format)
 {
   int32_t mdims;
   if (! is.read (reinterpret_cast<char *> (&mdims), 4))
@@ -347,7 +347,8 @@
     return (empty > 0);
 
   int rank = dv.length ();
-  hid_t space_hid = -1, data_hid = -1;
+  hid_t space_hid, data_hid;
+  space_hid = data_hid = -1;
   OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);
 
   // Octave uses column-major, while HDF5 uses row-major ordering
@@ -550,7 +551,8 @@
   hid_t save_type_hid = HDF5_SAVE_TYPE;
   bool retval = true;
   hsize_t dimens[3];
-  hid_t space_hid = -1, data_hid = -1;
+  hid_t space_hid, data_hid;
+  space_hid = data_hid = -1;
 
   space_hid = H5Screate_simple (0, dimens, 0);
   if (space_hid < 0) return false;
--- a/libinterp/octave-value/ov-base-int.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-base-int.h	Mon Jan 12 09:17:35 2015 -0800
@@ -74,10 +74,10 @@
 
   bool load_ascii (std::istream& is);
 
-  bool save_binary (std::ostream& os, bool& );
+  bool save_binary (std::ostream& os, bool&);
 
   bool load_binary (std::istream& is, bool swap,
-                    oct_mach_info::float_format );
+                    oct_mach_info::float_format);
 
 #if defined (HAVE_HDF5)
   bool save_hdf5 (hid_t loc_id, const char *name, bool);
@@ -119,13 +119,13 @@
 
   bool load_ascii (std::istream& is);
 
-  bool save_binary (std::ostream& os, bool& );
+  bool save_binary (std::ostream& os, bool&);
 
   bool load_binary (std::istream& is, bool swap,
-                    oct_mach_info::float_format );
+                    oct_mach_info::float_format);
 
 #if defined (HAVE_HDF5)
-  bool save_hdf5 (hid_t loc_id, const char *name, bool );
+  bool save_hdf5 (hid_t loc_id, const char *name, bool);
 
   bool load_hdf5 (hid_t loc_id, const char *name);
 #endif
--- a/libinterp/octave-value/ov-base-mat.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-base-mat.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -27,6 +27,8 @@
 
 #include <iostream>
 
+#include "Array-util.h"
+
 #include "Cell.h"
 #include "oct-obj.h"
 #include "oct-map.h"
@@ -351,7 +353,8 @@
               {
                 // optimize all scalar indices. Don't construct an index array,
                 // but rather calc a scalar index directly.
-                octave_idx_type k = 1, j = 0;
+                octave_idx_type k = 1;
+                octave_idx_type j = 0;
                 for (octave_idx_type i = 0; i < n_idx; i++)
                   {
                     j += idx_vec(i)(0) * k;
@@ -435,7 +438,7 @@
 
 template <class MT>
 void
-octave_base_matrix<MT>::print (std::ostream& os, bool pr_as_read_syntax) const
+octave_base_matrix<MT>::print (std::ostream& os, bool pr_as_read_syntax)
 {
   print_raw (os, pr_as_read_syntax);
   newline (os);
--- a/libinterp/octave-value/ov-base-mat.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-base-mat.h	Mon Jan 12 09:17:35 2015 -0800
@@ -153,7 +153,7 @@
 
   bool print_as_scalar (void) const;
 
-  void print (std::ostream& os, bool pr_as_read_syntax = false) const;
+  void print (std::ostream& os, bool pr_as_read_syntax = false);
 
   void print_info (std::ostream& os, const std::string& prefix) const;
 
--- a/libinterp/octave-value/ov-base-scalar.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-base-scalar.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -143,7 +143,7 @@
 
 template <class ST>
 void
-octave_base_scalar<ST>::print (std::ostream& os, bool pr_as_read_syntax) const
+octave_base_scalar<ST>::print (std::ostream& os, bool pr_as_read_syntax)
 {
   print_raw (os, pr_as_read_syntax);
   newline (os);
@@ -183,6 +183,13 @@
 }
 
 template <class ST>
+octave_value
+octave_base_scalar<ST>::fast_elem_extract (octave_idx_type n) const
+{
+  return (n == 0) ? octave_value (scalar) : octave_value ();
+}
+
+template <class ST>
 bool
 octave_base_scalar<ST>::fast_elem_insert_self (void *where,
                                                builtin_type_t btyp) const
--- a/libinterp/octave-value/ov-base-scalar.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-base-scalar.h	Mon Jan 12 09:17:35 2015 -0800
@@ -132,7 +132,7 @@
 
   bool is_true (void) const;
 
-  void print (std::ostream& os, bool pr_as_read_syntax = false) const;
+  void print (std::ostream& os, bool pr_as_read_syntax = false);
 
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
 
@@ -148,6 +148,8 @@
 
   ST& scalar_ref (void) { return scalar; }
 
+  octave_value fast_elem_extract (octave_idx_type n) const;
+
   bool fast_elem_insert_self (void *where, builtin_type_t btyp) const;
 
 protected:
--- a/libinterp/octave-value/ov-base-sparse.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-base-sparse.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -288,7 +288,7 @@
 
 template <class T>
 void
-octave_base_sparse<T>::print (std::ostream& os, bool pr_as_read_syntax) const
+octave_base_sparse<T>::print (std::ostream& os, bool pr_as_read_syntax)
 {
   print_raw (os, pr_as_read_syntax);
   newline (os);
@@ -436,31 +436,73 @@
   return success;
 }
 
+
+template <class T>
+octave_value
+octave_base_sparse<T>::fast_elem_extract (octave_idx_type n) const
+{
+  octave_idx_type nr = matrix.rows ();
+  octave_idx_type nc = matrix.cols ();
+
+  octave_idx_type i = n % nr;
+  octave_idx_type j = n / nr;
+
+  return (i < nr && j < nc) ? octave_value (matrix(i,j)) : octave_value ();
+}
+
 template <class T>
 octave_value
 octave_base_sparse<T>::map (octave_base_value::unary_mapper_t umap) const
 {
+  if (umap == umap_xtolower || umap == umap_xtoupper)
+    return matrix;
+
   // Try the map on the dense value.
+  // FIXME: We should probably be smarter about this, especially for the
+  // cases that are expected to return sparse matrices.
   octave_value retval = this->full_value ().map (umap);
 
   // Sparsify the result if possible.
-  // FIXME: intentionally skip this step for string mappers. Is this wanted?
-  if (umap >= umap_xisalnum && umap <= umap_xtoupper)
-    return retval;
 
-  switch (retval.builtin_type ())
+  switch (umap)
     {
-    case btyp_double:
-      retval = retval.sparse_matrix_value ();
+    case umap_xisalnum:
+    case umap_xisalpha:
+    case umap_xisascii:
+    case umap_xiscntrl:
+    case umap_xisdigit:
+    case umap_xisgraph:
+    case umap_xislower:
+    case umap_xisprint:
+    case umap_xispunct:
+    case umap_xisspace:
+    case umap_xisupper:
+    case umap_xisxdigit:
+    case umap_xtoascii:
+      // FIXME: intentionally skip this step for string mappers.
+      // Is this wanted?
       break;
-    case btyp_complex:
-      retval = retval.sparse_complex_matrix_value ();
-      break;
-    case btyp_bool:
-      retval = retval.sparse_bool_matrix_value ();
-      break;
+
     default:
-      break;
+      {
+        switch (retval.builtin_type ())
+          {
+          case btyp_double:
+            retval = retval.sparse_matrix_value ();
+            break;
+
+          case btyp_complex:
+            retval = retval.sparse_complex_matrix_value ();
+            break;
+
+          case btyp_bool:
+            retval = retval.sparse_bool_matrix_value ();
+            break;
+
+          default:
+            break;
+          }
+      }
     }
 
   return retval;
--- a/libinterp/octave-value/ov-base-sparse.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-base-sparse.h	Mon Jan 12 09:17:35 2015 -0800
@@ -147,7 +147,7 @@
 
   bool print_as_scalar (void) const;
 
-  void print (std::ostream& os, bool pr_as_read_syntax = false) const;
+  void print (std::ostream& os, bool pr_as_read_syntax = false);
 
   void print_info (std::ostream& os, const std::string& prefix) const;
 
@@ -165,6 +165,8 @@
 
   octave_idx_type *mex_get_jc (void) const { return matrix.mex_get_jc (); }
 
+  octave_value fast_elem_extract (octave_idx_type n) const;
+
 protected:
 
   octave_value map (octave_base_value::unary_mapper_t umap) const;
--- a/libinterp/octave-value/ov-base.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-base.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -52,6 +52,7 @@
 #include "parse.h"
 #include "pr-output.h"
 #include "utils.h"
+#include "toplev.h"
 #include "variables.h"
 
 builtin_type_t btyp_mixed_numeric (builtin_type_t x, builtin_type_t y)
@@ -396,7 +397,7 @@
 }
 
 void
-octave_base_value::print (std::ostream&, bool) const
+octave_base_value::print (std::ostream&, bool)
 {
   gripe_wrong_type_arg ("octave_base_value::print ()", type_name ());
 }
@@ -1536,6 +1537,111 @@
   return new octave_cell ();
 }
 
+static inline octave_value_list
+sanitize (const octave_value_list& ovl)
+{
+  octave_value_list retval = ovl;
+
+  for (octave_idx_type i = 0; i < ovl.length (); i++)
+    {
+      if (retval(i).is_magic_colon ())
+        retval(i) = ":";
+    }
+
+  return retval;
+}
+
+octave_value
+make_idx_args (const std::string& type,
+               const std::list<octave_value_list>& idx,
+               const std::string& who)
+{
+  octave_value retval;
+
+  size_t len = type.length ();
+
+  if (len == idx.size ())
+    {
+      Cell type_field (1, len);
+      Cell subs_field (1, len);
+
+      std::list<octave_value_list>::const_iterator p = idx.begin ();
+
+      for (size_t i = 0; i < len; i++)
+        {
+          char t = type[i];
+
+          switch (t)
+            {
+            case '(':
+              type_field(i) = "()";
+              subs_field(i) = Cell (sanitize (*p++));
+              break;
+
+            case '{':
+              type_field(i) = "{}";
+              subs_field(i) = Cell (sanitize (*p++));
+              break;
+
+            case '.':
+              {
+                type_field(i) = ".";
+
+                octave_value_list vlist = *p++;
+
+                if (vlist.length () == 1)
+                  {
+                    octave_value val = vlist(0);
+
+                    if (val.is_string ())
+                      subs_field(i) = val;
+                    else
+                      {
+                        error ("string argument required for '.' index");
+                        return retval;
+                      }
+                  }
+                else
+                  {
+                    error ("only single argument permitted for '.' index");
+                    return retval;
+                  }
+              }
+              break;
+
+            default:
+              panic_impossible ();
+              break;
+            }
+        }
+
+      octave_map m;
+
+      m.assign ("type", type_field);
+      m.assign ("subs", subs_field);
+
+      retval = m;
+    }
+  else
+    error ("invalid index for %s", who.c_str ());
+
+  return retval;
+}
+
+bool
+called_from_builtin (void)
+{
+  octave_function *fcn = octave_call_stack::caller ();
+
+  // FIXME: we probably need a better check here, or some other
+  // mechanism to avoid overloaded functions when builtin is used.
+  // For example, what if someone overloads the builtin function?
+  // Also, are there other places where using builtin is not properly
+  // avoiding dispatch?
+
+  return (fcn && fcn->name () == "builtin");
+}
+
 void
 install_base_type_conversions (void)
 {
--- a/libinterp/octave-value/ov-base.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-base.h	Mon Jan 12 09:17:35 2015 -0800
@@ -366,6 +366,8 @@
 
   virtual bool is_object (void) const { return false; }
 
+  virtual bool is_classdef_object (void) const { return false; }
+
   virtual bool is_java (void) const { return false; }
 
   virtual bool is_cs_list (void) const { return false; }
@@ -583,6 +585,9 @@
   virtual octave_base_value *unique_parent_class (const std::string&)
   { return 0; }
 
+  virtual bool is_instance_of (const std::string&) const
+  { return false; }
+
   virtual octave_function *function_value (bool silent = false);
 
   virtual octave_user_function *user_function_value (bool silent = false);
@@ -606,7 +611,7 @@
 
   virtual bool print_as_scalar (void) const { return false; }
 
-  virtual void print (std::ostream& os, bool pr_as_read_syntax = false) const;
+  virtual void print (std::ostream& os, bool pr_as_read_syntax = false);
 
   virtual void
   print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
@@ -828,4 +833,16 @@
 // is memory to be saved
 extern OCTINTERP_API bool Vsparse_auto_mutate;
 
+// Utility function to convert C++ arguments used in subsref/subsasgn into an
+// octave_value_list object that can be used to call a function/method in the
+// interpreter.
+extern OCTINTERP_API octave_value
+make_idx_args (const std::string& type,
+               const std::list<octave_value_list>& idx,
+               const std::string& who);
+
+// Tells whether some regular octave_value_base methods are being called from
+// within the "builtin" function.
+extern OCTINTERP_API bool called_from_builtin (void);
+
 #endif
--- a/libinterp/octave-value/ov-bool-mat.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-bool-mat.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -79,7 +79,7 @@
 
   if (matrix.ndims () == 2)
     {
-      boolMatrix bm = matrix.matrix_value ();
+      boolMatrix bm (matrix);
 
       octave_idx_type nr = bm.rows ();
       octave_idx_type nc = bm.cols ();
@@ -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 ();
 
@@ -551,7 +552,7 @@
 @deftypefn {Built-in Function} {} logical (@var{x})\n\
 Convert the numeric object @var{x} to logical type.\n\
 \n\
-Any non-zero values will be converted to true (1) while zero values\n\
+Any nonzero values will be converted to true (1) while zero values\n\
 will be converted to false (0).  The non-numeric value NaN cannot be\n\
 converted and will produce an error.\n\
 \n\
--- a/libinterp/octave-value/ov-bool-mat.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-bool-mat.h	Mon Jan 12 09:17:35 2015 -0800
@@ -135,10 +135,10 @@
   { return double_value (frc_str_conv); }
 
   Matrix matrix_value (bool = false) const
-  { return Matrix (matrix.matrix_value ()); }
+  { return Matrix (boolMatrix (matrix)); }
 
   FloatMatrix float_matrix_value (bool = false) const
-  { return FloatMatrix (matrix.matrix_value ()); }
+  { return FloatMatrix (boolMatrix (matrix)); }
 
   NDArray array_value (bool = false) const
   { return NDArray (matrix); }
@@ -151,10 +151,10 @@
   FloatComplex float_complex_value (bool = false) const;
 
   ComplexMatrix complex_matrix_value (bool = false) const
-  { return ComplexMatrix (matrix.matrix_value ( )); }
+  { return ComplexMatrix (boolMatrix (matrix)); }
 
   FloatComplexMatrix float_complex_matrix_value (bool = false) const
-  { return FloatComplexMatrix (matrix.matrix_value ( )); }
+  { return FloatComplexMatrix (boolMatrix (matrix)); }
 
   ComplexNDArray complex_array_value (bool = false) const
   { return ComplexNDArray (matrix); }
@@ -176,19 +176,19 @@
   }
 
   boolMatrix bool_matrix_value (bool = false) const
-  { return matrix.matrix_value (); }
+  { return boolMatrix (matrix); }
 
   boolNDArray bool_array_value (bool = false) const
   { return matrix; }
 
   SparseMatrix sparse_matrix_value (bool = false) const
-  { return SparseMatrix (Matrix (matrix.matrix_value ())); }
+  { return SparseMatrix (Matrix (boolMatrix (matrix))); }
 
   SparseComplexMatrix sparse_complex_matrix_value (bool = false) const
-  { return SparseComplexMatrix (ComplexMatrix (matrix.matrix_value ())); }
+  { return SparseComplexMatrix (ComplexMatrix (boolMatrix (matrix))); }
 
   SparseBoolMatrix sparse_bool_matrix_value (bool = false) const
-  { return SparseBoolMatrix (matrix.matrix_value ()); }
+  { return SparseBoolMatrix (boolMatrix (matrix)); }
 
   octave_value convert_to_str_internal (bool pad, bool force, char type) const;
 
--- a/libinterp/octave-value/ov-bool-sparse.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-bool-sparse.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -225,16 +225,16 @@
 
   int32_t itmp;
   // Use negative value for ndims to be consistent with other formats
-  itmp= -2;
+  itmp = -2;
   os.write (reinterpret_cast<char *> (&itmp), 4);
 
-  itmp= nr;
+  itmp = nr;
   os.write (reinterpret_cast<char *> (&itmp), 4);
 
-  itmp= nc;
+  itmp = nc;
   os.write (reinterpret_cast<char *> (&itmp), 4);
 
-  itmp= nz;
+  itmp = nz;
   os.write (reinterpret_cast<char *> (&itmp), 4);
 
   // add one to the printed indices to go from
@@ -358,7 +358,8 @@
   if (group_hid < 0)
     return false;
 
-  hid_t space_hid = -1, data_hid = -1;
+  hid_t space_hid, data_hid;
+  space_hid = data_hid = -1;
   bool retval = true;
   SparseBoolMatrix m = sparse_bool_matrix_value ();
   octave_idx_type tmp;
@@ -567,7 +568,7 @@
 #else
   group_hid = H5Gopen (loc_id, name);
 #endif
-  if (group_hid < 0 ) return false;
+  if (group_hid < 0) return false;
 
 #if HAVE_HDF5_18
   data_hid = H5Dopen (group_hid, "nr", H5P_DEFAULT);
--- a/libinterp/octave-value/ov-bool.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-bool.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -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 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-cell.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -687,7 +687,7 @@
 }
 
 void
-octave_cell::print (std::ostream& os, bool) const
+octave_cell::print (std::ostream& os, bool)
 {
   print_raw (os);
 }
@@ -1077,7 +1077,8 @@
     return (empty > 0);
 
   hsize_t rank = dv.length ();
-  hid_t space_hid = -1, data_hid = -1, size_hid = -1;
+  hid_t space_hid, data_hid, size_hid;
+  space_hid = data_hid = size_hid = -1;
 
 #if HAVE_HDF5_18
   data_hid = H5Gcreate (loc_id, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
--- a/libinterp/octave-value/ov-cell.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-cell.h	Mon Jan 12 09:17:35 2015 -0800
@@ -147,7 +147,7 @@
 
   bool print_as_scalar (void) const;
 
-  void print (std::ostream& os, bool pr_as_read_syntax = false) const;
+  void print (std::ostream& os, bool pr_as_read_syntax = false);
 
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
 
--- a/libinterp/octave-value/ov-ch-mat.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-ch-mat.h	Mon Jan 12 09:17:35 2015 -0800
@@ -107,10 +107,10 @@
   { return float_value (frc_str_conv); }
 
   Matrix matrix_value (bool = false) const
-  { return Matrix (matrix.matrix_value ()); }
+  { return Matrix (charMatrix (matrix)); }
 
   FloatMatrix float_matrix_value (bool = false) const
-  { return FloatMatrix (matrix.matrix_value ()); }
+  { return FloatMatrix (charMatrix (matrix)); }
 
   NDArray array_value (bool = false) const
   { return NDArray (matrix); }
@@ -123,10 +123,10 @@
   FloatComplex float_complex_value (bool = false) const;
 
   ComplexMatrix complex_matrix_value (bool = false) const
-  { return ComplexMatrix (matrix.matrix_value ()); }
+  { return ComplexMatrix (charMatrix (matrix)); }
 
   FloatComplexMatrix float_complex_matrix_value (bool = false) const
-  { return FloatComplexMatrix (matrix.matrix_value ()); }
+  { return FloatComplexMatrix (charMatrix (matrix)); }
 
   ComplexNDArray complex_array_value (bool = false) const
   { return ComplexNDArray (matrix); }
@@ -135,7 +135,7 @@
   { return FloatComplexNDArray (matrix); }
 
   charMatrix char_matrix_value (bool = false) const
-  { return matrix.matrix_value (); }
+  { return charMatrix (matrix); }
 
   charNDArray char_array_value (bool = false) const
   { return matrix; }
--- a/libinterp/octave-value/ov-class.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-class.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -268,97 +268,6 @@
   error ("assignment to class element failed");
 }
 
-static inline octave_value_list
-sanitize (const octave_value_list& ovl)
-{
-  octave_value_list retval = ovl;
-
-  for (octave_idx_type i = 0; i < ovl.length (); i++)
-    {
-      if (retval(i).is_magic_colon ())
-        retval(i) = ":";
-    }
-
-  return retval;
-}
-
-static inline octave_value
-make_idx_args (const std::string& type,
-               const std::list<octave_value_list>& idx,
-               const std::string& who)
-{
-  octave_value retval;
-
-  size_t len = type.length ();
-
-  if (len == idx.size ())
-    {
-      Cell type_field (1, len);
-      Cell subs_field (1, len);
-
-      std::list<octave_value_list>::const_iterator p = idx.begin ();
-
-      for (size_t i = 0; i < len; i++)
-        {
-          char t = type[i];
-
-          switch (t)
-            {
-            case '(':
-              type_field(i) = "()";
-              subs_field(i) = Cell (sanitize (*p++));
-              break;
-
-            case '{':
-              type_field(i) = "{}";
-              subs_field(i) = Cell (sanitize (*p++));
-              break;
-
-            case '.':
-              {
-                type_field(i) = ".";
-
-                octave_value_list vlist = *p++;
-
-                if (vlist.length () == 1)
-                  {
-                    octave_value val = vlist(0);
-
-                    if (val.is_string ())
-                      subs_field(i) = val;
-                    else
-                      {
-                        error ("expecting character string argument for '.' index");
-                        return retval;
-                      }
-                  }
-                else
-                  {
-                    error ("expecting single argument for '.' index");
-                    return retval;
-                  }
-              }
-              break;
-
-            default:
-              panic_impossible ();
-              break;
-            }
-        }
-
-      octave_map m;
-
-      m.assign ("type", type_field);
-      m.assign ("subs", subs_field);
-
-      retval = m;
-    }
-  else
-    error ("invalid index for %s", who.c_str ());
-
-  return retval;
-}
-
 Cell
 octave_class::dotref (const octave_value_list& idx)
 {
@@ -398,20 +307,6 @@
   return retval;
 }
 
-static bool
-called_from_builtin (void)
-{
-  octave_function *fcn = octave_call_stack::caller ();
-
-  // FIXME: we probably need a better check here, or some other
-  // mechanism to avoid overloaded functions when builtin is used.
-  // For example, what if someone overloads the builtin function?
-  // Also, are there other places where using builtin is not properly
-  // avoiding dispatch?
-
-  return (fcn && fcn->name () == "builtin");
-}
-
 Matrix
 octave_class::size (void)
 {
@@ -1120,6 +1015,35 @@
   return retval;
 }
 
+bool
+octave_class::is_instance_of (const std::string& cls_name) const
+{
+  bool retval = false;
+
+  if (cls_name == class_name ())
+    retval = true;
+  else
+    {
+      for (std::list<std::string>::const_iterator pit = parent_list.begin ();
+           pit != parent_list.end ();
+           pit++)
+        {
+          octave_map::const_iterator smap = map.seek (*pit);
+
+          const Cell& tmp = map.contents (smap);
+
+          const octave_value& vtmp = tmp(0);
+
+          retval = vtmp.is_instance_of (cls_name);
+
+          if (retval)
+            break;
+        }
+    }
+
+  return retval;
+}
+
 string_vector
 octave_class::all_strings (bool pad) const
 {
@@ -1139,7 +1063,7 @@
           if (tmp(0).is_string ())
             retval = tmp(0).all_strings (pad);
           else
-            error ("cname/char method did not return a character string");
+            error ("cname/char method did not return a string");
         }
     }
   else
@@ -1150,7 +1074,7 @@
 
 
 void
-octave_class::print (std::ostream& os, bool) const
+octave_class::print (std::ostream& os, bool)
 {
   print_raw (os);
 }
@@ -1279,7 +1203,8 @@
 bool
 octave_class::reconstruct_parents (void)
 {
-  bool retval = true, might_have_inheritance = false;
+  bool retval = true;
+  bool might_have_inheritance = false;
   std::string dbgstr = "dork";
 
   // First, check to see if there might be an issue with inheritance.
@@ -1287,10 +1212,10 @@
     {
       std::string  key = map.key (p);
       Cell         val = map.contents (p);
-      if ( val(0).is_object () )
+      if (val(0).is_object ())
         {
           dbgstr = "blork";
-          if ( key == val(0).class_name () )
+          if (key == val(0).class_name ())
             {
               might_have_inheritance = true;
               dbgstr = "cork";
@@ -1429,7 +1354,7 @@
                   success = false;
                 }
             }
-          else if (len == 0 )
+          else if (len == 0)
             {
               map = octave_map (dim_vector (1, 1));
               c_name = classname;
@@ -1573,7 +1498,7 @@
           success = false;
         }
     }
-  else if (len == 0 )
+  else if (len == 0)
     map = octave_map (dim_vector (1, 1));
   else
     panic_impossible ();
@@ -1950,10 +1875,10 @@
       // Called as class constructor
       octave_function *fcn = octave_call_stack::caller ();
 
-      std::string id = args(1).string_value ();
+      if (args(1).is_string ())
+        {
+          std::string id = args(1).string_value ();
 
-      if (! error_state)
-        {
           if (fcn)
             {
               if (fcn->is_class_constructor (id) || fcn->is_class_method (id))
@@ -1998,7 +1923,7 @@
             error ("class: invalid call from outside class constructor or method");
         }
       else
-        error ("class: ID (class name) must be a character string");
+        error ("class: ID (class name) must be a string");
     }
 
   return retval;
@@ -2054,7 +1979,7 @@
   const Array<std::string> cls = args(1).cellstr_value ();
   if (error_state)
     {
-      error ("isa: CLASSNAME must be a string or cell attay of strings");
+      error ("isa: CLASSNAME must be a string or cell array of strings");
       return retval;
     }
 
@@ -2066,7 +1991,7 @@
       if ((cl == "float"   && obj.is_float_type   ()) ||
           (cl == "integer" && obj.is_integer_type ()) ||
           (cl == "numeric" && obj.is_numeric_type ()) ||
-          obj.class_name () == cl || obj.find_parent_class (cl))
+          obj.class_name () == cl || obj.is_instance_of (cl))
         matches(idx) = true;
     }
   return octave_value (matches);
@@ -2148,7 +2073,7 @@
        "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} isobject (@var{x})\n\
 Return true if @var{x} is a class object.\n\
-@seealso{class, typeinfo, isa, ismethod}\n\
+@seealso{class, typeinfo, isa, ismethod, isprop}\n\
 @end deftypefn")
 {
   octave_value retval;
@@ -2163,8 +2088,8 @@
 
 DEFUN (ismethod, args, ,
        "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {} ismethod (@var{x}, @var{method})\n\
-Return true if @var{x} is a class object and the string @var{method}\n\
+@deftypefn {Built-in Function} {} ismethod (@var{obj}, @var{method})\n\
+Return true if @var{obj} is a class object and the string @var{method}\n\
 is a method of this class.\n\
 @seealso{isprop, isobject}\n\
 @end deftypefn")
--- a/libinterp/octave-value/ov-class.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-class.h	Mon Jan 12 09:17:35 2015 -0800
@@ -167,9 +167,11 @@
 
   octave_base_value *unique_parent_class (const std::string&);
 
+  bool is_instance_of (const std::string&) const;
+
   string_vector all_strings (bool pad) const;
 
-  void print (std::ostream& os, bool pr_as_read_syntax = false) const;
+  void print (std::ostream& os, bool pr_as_read_syntax = false);
 
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/octave-value/ov-classdef.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,4052 @@
+/*
+
+Copyright (C) 2012-2013 Michael Goffioul
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <algorithm>
+
+#include "defun.h"
+#include "load-path.h"
+#include "ov-builtin.h"
+#include "ov-classdef.h"
+#include "ov-fcn-handle.h"
+#include "ov-typeinfo.h"
+#include "ov-usr-fcn.h"
+#include "pt-assign.h"
+#include "pt-classdef.h"
+#include "pt-funcall.h"
+#include "pt-misc.h"
+#include "pt-stmt.h"
+#include "pt-walk.h"
+#include "singleton-cleanup.h"
+#include "symtab.h"
+#include "toplev.h"
+
+#include "Array.cc"
+
+// Define to 1 to enable debugging statements.
+#define DEBUG_TRACE 0
+
+static void
+gripe_method_access (const std::string& from, const cdef_method& meth)
+{
+  octave_value acc = meth.get ("Access");
+  std::string acc_s;
+
+  if (acc.is_string ())
+    acc_s = acc.string_value ();
+  else
+    acc_s = "class-restricted";
+
+  error ("%s: method `%s' has %s access and cannot be run in this context",
+         from.c_str (), meth.get_name ().c_str (), acc_s.c_str ());
+}
+
+static void
+gripe_property_access (const std::string& from, const cdef_property& prop,
+                       bool is_set = false)
+{
+  octave_value acc = prop.get (is_set ? "SetAccess" : "GetAccess");
+  std::string acc_s;
+
+  if (acc.is_string ())
+    acc_s = acc.string_value ();
+  else
+    acc_s = "class-restricted";
+
+  if (is_set)
+    error ("%s: property `%s' has %s access and cannot be set in this context",
+           from.c_str (), prop.get_name ().c_str (), acc_s.c_str ());
+  else
+    error ("%s: property `%s' has %s access and cannot be obtained in this context",
+           from.c_str (), prop.get_name ().c_str (), acc_s.c_str ());
+}
+
+static std::string
+get_base_name (const std::string& nm)
+{
+  std::string::size_type pos = nm.find_last_of ('.');
+
+  if (pos != std::string::npos)
+    return nm.substr (pos + 1);
+
+  return nm;
+}
+
+static void
+make_function_of_class (const std::string& class_name,
+                        const octave_value& fcn)
+{
+  octave_function *of = fcn.function_value ();
+
+  if (! error_state)
+    {
+      of->stash_dispatch_class (class_name);
+
+      octave_user_function *uf = of->user_function_value (true);
+
+      if (! error_state && uf)
+        {
+          if (get_base_name (class_name) == uf->name ())
+            {
+              uf->mark_as_class_constructor ();
+              uf->mark_as_classdef_constructor ();
+            }
+          else
+            uf->mark_as_class_method ();
+        }
+    }
+}
+
+static void
+make_function_of_class (const cdef_class& cls, const octave_value& fcn)
+{
+  make_function_of_class (cls.get_name (), fcn);
+}
+
+static octave_value
+make_fcn_handle (octave_builtin::fcn ff, const std::string& nm)
+{
+  octave_value fcn (new octave_builtin (ff, nm));
+
+  octave_value fcn_handle (new octave_fcn_handle (fcn, nm));
+
+  return fcn_handle;
+}
+
+static octave_value
+make_fcn_handle (const octave_value& fcn, const std::string& nm)
+{
+  octave_value retval;
+
+  if (fcn.is_defined ())
+    retval = octave_value (new octave_fcn_handle (fcn, nm));
+
+  return retval;
+}
+
+inline octave_value_list
+execute_ov (octave_value val, const octave_value_list& args, int nargout)
+{
+  std::list<octave_value_list> idx (1, args);
+
+  std::string type ("(");
+
+  return val.subsref (type, idx, nargout);
+}
+
+static cdef_class
+lookup_class (const std::string& name, bool error_if_not_found = true,
+              bool load_if_not_found = true)
+{
+  return cdef_manager::find_class (name, error_if_not_found,
+                                   load_if_not_found);
+}
+
+static cdef_class
+lookup_class (const cdef_class& cls)
+{
+  // FIXME: placeholder for the time being, the purpose
+  //        is to centralized any class update activity here.
+
+  return cls;
+}
+
+static cdef_class
+lookup_class (const octave_value& ov)
+{
+  if (ov.is_string())
+    return lookup_class (ov.string_value ());
+  else
+    {
+      cdef_class cls (to_cdef (ov));
+
+      if (! error_state)
+        return lookup_class (cls);
+    }
+
+  return cdef_class ();
+}
+
+static std::list<cdef_class>
+lookup_classes (const Cell& cls_list)
+{
+  std::list<cdef_class> retval;
+
+  for (int i = 0; i < cls_list.numel (); i++)
+    {
+      cdef_class c = lookup_class (cls_list(i));
+
+      if (! error_state)
+        retval.push_back (c);
+      else
+        {
+          retval.clear ();
+          break;
+        }
+    }
+
+  return retval;
+}
+
+static octave_value
+to_ov (const std::list<cdef_class>& class_list)
+{
+  Cell cls (class_list.size (), 1);
+  int i = 0;
+
+  for (std::list<cdef_class>::const_iterator it = class_list.begin ();
+       it != class_list.end (); ++it, ++i)
+    cls(i) = to_ov (*it);
+
+  return octave_value (cls);
+}
+
+static bool
+is_superclass (const cdef_class& clsa, const cdef_class& clsb,
+               bool allow_equal = true, int max_depth = -1)
+{
+  bool retval = false;
+
+  if (allow_equal && clsa == clsb)
+    retval = true;
+  else if (max_depth != 0)
+    {
+      Cell c = clsb.get ("SuperClasses").cell_value ();
+
+      for (int i = 0; ! error_state && ! retval && i < c.numel (); i++)
+        {
+          cdef_class cls = lookup_class (c(i));
+
+          if (! error_state)
+            retval = is_superclass (clsa, cls, true,
+                                    max_depth < 0 ? max_depth : max_depth-1);
+        }
+    }
+
+  return retval;
+}
+
+inline bool
+is_strict_superclass (const cdef_class& clsa, const cdef_class& clsb)
+{ return is_superclass (clsa, clsb, false); }
+
+inline bool
+is_direct_superclass (const cdef_class& clsa, const cdef_class& clsb)
+{ return is_superclass (clsa, clsb, false, 1); }
+
+static octave_value_list
+class_get_properties (const octave_value_list& args, int /* nargout */)
+{
+  octave_value_list retval;
+
+  if (args.length () == 1 && args(0).type_name () == "object")
+    {
+      cdef_class cls (to_cdef (args(0)));
+
+      retval(0) = cls.get_properties ();
+    }
+
+  return retval;
+}
+
+static cdef_class
+get_class_context (std::string& name, bool& in_constructor)
+{
+  cdef_class cls;
+
+  octave_function* fcn = octave_call_stack::current ();
+
+  in_constructor = false;
+
+  if (fcn &&
+      (fcn->is_class_method ()
+       || fcn->is_classdef_constructor ()
+       || fcn->is_anonymous_function_of_class ()
+       || (fcn->is_private_function ()
+           && ! fcn->dispatch_class ().empty ())))
+    {
+      cls = lookup_class (fcn->dispatch_class ());
+      if (! error_state)
+        {
+          name = fcn->name ();
+          in_constructor = fcn->is_classdef_constructor ();
+        }
+    }
+
+  return cls;
+}
+
+inline cdef_class
+get_class_context (void)
+{
+  std::string dummy_string;
+  bool dummy_bool;
+
+  return get_class_context (dummy_string, dummy_bool);
+}
+
+static bool
+in_class_method (const cdef_class& cls)
+{
+  cdef_class ctx = get_class_context ();
+
+  return (ctx.ok () && is_superclass (ctx, cls));
+}
+
+static bool
+check_access (const cdef_class& cls, const octave_value& acc,
+              const std::string& meth_name = std::string (),
+              const std::string& prop_name = std::string (),
+              bool is_prop_set = false)
+{
+  if (acc.is_string ())
+    {
+      std::string acc_s = acc.string_value ();
+
+      if (acc_s == "public")
+        return true;
+
+      cdef_class ctx = get_class_context ();
+
+      // The access is private or protected, this requires a
+      // valid class context.
+
+      if (! error_state && ctx.ok ())
+        {
+          if (acc_s == "private")
+            return (ctx == cls);
+          else if (acc_s == "protected")
+            {
+              if (is_superclass (cls, ctx))
+                // Calling a protected method in a superclass.
+                return true;
+              else if (is_strict_superclass (ctx, cls))
+                {
+                  // Calling a protected method or property in a derived class.
+                  // This is only allowed if the context class knows about it
+                  // and has access to it.
+
+                  if (! meth_name.empty ())
+                    {
+                      cdef_method m = ctx.find_method (meth_name);
+
+                      if (m.ok ())
+                        return check_access (ctx, m.get ("Access"), meth_name);
+
+                      return false;
+                    }
+                  else if (! prop_name.empty ())
+                    {
+                      cdef_property p = ctx.find_property (prop_name);
+
+                      if (p.ok ())
+                        {
+                          octave_value p_access = p.get (is_prop_set ?
+                                                         "SetAccess" :
+                                                         "GetAccess");
+
+                          return check_access (ctx, p_access, meth_name,
+                                               prop_name, is_prop_set);
+                        }
+
+                      return false;
+                    }
+                  else
+                    panic_impossible ();
+                }
+
+              return false;
+            }
+          else
+            panic_impossible ();
+        }
+    }
+  else if (acc.is_cell ())
+    {
+      Cell acc_c = acc.cell_value ();
+
+      cdef_class ctx = get_class_context ();
+
+      // At this point, a class context is always required.
+
+      if (! error_state && ctx.ok ())
+        {
+          if (ctx == cls)
+            return true;
+
+          for (int i = 0; ! error_state && i < acc.numel (); i++)
+            {
+              cdef_class acc_cls (to_cdef (acc_c(i)));
+
+              if (! error_state)
+                {
+                  if (is_superclass (acc_cls, ctx))
+                    return true;
+                }
+            }
+        }
+    }
+  else
+    error ("invalid property/method access in class `%s'",
+           cls.get_name ().c_str ());
+  
+  return false;
+}
+
+static bool
+is_dummy_method (const octave_value& fcn)
+{
+  bool retval = false;
+
+  if (fcn.is_defined ())
+    {
+      if (fcn.is_user_function ())
+        {
+          octave_user_function *uf = fcn.user_function_value (true);
+
+          if (! uf || ! uf->body ())
+            retval = true;
+        }
+    }
+  else
+    retval = true;
+
+  return retval;
+}
+
+bool
+is_method_executing (const octave_value& ov, const cdef_object& obj)
+{
+  octave_function* stack_fcn = octave_call_stack::current ();
+
+  octave_function* method_fcn = ov.function_value (true);
+
+  // Does the top of the call stack match our target function?
+
+  if (stack_fcn && stack_fcn == method_fcn)
+    {
+      octave_user_function* uf = method_fcn->user_function_value (true);
+
+      // We can only check the context object for user-function (not builtin),
+      // where we have access to the parameters (arguments and return values).
+      // That's ok as there's no need to call this function for builtin
+      // methods.
+
+      if (uf)
+        {
+          // At this point, the method is executing, but we still need to
+          // check the context object for which the method is executing. For
+          // methods, it's the first argument of the function; for ctors, it
+          // is the first return value.
+
+          tree_parameter_list* pl = uf->is_classdef_constructor ()
+            ? uf->return_list () : uf->parameter_list ();
+
+          if (pl && pl->size () > 0)
+            {
+              octave_value arg0 = pl->front ()->lvalue ().value ();
+
+              if (arg0.is_defined () && arg0.type_name () == "object")
+                {
+                  cdef_object arg0_obj = to_cdef (arg0);
+
+                  return obj.is (arg0_obj);
+                }
+            }
+        }
+    }
+
+  return false;
+}
+
+static octave_value_list
+class_get_methods (const octave_value_list& args, int /* nargout */)
+{
+  octave_value_list retval;
+
+  if (args.length () == 1 && args(0).type_name () == "object")
+    {
+      cdef_class cls (to_cdef (args(0)));
+
+      retval(0) = cls.get_methods ();
+    }
+
+  return retval;
+}
+
+static octave_value_list
+class_get_superclasses (const octave_value_list& args, int /* nargout */)
+{
+  octave_value_list retval;
+
+  if (args.length () == 1 && args(0).type_name () == "object"
+      && args(0).class_name () == "meta.class")
+    {
+      cdef_class cls (to_cdef (args(0)));
+
+      Cell classes = cls.get ("SuperClasses").cell_value ();
+
+      retval(0) = to_ov (lookup_classes (classes));
+    }
+
+  return retval;
+}
+
+static octave_value_list
+class_get_inferiorclasses (const octave_value_list& args, int /* nargout */)
+{
+  octave_value_list retval;
+
+  if (args.length () == 1 && args(0).type_name () == "object"
+      && args(0).class_name () == "meta.class")
+    {
+      cdef_class cls (to_cdef (args(0)));
+
+      Cell classes = cls.get ("InferiorClasses").cell_value ();
+
+      retval(0) = to_ov (lookup_classes (classes));
+    }
+
+  return retval;
+}
+
+static octave_value_list
+class_fromName (const octave_value_list& args, int /* nargout */)
+{
+  octave_value_list retval;
+
+  if (args.length () == 1)
+    {
+      std::string name = args(0).string_value ();
+
+      if (! error_state)
+        retval(0) = to_ov (lookup_class (name));
+      else
+        error ("fromName: invalid class name, expected a string value");
+    }
+  else
+    error ("fromName: invalid number of parameters");
+
+  return retval;
+}
+
+static octave_value_list
+class_fevalStatic (const octave_value_list& args, int nargout)
+{
+  octave_value_list retval;
+
+  if (args.length () > 1 && args(0).type_name () == "object")
+    {
+      cdef_class cls (to_cdef (args(0)));
+
+      if (! error_state)
+        {
+          std::string meth_name = args(1).string_value ();
+
+          if (! error_state)
+            {
+              cdef_method meth = cls.find_method (meth_name);
+
+              if (meth.ok ())
+                {
+                    if (meth.is_static ())
+                      retval = meth.execute (args.splice (0, 2), nargout,
+                                             true, "fevalStatic");
+                    else
+                      error ("fevalStatic: method `%s' is not static",
+                             meth_name.c_str ());
+                }
+              else
+                error ("fevalStatic: method not found: %s",
+                       meth_name.c_str ());
+            }
+          else
+            error ("fevalStatic: invalid method name, expected a string value");
+        }
+      error ("fevalStatic: invalid object, expected a meta.class object");
+    }
+  else
+    error ("fevalStatic: invalid arguments");
+
+  return retval;
+}
+
+static octave_value_list
+class_getConstant (const octave_value_list& args, int /* nargout */)
+{
+  octave_value_list retval;
+
+  if (args.length () == 2 && args(0).type_name () == "object"
+      && args(0).class_name () == "meta.class")
+    {
+      cdef_class cls = to_cdef (args(0));
+
+      if (! error_state)
+        {
+          std::string prop_name = args(1).string_value ();
+
+          if (! error_state)
+            {
+              cdef_property prop = cls.find_property (prop_name);
+
+              if (prop.ok ())
+                {
+                  if (prop.is_constant ())
+                    retval(0) = prop.get_value (true, "getConstant");
+                  else
+                    error ("getConstant: property `%s' is not constant",
+                           prop_name.c_str ());
+                }
+              else
+                error ("getConstant: property not found: %s",
+                       prop_name.c_str ());
+            }
+          else
+            error ("getConstant: invalid property name, expected a string value");
+        }
+      else
+        error ("getConstant: invalid object, expected a meta.class object");
+    }
+  else
+    error ("getConstant: invalid arguments");
+
+  return retval;
+}
+
+#define META_CLASS_CMP(OP, CLSA, CLSB, FUN) \
+static octave_value_list \
+class_ ## OP (const octave_value_list& args, int /* nargout */) \
+{ \
+  octave_value_list retval; \
+\
+  if (args.length () == 2 \
+      && args(0).type_name () == "object" && args(1).type_name () == "object" \
+      && args(0).class_name () == "meta.class" && args(1).class_name () == "meta.class") \
+    { \
+      cdef_class clsa = to_cdef (args(0)); \
+\
+      cdef_class clsb = to_cdef (args(1)); \
+\
+      if (! error_state) \
+        retval(0) = FUN (CLSA, CLSB); \
+      else \
+        error (#OP ": invalid objects, expected meta.class objects"); \
+    } \
+  else \
+    error (#OP ": invalid arguments"); \
+\
+  return retval; \
+}
+
+META_CLASS_CMP (lt, clsb, clsa, is_strict_superclass)
+META_CLASS_CMP (le, clsb, clsa, is_superclass)
+META_CLASS_CMP (gt, clsa, clsb, is_strict_superclass)
+META_CLASS_CMP (ge, clsa, clsb, is_superclass)
+META_CLASS_CMP (eq, clsa, clsb, operator==)
+META_CLASS_CMP (ne, clsa, clsb, operator!=)
+
+octave_value_list
+property_get_defaultvalue (const octave_value_list& args, int /* nargout */)
+{
+  octave_value_list retval;
+
+  if (args.length () == 1 && args(0).type_name () == "object")
+    {
+      cdef_property prop (to_cdef (args(0)));
+
+      retval(0) = prop.get ("DefaultValue");
+
+      if (! retval(0).is_defined ())
+        error_with_id ("Octave:class:NotDefaultDefined",
+                       "no default value for property `%s'",
+                       prop.get_name ().c_str ());
+    }
+
+  return retval;
+}
+
+static octave_value_list
+handle_delete (const octave_value_list& /* args */, int /* nargout */)
+{
+  octave_value_list retval;
+
+  // FIXME: implement this
+
+  return retval;
+}
+
+static cdef_class
+make_class (const std::string& name,
+            const std::list<cdef_class>& super_list = std::list<cdef_class> ())
+{
+  cdef_class cls (name, super_list);
+
+  cls.set_class (cdef_class::meta_class ());
+  cls.put ("Abstract", false);
+  cls.put ("ConstructOnLoad", false);
+  cls.put ("ContainingPackage", Matrix ());
+  cls.put ("Description", std::string ());
+  cls.put ("DetailedDescription", std::string ());
+  cls.put ("Events", Cell ());
+  cls.put ("Hidden", false);
+  cls.put ("InferiorClasses", Cell ());
+  cls.put ("Methods", Cell ());
+  cls.put ("Properties", Cell ());
+  cls.put ("Sealed", false);
+
+  if (name == "handle")
+    {
+      cls.put ("HandleCompatible", true);
+      cls.mark_as_handle_class ();
+    }
+  else if (super_list.empty ())
+    {
+      cls.put ("HandleCompatible", false);
+    }
+  else
+    {
+      bool all_handle_compatible = true;
+      bool has_handle_class = false;
+
+      for (std::list<cdef_class>::const_iterator it = super_list.begin ();
+           it != super_list.end (); ++it)
+        {
+          all_handle_compatible = all_handle_compatible && it->get ("HandleCompatible").bool_value ();
+          has_handle_class = has_handle_class || it->is_handle_class ();
+        }
+
+      if (has_handle_class && ! all_handle_compatible)
+        ::error ("%s: cannot mix handle and non-HandleCompatible classes",
+                 name.c_str ());
+      else
+        {
+          cls.put ("HandleCompatible", all_handle_compatible);
+          if (has_handle_class)
+            cls.mark_as_handle_class ();
+        }
+    }
+
+  if (error_state)
+    return cdef_class ();
+
+  if (! name.empty ())
+    cdef_manager::register_class (cls);
+
+  return cls;
+}
+
+static cdef_class
+make_class (const std::string& name, const cdef_class& super)
+{
+  return make_class (name, std::list<cdef_class> (1, super));
+}
+
+static cdef_class
+make_meta_class (const std::string& name, const cdef_class& super)
+{
+  cdef_class cls = make_class (name, super);
+
+  cls.put ("Sealed", true);
+  cls.mark_as_meta_class ();
+
+  return cls;
+}
+
+static cdef_property
+make_property (const cdef_class& cls, const std::string& name,
+               const octave_value& get_method = Matrix (),
+               const std::string& get_access = "public",
+               const octave_value& set_method = Matrix (),
+               const std::string& set_access = "public")
+{
+  cdef_property prop (name);
+
+  prop.set_class (cdef_class::meta_property ());
+  prop.put ("Description", std::string ());
+  prop.put ("DetailedDescription", std::string ());
+  prop.put ("Abstract", false);
+  prop.put ("Constant", false);
+  prop.put ("GetAccess", get_access);
+  prop.put ("SetAccess", set_access);
+  prop.put ("Dependent", false);
+  prop.put ("Transient", false);
+  prop.put ("Hidden", false);
+  prop.put ("GetObservable", false);
+  prop.put ("SetObservable", false);
+  prop.put ("GetMethod", get_method);
+  prop.put ("SetMethod", set_method);
+  prop.put ("DefiningClass", to_ov (cls));
+  prop.put ("DefaultValue", octave_value ());
+  prop.put ("HasDefault", false);
+
+  std::string class_name = cls.get_name ();
+
+  if (! get_method.is_empty ())
+    make_function_of_class (class_name, get_method);
+  if (! set_method.is_empty ())
+    make_function_of_class (class_name, set_method);
+
+  return prop;
+}
+
+inline cdef_property
+make_attribute (const cdef_class& cls, const std::string& name)
+{
+  return make_property (cls, name, Matrix (), "public", Matrix (), "private");
+}
+
+static cdef_method
+make_method (const cdef_class& cls, const std::string& name,
+             const octave_value& fcn,const std::string& m_access = "public",
+             bool is_static = false)
+{
+  cdef_method meth (name);
+
+  meth.set_class (cdef_class::meta_method ());
+  meth.put ("Abstract", false);
+  meth.put ("Access", m_access);
+  meth.put ("DefiningClass", to_ov (cls));
+  meth.put ("Description", std::string ());
+  meth.put ("DetailedDescription", std::string ());
+  meth.put ("Hidden", false);
+  meth.put ("Sealed", true);
+  meth.put ("Static", is_static);
+
+  if (fcn.is_defined ())
+    make_function_of_class (cls, fcn);
+
+  meth.set_function (fcn);
+
+  if (is_dummy_method (fcn))
+    meth.mark_as_external (cls.get_name ());
+
+  return meth;
+}
+
+inline cdef_method
+make_method (const cdef_class& cls, const std::string& name,
+             octave_builtin::fcn ff, const std::string& m_access = "public",
+             bool is_static = false)
+{
+  octave_value fcn (new octave_builtin (ff, name));
+
+  return make_method (cls, name, fcn, m_access, is_static);
+}
+
+static cdef_package
+make_package (const std::string& nm,
+              const std::string& parent = std::string ())
+{
+  cdef_package pack (nm);
+
+  pack.set_class (cdef_class::meta_package ());
+  if (parent.empty ())
+    pack.put ("ContainingPackage", Matrix ());
+  else
+    pack.put ("ContainingPackage", to_ov (cdef_manager::find_package (parent)));
+
+  if (! nm.empty ())
+    cdef_manager::register_package (pack);
+
+  return pack;
+}
+
+//----------------------------------------------------------------------------
+
+DEFINE_OCTAVE_ALLOCATOR (octave_classdef);
+
+int octave_classdef::t_id (-1);
+
+const std::string octave_classdef::t_name ("object");
+
+void
+octave_classdef::register_type (void)
+{
+  t_id = octave_value_typeinfo::register_type
+    (octave_classdef::t_name, "<unknown>", octave_value (new octave_classdef ()));
+}
+
+octave_value_list
+octave_classdef::subsref (const std::string& type,
+                          const std::list<octave_value_list>& idx,
+                          int nargout)
+{
+  size_t skip = 0;
+  octave_value_list retval;
+
+  cdef_class cls = object.get_class ();
+
+  if (! in_class_method (cls) && ! called_from_builtin ())
+    {
+      cdef_method meth = cls.find_method ("subsref");
+
+      if (meth.ok ())
+        {
+          octave_value_list args;
+
+          args(1) = make_idx_args (type, idx, "subsref");
+
+          if (! error_state)
+            {
+              count++;
+              args(0) = octave_value (this);
+
+              retval = meth.execute (args, nargout, true, "subsref");
+            }
+
+          return retval;
+        }
+    }
+
+  // At this point, the default subsref mechanism must be used.
+
+  retval = object.subsref (type, idx, nargout, skip, cdef_class ());
+
+  if (! error_state)
+    {
+      if (type.length () > skip && idx.size () > skip)
+        retval = retval(0).next_subsref (nargout, type, idx, skip);
+    }
+
+  return retval;
+}
+
+octave_value
+octave_classdef::subsref (const std::string& type,
+                          const std::list<octave_value_list>& idx,
+                          bool auto_add)
+{
+  size_t skip = 0;
+  octave_value_list retval;
+
+  // This variant of subsref is used to create temporary values when doing
+  // assignment with multi-level indexing. AFAIK this is only used for internal
+  // purpose (not sure we should even implement this) and any overload subsref
+  // should not be called.
+
+  retval = object.subsref (type, idx, 1, skip, cdef_class (), auto_add);
+
+  if (! error_state)
+    {
+      if (type.length () > skip && idx.size () > skip)
+        retval = retval(0).next_subsref (1, type, idx, skip);
+    }
+
+  return retval.length () > 0 ? retval(0) : octave_value ();
+}
+
+octave_value
+octave_classdef::subsasgn (const std::string& type,
+                           const std::list<octave_value_list>& idx,
+                           const octave_value& rhs)
+{
+  octave_value retval;
+
+  cdef_class cls = object.get_class ();
+
+  if (! in_class_method (cls) && ! called_from_builtin ())
+    {
+      cdef_method meth = cls.find_method ("subsasgn");
+
+      if (meth.ok ())
+        {
+          octave_value_list args;
+
+          args(1) = make_idx_args (type, idx, "subsasgn");
+
+          if (! error_state)
+            {
+              count++;
+              args(0) = octave_value (this);
+              args(2) = rhs;
+
+              octave_value_list retlist;
+
+              retlist = meth.execute (args, 1, true, "subsasgn");
+
+              if (! error_state)
+                {
+                  if (retlist.length () > 0)
+                    retval = retlist(0);
+                  else
+                    ::error ("overloaded method `subsasgn' did not return any value");
+                }
+            }
+        }
+    }
+
+  if (! error_state && ! retval.is_defined ())
+    retval = object.subsasgn (type, idx, rhs);
+
+  return retval;
+}
+
+octave_value
+octave_classdef::undef_subsasgn (const std::string& type,
+                                 const std::list<octave_value_list>& idx,
+                                 const octave_value& rhs)
+{
+  if (type.length () == 1 && type[0] == '(')
+    {
+      object = object.make_array ();
+
+      if (! error_state)
+        return subsasgn (type, idx, rhs);
+    }
+  else
+    return octave_base_value::undef_subsasgn (type, idx, rhs);
+
+  return octave_value ();
+}
+
+void
+octave_classdef::print (std::ostream& os, bool)
+{
+  if (! called_from_builtin ())
+    {
+      cdef_method meth = object.get_class ().find_method ("disp");
+
+      if (meth.ok ())
+        {
+          octave_value_list args;
+
+          count++;
+          args(0) = octave_value (this);
+
+          indent (os);
+          meth.execute (args, 0, true, "disp");
+
+          return;
+        }
+    }
+
+  print_raw (os);
+}
+
+void
+octave_classdef::print_raw (std::ostream& os, bool) const
+{
+  indent (os);
+  os << "<object ";
+  if (object.is_array ())
+    os << "array ";
+  os << class_name () << ">";
+  newline (os);
+}
+
+bool
+octave_classdef::print_name_tag (std::ostream& os,
+                                 const std::string& name) const
+{
+  return octave_base_value::print_name_tag (os, name);
+}
+
+void
+octave_classdef::print_with_name (std::ostream& os, const std::string& name,
+                                  bool print_padding)
+{
+  cdef_method meth = object.get_class ().find_method ("display");
+
+  if (meth.ok ())
+    {
+      octave_value_list args;
+
+      count++;
+      args(0) = octave_value (this);
+
+      string_vector arg_names (1);
+
+      arg_names[0] = name;
+      args.stash_name_tags (arg_names);
+
+      indent (os);
+      meth.execute (args, 0, true, "display");
+    }
+  else
+    octave_base_value::print_with_name (os, name, print_padding);
+}
+
+bool
+octave_classdef::is_instance_of (const std::string& cls_name) const
+{
+  cdef_class cls = lookup_class (cls_name, false, false);
+
+  if (cls.ok ())
+    return is_superclass (cls, object.get_class ());
+
+  return false;
+}
+
+//----------------------------------------------------------------------------
+
+class octave_classdef_meta : public octave_function
+{
+public:
+  octave_classdef_meta (const cdef_meta_object& obj)
+    : object (obj) { }
+
+  ~octave_classdef_meta (void)
+    { object.meta_release (); }
+
+  octave_function* function_value (bool = false) { return this; }
+
+  octave_value_list
+  subsref (const std::string& type,
+           const std::list<octave_value_list>& idx,
+           int nargout)
+    { return object.meta_subsref (type, idx, nargout); }
+
+  octave_value
+  subsref (const std::string& type,
+           const std::list<octave_value_list>& idx)
+    {
+      octave_value_list retval;
+
+      retval = subsref (type, idx, 1);
+
+      return (retval.length () > 0 ? retval(0) : octave_value ());
+    }
+
+  octave_value_list
+  do_multi_index_op (int nargout, const octave_value_list& idx)
+    {
+      // Emulate ()-type meta subsref
+
+      std::list<octave_value_list> l (1, idx);
+      std::string type ("(");
+
+      return subsref (type, l, nargout);
+    }
+
+  bool is_postfix_index_handled (char type) const
+    { return object.meta_is_postfix_index_handled (type); }
+
+  bool
+  is_classdef_constructor (const std::string& cname = std::string ()) const
+    {
+      bool retval = false;
+
+      if (object.is_class ())
+        {
+          if (cname.empty ())
+            retval = true;
+          else
+            {
+              cdef_class cls (object);
+
+              if (cls.get_name () == cname)
+                retval = true;
+            }
+        }
+
+      return retval;
+    }
+
+private:
+  cdef_meta_object object;
+};
+
+//----------------------------------------------------------------------------
+
+class octave_classdef_superclass_ref : public octave_function
+{
+public:
+  octave_classdef_superclass_ref (const octave_value_list& a)
+    : octave_function (), args (a) { }
+
+  ~octave_classdef_superclass_ref (void) { }
+
+  octave_function* function_value (bool = false) { return this; }
+
+  octave_value_list
+  subsref (const std::string& type,
+           const std::list<octave_value_list>& idx,
+           int nargout)
+    {
+      size_t skip = 0;
+      octave_value_list retval;
+
+      switch (type[0])
+        {
+        case '(':
+          skip = 1;
+          retval = do_multi_index_op (type.length () > 1 ? 1 : nargout,
+                                      idx.front ());
+          break;
+        default:
+          retval = do_multi_index_op (1, octave_value_list ());
+          break;
+        }
+
+      if (! error_state)
+        {
+          if (type.length () > skip && idx.size () > skip
+              && retval.length () > 0)
+            retval = retval(0).next_subsref (nargout, type, idx, skip);
+        }
+
+      return retval;
+    }
+
+  octave_value
+  subsref (const std::string& type,
+           const std::list<octave_value_list>& idx)
+    {
+      octave_value_list retval;
+
+      retval = subsref (type, idx, 1);
+
+      return (retval.length () > 0 ? retval(0) : octave_value ());
+    }
+
+  octave_value_list
+  do_multi_index_op (int nargout, const octave_value_list& idx)
+    {
+      octave_value_list retval;
+
+      std::string meth_name;
+      bool in_constructor;
+      cdef_class ctx;
+
+      ctx = get_class_context (meth_name, in_constructor);
+
+      if (! error_state && ctx.ok ())
+        {
+          std::string mname = args(0).string_value ();
+          std::string cname = args(1).string_value ();
+
+          cdef_class cls = lookup_class (cname);
+
+          if (! error_state)
+            {
+              if (in_constructor)
+                {
+                  if (is_direct_superclass (cls, ctx))
+                    {
+                      if (is_constructed_object (mname))
+                        {
+                          octave_value sym = symbol_table::varval (mname);
+
+                          cls.run_constructor (to_cdef_ref (sym), idx);
+
+                          retval(0) = sym;
+                        }
+                      else
+                        ::error ("cannot call superclass constructor with "
+                                 "variable `%s'", mname.c_str ());
+                    }
+                  else
+                    ::error ("`%s' is not a direct superclass of `%s'",
+                             cname.c_str (), ctx.get_name ().c_str ());
+                }
+              else
+                {
+                  if (mname == meth_name)
+                    {
+                      if (is_strict_superclass (cls, ctx))
+                        {
+                          // I see 2 possible implementations here:
+                          // 1) use cdef_object::subsref with a different class
+                          //    context; this avoids duplicating code, but
+                          //    assumes the object is always the first argument
+                          // 2) lookup the method manually and call
+                          //    cdef_method::execute; this duplicates part of
+                          //    logic in cdef_object::subsref, but avoid the
+                          //    assumption of 1)
+                          // Not being sure about the assumption of 1), I
+                          // go with option 2) for the time being.
+
+                          cdef_method meth = cls.find_method (meth_name, false);
+
+                          if (meth.ok ())
+                            retval = meth.execute (idx, nargout, true,
+                                                   meth_name);
+                          else
+                            ::error ("no method `%s' found in superclass `%s'",
+                                     meth_name.c_str (), cname.c_str ());
+                        }
+                      else
+                        ::error ("`%s' is not a superclass of `%s'",
+                                 cname.c_str (), ctx.get_name ().c_str ());
+                    }
+                  else
+                    ::error ("method name mismatch (`%s' != `%s')",
+                             mname.c_str (), meth_name.c_str ());
+                }
+            }
+        }
+      else if (! error_state)
+        ::error ("superclass calls can only occur in methods or constructors");
+
+      return retval;
+    }
+
+private:
+  bool is_constructed_object (const std::string nm)
+    {
+      octave_function *of = octave_call_stack::current ();
+
+      if (of->is_classdef_constructor ())
+        {
+          octave_user_function *uf = of->user_function_value (true);
+
+          if (uf)
+            {
+              tree_parameter_list *ret_list = uf->return_list ();
+
+              if (ret_list && ret_list->length () == 1)
+                return (ret_list->front ()->name () == nm);
+            }
+        }
+
+      return false;
+    }
+
+private:
+  octave_value_list args;
+};
+
+//----------------------------------------------------------------------------
+
+octave_map
+cdef_object::map_value (void) const
+{
+  octave_map retval;
+
+  warning_with_id ("Octave:classdef-to-struct",
+                   "struct: converting a classdef object into a struct "
+                   "overrides the access restrictions defined for properties. "
+                   "All properties are returned, including private and "
+                   "protected ones.");
+
+  cdef_class cls = get_class ();
+
+  if (cls.ok ())
+    {
+      std::map<std::string, cdef_property> props;
+
+      props = cls.get_property_map (cdef_class::property_all);
+
+      for (std::map<std::string, cdef_property>::iterator it = props.begin ();
+           it != props.end (); ++it)
+        {
+          octave_value pvalue;
+
+          if (is_array ())
+            {
+              Array<cdef_object> a_obj = array_value ();
+
+              Cell cvalue (a_obj.dims ());
+
+              for (octave_idx_type i = 0; i < a_obj.numel (); i++)
+                {
+                  cvalue (i) = it->second.get_value (a_obj(i), false);
+
+                  if (error_state)
+                    break;
+                }
+
+              if (! error_state)
+                retval.setfield (it->first, cvalue);
+            }
+          else
+            {
+              Cell cvalue (dim_vector (1, 1), it->second.get_value (*this, false));
+
+              if (! error_state)
+                retval.setfield (it->first, cvalue);
+            }
+
+          if (error_state)
+            break;
+        }
+    }
+
+  return retval;
+}
+
+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)
+{
+#if DEBUG_TRACE
+  std::cerr << "deleting " << get_class ().get_name ()
+            << " object (handle)" << std::endl;
+#endif
+}
+
+value_cdef_object::~value_cdef_object (void)
+{
+#if DEBUG_TRACE
+  std::cerr << "deleting " << get_class ().get_name ()
+            << " object (value)" << std::endl;
+#endif
+}
+
+cdef_class::cdef_class_rep::cdef_class_rep (const std::list<cdef_class>& superclasses)
+     : cdef_meta_object_rep (), member_count (0), handle_class (false),
+       object_count (0), meta (false)
+{
+  put ("SuperClasses", to_ov (superclasses));
+  implicit_ctor_list = superclasses;
+}
+
+cdef_method
+cdef_class::cdef_class_rep::find_method (const std::string& nm, bool local)
+{
+  method_iterator it = method_map.find (nm);
+
+  if (it == method_map.end ())
+    {
+      // FIXME: look into class directory
+    }
+  else
+    {
+      cdef_method& meth = it->second;
+
+      // FIXME: check if method reload needed
+
+      if (meth.ok ())
+        return meth;
+    }
+
+  if (! local)
+    {
+      // Look into superclasses
+
+      Cell super_classes = get ("SuperClasses").cell_value ();
+
+      for (int i = 0; i < super_classes.numel (); i++)
+        {
+          cdef_class cls = lookup_class (super_classes(i));
+
+          if (! error_state)
+            {
+              cdef_method meth = cls.find_method (nm);
+
+              if (meth.ok ())
+                return meth;
+            }
+        }
+    }
+
+  return cdef_method ();
+}
+
+class ctor_analyzer : public tree_walker
+{
+public:
+  ctor_analyzer (const std::string& ctor, const std::string& obj)
+    : tree_walker (), who (ctor), obj_name (obj) { }
+
+  void visit_statement_list (tree_statement_list& t)
+    {
+      for (tree_statement_list::const_iterator it = t.begin ();
+           ! error_state && it != t.end (); ++it)
+        (*it)->accept (*this);
+    }
+
+  void visit_statement (tree_statement& t)
+    {
+      if (t.is_expression ())
+        t.expression ()->accept (*this);
+    }
+
+  void visit_simple_assignment (tree_simple_assignment& t)
+    {
+      t.right_hand_side ()->accept (*this);
+    }
+
+  void visit_multi_assignment (tree_multi_assignment& t)
+    {
+      t.right_hand_side ()->accept (*this);
+    }
+
+  void visit_index_expression (tree_index_expression& t)
+    {
+      t.expression ()->accept (*this);
+    }
+
+  void visit_funcall (tree_funcall& t)
+    {
+      octave_value fcn = t.function ();
+
+      if (fcn.is_function ())
+        {
+          octave_function *of = fcn.function_value (true);
+
+          if (of)
+            {
+              if (of->name () == "__superclass_reference__")
+                {
+                  octave_value_list args = t.arguments ();
+
+                  if (args(0).string_value () == obj_name)
+                    {
+                      std::string class_name = args(1).string_value ();
+
+                      cdef_class cls = lookup_class (class_name, false);
+
+                      if (cls.ok ())
+                        ctor_list.push_back (cls);
+                    }
+                }
+            }
+        }
+    }
+
+  std::list<cdef_class> get_constructor_list (void) const
+    { return ctor_list; }
+
+  // NO-OP
+  void visit_anon_fcn_handle (tree_anon_fcn_handle&) { }
+  void visit_argument_list (tree_argument_list&) { }
+  void visit_binary_expression (tree_binary_expression&) { }
+  void visit_break_command (tree_break_command&) { }
+  void visit_colon_expression (tree_colon_expression&) { }
+  void visit_continue_command (tree_continue_command&) { }
+  void visit_global_command (tree_global_command&) { }
+  void visit_persistent_command (tree_persistent_command&) { }
+  void visit_decl_elt (tree_decl_elt&) { }
+  void visit_decl_init_list (tree_decl_init_list&) { }
+  void visit_simple_for_command (tree_simple_for_command&) { }
+  void visit_complex_for_command (tree_complex_for_command&) { }
+  void visit_octave_user_script (octave_user_script&) { }
+  void visit_octave_user_function (octave_user_function&) { }
+  void visit_function_def (tree_function_def&) { }
+  void visit_identifier (tree_identifier&) { }
+  void visit_if_clause (tree_if_clause&) { }
+  void visit_if_command (tree_if_command&) { }
+  void visit_if_command_list (tree_if_command_list&) { }
+  void visit_switch_case (tree_switch_case&) { }
+  void visit_switch_case_list (tree_switch_case_list&) { }
+  void visit_switch_command (tree_switch_command&) { }
+  void visit_matrix (tree_matrix&) { }
+  void visit_cell (tree_cell&) { }
+  void visit_no_op_command (tree_no_op_command&) { }
+  void visit_constant (tree_constant&) { }
+  void visit_fcn_handle (tree_fcn_handle&) { }
+  void visit_parameter_list (tree_parameter_list&) { }
+  void visit_postfix_expression (tree_postfix_expression&) { }
+  void visit_prefix_expression (tree_prefix_expression&) { }
+  void visit_return_command (tree_return_command&) { }
+  void visit_return_list (tree_return_list&) { }
+  void visit_try_catch_command (tree_try_catch_command&) { }
+  void visit_unwind_protect_command (tree_unwind_protect_command&) { }
+  void visit_while_command (tree_while_command&) { }
+  void visit_do_until_command (tree_do_until_command&) { }
+
+private:
+  /* The name of the constructor being analyzed */
+  std::string who;
+
+  /* The name of the first output argument of the constructor */
+  std::string obj_name;
+
+  /* The list of superclass constructors that are explicitly called */
+  std::list<cdef_class> ctor_list;
+};
+
+void
+cdef_class::cdef_class_rep::install_method (const cdef_method& meth)
+{
+  method_map[meth.get_name ()] = meth;
+
+  member_count++;
+
+  if (meth.is_constructor ())
+    {
+      // Analyze the constructor code to determine what superclass
+      // constructors are called explicitly.
+
+      octave_function *of = meth.get_function ().function_value (true);
+
+      if (of)
+        {
+          octave_user_function *uf = of->user_function_value (true);
+
+          if (uf)
+            {
+              tree_parameter_list *ret_list = uf->return_list ();
+              tree_statement_list *body = uf->body ();
+
+              if (ret_list && ret_list->size () == 1)
+                {
+                  std::string obj_name = ret_list->front ()->name ();
+                  ctor_analyzer a (meth.get_name (), obj_name);
+
+                  body->accept (a);
+                  if (! error_state)
+                    {
+                      std::list<cdef_class> explicit_ctor_list
+                        = a.get_constructor_list ();
+
+                      for (std::list<cdef_class>::const_iterator it = explicit_ctor_list.begin ();
+                           ! error_state && it != explicit_ctor_list.end (); ++it)
+                        {
+#if DEBUG_TRACE
+                          std::cerr << "explicit superclass constructor: "
+                                    << it->get_name () << std::endl;
+#endif
+
+                          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 (int mode)
+{
+  std::map<std::string,cdef_property> props;
+
+  props = get_property_map (mode);
+
+  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 ();
+}
+
+std::map<std::string, cdef_property>
+cdef_class::cdef_class_rep::get_property_map (int mode)
+{
+  std::map<std::string,cdef_property> props;
+
+  find_properties (props, mode);
+
+  return props;
+}
+
+void
+cdef_class::cdef_class_rep::find_properties (std::map<std::string,cdef_property>& props,
+                                             int mode)
+{
+  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 (mode == property_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,
+                                         (mode == property_all ?
+                                          property_all :
+                                          property_inherited));
+      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
+
+#if DEBUG_TRACE
+      std::cerr << "constructor" << std::endl;
+#endif
+
+      retval(0) = construct (idx.front ());
+      break;
+
+    case '.':
+      // Static method, constant (or property?)
+
+#if DEBUG_TRACE
+      std::cerr << "static method/property" << std::endl;
+#endif
+
+      if (idx.front ().length () == 1)
+        {
+          std::string nm = idx.front ()(0).string_value ();
+
+          if (! error_state)
+            {
+              cdef_method meth = find_method (nm);
+
+              if (meth.ok ())
+                {
+                  if (meth.is_static ())
+                    {
+                      octave_value_list args;
+
+                      if (type.length () > 1 && idx.size () > 1
+                          && type[1] == '(')
+                        {
+                          args = *(++(idx.begin ()));
+                          skip++;
+                        }
+
+                      retval = meth.execute (args, (type.length () > skip
+                                                    ? 1 : nargout), true,
+                                             "meta.class");
+                    }
+                  else
+                    ::error ("method `%s' is not static", nm.c_str ());
+                }
+              else
+                {
+                  cdef_property prop = find_property (nm);
+
+                  if (prop.ok ())
+                    {
+                      if (prop.is_constant ())
+                        retval(0) = prop.get_value (true, "meta.class");
+                      else
+                        ::error ("property `%s' is not constant",
+                                 nm.c_str ());
+                    }
+                  else
+                    ::error ("no such method or property `%s'", nm.c_str ());
+                }
+            }
+          else
+            ::error ("invalid meta.class indexing, expected a method or property name");
+        }
+      else
+        ::error ("invalid meta.class indexing");
+      break;
+
+    default:
+      ::error ("invalid meta.class indexing");
+      break;
+    }
+
+  if (! error_state)
+    {
+      if (type.length () > skip && idx.size () > skip && ! retval.empty ())
+        retval = retval(0).next_subsref (nargout, type, idx, skip);
+    }
+
+  return retval;
+}
+
+void
+cdef_class::cdef_class_rep::meta_release (void)
+{
+  cdef_manager::unregister_class (wrap ());
+}
+
+void
+cdef_class::cdef_class_rep::initialize_object (cdef_object& obj)
+{
+  // Populate the object with default property values
+
+  std::list<cdef_class> super_classes = lookup_classes (get ("SuperClasses").cell_value ());
+
+  if (! error_state)
+    {
+      for (std::list<cdef_class>::iterator it = super_classes.begin ();
+           ! error_state && it != super_classes.end (); ++it)
+        it->initialize_object (obj);
+
+      if (! error_state)
+        {
+          for (property_const_iterator it = property_map.begin ();
+               ! error_state && it != property_map.end (); ++it)
+            {
+              if (! it->second.get ("Dependent").bool_value ())
+                {
+                  octave_value pvalue = it->second.get ("DefaultValue");
+
+                  if (pvalue.is_defined ())
+                    obj.put (it->first, pvalue);
+                  else
+                    obj.put (it->first, octave_value (Matrix ()));
+                }
+            }
+
+          if (! error_state)
+            {
+              refcount++;
+              obj.mark_for_construction (cdef_class (this));
+            }
+        }
+    }
+}
+
+void
+cdef_class::cdef_class_rep::run_constructor (cdef_object& obj,
+                                             const octave_value_list& args)
+{
+  octave_value_list empty_args;
+
+  for (std::list<cdef_class>::const_iterator it = implicit_ctor_list.begin ();
+       ! error_state && it != implicit_ctor_list.end (); ++it)
+    {
+      cdef_class supcls = lookup_class (*it);
+
+      if (! error_state)
+        supcls.run_constructor (obj, empty_args);
+    }
+
+  if (error_state)
+    return;
+
+  std::string cls_name = get_name ();
+  std::string ctor_name = get_base_name (cls_name);
+
+  cdef_method ctor = find_method (ctor_name);
+
+  if (ctor.ok ())
+    {
+      octave_value_list ctor_args (args);
+      octave_value_list ctor_retval;
+
+      ctor_args.prepend (to_ov (obj));
+      ctor_retval = ctor.execute (ctor_args, 1, true, "constructor");
+
+      if (! error_state)
+        {
+          if (ctor_retval.length () == 1)
+            obj = to_cdef (ctor_retval(0));
+          else
+            {
+              ::error ("%s: invalid number of output arguments for classdef constructor",
+                       ctor_name.c_str ());
+              return;
+            }
+        }
+    }
+
+  obj.mark_as_constructed (wrap ());
+}
+
+octave_value
+cdef_class::cdef_class_rep::construct (const octave_value_list& args)
+{
+  cdef_object obj = construct_object (args);
+
+  if (! error_state && obj.ok ())
+    return to_ov (obj);
+
+  return octave_value ();
+}
+
+cdef_object
+cdef_class::cdef_class_rep::construct_object (const octave_value_list& args)
+{
+  if (! is_abstract ())
+    {
+      cdef_object obj;
+
+      if (is_meta_class ())
+        {
+          // This code path is only used to create empty meta objects
+          // as filler for the empty values within a meta object array.
+
+          cdef_class this_cls = wrap ();
+
+          static cdef_object empty_class;
+
+          if (this_cls == cdef_class::meta_class ())
+            {
+              if (! empty_class.ok ())
+                empty_class = make_class ("", std::list<cdef_class> ());
+              obj = empty_class;
+            }
+          else if (this_cls == cdef_class::meta_property ())
+            {
+              static cdef_property empty_property;
+
+              if (! empty_class.ok ())
+                empty_class = make_class ("", std::list<cdef_class> ());
+              if (! empty_property.ok ())
+                empty_property = make_property (empty_class, "");
+              obj = empty_property;
+            }
+          else if (this_cls == cdef_class::meta_method ())
+            {
+              static cdef_method empty_method;
+
+              if (! empty_class.ok ())
+                empty_class = make_class ("", std::list<cdef_class> ());
+              if (! empty_method.ok ())
+                empty_method = make_method (empty_class, "", octave_value ());
+              obj = empty_method;
+            }
+          else if (this_cls == cdef_class::meta_package ())
+            {
+              static cdef_package empty_package;
+
+              if (! empty_package.ok ())
+                empty_package = make_package ("");
+              obj = empty_package;
+            }
+          else
+            panic_impossible ();
+
+          return obj;
+        }
+      else
+        {
+          if (is_handle_class ())
+            obj = cdef_object (new handle_cdef_object ());
+          else
+            obj = cdef_object (new value_cdef_object ());
+          obj.set_class (wrap ());
+
+          initialize_object (obj);
+
+          if (! error_state)
+            {
+              run_constructor (obj, args);
+
+              if (! error_state)
+                return obj;
+            }
+        }
+    }
+  else
+    error ("cannot instantiate object for abstract class `%s'",
+           get_name ().c_str ());
+
+  return cdef_object ();
+}
+
+static octave_value
+compute_attribute_value (tree_classdef_attribute* t)
+{
+  if (t->expression ())
+    {
+      if (t->expression ()->is_identifier ())
+        {
+          std::string s = t->expression ()->name ();
+
+          if (s == "public")
+            return std::string ("public");
+          else if (s == "protected")
+            return std::string ("protected");
+          else if (s == "private")
+            return std::string ("private");
+        }
+
+      return t->expression ()->rvalue1 ();
+    }
+  else
+    return octave_value (true);
+}
+
+template<class T>
+static std::string
+attribute_value_to_string (T* t, octave_value v)
+{
+  if (v.is_string ())
+    return v.string_value ();
+  else if (t->expression ())
+    return t->expression ()->original_text ();
+  else
+    return std::string ("true");
+}
+
+cdef_class
+cdef_class::make_meta_class (tree_classdef* t, bool is_at_folder)
+{
+  cdef_class retval;
+  std::string class_name, full_class_name;
+
+  // Class creation
+
+  class_name = full_class_name = t->ident ()->name ();
+  if (! t->package_name ().empty ())
+    full_class_name = t->package_name () + "." + full_class_name;
+
+#if DEBUG_TRACE
+  std::cerr << "class: " << full_class_name << std::endl;
+#endif
+
+  std::list<cdef_class> slist;
+
+  if (t->superclass_list ())
+    {
+      for (tree_classdef_superclass_list::iterator it = t->superclass_list ()->begin ();
+           ! error_state && it != t->superclass_list ()->end (); ++it)
+        {
+          std::string sclass_name = (*it)->class_name ();
+
+#if DEBUG_TRACE
+          std::cerr << "superclass: " << sclass_name << std::endl;
+#endif
+
+          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);
+
+#if DEBUG_TRACE
+          std::cerr << "class attribute: " << aname << " = "
+                    << attribute_value_to_string (*it, avalue) << std::endl;
+#endif
+
+          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;
+
+#if DEBUG_TRACE
+          std::cerr << "method block" << std::endl;
+#endif
+
+          // 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);
+
+#if DEBUG_TRACE
+                  std::cerr << "method attribute: " << aname << " = "
+                            << attribute_value_to_string (*ait, avalue)
+                            << std::endl;
+#endif
+
+                  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);
+
+#if DEBUG_TRACE
+                      std::cerr << (mname == class_name ? "constructor" : "method")
+                                << ": " << mname << std::endl;
+#endif
+
+                      for (std::map<std::string, octave_value>::iterator ait = amap.begin ();
+                           ait != amap.end (); ++ait)
+                        meth.put (ait->first, ait->second);
+
+                      retval.install_method (meth);
+                    }
+                }
+            }
+        }
+
+      if (is_at_folder)
+        {
+          // Look for all external methods visible on octave path at the
+          // time of loading of the class.
+          //
+          // TODO: This is an "extension" to Matlab behavior, which only
+          // looks in the @-folder containing the original classdef
+          // file. However, this is easier to implement it that way at
+          // the moment.
+
+          std::list<std::string> external_methods =
+            load_path::methods (full_class_name);
+
+          for (std::list<std::string>::const_iterator it = external_methods.begin ();
+               it != external_methods.end (); ++it)
+            {
+              // TODO: should we issue a warning if the method is already
+              // defined in the classdef file?
+
+              if (*it != class_name
+                  && ! retval.find_method (*it, true).ok ())
+                {
+                  // Create a dummy method that is used until the actual
+                  // method is loaded.
+
+                  octave_user_function *fcn = new octave_user_function ();
+
+                  fcn->stash_function_name (*it);
+
+                  cdef_method meth = make_method (retval, *it,
+                                                  octave_value (fcn));
+
+                  retval.install_method (meth);
+                }
+            }
+        }
+
+      // Property blocks
+
+      // FIXME: default property expression should be able to call static
+      //        methods of the class being constructed. A restricted CLASSNAME
+      //        symbol should be added to the scope before evaluating default
+      //        value expressions.
+
+      std::list<tree_classdef_properties_block *> pb_list = b->properties_list ();
+
+      for (tree_classdef_body::properties_list_iterator it = pb_list.begin ();
+           it != pb_list.end (); ++it)
+        {
+          std::map<std::string, octave_value> amap;
+
+#if DEBUG_TRACE
+          std::cerr << "property block" << std::endl;
+#endif
+
+          // 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);
+
+#if DEBUG_TRACE
+                  std::cerr << "property attribute: " << aname << " = "
+                            << attribute_value_to_string (*ait, avalue)
+                            << std::endl;
+#endif
+
+                  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);
+
+#if DEBUG_TRACE
+                  std::cerr << "property: " << (*pit)->ident ()->name ()
+                            << std::endl;
+#endif
+
+                  if ((*pit)->expression ())
+                    {
+                      octave_value pvalue = (*pit)->expression ()->rvalue1 ();
+
+#if DEBUG_TRACE
+                      std::cerr << "property default: "
+                                << attribute_value_to_string (*pit, pvalue)
+                                << std::endl;
+#endif
+
+                      prop.put ("DefaultValue", pvalue);
+                    }
+
+                  // Install property attributes. This is done before assigning the
+                  // property accessors so we can do validationby using cdef_property
+                  // methods.
+
+                  for (std::map<std::string, octave_value>::iterator ait = amap.begin ();
+                       ait != amap.end (); ++ait)
+                    prop.put (ait->first, ait->second);
+
+                  // Install property access methods, if any. Remove the accessor
+                  // methods from the temporary storage map, so we can detect which
+                  // ones are invalid and do not correspond to a defined property.
+
+                  std::map<std::string, octave_value>::iterator git =
+                    get_methods.find (prop_name);
+
+                  if (git != get_methods.end ())
+                    {
+                      make_function_of_class (retval, git->second);
+                      prop.put ("GetMethod", git->second);
+                      get_methods.erase (git);
+                    }
+
+                  std::map<std::string, octave_value>::iterator sit =
+                    set_methods.find (prop_name);
+
+                  if (sit != set_methods.end ())
+                    {
+                      make_function_of_class (retval, sit->second);
+                      prop.put ("SetMethod", sit->second);
+                      set_methods.erase (sit);
+                    }
+
+                  retval.install_property (prop);
+                }
+            }
+        }
+    }
+
+  return retval;
+}
+
+octave_function*
+cdef_class::get_method_function (const std::string& /* nm */)
+{
+  octave_classdef_meta* p = new octave_classdef_meta (*this);
+
+  return p;
+}
+
+octave_value
+cdef_property::cdef_property_rep::get_value (const cdef_object& obj,
+                                             bool do_check_access,
+                                             const std::string& who)
+{
+  octave_value retval;
+
+  if (do_check_access && ! check_get_access ())
+    {
+      gripe_property_access (who, wrap (), false);
+
+      return retval;
+    }
+
+  if (! obj.is_constructed ())
+    {
+      cdef_class cls (to_cdef (get ("DefiningClass")));
+
+      if (! obj.is_partially_constructed_for (cls))
+        {
+          ::error ("cannot reference properties of class `%s' for non-constructed object",
+                   cls.get_name ().c_str ());
+          return retval;
+        }
+    }
+ 
+  octave_value get_fcn = get ("GetMethod");
+
+  // FIXME: should check whether we're already in get accessor method
+
+  if (get_fcn.is_empty () || is_method_executing (get_fcn, obj))
+    retval = obj.get (get ("Name").string_value ());
+  else
+    {
+      octave_value_list args;
+
+      args(0) = to_ov (obj);
+      
+      args = execute_ov (get_fcn, args, 1);
+
+      if (! error_state)
+        retval = args(0);
+    }
+
+  return retval;
+}
+
+octave_value
+cdef_property::cdef_property_rep::get_value (bool do_check_access,
+                                             const std::string& who)
+{
+  if (do_check_access && ! check_get_access ())
+    {
+      gripe_property_access (who, wrap (), false);
+
+      return octave_value ();
+    }
+
+  return get ("DefaultValue");
+}
+
+bool
+cdef_property::cdef_property_rep::is_recursive_set (const cdef_object& /* obj */) const
+{
+  // FIXME: implement
+  return false;
+}
+
+void
+cdef_property::cdef_property_rep::set_value (cdef_object& obj,
+                                             const octave_value& val,
+                                             bool do_check_access,
+                                             const std::string& who)
+{
+  if (do_check_access && ! check_set_access ())
+    {
+      gripe_property_access (who, wrap (), true);
+
+      return;
+    }
+
+  if (! obj.is_constructed ())
+    {
+      cdef_class cls (to_cdef (get ("DefiningClass")));
+
+      if (! obj.is_partially_constructed_for (cls))
+        {
+          ::error ("cannot reference properties of class `%s' for non-constructed object",
+                   cls.get_name ().c_str ());
+          return;
+        }
+    }
+ 
+  octave_value set_fcn = get ("SetMethod");
+
+  if (set_fcn.is_empty () || is_method_executing (set_fcn, obj))
+    obj.put (get ("Name").string_value (), val);
+  else
+    {
+      octave_value_list args;
+
+      args(0) = to_ov (obj);
+      args(1) = val;
+
+      args = execute_ov (set_fcn, args, 1);
+
+      if (! error_state)
+        {
+          if (args.length () > 0 && args(0).is_defined ())
+            {
+              if (args (0).is_classdef_object ())
+                {
+                  cdef_object new_obj = to_cdef (args(0));
+
+                  if (! error_state)
+                    obj = new_obj;
+                }
+              else
+                ::warning ("set-method of property `%s' returned a non-classdef object",
+                           get_name ().c_str ());
+            }
+        }
+    }
+}
+
+bool
+cdef_property::cdef_property_rep::check_get_access (void) const
+{
+  cdef_class cls (to_cdef (get ("DefiningClass")));
+
+  if (! error_state)
+    return ::check_access (cls, get ("GetAccess"), std::string (),
+                           get_name (), false);
+
+  return false;
+}
+
+bool
+cdef_property::cdef_property_rep::check_set_access (void) const
+{
+  cdef_class cls (to_cdef (get ("DefiningClass")));
+
+  if (! error_state)
+    return ::check_access (cls, get ("SetAccess"), std::string (),
+                           get_name (), true);
+
+  return false;
+}
+
+void
+cdef_method::cdef_method_rep::check_method (void)
+{
+  if (is_external ())
+    {
+      if (is_dummy_method (function))
+        {
+          std::string name = get_name ();
+          std::string cls_name = dispatch_type;
+          std::string pack_name;
+
+          size_t pos = cls_name.rfind ('.');
+
+          if (pos != std::string::npos)
+            {
+              pack_name = cls_name.substr (0, pos);
+              cls_name = cls_name.substr (pos + 1);
+            }
+
+          std::string dir_name;
+          std::string file_name = load_path::find_method (cls_name, name,
+                                                          dir_name, pack_name);
+
+          if (! file_name.empty ())
+            {
+              octave_function *fcn = load_fcn_from_file (file_name, dir_name,
+                                                         dispatch_type,
+                                                         pack_name);
+
+              if (fcn)
+                {
+                  function = octave_value (fcn);
+
+                  make_function_of_class (dispatch_type, function);
+                }
+            }
+        }
+      else
+        {
+          // FIXME: check out-of-date status
+        }
+
+      if (is_dummy_method (function))
+        ::error ("no definition found for method `%s' of class `%s'",
+                 get_name ().c_str (), dispatch_type.c_str ());
+    }
+}
+
+octave_value_list
+cdef_method::cdef_method_rep::execute (const octave_value_list& args,
+                                       int nargout, bool do_check_access,
+                                       const std::string& who)
+{
+  octave_value_list retval;
+
+  if (do_check_access && ! check_access ())
+    {
+      gripe_method_access (who, wrap ());
+
+      return retval;
+    }
+
+  if (! get ("Abstract").bool_value ())
+    {
+      check_method ();
+
+      if (! error_state && function.is_defined ())
+        {
+          retval = execute_ov (function, args, nargout);
+        }
+    }
+  else
+    error ("%s: cannot execute abstract method",
+           get ("Name").string_value ().c_str ());
+
+  return retval;
+}
+
+octave_value_list
+cdef_method::cdef_method_rep::execute (const cdef_object& obj,
+                                       const octave_value_list& args,
+                                       int nargout, bool do_check_access,
+                                       const std::string& who)
+{
+  octave_value_list retval;
+
+  if (do_check_access && ! check_access ())
+    {
+      gripe_method_access (who, wrap ());
+
+      return retval;
+    }
+
+  if (! get ("Abstract").bool_value ())
+    {
+      check_method ();
+
+      if (! error_state && function.is_defined ())
+        {
+          octave_value_list new_args;
+
+          new_args.resize (args.length () + 1);
+
+          new_args(0) = to_ov (obj);
+          for (int i = 0; i < args.length (); i++)
+            new_args(i+1) = args(i);
+
+          retval = execute_ov (function, new_args, nargout);
+        }
+    }
+  else
+    error ("%s: cannot execute abstract method",
+           get ("Name").string_value ().c_str ());
+
+  return retval;
+}
+
+bool
+cdef_method::cdef_method_rep::is_constructor (void) const
+{
+  if (function.is_function())
+    return function.function_value ()->is_classdef_constructor ();
+
+  return false;
+}
+
+bool
+cdef_method::cdef_method_rep::check_access (void) const
+{
+  cdef_class cls (to_cdef (get ("DefiningClass")));
+
+  if (! error_state)
+    return ::check_access (cls, get ("Access"), get_name ());
+
+  return false;
+}
+
+octave_value_list
+cdef_method::cdef_method_rep::meta_subsref
+  (const std::string& type, const std::list<octave_value_list>& idx,
+   int nargout)
+{
+  octave_value_list retval;
+
+  switch (type[0])
+    {
+    case '(':
+      retval = execute (idx.front (), type.length () > 1 ? 1 : nargout, true);
+      break;
+
+    default:
+      error ("invalid meta.method indexing");
+      break;
+    }
+
+  if (! error_state)
+    {
+      if (type.length () > 1 && idx.size () > 1 && ! retval.empty ())
+        retval = retval(0).next_subsref (nargout, type, idx, 1);
+    }
+
+  return retval;
+}
+
+static cdef_package
+lookup_package (const std::string& name)
+{
+  return cdef_manager::find_package (name);
+}
+
+static octave_value_list
+package_fromName (const octave_value_list& args, int /* nargout */)
+{
+  octave_value_list retval;
+
+  if (args.length () == 1)
+    {
+      std::string name = args(0).string_value ();
+
+      if (! error_state)
+        retval(0) = to_ov (lookup_package (name));
+      else
+        error ("fromName: invalid package name, expected a string value");
+    }
+  else
+    error ("fromName: invalid number of parameters");
+
+  return retval;
+}
+
+static octave_value_list
+package_get_classes (const octave_value_list& args, int /* nargout */)
+{
+  octave_value_list retval (1, Matrix ());
+
+  if (args.length () == 1 && args(0).type_name () == "object"
+      && args(0).class_name () == "meta.package")
+    {
+      cdef_package pack (to_cdef (args(0)));
+
+      retval(0) = pack.get_classes ();
+    }
+
+  return retval;
+}
+
+static octave_value_list
+package_get_functions (const octave_value_list& args, int /* nargout */)
+{
+  octave_value_list retval (1, Matrix ());
+
+  if (args.length () == 0 && args(0).type_name () == "object"
+      && args(0).class_name () == "meta.package")
+    {
+      cdef_package pack (to_cdef (args(0)));
+
+      retval(0) = pack.get_functions ();
+    }
+
+  return retval;
+}
+
+static octave_value_list
+package_get_packages (const octave_value_list& args, int /* nargout */)
+{
+  octave_value_list retval (1, Matrix ());
+
+  if (args.length () == 0 && args(0).type_name () == "object"
+      && args(0).class_name () == "meta.package")
+    {
+      cdef_package pack (to_cdef (args(0)));
+
+      retval(0) = pack.get_packages ();
+    }
+
+  return retval;
+}
+
+static octave_value_list
+package_getAllPackages (const octave_value_list& /* args */,
+                        int /* nargout */)
+{
+  std::map<std::string, cdef_package> toplevel_packages;
+
+  std::list<std::string> names = load_path::get_all_package_names ();
+
+  toplevel_packages["meta"] = cdef_manager::find_package ("meta", false,
+                                                          false);
+
+  for (std::list<std::string>::const_iterator it = names.begin ();
+       it != names.end (); ++it)
+    toplevel_packages[*it] = cdef_manager::find_package (*it, false, true);
+
+  Cell c (toplevel_packages.size (), 1);
+
+  int i = 0;
+
+  for (std::map<std::string, cdef_package>::const_iterator it = toplevel_packages.begin ();
+       it != toplevel_packages.end (); ++it)
+    c(i++,0) = to_ov (it->second);
+
+  return octave_value_list (octave_value (c));
+}
+
+void
+cdef_package::cdef_package_rep::install_class (const cdef_class& cls,
+                                               const std::string& nm)
+{
+  class_map[nm] = cls;
+
+  member_count++;
+}
+
+void
+cdef_package::cdef_package_rep::install_function (const octave_value& fcn,
+                                                  const std::string& nm)
+{
+  function_map[nm] = fcn;
+}
+
+void
+cdef_package::cdef_package_rep::install_package (const cdef_package& pack,
+                                                 const std::string& nm)
+{
+  package_map[nm] = pack;
+
+  member_count++;
+}
+
+template<class T1, class T2>
+Cell
+map2Cell (const std::map<T1, T2>& m)
+{
+  Cell retval (1, m.size ());
+  int i = 0;
+
+  for (typename std::map<T1, T2>::const_iterator it = m.begin ();
+       it != m.end (); ++it, ++i)
+    {
+      retval(i) = to_ov (it->second);
+    }
+
+  return retval;
+}
+
+Cell
+cdef_package::cdef_package_rep::get_classes (void) const
+{ return map2Cell (class_map); }
+
+Cell
+cdef_package::cdef_package_rep::get_functions (void) const
+{ return map2Cell (function_map); }
+
+Cell
+cdef_package::cdef_package_rep::get_packages (void) const
+{ return map2Cell (package_map); }
+
+octave_value
+cdef_package::cdef_package_rep::find (const std::string& nm)
+{
+  std::string symbol_name = get_name () + "." + nm;
+
+  return symbol_table::find (symbol_name, octave_value_list (), true, false);
+}
+
+octave_value_list
+cdef_package::cdef_package_rep::meta_subsref
+  (const std::string& type, const std::list<octave_value_list>& idx,
+   int nargout)
+{
+  octave_value_list retval;
+
+  switch (type[0])
+    {
+    case '.':
+      if (idx.front ().length () == 1)
+        {
+          std::string nm = idx.front ()(0).string_value ();
+
+          if (! error_state)
+            {
+#if DEBUG_TRACE
+              std::cerr << "meta.package query: " << nm << std::endl;
+#endif
+
+              octave_value o = find (nm);
+
+              if (o.is_defined ())
+                {
+                  if (o.is_function ())
+                    {
+                      octave_function* fcn = o.function_value ();
+
+                      if (! error_state)
+                        {
+                          // NOTE: the case where the package query is the last
+                          // part of this subsref index is handled in the parse
+                          // tree, because there is some logic to handle magic
+                          // "end" that makes it impossible to execute the
+                          // function call at this stage.
+
+                          if (type.size () > 1 &&
+                              ! fcn->is_postfix_index_handled (type[1]))
+                            {
+                              octave_value_list tmp_args;
+
+                              retval = o.do_multi_index_op (nargout,
+                                                            tmp_args);
+                            }
+                          else
+                            retval(0) = o;
+
+                          if (type.size () > 1 && idx.size () > 1)
+                            retval = retval(0).next_subsref (nargout, type,
+                                                             idx, 1);
+                        }
+                    }
+                  else if (type.size () > 1 && idx.size () > 1)
+                    retval = o.next_subsref (nargout, type, idx, 1);
+                  else
+                    retval(0) = o;
+                }
+              else if (! error_state)
+                error ("member `%s' in package `%s' does not exist",
+                       nm.c_str (), get_name ().c_str ());
+            }
+          else
+            error ("invalid meta.package indexing, expected a symbol name");
+        }
+      else
+        error ("invalid meta.package indexing");
+      break;
+
+    default:
+      error ("invalid meta.package indexing");
+      break;
+    }
+
+  return retval;
+}
+
+void
+cdef_package::cdef_package_rep::meta_release (void)
+{
+  // FIXME: Do we really want to unregister the package, as it
+  //        could still be referenced by classes or sub-packages?
+  //        If the package object is recreated later on, it won't
+  //        match the one already referenced by those classes or
+  //        sub-packages.
+
+  //cdef_manager::unregister_package (wrap ());
+}
+
+cdef_class cdef_class::_meta_class = cdef_class ();
+cdef_class cdef_class::_meta_property = cdef_class ();
+cdef_class cdef_class::_meta_method = cdef_class ();
+cdef_class cdef_class::_meta_package = cdef_class ();
+
+cdef_package cdef_package::_meta = cdef_package ();
+
+void
+install_classdef (void)
+{
+  octave_classdef::register_type ();
+
+  /* bootstrap */
+  cdef_class handle = make_class ("handle");
+  cdef_class meta_class = cdef_class::_meta_class = make_meta_class ("meta.class", handle);
+  handle.set_class (meta_class);
+  meta_class.set_class (meta_class);
+
+  /* meta classes */
+  cdef_class meta_property = cdef_class::_meta_property = make_meta_class ("meta.property", handle);
+  cdef_class meta_method = cdef_class::_meta_method = make_meta_class ("meta.method", handle);
+  cdef_class meta_package = cdef_class::_meta_package = make_meta_class ("meta.package", handle);
+
+  cdef_class meta_event = make_meta_class ("meta.event", handle);
+  cdef_class meta_dynproperty = make_meta_class ("meta.dynamicproperty", handle);
+
+  /* meta.class properties */
+  meta_class.install_property (make_attribute (meta_class, "Abstract"));
+  meta_class.install_property (make_attribute (meta_class, "ConstructOnLoad"));
+  meta_class.install_property (make_property  (meta_class, "ContainingPackage"));
+  meta_class.install_property (make_property  (meta_class, "Description"));
+  meta_class.install_property (make_property  (meta_class, "DetailedDescription"));
+  meta_class.install_property (make_property  (meta_class, "Events"));
+  meta_class.install_property (make_attribute (meta_class, "HandleCompatible"));
+  meta_class.install_property (make_attribute (meta_class, "Hidden"));
+  meta_class.install_property
+      (make_property (meta_class, "InferiorClasses",
+                      make_fcn_handle (class_get_inferiorclasses, "meta.class>get.InferiorClasses"),
+                      "public", Matrix (), "private"));
+  meta_class.install_property
+      (make_property  (meta_class, "Methods",
+                       make_fcn_handle (class_get_methods, "meta.class>get.Methods"),
+                       "public", Matrix (), "private"));
+  meta_class.install_property
+      (make_property  (meta_class, "MethodList",
+                       make_fcn_handle (class_get_methods, "meta.class>get.MethodList"),
+                       "public", Matrix (), "private"));
+  meta_class.install_property (make_attribute (meta_class, "Name"));
+  meta_class.install_property
+      (make_property  (meta_class, "Properties",
+                       make_fcn_handle (class_get_properties, "meta.class>get.Properties"),
+                       "public", Matrix (), "private"));
+  meta_class.install_property
+      (make_property  (meta_class, "PropertyList",
+                       make_fcn_handle (class_get_properties, "meta.class>get.PropertyList"),
+                       "public", Matrix (), "private"));
+  meta_class.install_property (make_attribute (meta_class, "Sealed"));
+  meta_class.install_property
+      (make_property (meta_class, "SuperClasses",
+                      make_fcn_handle (class_get_superclasses, "meta.class>get.SuperClasses"),
+                      "public", Matrix (), "private"));
+  meta_class.install_property
+      (make_property (meta_class, "SuperClassList",
+                      make_fcn_handle (class_get_superclasses, "meta.class>get.SuperClassList"),
+                      "public", Matrix (), "private"));
+  /* meta.class methods */
+  meta_class.install_method (make_method (meta_class, "fromName", class_fromName,
+                                          "public", true));
+  meta_class.install_method (make_method (meta_class, "fevalStatic", class_fevalStatic,
+                                          "public", false));
+  meta_class.install_method (make_method (meta_class, "getConstant", class_getConstant,
+                                          "public", false));
+  meta_class.install_method (make_method (meta_class, "eq", class_eq));
+  meta_class.install_method (make_method (meta_class, "ne", class_ne));
+  meta_class.install_method (make_method (meta_class, "lt", class_lt));
+  meta_class.install_method (make_method (meta_class, "le", class_le));
+  meta_class.install_method (make_method (meta_class, "gt", class_gt));
+  meta_class.install_method (make_method (meta_class, "ge", class_ge));
+
+  /* meta.method properties */
+  meta_method.install_property (make_attribute (meta_method, "Abstract"));
+  meta_method.install_property (make_attribute (meta_method, "Access"));
+  meta_method.install_property (make_attribute (meta_method, "DefiningClass"));
+  meta_method.install_property (make_attribute (meta_method, "Description"));
+  meta_method.install_property (make_attribute (meta_method, "DetailedDescription"));
+  meta_method.install_property (make_attribute (meta_method, "Hidden"));
+  meta_method.install_property (make_attribute (meta_method, "Name"));
+  meta_method.install_property (make_attribute (meta_method, "Sealed"));
+  meta_method.install_property (make_attribute (meta_method, "Static"));
+
+  /* meta.property properties */
+  meta_property.install_property (make_attribute (meta_property, "Name"));
+  meta_property.install_property (make_attribute (meta_property, "Description"));
+  meta_property.install_property (make_attribute (meta_property, "DetailedDescription"));
+  meta_property.install_property (make_attribute (meta_property, "Abstract"));
+  meta_property.install_property (make_attribute (meta_property, "Constant"));
+  meta_property.install_property (make_attribute (meta_property, "GetAccess"));
+  meta_property.install_property (make_attribute (meta_property, "SetAccess"));
+  meta_property.install_property (make_attribute (meta_property, "Dependent"));
+  meta_property.install_property (make_attribute (meta_property, "Transient"));
+  meta_property.install_property (make_attribute (meta_property, "Hidden"));
+  meta_property.install_property (make_attribute (meta_property, "GetObservable"));
+  meta_property.install_property (make_attribute (meta_property, "SetObservable"));
+  meta_property.install_property (make_attribute (meta_property, "GetMethod"));
+  meta_property.install_property (make_attribute (meta_property, "SetMethod"));
+  meta_property.install_property (make_attribute (meta_property, "DefiningClass"));
+  meta_property.install_property
+      (make_property (meta_property, "DefaultValue",
+                      make_fcn_handle (property_get_defaultvalue, "meta.property>get.DefaultValue"),
+                      "public", Matrix (), "private"));
+  meta_property.install_property (make_attribute (meta_property, "HasDefault"));
+  /* meta.property events */
+  // FIXME: add events
+
+  /* handle methods */
+  handle.install_method (make_method (handle, "delete", handle_delete));
+
+  /* meta.package properties */
+  meta_package.install_property (make_attribute (meta_package, "Name"));
+  meta_package.install_property (make_property  (meta_package, "ContainingPackage"));
+  meta_package.install_property
+      (make_property (meta_package, "ClassList",
+                      make_fcn_handle (package_get_classes, "meta.package>get.ClassList"),
+                      "public", Matrix (), "private"));
+  meta_package.install_property
+      (make_property (meta_package, "Classes",
+                      make_fcn_handle (package_get_classes, "meta.package>get.Classes"),
+                      "public", Matrix (), "private"));
+  meta_package.install_property
+      (make_property (meta_package, "FunctionList",
+                      make_fcn_handle (package_get_functions, "meta.package>get.FunctionList"),
+                      "public", Matrix (), "private"));
+  meta_package.install_property
+      (make_property (meta_package, "Functions",
+                      make_fcn_handle (package_get_functions, "meta.package>get.Functions"),
+                      "public", Matrix (), "private"));
+  meta_package.install_property
+      (make_property (meta_package, "PackageList",
+                      make_fcn_handle (package_get_packages, "meta.package>get.PackageList"),
+                      "public", Matrix (), "private"));
+  meta_package.install_property
+      (make_property (meta_package, "Packages",
+                      make_fcn_handle (package_get_packages, "meta.package>get.Packages"),
+                      "public", Matrix (), "private"));
+  meta_package.install_method (make_method (meta_package, "fromName", package_fromName,
+                                            "public", true));
+  meta_package.install_method (make_method (meta_package, "getAllPackages", package_getAllPackages,
+                                            "public", true));
+
+  /* create "meta" package */
+  cdef_package package_meta = cdef_package::_meta = make_package ("meta");
+  package_meta.install_class (meta_class,       "class");
+  package_meta.install_class (meta_property,    "property");
+  package_meta.install_class (meta_method,      "method");
+  package_meta.install_class (meta_package,     "package");
+  package_meta.install_class (meta_event,       "event");
+  package_meta.install_class (meta_dynproperty, "dynproperty");
+
+  /* install built-in classes into the symbol table */
+  symbol_table::install_built_in_function
+    ("meta.class", octave_value (meta_class.get_constructor_function ()));
+  symbol_table::install_built_in_function
+    ("meta.method", octave_value (meta_method.get_constructor_function ()));
+  symbol_table::install_built_in_function
+    ("meta.property", octave_value (meta_property.get_constructor_function ()));
+  symbol_table::install_built_in_function
+    ("meta.package", octave_value (meta_package.get_constructor_function ()));
+  symbol_table::install_built_in_function
+    ("meta.event", octave_value (meta_event.get_constructor_function ()));
+  symbol_table::install_built_in_function
+    ("meta.dynproperty", octave_value (meta_dynproperty.get_constructor_function ()));
+}
+
+//----------------------------------------------------------------------------
+
+cdef_manager* cdef_manager::instance = 0;
+
+void
+cdef_manager::create_instance (void)
+{
+  instance = new cdef_manager ();
+
+  if (instance)
+    singleton_cleanup_list::add (cleanup_instance);
+}
+
+cdef_class
+cdef_manager::do_find_class (const std::string& name,
+                             bool error_if_not_found, bool load_if_not_found)
+{
+  std::map<std::string, cdef_class>::iterator it = all_classes.find (name);
+
+  if (it == all_classes.end ())
+    {
+      if (load_if_not_found)
+        {
+          octave_value ov_cls;
+
+          size_t pos = name.rfind ('.');
+
+          if (pos == std::string::npos)
+            ov_cls = symbol_table::find (name);
+          else
+            {
+              std::string pack_name = name.substr (0, pos);
+
+              cdef_package pack = do_find_package (pack_name, false, true);
+
+              if (pack.ok ())
+                ov_cls = pack.find (name.substr (pos+1));
+            }
+
+          if (ov_cls.is_defined ())
+            it = all_classes.find (name);
+        }
+    }
+
+  if (it == all_classes.end ())
+    {
+      if (error_if_not_found)
+        error ("class not found: %s", name.c_str ());
+    }
+  else
+    {
+      cdef_class cls = it->second;
+
+      if (! cls.is_builtin ())
+        cls = lookup_class (cls);
+
+      if (cls.ok ())
+        return cls;
+      else
+        all_classes.erase (it);
+    }
+
+  return cdef_class ();
+}
+
+octave_function*
+cdef_manager::do_find_method_symbol (const std::string& method_name,
+                                     const std::string& class_name)
+{
+  octave_function *retval = 0;
+
+  cdef_class cls = find_class (class_name, false, false);
+
+  if (cls.ok ())
+    {
+      cdef_method meth = cls.find_method (method_name);
+
+      if (meth.ok ())
+        retval = new octave_classdef_meta (meth);
+    }
+
+  return retval;
+}
+
+cdef_package
+cdef_manager::do_find_package (const std::string& name,
+                               bool error_if_not_found,
+                               bool load_if_not_found)
+{
+  cdef_package retval;
+
+  std::map<std::string, cdef_package>::const_iterator it
+    = all_packages.find (name);
+
+  if (it != all_packages.end ())
+    {
+      retval = it->second;
+
+      if (! retval.ok ())
+        error ("invalid package `%s'", name.c_str ());
+    }
+  else
+    {
+      if (load_if_not_found && load_path::find_package (name))
+        {
+          size_t pos = name.find ('.');
+
+          if (pos == std::string::npos)
+            retval = make_package (name, std::string ());
+          else
+            {
+              std::string parent_name = name.substr (0, pos);
+
+              retval = make_package (name, parent_name);
+            }
+        }
+      else if (error_if_not_found)
+        error ("unknown package `%s'", name.c_str ());
+    }
+
+  return retval;
+}
+
+octave_function*
+cdef_manager::do_find_package_symbol (const std::string& pack_name)
+{
+  octave_function* retval = 0;
+
+  cdef_package pack = find_package (pack_name, false);
+
+  if (pack.ok ())
+    retval = new octave_classdef_meta (pack);
+
+  return retval;
+}
+
+//----------------------------------------------------------------------------
+
+DEFUN (__meta_get_package__, args, , "")
+{
+  octave_value retval;
+
+  if (args.length () == 1)
+    {
+      std::string cname = args(0).string_value ();
+
+      if (! error_state)
+        retval = to_ov (lookup_package (cname));
+      else
+        error ("invalid package name, expected a string value");
+    }
+  else
+    print_usage ();
+
+  return retval;
+}
+
+DEFUN (__superclass_reference__, args, /* nargout */,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {} __superclass_reference__ ()\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  return octave_value (new octave_classdef_superclass_ref (args));
+}
+
+DEFUN (__meta_class_query__, args, /* nargout */,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {} __meta_class_query__ ()\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+#if DEBUG_TRACE
+  std::cerr << "__meta_class_query__ ("
+            << args(0).string_value () << ")"
+            << std::endl;
+#endif
+
+  if (args.length () == 1)
+    {
+      std::string cls = args(0).string_value ();
+
+      if (! error_state)
+        retval = to_ov (lookup_class (cls));
+      else
+        error ("invalid class name, expected a string value");
+    }
+  else
+    print_usage ();
+
+  return retval;
+}
+
+DEFUN (metaclass, args, /* nargout */,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {} metaclass (obj)\n\
+Returns the meta.class object corresponding to the class of @var{obj}.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+  if (args.length () == 1)
+    {
+      cdef_object obj = to_cdef (args(0));
+
+      if (! error_state)
+        retval = to_ov (obj.get_class ());
+      else
+        print_usage ();
+    }
+  else
+    print_usage ();
+
+  return retval;
+}
+
+/*
+;;; Local Variables: ***
+;;; mode: C++ ***
+;;; End: ***
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/octave-value/ov-classdef.h	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,1689 @@
+/*
+
+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 (); }
+
+  octave_map map_value (void) const;
+
+  const cdef_object_rep* get_rep (void) const { return rep; }
+
+  bool ok (void) const { return rep->is_valid (); }
+
+  void mark_for_construction (const cdef_class& cls)
+    { rep->mark_for_construction (cls); }
+
+  bool is_constructed (void) const { return rep->is_constructed (); }
+
+  bool is_constructed_for (const cdef_class& cls) const
+    { return rep->is_constructed_for (cls); }
+
+  bool is_partially_constructed_for (const cdef_class& cls) const
+    { return rep->is_partially_constructed_for (cls); }
+
+  void mark_as_constructed (void) { rep->mark_as_constructed (); }
+
+  void mark_as_constructed (const cdef_class& cls)
+    { rep->mark_as_constructed (cls); }
+
+  bool is (const cdef_object& obj) const { return rep == obj.rep; }
+
+protected:
+  cdef_object_rep* get_rep (void) { return rep; }
+
+  void make_unique (int ignore_copies)
+    {
+      if (rep->refcount > ignore_copies + 1)
+        *this = clone ();
+    }
+
+private:
+  cdef_object_rep *rep;
+};
+
+class
+cdef_object_base : public cdef_object_rep
+{
+public:
+  cdef_object_base (void)
+    : cdef_object_rep (), klass ()
+    {
+      register_object ();
+    }
+
+  ~cdef_object_base (void) { unregister_object (); }
+
+  cdef_class get_class (void) const;
+
+  void set_class (const cdef_class& cls);
+
+  cdef_object_rep* empty_clone (void) const
+    { return new cdef_object_base (*this); }
+
+  cdef_object_rep* make_array (void) const;
+
+protected:
+  // Restricted copying!
+  cdef_object_base (const cdef_object_base& obj)
+    : cdef_object_rep (obj), klass (obj.klass)
+    {
+      register_object ();
+    }
+
+private:
+  void register_object (void);
+
+  void unregister_object (void);
+
+private:
+  // The class of the object
+  cdef_object klass;
+
+private:
+  // No assignment!
+  cdef_object_base& operator = (const cdef_object_base&);
+};
+
+class
+cdef_object_array : public cdef_object_base
+{
+public:
+  cdef_object_array (void) : cdef_object_base () { }
+
+  cdef_object_array (const Array<cdef_object>& a)
+    : cdef_object_base (), array (a) { }
+
+  cdef_object_rep* clone (void) const
+    { return new cdef_object_array (*this); }
+
+  dim_vector dims (void) const { return array.dims (); }
+
+  bool is_valid (void) const { return true; }
+
+  bool is_array (void) const { return true; }
+
+  Array<cdef_object> array_value (void) const { return array; }
+
+  octave_value_list
+  subsref (const std::string& type, const std::list<octave_value_list>& idx,
+           int nargout, size_t& skip, const cdef_class& context,
+           bool auto_add);
+
+  octave_value
+  subsasgn (const std::string& type, const std::list<octave_value_list>& idx,
+            const octave_value& rhs);
+
+private:
+  Array<cdef_object> array;
+
+private:
+  void fill_empty_values (void) { fill_empty_values (array); }
+
+  void fill_empty_values (Array<cdef_object>& arr);
+
+  // Private copying!
+  cdef_object_array (const cdef_object_array& obj)
+    : cdef_object_base (obj), array (obj.array) { }
+
+  // No assignment!
+  cdef_object_array& operator = (const cdef_object_array&);
+};
+
+class
+cdef_object_scalar : public cdef_object_base
+{
+public:
+  cdef_object_scalar (void) : cdef_object_base () { }
+
+  ~cdef_object_scalar (void) { }
+
+  dim_vector dims (void) const { return dim_vector (1, 1); }
+
+  void put (const std::string& pname, const octave_value& val)
+    { map.assign (pname, val); }
+
+  octave_value get (const std::string& pname) const
+    {
+      Cell val = map.contents (pname);
+
+      if (val.numel () > 0)
+        return val(0, 0);
+      else
+        {
+          error ("get: unknown slot: %s", pname.c_str ());
+          return octave_value ();
+        }
+    }
+
+  octave_value_list
+  subsref (const std::string& type, const std::list<octave_value_list>& idx,
+           int nargout, size_t& skip, const cdef_class& context,
+           bool auto_add);
+
+  octave_value
+  subsasgn (const std::string& type, const std::list<octave_value_list>& idx,
+            const octave_value& rhs);
+
+  void mark_for_construction (const cdef_class&);
+
+  bool is_constructed_for (const cdef_class& cls) const;
+
+  bool is_partially_constructed_for (const cdef_class& cls) const;
+
+  void mark_as_constructed (void) { ctor_list.clear (); }
+
+  void mark_as_constructed (const cdef_class& cls) { ctor_list.erase (cls); }
+
+  bool is_constructed (void) const { return ctor_list.empty (); }
+
+protected:
+  // Object property values
+  octave_scalar_map map;
+
+  // Internal/temporary structure used during object construction
+  std::map< cdef_class, std::list<cdef_class> > ctor_list;
+
+protected:
+  // Restricted object copying!
+  cdef_object_scalar (const cdef_object_scalar& obj)
+    : cdef_object_base (obj), map (obj.map), ctor_list (obj.ctor_list) { }
+
+private:
+  // No assignment!
+  cdef_object_scalar& operator = (const cdef_object_scalar&);
+};
+
+class
+handle_cdef_object : public cdef_object_scalar
+{
+public:
+  handle_cdef_object (void)
+      : cdef_object_scalar () { }
+
+  ~handle_cdef_object (void);
+
+  cdef_object_rep* clone (void) const
+    {
+      handle_cdef_object *obj = const_cast<handle_cdef_object *> (this);
+      obj->refcount++;
+      return obj;
+    }
+
+  cdef_object_rep* copy (void) const
+    { return new handle_cdef_object (*this); }
+
+  bool is_valid (void) const { return true; }
+
+  bool is_handle_object (void) const { return true; }
+
+protected:
+  // Restricted copying!
+  handle_cdef_object (const handle_cdef_object& obj)
+    : cdef_object_scalar (obj) { }
+
+private:
+  // No assignment
+  handle_cdef_object& operator = (const handle_cdef_object&);
+};
+
+class
+value_cdef_object : public cdef_object_scalar
+{
+public:
+  value_cdef_object (void)
+      : cdef_object_scalar () { }
+
+  ~value_cdef_object (void);
+
+  cdef_object_rep* clone (void) const
+    { return new value_cdef_object (*this); }
+
+  cdef_object_rep* copy (void) const { return clone (); }
+
+  bool is_valid (void) const { return true; }
+
+  bool is_value_object (void) const { return true; }
+
+private:
+  // Private copying!
+  value_cdef_object (const value_cdef_object& obj)
+    : cdef_object_scalar (obj) { }
+
+  // No assignment!
+  value_cdef_object& operator = (const value_cdef_object&);
+};
+
+class
+cdef_meta_object_rep : public handle_cdef_object
+{
+public:
+  cdef_meta_object_rep (void)
+    : handle_cdef_object () { }
+
+  ~cdef_meta_object_rep (void) { }
+
+  cdef_object_rep* copy (void) const
+    { return new cdef_meta_object_rep (*this); }
+
+  bool is_meta_object (void) const { return true; }
+
+  virtual bool is_class (void) const { return false; }
+
+  virtual bool is_property (void) const { return false; }
+
+  virtual bool is_method (void) const { return false; }
+
+  virtual bool is_package (void) const { return false; }
+  
+  virtual octave_value_list
+  meta_subsref (const std::string& /* type */,
+                const std::list<octave_value_list>& /* idx */,
+                int /* nargout */)
+    {
+      ::error ("subsref: invalid meta object");
+      return octave_value_list ();
+    }
+
+  virtual void meta_release (void) { }
+
+  virtual bool meta_is_postfix_index_handled (char /* type */) const
+    { return false; }
+
+protected:
+  // Restricted copying!
+  cdef_meta_object_rep (const cdef_meta_object_rep& obj)
+    : handle_cdef_object (obj) { }
+
+private:
+  // No assignment!
+  cdef_meta_object_rep& operator = (const cdef_meta_object_rep&);
+};
+
+class
+cdef_meta_object : public cdef_object
+{
+public:
+  cdef_meta_object (void)
+    : cdef_object () { }
+
+  cdef_meta_object (const cdef_meta_object& obj)
+    : cdef_object (obj) { }
+
+  cdef_meta_object (cdef_meta_object_rep *r)
+    : cdef_object (r) { }
+
+  // Object consistency is checked in sub-classes.
+  cdef_meta_object (const cdef_object& obj)
+    : cdef_object (obj) { }
+
+  ~cdef_meta_object (void) { }
+
+  bool is_class (void) const { return get_rep ()->is_class (); }
+
+  bool is_property (void) const { return get_rep ()->is_property (); }
+
+  bool is_method (void) const { return get_rep ()->is_method (); }
+
+  bool is_package (void) const { return get_rep ()->is_package (); }
+
+  octave_value_list
+  meta_subsref (const std::string& type,
+                const std::list<octave_value_list>& idx, int nargout)
+    { return get_rep ()->meta_subsref (type, idx, nargout); }
+
+  void meta_release (void) { get_rep ()->meta_release (); }
+
+  bool meta_is_postfix_index_handled (char type) const
+    { return get_rep ()->meta_is_postfix_index_handled (type); }
+
+private:
+  cdef_meta_object_rep* get_rep (void)
+    { return dynamic_cast<cdef_meta_object_rep *> (cdef_object::get_rep ()); }
+  
+  const cdef_meta_object_rep* get_rep (void) const
+    { return dynamic_cast<const cdef_meta_object_rep *> (cdef_object::get_rep ()); }
+};
+
+class
+cdef_class : public cdef_meta_object
+{
+private:
+
+  class
+  cdef_class_rep : public cdef_meta_object_rep
+  {
+  public:
+    cdef_class_rep (void)
+        : cdef_meta_object_rep (), member_count (0), handle_class (false),
+          object_count (0), meta (false) { }
+
+    cdef_class_rep (const std::list<cdef_class>& superclasses);
+
+    cdef_object_rep* copy (void) const { return new cdef_class_rep (*this); }
+
+    bool is_class (void) const { return true; }
+
+    std::string get_name (void) const
+      { return get ("Name").string_value (); }
+
+    void set_name (const std::string& nm) { put ("Name", nm); }
+
+    bool is_abstract (void) const { return get ("Abstract").bool_value (); }
+
+    bool is_sealed (void) const { return get ("Sealed").bool_value (); }
+
+    cdef_method find_method (const std::string& nm, bool local = false);
+
+    void install_method (const cdef_method& meth);
+
+    Cell get_methods (void);
+
+    cdef_property find_property (const std::string& nm);
+
+    void install_property (const cdef_property& prop);
+
+    Cell get_properties (int mode);
+
+    std::map<std::string, cdef_property> get_property_map (int mode);
+
+    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,
+                          int mode = 0);
+
+    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 (int mode = property_normal)
+    { return get_rep ()->get_properties (mode); }
+
+  std::map<std::string, cdef_property>
+  get_property_map (int mode = property_normal)
+    { return get_rep ()->get_property_map (mode); }
+
+  string_vector get_names (void) { return get_rep ()->get_names (); }
+
+  bool is_abstract (void) const { return get_rep ()->is_abstract (); }
+
+  bool is_sealed (void) const { return get_rep ()->is_sealed (); }
+
+  void set_directory (const std::string& dir)
+    { get_rep ()->set_directory (dir); }
+
+  std::string get_directory (void) const
+    { return get_rep ()->get_directory (); }
+
+  std::string get_name (void) const
+    { return get_rep ()->get_name (); }
+
+  bool is_builtin (void) const
+    { return get_directory ().empty (); }
+
+  void delete_object (cdef_object obj)
+    { get_rep ()->delete_object (obj); }
+
+  static cdef_class make_meta_class (tree_classdef* t,
+                                     bool is_at_folder = false);
+
+  octave_function* get_method_function (const std::string& nm);
+
+  octave_function* get_constructor_function (void)
+    { return get_method_function (get_name ()); }
+
+  octave_value construct (const octave_value_list& args)
+    { return get_rep ()->construct (args); }
+
+  cdef_object construct_object (const octave_value_list& args)
+    { return get_rep ()->construct_object (args); }
+
+  void initialize_object (cdef_object& obj)
+    { get_rep ()->initialize_object (obj); }
+
+  void run_constructor (cdef_object& obj, const octave_value_list& args)
+    { get_rep ()->run_constructor (obj, args); }
+
+  void mark_as_handle_class (void)
+    { get_rep ()->mark_as_handle_class (); }
+
+  bool is_handle_class (void) const
+    { return get_rep ()->is_handle_class (); }
+
+  void mark_as_meta_class (void) { get_rep ()->mark_as_meta_class (); }
+
+  bool is_meta_class (void) const { return get_rep ()->is_meta_class (); }
+
+  static const cdef_class& meta_class (void) { return _meta_class; }
+  static const cdef_class& meta_property (void) { return _meta_property; }
+  static const cdef_class& meta_method (void) { return _meta_method; }
+  static const cdef_class& meta_package (void) { return _meta_package; }
+
+  void register_object (void) { get_rep ()->register_object (); }
+
+  void unregister_object (void) { get_rep ()->unregister_object (); }
+
+public:
+  enum
+    {
+      property_normal,
+      property_inherited,
+      property_all
+    };
+
+private:
+  cdef_class_rep* get_rep (void)
+    { return dynamic_cast<cdef_class_rep *> (cdef_object::get_rep ()); }
+  
+  const cdef_class_rep* get_rep (void) const
+    { return dynamic_cast<const cdef_class_rep *> (cdef_object::get_rep ()); }
+
+  friend bool operator == (const cdef_class&, const cdef_class&);
+  friend bool operator != (const cdef_class&, const cdef_class&);
+  friend bool operator < (const cdef_class&, const cdef_class&);
+
+private:
+  static cdef_class _meta_class;
+  static cdef_class _meta_property;
+  static cdef_class _meta_method;
+  static cdef_class _meta_package;
+
+  friend void install_classdef (void);
+};
+
+inline bool
+operator == (const cdef_class& clsa, const cdef_class& clsb)
+// FIXME: is this really the right way to check class equality?
+{ return (clsa.get_rep () == clsb.get_rep ()); }
+
+inline bool
+operator != (const cdef_class& clsa, const cdef_class& clsb)
+{ return ! (clsa == clsb); }
+
+// This is only to be able to use cdef_class as map keys.
+inline bool
+operator < (const cdef_class& clsa, const cdef_class& clsb)
+{ return clsa.get_rep () < clsb.get_rep (); }
+
+class
+cdef_property : public cdef_meta_object
+{
+  friend class cdef_class;
+
+private:
+
+  class
+  cdef_property_rep : public cdef_meta_object_rep
+  {
+  public:
+    cdef_property_rep (void)
+        : cdef_meta_object_rep () { }
+
+    cdef_object_rep* copy (void) const { return new cdef_property_rep (*this); }
+
+    bool is_property (void) const { return true; }
+
+    std::string get_name (void) const { return get("Name").string_value (); }
+
+    void set_name (const std::string& nm) { put ("Name", nm); }
+
+    bool is_constant (void) const { return get("Constant").bool_value (); }
+
+    octave_value get_value (bool do_check_access = true,
+                            const std::string& who = std::string ());
+
+    octave_value get_value (const cdef_object& obj,
+                            bool do_check_access = true,
+                            const std::string& who = std::string ());
+
+    void set_value (cdef_object& obj, const octave_value& val,
+                    bool do_check_access = true,
+                    const std::string& who = std::string ());
+
+    bool check_get_access (void) const;
+
+    bool check_set_access (void) const;
+
+  private:
+    cdef_property_rep (const cdef_property_rep& p)
+      : cdef_meta_object_rep (p) { }
+
+    bool is_recursive_set (const cdef_object& obj) const;
+    
+    cdef_property wrap (void)
+      {
+        refcount++;
+        return cdef_property (this);
+      }
+  };
+
+public:
+  cdef_property (void) : cdef_meta_object () { }
+
+  cdef_property (const std::string& nm)
+      : cdef_meta_object (new cdef_property_rep ())
+    { get_rep ()->set_name (nm); }
+
+  cdef_property (const cdef_property& prop)
+      : cdef_meta_object (prop) { }
+
+  cdef_property (const cdef_object& obj)
+      : cdef_meta_object (obj)
+    {
+      // This should never happen...
+      if (! is_property ())
+        error ("internal error: invalid assignment from %s to meta.property object",
+               class_name ().c_str ());
+    }
+
+  cdef_property& operator = (const cdef_property& prop)
+    {
+      cdef_object::operator= (prop);
+
+      return *this;
+    }
+
+  octave_value get_value (const cdef_object& obj, bool do_check_access = true,
+                          const std::string& who = std::string ())
+    { return get_rep ()->get_value (obj, do_check_access, who); }
+
+  octave_value get_value (bool do_check_access = true,
+                          const std::string& who = std::string ())
+    { return get_rep ()->get_value (do_check_access, who); }
+
+  void set_value (cdef_object& obj, const octave_value& val,
+                  bool do_check_access = true,
+                  const std::string& who = std::string ())
+    { get_rep ()->set_value (obj, val, do_check_access, who); }
+
+  bool check_get_access (void) const
+    { return get_rep ()->check_get_access (); }
+  
+  bool check_set_access (void) const
+    { return get_rep ()->check_set_access (); }
+
+  std::string get_name (void) const { return get_rep ()->get_name (); }
+
+  bool is_constant (void) const { return get_rep ()->is_constant (); }
+
+private:
+  cdef_property_rep* get_rep (void)
+    { return dynamic_cast<cdef_property_rep *> (cdef_object::get_rep ()); }
+  
+  const cdef_property_rep* get_rep (void) const
+    { return dynamic_cast<const cdef_property_rep *> (cdef_object::get_rep ()); }
+};
+
+class
+cdef_method : public cdef_meta_object
+{
+  friend class cdef_class;
+
+private:
+
+  class
+  cdef_method_rep : public cdef_meta_object_rep
+  {
+  public:
+    cdef_method_rep (void)
+      : cdef_meta_object_rep (), function (), dispatch_type ()
+      { }
+
+    cdef_object_rep* copy (void) const { return new cdef_method_rep(*this); }
+
+    bool is_method (void) const { return true; }
+
+    std::string get_name (void) const { return get("Name").string_value (); }
+
+    void set_name (const std::string& nm) { put ("Name", nm); }
+
+    bool is_static (void) const { return get("Static").bool_value (); }
+
+    octave_value get_function (void) const { return function; }
+
+    void set_function (const octave_value& fcn) { function = fcn; }
+
+    bool check_access (void) const;
+
+    bool is_external (void) const { return ! dispatch_type.empty (); }
+
+    void mark_as_external (const std::string& dtype)
+      { dispatch_type = dtype; }
+
+    octave_value_list execute (const octave_value_list& args, int nargout,
+                               bool do_check_access = true,
+                               const std::string& who = std::string ());
+
+    octave_value_list execute (const cdef_object& obj,
+                               const octave_value_list& args, int nargout,
+                               bool do_check_access = true,
+                               const std::string& who = std::string ());
+
+    bool is_constructor (void) const;
+
+    octave_value_list
+    meta_subsref (const std::string& type,
+                  const std::list<octave_value_list>& idx, int nargout);
+
+    bool meta_is_postfix_index_handled (char type) const
+      { return (type == '(' || type == '.'); }
+
+  private:
+    cdef_method_rep (const cdef_method_rep& m)
+      : cdef_meta_object_rep (m), function (m.function),
+        dispatch_type (m.dispatch_type)
+      { }
+
+    void check_method (void);
+
+    cdef_method wrap (void)
+      {
+        refcount++;
+        return cdef_method (this);
+      }
+
+  private:
+    octave_value function;
+
+    // When non-empty, the method is externally defined and this member
+    // is used to cache the dispatch type to look for the method.
+    std::string dispatch_type;
+  };
+
+public:
+  cdef_method (void) : cdef_meta_object () { }
+
+  cdef_method (const std::string& nm)
+      : cdef_meta_object (new cdef_method_rep ())
+    { get_rep ()->set_name (nm); }
+
+  cdef_method (const cdef_method& meth)
+      : cdef_meta_object (meth) { }
+
+  cdef_method (const cdef_object& obj)
+      : cdef_meta_object (obj)
+    {
+      // This should never happen...
+      if (! is_method ())
+        error ("internal error: invalid assignment from %s to meta.method object",
+               class_name ().c_str ());
+    }
+
+  cdef_method& operator = (const cdef_method& meth)
+    {
+      cdef_object::operator= (meth);
+
+      return *this;
+    }
+
+  /* normal invokation */
+  octave_value_list execute (const octave_value_list& args, int nargout,
+                             bool do_check_access = true,
+                             const std::string& who = std::string ())
+    { return get_rep ()->execute (args, nargout, do_check_access, who); }
+
+  /* dot-invokation: object is pushed as 1st argument */
+  octave_value_list execute (const cdef_object& obj,
+                             const octave_value_list& args, int nargout,
+                             bool do_check_access = true,
+                             const std::string& who = std::string ())
+    { return get_rep ()->execute (obj, args, nargout, do_check_access, who); }
+
+  bool check_access (void) const { return get_rep ()->check_access (); }
+  
+  std::string get_name (void) const { return get_rep ()->get_name (); }
+
+  bool is_static (void) const { return get_rep ()->is_static (); }
+
+  void set_function (const octave_value& fcn)
+    { get_rep ()->set_function (fcn); }
+
+  octave_value get_function (void) const
+    { return get_rep ()->get_function (); }
+
+  bool is_constructor (void) const
+    { return get_rep ()->is_constructor (); }
+
+  bool is_external (void) const { return get_rep ()->is_external (); }
+
+  void mark_as_external (const std::string& dtype)
+    { get_rep ()->mark_as_external (dtype); }
+
+private:
+  cdef_method_rep* get_rep (void)
+    { return dynamic_cast<cdef_method_rep *> (cdef_object::get_rep ()); }
+  
+  const cdef_method_rep* get_rep (void) const
+    { return dynamic_cast<const cdef_method_rep *> (cdef_object::get_rep ()); }
+};
+
+inline cdef_class
+cdef_object_rep::get_class (void) const
+{
+  gripe_invalid_object ("get_class");
+  return cdef_class ();
+}
+
+inline std::string
+cdef_object_rep::class_name (void) const
+{ return get_class ().get_name (); }
+
+inline cdef_class
+cdef_object::get_class (void) const
+{ return rep->get_class (); }
+
+inline cdef_class
+cdef_object_base::get_class (void) const
+{ return cdef_class (klass); }
+
+inline void
+cdef_object_base::set_class (const cdef_class& cls)
+{
+  if ((klass.ok () && cls.ok () && cls != get_class ())
+      || (klass.ok () && ! cls.ok ())
+      || (! klass.ok () && cls.ok ()))
+    {
+      unregister_object ();
+      klass = cls;
+      register_object ();
+    }
+}
+
+inline void
+cdef_object_base::register_object (void)
+{
+  if (klass.ok ())
+    {
+      cdef_class cls (get_class ());
+
+      if (! error_state && cls.ok ())
+        cls.register_object ();
+    }
+}
+
+inline void
+cdef_object_base::unregister_object (void)
+{
+  if (klass.ok ())
+    {
+      cdef_class cls (get_class ());
+
+      if (! error_state && cls.ok ())
+        cls.unregister_object ();
+    }
+}
+
+inline cdef_object_rep*
+cdef_object_base::make_array (void) const
+{
+  cdef_object_rep* r = new cdef_object_array ();
+
+  r->set_class (get_class ());
+
+  return r;
+}
+
+inline cdef_method
+cdef_class::find_method (const std::string& nm, bool local)
+{ return get_rep ()->find_method (nm, local); }
+
+inline cdef_property
+cdef_class::find_property (const std::string& nm)
+{ return get_rep ()->find_property (nm); }
+
+class
+cdef_package : public cdef_meta_object
+{
+  friend class cdef_class;
+
+private:
+
+  class
+  cdef_package_rep : public cdef_meta_object_rep
+  {
+  public:
+    cdef_package_rep (void)
+      : cdef_meta_object_rep (), member_count (0) { }
+
+    ~cdef_package_rep (void) { }
+
+    cdef_object_rep* copy (void) const { return new cdef_package_rep (*this); }
+
+    bool is_package (void) const { return true; }
+
+    std::string get_name (void) const { return get("Name").string_value (); }
+
+    void set_name (const std::string& nm) { put ("Name", nm); }
+
+    void install_class (const cdef_class& cls, const std::string& nm);
+
+    void install_function (const octave_value& fcn, const std::string& nm);
+
+    void install_package (const cdef_package& pack, const std::string& nm);
+
+    Cell get_classes (void) const;
+
+    Cell get_functions (void) const;
+
+    Cell get_packages (void) const;
+
+    octave_idx_type static_count (void) const { return member_count; }
+
+    void destroy (void)
+      {
+        if (member_count)
+          {
+            refcount++;
+            cdef_package lock (this);
+
+            member_count = 0;
+            class_map.clear ();
+            package_map.clear ();
+          }
+        else
+          delete this;
+      }
+
+    octave_value_list
+    meta_subsref (const std::string& type,
+                  const std::list<octave_value_list>& idx, int nargout);
+
+    void meta_release (void);
+
+    bool meta_is_postfix_index_handled (char type) const
+      { return (type == '.'); }
+
+    octave_value find (const std::string& nm);
+
+  private:
+    std::string full_name;
+    std::map<std::string, cdef_class> class_map;
+    std::map<std::string, octave_value> function_map;
+    std::map<std::string, cdef_package> package_map;
+
+    // The number of registered members in this package (classes, packages).
+    // This only accounts for the members that back-reference to this package.
+    octave_idx_type member_count;
+
+    typedef std::map<std::string, cdef_class>::iterator class_iterator;
+    typedef std::map<std::string, cdef_class>::const_iterator class_const_iterator;
+    typedef std::map<std::string, octave_value>::iterator function_iterator;
+    typedef std::map<std::string, octave_value>::const_iterator function_const_iterator;
+    typedef std::map<std::string, cdef_package>::iterator package_iterator;
+    typedef std::map<std::string, cdef_package>::const_iterator package_const_iterator;
+
+  private:
+    cdef_package_rep (const cdef_package_rep& p)
+      : cdef_meta_object_rep (p), full_name (p.full_name),
+        class_map (p.class_map), function_map (p.function_map),
+        package_map (p.package_map), member_count (p.member_count)
+      { }
+
+    cdef_package wrap (void)
+      {
+        refcount++;
+        return cdef_package (this);
+      }
+  };
+
+public:
+  cdef_package (void) : cdef_meta_object () { }
+
+  cdef_package (const std::string& nm)
+      : cdef_meta_object (new cdef_package_rep ())
+    { get_rep ()->set_name (nm); }
+
+  cdef_package (const cdef_package& pack)
+    : cdef_meta_object (pack) { }
+
+  cdef_package (const cdef_object& obj)
+      : cdef_meta_object (obj)
+    {
+      // This should never happen...
+      if (! is_package ())
+        error ("internal error: invalid assignment from %s to meta.package object",
+               class_name ().c_str ());
+    }
+
+  cdef_package& operator = (const cdef_package& pack)
+    {
+      cdef_object::operator= (pack);
+
+      return *this;
+    }
+
+  void install_class (const cdef_class& cls, const std::string& nm)
+    { get_rep ()->install_class (cls, nm); }
+
+  void install_function (const octave_value& fcn, const std::string& nm)
+    { get_rep ()->install_function (fcn, nm); }
+
+  void install_package (const cdef_package& pack, const std::string& nm)
+    { get_rep ()->install_package (pack, nm); }
+
+  Cell get_classes (void) const
+    { return get_rep ()->get_classes (); }
+
+  Cell get_functions (void) const
+    { return get_rep ()->get_functions (); }
+
+  Cell get_packages (void) const
+    { return get_rep ()->get_packages (); }
+
+  std::string get_name (void) const { return get_rep ()->get_name (); }
+
+  octave_value find (const std::string& nm) { return get_rep ()->find (nm); }
+
+  static const cdef_package& meta (void) { return _meta; }
+
+private:
+  cdef_package_rep* get_rep (void)
+    { return dynamic_cast<cdef_package_rep *> (cdef_object::get_rep ()); }
+  
+  const cdef_package_rep* get_rep (void) const
+    { return dynamic_cast<const cdef_package_rep *> (cdef_object::get_rep ()); }
+
+private:
+  static cdef_package _meta;
+
+  friend void install_classdef (void);
+};
+
+class
+octave_classdef : public octave_base_value
+{
+public:
+  octave_classdef (void)
+      : octave_base_value (), object () { }
+
+  octave_classdef (const cdef_object& obj)
+      : octave_base_value (), object (obj) { }
+
+  octave_classdef (const octave_classdef& obj)
+      : octave_base_value (obj), object (obj.object) { }
+
+  octave_base_value* clone (void) const
+    { return new octave_classdef (object.clone ()); }
+
+  octave_base_value* empty_clone (void) const
+    { return new octave_classdef (object.empty_clone ()); }
+
+  cdef_object get_object (void) const { return object; }
+
+  cdef_object& get_object_ref (void) { return object; }
+
+  bool is_defined (void) const { return true; }
+
+  bool is_map (void) const { return false; }
+
+  bool is_object (void) const { return true; }
+
+  bool is_classdef_object (void) const { return true; }
+
+  void print (std::ostream& os, bool pr_as_read_syntax = false);
+
+  void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
+
+  bool print_name_tag (std::ostream& os, const std::string& name) const;
+
+  void print_with_name (std::ostream& os, const std::string& name,
+                        bool print_padding = true);
+
+  bool is_instance_of (const std::string& cls_name) const;
+
+  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 (); }
+
+  octave_map map_value (void) const { return object.map_value (); }
+
+  dim_vector dims (void) const { return object.dims (); }
+
+private:
+  cdef_object object;
+
+private:
+  DECLARE_OCTAVE_ALLOCATOR
+
+public:
+  int type_id (void) const { return t_id; }
+  std::string type_name (void) const { return t_name; }
+  std::string class_name (void) const { return object.class_name (); }
+
+  static int static_type_id (void) { return t_id; }
+  static std::string static_type_name (void) { return t_name; }
+  static std::string static_class_name (void) { return "<unknown>"; }
+  static void register_type (void);
+
+private:
+  static int t_id;
+
+  static const std::string t_name;
+};
+
+inline octave_value
+to_ov (const cdef_object& obj)
+{
+  if (obj.ok ())
+    return octave_value (new octave_classdef (obj));
+  else
+    return octave_value (Matrix ());
+}
+
+inline octave_value
+to_ov (const octave_value& ov)
+{ return ov; }
+
+inline cdef_object
+to_cdef (const octave_value& val)
+{
+  if (val.type_name () == "object")
+    return dynamic_cast<octave_classdef *> (val.internal_rep ())->get_object ();
+  else
+    {
+      error ("cannot convert `%s' into `object'", val.type_name().c_str ());
+      return cdef_object ();
+    }
+}
+
+inline cdef_object&
+to_cdef_ref (const octave_value& val)
+{
+  static cdef_object empty;
+
+  if (val.type_name () == "object")
+    return dynamic_cast<octave_classdef *> (val.internal_rep ())->get_object_ref ();
+  else
+    {
+      error ("cannot convert `%s' into `object'", val.type_name().c_str ());
+      return empty;
+    }
+}
+
+inline cdef_object
+to_cdef (const cdef_object& obj)
+{ return obj; }
+
+OCTINTERP_API void install_classdef (void);
+
+class
+cdef_manager
+{
+public:
+
+  static cdef_class find_class (const std::string& name,
+                                bool error_if_not_found = true,
+                                bool load_if_not_found = true)
+    {
+      if (instance_ok ())
+        return instance->do_find_class (name, error_if_not_found,
+                                        load_if_not_found);
+
+      return cdef_class ();
+    }
+
+  static octave_function* find_method_symbol (const std::string& method_name,
+                                              const std::string& class_name)
+    {
+      if (instance_ok ())
+        return instance->do_find_method_symbol (method_name, class_name);
+
+      return 0;
+    }
+
+  static cdef_package find_package (const std::string& name,
+                                    bool error_if_not_found = true,
+                                    bool load_if_not_found = true)
+    {
+      if (instance_ok ())
+        return instance->do_find_package (name, error_if_not_found,
+                                          load_if_not_found);
+
+      return cdef_package ();
+    }
+
+  static octave_function* find_package_symbol (const std::string& pack_name)
+    {
+      if (instance_ok ())
+        return instance->do_find_package_symbol (pack_name);
+
+      return 0;
+    }
+
+  static void register_class (const cdef_class& cls)
+    {
+      if (instance_ok ())
+        instance->do_register_class (cls);
+    }
+
+  static void unregister_class (const cdef_class& cls)
+    {
+      if (instance_ok ())
+        instance->do_unregister_class (cls);
+    }
+
+  static void register_package (const cdef_package& pkg)
+    {
+      if (instance_ok ())
+        instance->do_register_package (pkg);
+    }
+
+  static void unregister_package (const cdef_package& pkg)
+    {
+      if (instance_ok ())
+        instance->do_unregister_package (pkg);
+    }
+
+private:
+
+  cdef_manager (void) { }
+
+  cdef_manager (const cdef_manager&);
+
+  cdef_manager& operator = (const cdef_manager&);
+
+  ~cdef_manager (void) { }
+
+  static void create_instance (void);
+
+  static bool instance_ok (void)
+    {
+      bool retval = true;
+
+      if (! instance)
+        create_instance ();
+
+      if (! instance)
+        {
+          ::error ("unable to create cdef_manager!");
+
+          retval = false;
+        }
+
+      return retval;
+    }
+
+  static void cleanup_instance (void)
+    {
+      delete instance;
+
+      instance = 0;
+    }
+
+  cdef_class do_find_class (const std::string& name, bool error_if_not_found,
+                            bool load_if_not_found);
+
+  octave_function* do_find_method_symbol (const std::string& method_name,
+                                          const std::string& class_name);
+
+  cdef_package do_find_package (const std::string& name,
+                                bool error_if_not_found,
+                                bool load_if_not_found);
+
+  octave_function* do_find_package_symbol (const std::string& pack_name);
+
+  void do_register_class (const cdef_class& cls)
+    { all_classes[cls.get_name ()] = cls; }
+
+  void do_unregister_class (const cdef_class& cls)
+    { all_classes.erase(cls.get_name ()); }
+
+  void do_register_package (const cdef_package& pkg)
+    { all_packages[pkg.get_name ()] = pkg; }
+
+  void do_unregister_package (const cdef_package& pkg)
+    { all_packages.erase(pkg.get_name ()); }
+
+private:
+
+  // The single cdef_manager instance
+  static cdef_manager *instance;
+
+  // All registered/loaded classes
+  std::map<std::string, cdef_class> all_classes;
+
+  // All registered/loaded packages
+  std::map<std::string, cdef_package> all_packages;
+};
+
+#endif
+
+/*
+;;; Local Variables: ***
+;;; mode: C++ ***
+;;; End: ***
+*/
--- a/libinterp/octave-value/ov-colon.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-colon.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -35,7 +35,7 @@
                                      "magic-colon", "magic-colon");
 
 void
-octave_magic_colon::print (std::ostream& os, bool) const
+octave_magic_colon::print (std::ostream& os, bool)
 {
   indent (os);
   print_raw (os);
--- a/libinterp/octave-value/ov-colon.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-colon.h	Mon Jan 12 09:17:35 2015 -0800
@@ -67,7 +67,7 @@
 
   bool is_magic_colon (void) const { return true; }
 
-  void print (std::ostream& os, bool pr_as_read_syntax = false) const;
+  void print (std::ostream& os, bool pr_as_read_syntax = false);
 
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
 
--- a/libinterp/octave-value/ov-complex.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-complex.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -105,7 +105,7 @@
 double
 octave_complex::double_value (bool force_conversion) const
 {
-  double retval = lo_ieee_nan_value ();
+  double retval;
 
   if (! force_conversion)
     gripe_implicit_conversion ("Octave:imag-to-real",
@@ -119,7 +119,7 @@
 float
 octave_complex::float_value (bool force_conversion) const
 {
-  float retval = lo_ieee_float_nan_value ();
+  float retval;
 
   if (! force_conversion)
     gripe_implicit_conversion ("Octave:imag-to-real",
@@ -315,7 +315,8 @@
                            bool /* save_as_floats */)
 {
   hsize_t dimens[3];
-  hid_t space_hid = -1, type_hid = -1, data_hid = -1;
+  hid_t space_hid, type_hid, data_hid;
+  space_hid = type_hid = data_hid = -1;
   bool retval = true;
 
   space_hid = H5Screate_simple (0, dimens, 0);
--- a/libinterp/octave-value/ov-cx-diag.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-cx-diag.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -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 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-cx-mat.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -152,7 +152,7 @@
     gripe_implicit_conversion ("Octave:imag-to-real",
                                "complex matrix", "real matrix");
 
-  retval = ::real (matrix.matrix_value ());
+  retval = ::real (ComplexMatrix (matrix));
 
   return retval;
 }
@@ -166,7 +166,7 @@
     gripe_implicit_conversion ("Octave:imag-to-real",
                                "complex matrix", "real matrix");
 
-  retval = ::real (matrix.matrix_value ());
+  retval = ::real (ComplexMatrix (matrix));
 
   return retval;
 }
@@ -214,13 +214,13 @@
 ComplexMatrix
 octave_complex_matrix::complex_matrix_value (bool) const
 {
-  return matrix.matrix_value ();
+  return ComplexMatrix (matrix);
 }
 
 FloatComplexMatrix
 octave_complex_matrix::float_complex_matrix_value (bool) const
 {
-  return FloatComplexMatrix (matrix.matrix_value ());
+  return FloatComplexMatrix (ComplexMatrix (matrix));
 }
 
 boolNDArray
@@ -270,7 +270,7 @@
     gripe_implicit_conversion ("Octave:imag-to-real",
                                "complex matrix", "real matrix");
 
-  retval = SparseMatrix (::real (matrix.matrix_value ()));
+  retval = SparseMatrix (::real (ComplexMatrix (matrix)));
 
   return retval;
 }
@@ -278,7 +278,7 @@
 SparseComplexMatrix
 octave_complex_matrix::sparse_complex_matrix_value (bool) const
 {
-  return SparseComplexMatrix (matrix.matrix_value ());
+  return SparseComplexMatrix (ComplexMatrix (matrix));
 }
 
 octave_value
@@ -302,7 +302,7 @@
   if (matrix.ndims () == 2
       && (matrix.rows () == 1 || matrix.columns () == 1))
     {
-      ComplexMatrix mat = matrix.matrix_value ();
+      ComplexMatrix mat (matrix);
 
       retval = mat.diag (m, n);
     }
@@ -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 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-cx-sparse.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -241,16 +241,16 @@
 
   int32_t itmp;
   // Use negative value for ndims to be consistent with other formats
-  itmp= -2;
+  itmp = -2;
   os.write (reinterpret_cast<char *> (&itmp), 4);
 
-  itmp= nr;
+  itmp = nr;
   os.write (reinterpret_cast<char *> (&itmp), 4);
 
-  itmp= nc;
+  itmp = nc;
   os.write (reinterpret_cast<char *> (&itmp), 4);
 
-  itmp= nz;
+  itmp = nz;
   os.write (reinterpret_cast<char *> (&itmp), 4);
 
   save_type st = LS_DOUBLE;
@@ -390,7 +390,8 @@
   if (group_hid < 0)
     return false;
 
-  hid_t space_hid = -1, data_hid = -1;
+  hid_t space_hid, data_hid;
+  space_hid = data_hid = -1;
   bool retval = true;
   SparseComplexMatrix m = sparse_complex_matrix_value ();
   octave_idx_type tmp;
@@ -636,7 +637,7 @@
 #else
   group_hid = H5Gopen (loc_id, name);
 #endif
-  if (group_hid < 0 ) return false;
+  if (group_hid < 0) return false;
 
 #if HAVE_HDF5_18
   data_hid = H5Dopen (group_hid, "nr", H5P_DEFAULT);
--- a/libinterp/octave-value/ov-fcn-handle.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-fcn-handle.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -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);
@@ -1315,7 +1316,7 @@
 %! endif
 %! for i = 1:numel (modes)
 %!   mode = modes{i};
-%!   nm = tmpnam ();
+%!   nm = tempname ();
 %!   unwind_protect
 %!     f2 (1); # bug #33857
 %!     save (mode, nm, "f2", "g2", "hm2", "hdld2", "hbi2");
@@ -1368,7 +1369,7 @@
 %! endif
 %! for i = 1:numel (modes)
 %!   mode = modes{i};
-%!   nm = tmpnam ();
+%!   nm = tempname ();
 %!   unwind_protect
 %!     fcn_handle_save_recurse (2, mode, nm, f2, g2, hm2, hdld2, hbi2);
 %!     clear f2 g2 hm2 hdld2 hbi2
@@ -1386,7 +1387,7 @@
 */
 
 void
-octave_fcn_handle::print (std::ostream& os, bool pr_as_read_syntax) const
+octave_fcn_handle::print (std::ostream& os, bool pr_as_read_syntax)
 {
   print_raw (os, pr_as_read_syntax);
   newline (os);
@@ -1572,7 +1573,8 @@
   // for any class.
   if (local_funcs && fptr
       && (fptr->is_subfunction () || fptr->is_private_function ()
-          || fptr->is_class_constructor ()))
+          || fptr->is_class_constructor ()
+          || fptr->is_classdef_constructor ()))
     {
       // Locally visible function.
       retval = octave_value (new octave_fcn_handle (f, tnm));
@@ -1848,10 +1850,11 @@
 
   if (nargin == 1 || nargin == 2)
     {
-      std::string nm = args(0).string_value ();
-
-      if (! error_state)
-        retval = make_fcn_handle (nm, nargin != 2);
+      if (args(0).is_string ())
+        {
+          std::string nm = args(0).string_value ();
+          retval = make_fcn_handle (nm, nargin != 2);
+        }
       else
         error ("str2func: FCN_NAME must be a string");
     }
--- a/libinterp/octave-value/ov-fcn-handle.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-fcn-handle.h	Mon Jan 12 09:17:35 2015 -0800
@@ -153,7 +153,7 @@
   bool load_hdf5 (hid_t loc_id, const char *name);
 #endif
 
-  void print (std::ostream& os, bool pr_as_read_syntax = false) const;
+  void print (std::ostream& os, bool pr_as_read_syntax = false);
 
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
 
--- a/libinterp/octave-value/ov-fcn-inline.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-fcn-inline.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -284,14 +284,15 @@
 #else
   group_hid = H5Gcreate (loc_id, name, 0);
 #endif
-  if (group_hid < 0 ) return false;
+  if (group_hid < 0) return false;
 
   size_t len = 0;
   for (int i = 0; i < ifargs.length (); i++)
     if (len < ifargs(i).length ())
       len = ifargs(i).length ();
 
-  hid_t space_hid = -1, data_hid = -1, type_hid = -1;;
+  hid_t space_hid, data_hid, type_hid;
+  space_hid = data_hid = type_hid = -1;
   bool retval = true;
 
   // FIXME: Is there a better way of saving string vectors,
@@ -423,7 +424,7 @@
 #else
   group_hid = H5Gopen (loc_id, name);
 #endif
-  if (group_hid < 0 ) return false;
+  if (group_hid < 0) return false;
 
 #if HAVE_HDF5_18
   data_hid = H5Dopen (group_hid, "args", H5P_DEFAULT);
@@ -597,7 +598,7 @@
 #endif
 
 void
-octave_fcn_inline::print (std::ostream& os, bool pr_as_read_syntax) const
+octave_fcn_inline::print (std::ostream& os, bool pr_as_read_syntax)
 {
   print_raw (os, pr_as_read_syntax);
   newline (os);
@@ -852,9 +853,10 @@
        "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} formula (@var{fun})\n\
 Return a character string representing the inline function @var{fun}.\n\
+\n\
 Note that @code{char (@var{fun})} is equivalent to\n\
 @code{formula (@var{fun})}.\n\
-@seealso{argnames, inline, vectorize}\n\
+@seealso{char, argnames, inline, vectorize}\n\
 @end deftypefn")
 {
   octave_value retval;
--- a/libinterp/octave-value/ov-fcn-inline.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-fcn-inline.h	Mon Jan 12 09:17:35 2015 -0800
@@ -86,7 +86,7 @@
   bool load_hdf5 (hid_t loc_id, const char *name);
 #endif
 
-  void print (std::ostream& os, bool pr_as_read_syntax = false) const;
+  void print (std::ostream& os, bool pr_as_read_syntax = false);
 
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
 
--- a/libinterp/octave-value/ov-fcn.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-fcn.h	Mon Jan 12 09:17:35 2015 -0800
@@ -46,7 +46,8 @@
 
   octave_function (void)
     : relative (false), locked (false), private_function (false),
-      xdispatch_class (), my_name (), my_dir_name (), doc () { }
+      xdispatch_class (), xpackage_name (), my_name (), my_dir_name (),
+      doc () { }
 
   ~octave_function (void) { }
 
@@ -85,6 +86,10 @@
   virtual bool is_class_constructor (const std::string& = std::string ()) const
   { return false; }
 
+  virtual bool
+  is_classdef_constructor (const std::string& = std::string ()) const
+    { return false; }
+
   virtual bool is_class_method (const std::string& = std::string ()) const
   { return false; }
 
@@ -96,6 +101,10 @@
 
   std::string dispatch_class (void) const { return xdispatch_class; }
 
+  void stash_package_name (const std::string& pack) { xpackage_name = pack; }
+
+  std::string package_name (void) const { return xpackage_name; }
+
   virtual void
   mark_as_private_function (const std::string& cname = std::string ())
   {
@@ -152,6 +161,14 @@
 
   std::string name (void) const { return my_name; }
 
+  std::string canonical_name (void) const
+    {
+      if (xpackage_name.empty ())
+        return my_name;
+      else
+        return xpackage_name + "." + my_name;
+    }
+
   void document (const std::string& ds) { doc = ds; }
 
   std::string doc_string (void) const { return doc; }
@@ -160,6 +177,9 @@
 
   virtual void accept (tree_walker&) { }
 
+  virtual bool is_postfix_index_handled (char type) const
+    { return (type == '(' || type == '{'); }
+
 protected:
 
   octave_function (const std::string& nm,
@@ -181,6 +201,10 @@
   // to which the method belongs.
   std::string xdispatch_class;
 
+  // If this function is part of a package, this is the full name
+  // of the package to which the function belongs.
+  std::string xpackage_name;
+
   // The name of this function.
   std::string my_name;
 
--- a/libinterp/octave-value/ov-float.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-float.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -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 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-flt-complex.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -89,7 +89,7 @@
 double
 octave_float_complex::double_value (bool force_conversion) const
 {
-  double retval = lo_ieee_nan_value ();
+  double retval;
 
   if (! force_conversion)
     gripe_implicit_conversion ("Octave:imag-to-real",
@@ -103,7 +103,7 @@
 float
 octave_float_complex::float_value (bool force_conversion) const
 {
-  float retval = lo_ieee_float_nan_value ();
+  float retval;
 
   if (! force_conversion)
     gripe_implicit_conversion ("Octave:imag-to-real",
@@ -300,7 +300,8 @@
                                  bool /* save_as_floats */)
 {
   hsize_t dimens[3];
-  hid_t space_hid = -1, type_hid = -1, data_hid = -1;
+  hid_t space_hid, type_hid, data_hid;
+  space_hid = type_hid = data_hid = -1;
   bool retval = true;
 
   space_hid = H5Screate_simple (0, dimens, 0);
--- a/libinterp/octave-value/ov-flt-cx-diag.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-flt-cx-diag.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -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 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-flt-cx-mat.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -140,7 +140,7 @@
     gripe_implicit_conversion ("Octave:imag-to-real",
                                "complex matrix", "real matrix");
 
-  retval = ::real (matrix.matrix_value ());
+  retval = ::real (FloatComplexMatrix (matrix));
 
   return retval;
 }
@@ -154,7 +154,7 @@
     gripe_implicit_conversion ("Octave:imag-to-real",
                                "complex matrix", "real matrix");
 
-  retval = ::real (matrix.matrix_value ());
+  retval = ::real (FloatComplexMatrix (matrix));
 
   return retval;
 }
@@ -202,13 +202,13 @@
 ComplexMatrix
 octave_float_complex_matrix::complex_matrix_value (bool) const
 {
-  return matrix.matrix_value ();
+  return FloatComplexMatrix (matrix);
 }
 
 FloatComplexMatrix
 octave_float_complex_matrix::float_complex_matrix_value (bool) const
 {
-  return FloatComplexMatrix (matrix.matrix_value ());
+  return FloatComplexMatrix (matrix);
 }
 
 boolNDArray
@@ -290,7 +290,7 @@
   if (matrix.ndims () == 2
       && (matrix.rows () == 1 || matrix.columns () == 1))
     {
-      FloatComplexMatrix mat = matrix.matrix_value ();
+      FloatComplexMatrix mat (matrix);
 
       retval = mat.diag (m, n);
     }
@@ -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 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-flt-re-diag.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -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 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-flt-re-mat.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -127,13 +127,13 @@
 Matrix
 octave_float_matrix::matrix_value (bool) const
 {
-  return Matrix (matrix.matrix_value ());
+  return Matrix (FloatMatrix (matrix));
 }
 
 FloatMatrix
 octave_float_matrix::float_matrix_value (bool) const
 {
-  return matrix.matrix_value ();
+  return FloatMatrix (matrix);
 }
 
 Complex
@@ -181,13 +181,13 @@
 ComplexMatrix
 octave_float_matrix::complex_matrix_value (bool) const
 {
-  return ComplexMatrix (matrix.matrix_value ());
+  return ComplexMatrix (FloatMatrix (matrix));
 }
 
 FloatComplexMatrix
 octave_float_matrix::float_complex_matrix_value (bool) const
 {
-  return FloatComplexMatrix (matrix.matrix_value ());
+  return FloatComplexMatrix (FloatMatrix (matrix));
 }
 
 ComplexNDArray
@@ -268,7 +268,7 @@
   if (matrix.ndims () == 2
       && (matrix.rows () == 1 || matrix.columns () == 1))
     {
-      FloatMatrix mat = matrix.matrix_value ();
+      FloatMatrix mat (matrix);
 
       retval = mat.diag (m, n);
     }
@@ -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 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-intx.h	Mon Jan 12 09:17:35 2015 -0800
@@ -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 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-java.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -1150,7 +1150,8 @@
           if (jni_env->IsInstanceOf (jobj, cls))
             {
               jobjectArray jarr = reinterpret_cast<jobjectArray> (jobj);
-              int rows = jni_env->GetArrayLength (jarr), cols = 0;
+              int rows = jni_env->GetArrayLength (jarr);
+              int cols = 0;
 
               if (rows > 0)
                 {
@@ -1761,7 +1762,7 @@
 }
 
 void
-octave_java::print (std::ostream& os, bool) const
+octave_java::print (std::ostream& os, bool)
 {
   print_raw (os);
   newline (os);
@@ -2049,9 +2050,10 @@
 
       if (args.length () > 0)
         {
-          std::string classname = args(0).string_value ();
-          if (! error_state)
+          if (args(0).is_string ())
             {
+              std::string classname = args(0).string_value ();
+
               octave_value_list tmp;
               for (int i=1; i<args.length (); i++)
                 tmp(i-1) = args(i);
@@ -2113,9 +2115,10 @@
 
       if (args.length () > 1)
         {
-          std::string methodname = args(0).string_value ();
-          if (! error_state)
+          if (args(0).is_string ())
             {
+              std::string methodname = args(0).string_value ();
+
               octave_value_list tmp;
               for (int i=2; i<args.length (); i++)
                 tmp(i-2) = args(i);
@@ -2186,9 +2189,10 @@
 
       if (args.length () == 2)
         {
-          std::string name = args(1).string_value ();
-          if (! error_state)
+          if (args(1).is_string ())
             {
+              std::string name = args(1).string_value ();
+
               if (args(0).is_java ())
                 {
                   octave_java *jobj = TO_JAVA (args(0));
@@ -2248,9 +2252,10 @@
 
       if (args.length () == 3)
         {
-          std::string name = args(1).string_value ();
-          if (! error_state)
+          if (args(1).is_string ())
             {
+              std::string name = args(1).string_value ();
+
               if (args(0).is_java ())
                 {
                   octave_java *jobj = TO_JAVA (args(0));
--- a/libinterp/octave-value/ov-java.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-java.h	Mon Jan 12 09:17:35 2015 -0800
@@ -149,7 +149,7 @@
 
   dim_vector dims (void) const;
 
-  void print (std::ostream& os, bool pr_as_read_syntax = false) const;
+  void print (std::ostream& os, bool pr_as_read_syntax = false);
 
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
 
--- a/libinterp/octave-value/ov-lazy-idx.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-lazy-idx.h	Mon Jan 12 09:17:35 2015 -0800
@@ -128,7 +128,7 @@
   bool print_as_scalar (void) const
   { return make_value ().print_as_scalar (); }
 
-  void print (std::ostream& os, bool pr_as_read_syntax = false) const
+  void print (std::ostream& os, bool pr_as_read_syntax = false)
   { make_value ().print (os, pr_as_read_syntax); }
 
   void print_info (std::ostream& os, const std::string& prefix) const
--- a/libinterp/octave-value/ov-oncleanup.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-oncleanup.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -98,14 +98,9 @@
       error ("onCleanup: internal error: unhandled exception in cleanup action");
     }
 
-  // We don't want to ignore errors that occur in the cleanup code, so
-  // if an error is encountered there, leave error_state alone.
-  // Otherwise, set it back to what it was before.
+  // FIXME: can this happen now?
   if (error_state)
-    {
-      frame.discard_first ();
-      octave_call_stack::backtrace_error_message ();
-    }
+    frame.discard_first ();
 }
 
 octave_scalar_map
@@ -170,7 +165,7 @@
 #endif
 
 void
-octave_oncleanup::print (std::ostream& os, bool pr_as_read_syntax) const
+octave_oncleanup::print (std::ostream& os, bool pr_as_read_syntax)
 {
   print_raw (os, pr_as_read_syntax);
   newline (os);
--- a/libinterp/octave-value/ov-oncleanup.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-oncleanup.h	Mon Jan 12 09:17:35 2015 -0800
@@ -87,7 +87,7 @@
   bool load_hdf5 (hid_t loc_id, const char *name);
 #endif
 
-  void print (std::ostream& os, bool pr_as_read_syntax = false) const;
+  void print (std::ostream& os, bool pr_as_read_syntax = false);
 
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
 
--- a/libinterp/octave-value/ov-perm.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-perm.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -260,12 +260,10 @@
 bool
 octave_perm_matrix::save_ascii (std::ostream& os)
 {
-  typedef octave_int<octave_idx_type> idx_int_type;
+  os << "# size: " << matrix.rows () << "\n";
+  os << "# orient: c\n";
 
-  os << "# size: " << matrix.rows () << "\n";
-  os << "# orient: " << (matrix.is_col_perm () ? 'c' : 'r') << '\n';
-
-  Array<octave_idx_type> pvec = matrix.pvec ();
+  Array<octave_idx_type> pvec = matrix.col_perm_vec ();
   octave_idx_type n = pvec.length ();
   ColumnVector tmp (n);
   for (octave_idx_type i = 0; i < n; i++) tmp(i) = pvec(i) + 1;
@@ -277,7 +275,6 @@
 bool
 octave_perm_matrix::load_ascii (std::istream& is)
 {
-  typedef octave_int<octave_idx_type> idx_int_type;
   octave_idx_type n;
   bool success = true;
   char orient;
@@ -317,18 +314,19 @@
 {
 
   int32_t sz = matrix.rows ();
-  bool colp = matrix.is_col_perm ();
+  bool colp = true;
   os.write (reinterpret_cast<char *> (&sz), 4);
   os.write (reinterpret_cast<char *> (&colp), 1);
-  os.write (reinterpret_cast<const char *> (matrix.data ()),
-                                            matrix.byte_size ());
+  const Array<octave_idx_type>& col_perm = matrix.col_perm_vec ();
+  os.write (reinterpret_cast<const char *> (col_perm.data ()),
+                                            col_perm.byte_size ());
 
   return true;
 }
 
 bool
 octave_perm_matrix::load_binary (std::istream& is, bool swap,
-                                 oct_mach_info::float_format )
+                                 oct_mach_info::float_format)
 {
   int32_t sz;
   bool colp;
@@ -389,7 +387,7 @@
 }
 
 void
-octave_perm_matrix::print (std::ostream& os, bool pr_as_read_syntax) const
+octave_perm_matrix::print (std::ostream& os, bool pr_as_read_syntax)
 {
   print_raw (os, pr_as_read_syntax);
   newline (os);
@@ -451,3 +449,18 @@
   return retval;
 }
 
+octave_value
+octave_perm_matrix::fast_elem_extract (octave_idx_type n) const
+{
+  if (n < matrix.numel ())
+    {
+      octave_idx_type nr = matrix.rows ();
+
+      octave_idx_type r = n % nr;
+      octave_idx_type c = n / nr;
+
+      return octave_value (matrix.elem (r, c));
+    }
+  else
+    return octave_value ();
+}
--- a/libinterp/octave-value/ov-perm.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-perm.h	Mon Jan 12 09:17:35 2015 -0800
@@ -211,13 +211,15 @@
 
   bool print_as_scalar (void) const;
 
-  void print (std::ostream& os, bool pr_as_read_syntax = false) const;
+  void print (std::ostream& os, bool pr_as_read_syntax = false);
 
   void print_info (std::ostream& os, const std::string& prefix) const;
 
   octave_value map (unary_mapper_t umap) const
   { return to_dense ().map (umap); }
 
+  octave_value fast_elem_extract (octave_idx_type n) const;
+
 protected:
 
   PermMatrix matrix;
--- a/libinterp/octave-value/ov-range.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-range.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -352,7 +352,7 @@
 }
 
 void
-octave_range::print (std::ostream& os, bool pr_as_read_syntax) const
+octave_range::print (std::ostream& os, bool pr_as_read_syntax)
 {
   print_raw (os, pr_as_read_syntax);
   newline (os);
@@ -549,7 +549,8 @@
                          bool /* save_as_floats */)
 {
   hsize_t dimens[3];
-  hid_t space_hid = -1, type_hid = -1, data_hid = -1;
+  hid_t space_hid, type_hid, data_hid;
+  space_hid = type_hid = data_hid = -1;
   bool retval = true;
 
   space_hid = H5Screate_simple (0, dimens, 0);
@@ -676,6 +677,13 @@
   return retval;
 }
 
+octave_value
+octave_range::fast_elem_extract (octave_idx_type n) const
+{
+  return (n < range.nelem ())
+    ? octave_value (range.elem (n)) : octave_value ();
+}
+
 DEFUN (allow_noninteger_range_as_index, args, nargout,
        "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {@var{val} =} allow_noninteger_range_as_index ()\n\
--- a/libinterp/octave-value/ov-range.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-range.h	Mon Jan 12 09:17:35 2015 -0800
@@ -249,7 +249,7 @@
 
   octave_value convert_to_str_internal (bool pad, bool force, char type) const;
 
-  void print (std::ostream& os, bool pr_as_read_syntax = false) const;
+  void print (std::ostream& os, bool pr_as_read_syntax = false);
 
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
 
@@ -290,6 +290,8 @@
     return m.map (umap);
   }
 
+  octave_value fast_elem_extract (octave_idx_type n) const;
+
 private:
 
   Range range;
--- a/libinterp/octave-value/ov-re-diag.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-re-diag.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -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 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-re-mat.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -142,13 +142,13 @@
 Matrix
 octave_matrix::matrix_value (bool) const
 {
-  return matrix.matrix_value ();
+  return Matrix (matrix);
 }
 
 FloatMatrix
 octave_matrix::float_matrix_value (bool) const
 {
-  return FloatMatrix (matrix.matrix_value ());
+  return FloatMatrix (Matrix (matrix));
 }
 
 Complex
@@ -196,13 +196,13 @@
 ComplexMatrix
 octave_matrix::complex_matrix_value (bool) const
 {
-  return ComplexMatrix (matrix.matrix_value ());
+  return ComplexMatrix (Matrix (matrix));
 }
 
 FloatComplexMatrix
 octave_matrix::float_complex_matrix_value (bool) const
 {
-  return FloatComplexMatrix (matrix.matrix_value ());
+  return FloatComplexMatrix (Matrix (matrix));
 }
 
 ComplexNDArray
@@ -244,7 +244,7 @@
 SparseMatrix
 octave_matrix::sparse_matrix_value (bool) const
 {
-  return SparseMatrix (matrix.matrix_value ());
+  return SparseMatrix (Matrix (matrix));
 }
 
 SparseComplexMatrix
@@ -277,7 +277,7 @@
   if (matrix.ndims () == 2
       && (matrix.rows () == 1 || matrix.columns () == 1))
     {
-      Matrix mat = matrix.matrix_value ();
+      Matrix mat (matrix);
 
       retval = mat.diag (m, n);
     }
@@ -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 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-re-sparse.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -274,16 +274,16 @@
 
   int32_t itmp;
   // Use negative value for ndims to be consistent with other formats
-  itmp= -2;
+  itmp = -2;
   os.write (reinterpret_cast<char *> (&itmp), 4);
 
-  itmp= nr;
+  itmp = nr;
   os.write (reinterpret_cast<char *> (&itmp), 4);
 
-  itmp= nc;
+  itmp = nc;
   os.write (reinterpret_cast<char *> (&itmp), 4);
 
-  itmp= nz;
+  itmp = nz;
   os.write (reinterpret_cast<char *> (&itmp), 4);
 
   save_type st = LS_DOUBLE;
@@ -421,7 +421,8 @@
   if (group_hid < 0)
     return false;
 
-  hid_t space_hid = -1, data_hid = -1;
+  hid_t space_hid, data_hid;
+  space_hid = data_hid = -1;
   bool retval = true;
   SparseMatrix m = sparse_matrix_value ();
   octave_idx_type tmp;
--- a/libinterp/octave-value/ov-scalar.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-scalar.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -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 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-str-mat.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -211,7 +211,7 @@
 
   if (matrix.ndims () == 2)
     {
-      charMatrix chm = matrix.matrix_value ();
+      charMatrix chm (matrix);
 
       octave_idx_type n = chm.rows ();
 
@@ -233,7 +233,7 @@
 
   if (matrix.ndims () == 2)
     {
-      charMatrix chm = matrix.matrix_value ();
+      charMatrix chm (matrix);
 
       retval = chm.row_as_string (0);  // FIXME?
     }
@@ -250,7 +250,7 @@
 
   if (matrix.ndims () == 2)
     {
-      const charMatrix chm = matrix.matrix_value ();
+      const charMatrix chm (matrix);
       octave_idx_type nr = chm.rows ();
       retval.clear (nr, 1);
       for (octave_idx_type i = 0; i < nr; i++)
@@ -583,7 +583,8 @@
     return (empty > 0);
 
   int rank = dv.length ();
-  hid_t space_hid = -1, data_hid = -1;
+  hid_t space_hid, data_hid;
+  space_hid = data_hid = -1;
   bool retval = true;
   charNDArray m = char_array_value ();
 
--- a/libinterp/octave-value/ov-struct.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-struct.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -648,7 +648,7 @@
 }
 
 void
-octave_struct::print (std::ostream& os, bool) const
+octave_struct::print (std::ostream& os, bool)
 {
   print_raw (os);
 }
@@ -844,7 +844,7 @@
               success = false;
             }
         }
-      else if (len == 0 )
+      else if (len == 0)
         map = octave_map (dv);
       else
         panic_impossible ();
@@ -1359,7 +1359,7 @@
 }
 
 void
-octave_scalar_struct::print (std::ostream& os, bool) const
+octave_scalar_struct::print (std::ostream& os, bool)
 {
   print_raw (os);
 }
@@ -1814,7 +1814,7 @@
 \n\
 Finally, if the value is a non-scalar cell array, then @code{struct}\n\
 produces a struct @strong{array}.\n\
-@seealso{cell2struct, fieldnames, orderfields, getfield, setfield, rmfield, structfun}\n\
+@seealso{cell2struct, fieldnames, getfield, setfield, rmfield, isfield, orderfields, isstruct, structfun}\n\
 @end deftypefn")
 {
   octave_value retval;
@@ -2012,8 +2012,10 @@
 @deftypefn  {Built-in Function} {} isfield (@var{x}, \"@var{name}\")\n\
 @deftypefnx {Built-in Function} {} isfield (@var{x}, @var{name})\n\
 Return true if the @var{x} is a structure and it includes an element named\n\
-@var{name}.  If @var{name} is a cell array of strings then a logical array of\n\
-equal dimension is returned.\n\
+@var{name}.\n\
+\n\
+If @var{name} is a cell array of strings then a logical array of equal\n\
+dimension is returned.\n\
 @seealso{fieldnames}\n\
 @end deftypefn")
 {
@@ -2066,9 +2068,9 @@
   return retval;
 }
 
-DEFUN (nfields, args, ,
+DEFUN (numfields, args, ,
        "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {} nfields (@var{s})\n\
+@deftypefn {Built-in Function} {} numfields (@var{s})\n\
 Return the number of fields of the structure @var{s}.\n\
 @seealso{fieldnames}\n\
 @end deftypefn")
@@ -2237,12 +2239,14 @@
 
 DEFUN (rmfield, args, ,
        "-*- texinfo -*-\n\
-@deftypefn  {Built-in Function} {@var{s} =} rmfield (@var{s}, \"@var{f}\")\n\
-@deftypefnx {Built-in Function} {@var{s} =} rmfield (@var{s}, @var{f})\n\
+@deftypefn  {Built-in Function} {@var{sout} =} rmfield (@var{s}, \"@var{f}\")\n\
+@deftypefnx {Built-in Function} {@var{sout} =} rmfield (@var{s}, @var{f})\n\
 Return a @emph{copy} of the structure (array) @var{s} with the field @var{f}\n\
-removed.  If @var{f} is a cell array of strings or a character array, remove\n\
-each of the named fields.\n\
-@seealso{orderfields, fieldnames}\n\
+removed.\n\
+\n\
+If @var{f} is a cell array of strings or a character array, remove each of\n\
+the named fields.\n\
+@seealso{orderfields, fieldnames, isfield}\n\
 @end deftypefn")
 {
   octave_value retval;
--- a/libinterp/octave-value/ov-struct.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-struct.h	Mon Jan 12 09:17:35 2015 -0800
@@ -126,7 +126,7 @@
 
   string_vector map_keys (void) const { return map.fieldnames (); }
 
-  void print (std::ostream& os, bool pr_as_read_syntax = false) const;
+  void print (std::ostream& os, bool pr_as_read_syntax = false);
 
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
 
@@ -249,7 +249,7 @@
 
   string_vector map_keys (void) const { return map.fieldnames (); }
 
-  void print (std::ostream& os, bool pr_as_read_syntax = false) const;
+  void print (std::ostream& os, bool pr_as_read_syntax = false);
 
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
 
--- a/libinterp/octave-value/ov-usr-fcn.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-usr-fcn.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -160,9 +160,6 @@
 
                   if (tree_break_command::breaking)
                     tree_break_command::breaking--;
-
-                  if (error_state)
-                    octave_call_stack::backtrace_error_message ();
                 }
               else
                 ::error ("max_recursion_depth exceeded");
@@ -205,7 +202,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
@@ -321,14 +318,18 @@
 {
   std::ostringstream result;
 
-  if (is_inline_function ())
-    result << "inline@" << fcn_file_name ()
-           << ":" << location_line << ":" << location_column;
-  else if (is_anonymous_function ())
+  if (is_anonymous_function ())
     result << "anonymous@" << fcn_file_name ()
            << ":" << location_line << ":" << location_column;
   else if (is_subfunction ())
     result << parent_fcn_name () << ">" << name ();
+  else if (is_class_method ())
+    result << "@" << dispatch_class () << "/" << name ();
+  else if (is_class_constructor () || is_classdef_constructor ())
+    result << "@" << name ();
+  else if (is_inline_function ())
+    result << "inline@" << fcn_file_name ()
+           << ":" << location_line << ":" << location_column;
   else
     result << name ();
 
@@ -472,7 +473,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;
@@ -483,6 +484,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))
@@ -526,6 +544,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.
@@ -602,10 +639,7 @@
     tree_break_command::breaking--;
 
   if (error_state)
-    {
-      octave_call_stack::backtrace_error_message ();
-      return retval;
-    }
+    return retval;
 
   // Copy return values out.
 
@@ -746,7 +780,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++)
             {
@@ -793,9 +828,11 @@
        "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {} nargin ()\n\
 @deftypefnx {Built-in Function} {} nargin (@var{fcn})\n\
-Within a function, return the number of arguments passed to the function.\n\
-At the top level, return the number of command line arguments passed to\n\
-Octave.\n\
+Report the number of input arguments to a function.\n\
+\n\
+Called from within a function, return the number of arguments passed to the\n\
+function.  At the top level, return the number of command line arguments\n\
+passed to Octave.\n\
 \n\
 If called with the optional argument @var{fcn}---a function name or handle---\n\
 return the declared number of arguments that the function can accept.\n\
@@ -815,7 +852,7 @@
 @end example\n\
 \n\
 Programming Note: @code{nargin} does not work on built-in functions.\n\
-@seealso{nargout, varargin, isargout, varargout, nthargout}\n\
+@seealso{nargout, narginchk, varargin, inputname}\n\
 @end deftypefn")
 {
   octave_value retval;
@@ -851,7 +888,7 @@
             {
               // Matlab gives up for histc,
               // so maybe it's ok that that we give up somtimes too?
-              error ("nargin: nargin information not available for builtin functions");
+              error ("nargin: nargin information not available for built-in functions");
             }
         }
       else
@@ -874,11 +911,18 @@
        "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {} nargout ()\n\
 @deftypefnx {Built-in Function} {} nargout (@var{fcn})\n\
-Within a function, return the number of values the caller expects to\n\
-receive.  If called with the optional argument @var{fcn}---a function\n\
-name or handle---return the number of declared output values that the\n\
-function can produce.  If the final output argument is @var{varargout}\n\
-the returned value is negative.\n\
+Report the number of output arguments from a function.\n\
+\n\
+Called from within a function, return the number of values the caller expects\n\
+to receive.  At the top level, @code{nargout} with no argument is undefined\n\
+and will produce an error.\n\
+\n\
+If called with the optional argument @var{fcn}---a function name or\n\
+handle---return the number of declared output values that the function can\n\
+produce.\n\
+\n\
+If the final output argument is @var{varargout} the returned value is\n\
+negative.\n\
 \n\
 For example,\n\
 \n\
@@ -913,10 +957,9 @@
 will return -2, because @code{imread} has two outputs and the second is\n\
 @var{varargout}.\n\
 \n\
-At the top level, @code{nargout} with no argument is undefined and will\n\
-produce an error.  @code{nargout} does not work for built-in functions and\n\
+Programming Note.  @code{nargout} does not work for built-in functions and\n\
 returns -1 for all anonymous functions.\n\
-@seealso{nargin, varargin, isargout, varargout, nthargout}\n\
+@seealso{nargin, varargout, isargout, nthargout}\n\
 @end deftypefn")
 {
   octave_value retval;
@@ -973,7 +1016,7 @@
               // without making intrusive changes to Octave.
               // Matlab gives up for histc,
               // so maybe it's ok that we give up somtimes too?
-              error ("nargout: nargout information not available for builtin functions.");
+              error ("nargout: nargout information not available for built-in functions.");
             }
         }
       else
@@ -1039,16 +1082,18 @@
        "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} isargout (@var{k})\n\
 Within a function, return a logical value indicating whether the argument\n\
-@var{k} will be assigned to a variable on output.  If the result is false,\n\
-the argument has been ignored during the function call through the use of\n\
-the tilde (~) special output argument.  Functions can use @code{isargout} to\n\
-avoid performing unnecessary calculations for outputs which are unwanted.\n\
+@var{k} will be assigned to a variable on output.\n\
+\n\
+If the result is false, the argument has been ignored during the function\n\
+call through the use of the tilde (~) special output argument.  Functions\n\
+can use @code{isargout} to avoid performing unnecessary calculations for\n\
+outputs which are unwanted.\n\
 \n\
 If @var{k} is outside the range @code{1:max (nargout)}, the function returns\n\
 false.  @var{k} can also be an array, in which case the function works\n\
 element-by-element and a logical array is returned.  At the top level,\n\
 @code{isargout} returns an error.\n\
-@seealso{nargout, nargin, varargin, varargout, nthargout}\n\
+@seealso{nargout, varargout, nthargout}\n\
 @end deftypefn")
 {
   octave_value retval;
--- a/libinterp/octave-value/ov-usr-fcn.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov-usr-fcn.h	Mon Jan 12 09:17:35 2015 -0800
@@ -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 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -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"
@@ -94,6 +95,18 @@
 // make the grow_size large.
 DEFINE_OCTAVE_ALLOCATOR2(octave_value, 1024);
 
+// If TRUE, don't create special diagonal matrix objects.
+
+static bool Vdisable_diagonal_matrix = false;
+
+// If TRUE, don't create special permutation matrix objects.
+
+static bool Vdisable_permutation_matrix = false;
+
+// If TRUE, don't create special range objects.
+
+static bool Vdisable_range = false;
+
 // FIXME
 
 // Octave's value type.
@@ -673,37 +686,49 @@
 }
 
 octave_value::octave_value (const DiagArray2<double>& d)
-  : rep (new octave_diag_matrix (d))
+  : rep (Vdisable_diagonal_matrix
+         ? dynamic_cast<octave_base_value *> (new octave_matrix (Matrix (d)))
+         : dynamic_cast<octave_base_value *> (new octave_diag_matrix (d)))
 {
   maybe_mutate ();
 }
 
 octave_value::octave_value (const DiagArray2<float>& d)
-  : rep (new octave_float_diag_matrix (d))
+  : rep (Vdisable_diagonal_matrix
+         ? dynamic_cast<octave_base_value *> (new octave_float_matrix (FloatMatrix (d)))
+         : dynamic_cast<octave_base_value *> (new octave_float_diag_matrix (d)))
 {
   maybe_mutate ();
 }
 
 octave_value::octave_value (const DiagArray2<Complex>& d)
-  : rep (new octave_complex_diag_matrix (d))
+  : rep (Vdisable_diagonal_matrix
+         ? dynamic_cast<octave_base_value *> (new octave_complex_matrix (ComplexMatrix (d)))
+         : dynamic_cast<octave_base_value *> (new octave_complex_diag_matrix (d)))
 {
   maybe_mutate ();
 }
 
 octave_value::octave_value (const DiagArray2<FloatComplex>& d)
-  : rep (new octave_float_complex_diag_matrix (d))
+  : rep (Vdisable_diagonal_matrix
+         ? dynamic_cast<octave_base_value *> (new octave_float_complex_matrix (FloatComplexMatrix (d)))
+         : dynamic_cast<octave_base_value *> (new octave_float_complex_diag_matrix (d)))
 {
   maybe_mutate ();
 }
 
 octave_value::octave_value (const DiagMatrix& d)
-  : rep (new octave_diag_matrix (d))
+  : rep (Vdisable_diagonal_matrix
+         ? dynamic_cast<octave_base_value *> (new octave_matrix (Matrix (d)))
+         : dynamic_cast<octave_base_value *> (new octave_diag_matrix (d)))
 {
   maybe_mutate ();
 }
 
 octave_value::octave_value (const FloatDiagMatrix& d)
-  : rep (new octave_float_diag_matrix (d))
+  : rep (Vdisable_diagonal_matrix
+         ? dynamic_cast<octave_base_value *> (new octave_float_matrix (FloatMatrix (d)))
+         : dynamic_cast<octave_base_value *> (new octave_float_diag_matrix (d)))
 {
   maybe_mutate ();
 }
@@ -781,13 +806,17 @@
 }
 
 octave_value::octave_value (const ComplexDiagMatrix& d)
-  : rep (new octave_complex_diag_matrix (d))
+  : rep (Vdisable_diagonal_matrix
+         ? dynamic_cast<octave_base_value *> (new octave_complex_matrix (ComplexMatrix (d)))
+         : dynamic_cast<octave_base_value *> (new octave_complex_diag_matrix (d)))
 {
   maybe_mutate ();
 }
 
 octave_value::octave_value (const FloatComplexDiagMatrix& d)
-  : rep (new octave_float_complex_diag_matrix (d))
+  : rep (Vdisable_diagonal_matrix
+         ? dynamic_cast<octave_base_value *> (new octave_float_complex_matrix (FloatComplexMatrix (d)))
+         : dynamic_cast<octave_base_value *> (new octave_float_complex_diag_matrix (d)))
 {
   maybe_mutate ();
 }
@@ -817,7 +846,9 @@
 }
 
 octave_value::octave_value (const PermMatrix& p)
-  : rep (new octave_perm_matrix (p))
+  : rep (Vdisable_permutation_matrix
+         ? dynamic_cast<octave_base_value *> (new octave_matrix (Matrix (p)))
+         : dynamic_cast<octave_base_value *> (new octave_perm_matrix (p)))
 {
   maybe_mutate ();
 }
@@ -1176,8 +1207,10 @@
   maybe_mutate ();
 }
 
-octave_value::octave_value (const Range& r)
-  : rep (new octave_range (r))
+octave_value::octave_value (const Range& r, bool force_range)
+  : rep (force_range || ! Vdisable_range
+         ? dynamic_cast<octave_base_value *> (new octave_range (r))
+         : dynamic_cast<octave_base_value *> (new octave_matrix (r.matrix_value ())))
 {
   maybe_mutate ();
 }
@@ -1193,13 +1226,14 @@
 {
 }
 
-octave_value::octave_value (const Octave_map& m)
-  : rep (new octave_struct (m))
+octave_value::octave_value (const octave_map& m, const std::string& id,
+                            const std::list<std::string>& plist)
+  : rep (new octave_class (m, id, plist))
 {
   maybe_mutate ();
 }
 
-octave_value::octave_value (const Octave_map& m, const std::string& id,
+octave_value::octave_value (const octave_scalar_map& m, const std::string& id,
                             const std::list<std::string>& plist)
   : rep (new octave_class (m, id, plist))
 {
@@ -1951,7 +1985,9 @@
   int t2 = v2.type_id ();
 
   if (t1 == octave_class::static_type_id ()
-      || t2 == octave_class::static_type_id ())
+      || t2 == octave_class::static_type_id ()
+      || t1 == octave_classdef::static_type_id ()
+      || t2 == octave_classdef::static_type_id ())
     {
       octave_value_typeinfo::binary_class_op_fcn f
         = octave_value_typeinfo::lookup_binary_class_op (op);
@@ -2207,7 +2243,9 @@
   int t2 = v2.type_id ();
 
   if (t1 == octave_class::static_type_id ()
-      || t2 == octave_class::static_type_id ())
+      || t2 == octave_class::static_type_id ()
+      || t1 == octave_classdef::static_type_id ()
+      || t2 == octave_classdef::static_type_id ())
     {
       octave_value_typeinfo::binary_class_op_fcn f
         = octave_value_typeinfo::lookup_binary_class_op (op);
@@ -2381,7 +2419,8 @@
 
   int t = v.type_id ();
 
-  if (t == octave_class::static_type_id ())
+  if (t == octave_class::static_type_id ()
+      || t == octave_classdef::static_type_id ())
     {
       octave_value_typeinfo::unary_class_op_fcn f
         = octave_value_typeinfo::lookup_unary_class_op (op);
@@ -2835,10 +2874,9 @@
 
       for (int k = 0; k < nel; k++)
         {
-          std::string item = type(k).string_value ();
-
-          if (! error_state)
+          if (type(k).is_string ())
             {
+              std::string item = type(k).string_value ();
               if (item == "{}")
                 type_string[k] = '{';
               else if (item == "()")
@@ -2853,8 +2891,7 @@
             }
           else
             {
-              error ("%s: expecting type(%d) to be a character string",
-                     name, k+1);
+              error ("%s: type(%d) must be a string", name, k+1);
               return;
             }
 
@@ -2877,8 +2914,7 @@
             }
           else
             {
-              error ("%s: expecting subs(%d) to be a character string or cell array",
-                     name, k+1);
+              error ("%s: subs(%d) must be a string or cell array", name, k+1);
               return;
             }
 
@@ -3141,3 +3177,107 @@
 %!error is_dq_string ()
 %!error is_dq_string ("foo", 2)
 */
+
+DEFUN (disable_permutation_matrix, args, nargout,
+       "-*- texinfo -*-\n\
+@deftypefn  {Built-in Function} {@var{val} =} disable_permutation_matrix ()\n\
+@deftypefnx {Built-in Function} {@var{old_val} =} disable_permutation_matrix (@var{new_val})\n\
+@deftypefnx {Built-in Function} {} disable_permutation_matrix (@var{new_val}, \"local\")\n\
+Query or set the internal variable that controls whether permutation\n\
+matrices are stored in a special space-efficient format.  The default\n\
+value is true.  If this option is disabled Octave will store permutation\n\
+matrices as full matrices.\n\
+\n\
+When called from inside a function with the @qcode{\"local\"} option, the\n\
+variable is changed locally for the function and any subroutines it calls.\n\
+The original variable value is restored when exiting the function.\n\
+@seealso{disable_range, disable_diagonal_matrix}\n\
+@end deftypefn")
+{
+  return SET_INTERNAL_VARIABLE (disable_permutation_matrix);
+}
+
+/*
+%!function p = __test_dpm__ (dpm)
+%!  disable_permutation_matrix (dpm, "local");
+%!  [~, ~, p] = lu ([1,2;3,4]);
+%!endfunction
+
+%!assert (typeinfo (__test_dpm__ (false)), "permutation matrix");
+%!assert (typeinfo (__test_dpm__ (true)), "matrix");
+*/
+
+DEFUN (disable_diagonal_matrix, args, nargout,
+       "-*- texinfo -*-\n\
+@deftypefn  {Built-in Function} {@var{val} =} disable_diagonal_matrix ()\n\
+@deftypefnx {Built-in Function} {@var{old_val} =} disable_diagonal_matrix (@var{new_val})\n\
+@deftypefnx {Built-in Function} {} disable_diagonal_matrix (@var{new_val}, \"local\")\n\
+Query or set the internal variable that controls whether diagonal\n\
+matrices are stored in a special space-efficient format.  The default\n\
+value is true.  If this option is disabled Octave will store diagonal\n\
+matrices as full matrices.\n\
+\n\
+When called from inside a function with the @qcode{\"local\"} option, the\n\
+variable is changed locally for the function and any subroutines it calls.\n\
+The original variable value is restored when exiting the function.\n\
+@seealso{disable_range, disable_permutation_matrix}\n\
+@end deftypefn")
+{
+  return SET_INTERNAL_VARIABLE (disable_diagonal_matrix);
+}
+
+/*
+%!function [x, xi, fx, fxi] = __test_ddm__ (ddm)
+%!  disable_diagonal_matrix (ddm, "local");
+%!  x = eye (2);
+%!  xi = x*i;
+%!  fx = single (x);
+%!  fxi = single (xi);
+%!endfunction
+
+%!shared x, xi, fx, fxi
+%!  [x, xi, fx, fxi] = __test_ddm__ (false);
+%!assert (typeinfo (x), "diagonal matrix");
+%!assert (typeinfo (xi), "complex diagonal matrix");
+%!assert (typeinfo (fx), "float diagonal matrix");
+%!assert (typeinfo (fxi), "float complex diagonal matrix");
+
+%!shared x, xi, fx, fxi
+%!  [x, xi, fx, fxi] = __test_ddm__ (true);
+%!assert (typeinfo (x), "matrix");
+%!assert (typeinfo (xi), "complex matrix");
+%!assert (typeinfo (fx), "float matrix");
+%!assert (typeinfo (fxi), "float complex matrix");
+*/
+
+DEFUN (disable_range, args, nargout,
+       "-*- texinfo -*-\n\
+@deftypefn  {Built-in Function} {@var{val} =} disable_range ()\n\
+@deftypefnx {Built-in Function} {@var{old_val} =} disable_range (@var{new_val})\n\
+@deftypefnx {Built-in Function} {} disable_range (@var{new_val}, \"local\")\n\
+Query or set the internal variable that controls whether ranges are stored\n\
+in a special space-efficient format.  The default value is true.  If this\n\
+option is disabled Octave will store ranges as full matrices.\n\
+\n\
+When called from inside a function with the @qcode{\"local\"} option, the\n\
+variable is changed locally for the function and any subroutines it calls.\n\
+The original variable value is restored when exiting the function.\n\
+@seealso{disable_diagonal_matrix, disable_permutation_matrix}\n\
+@end deftypefn")
+{
+  return SET_INTERNAL_VARIABLE (disable_range);
+}
+
+/*
+%!function r = __test_dr__ (dr)
+%!  disable_range (dr, "local");
+%!  ## Constant folding will produce range for 1:13.
+%!  base = 1;
+%!  limit = 13;
+%!  r = base:limit;
+%!endfunction
+
+%!assert (typeinfo (__test_dr__ (false)), "range");
+%!assert (typeinfo (__test_dr__ (true)), "matrix");
+*/
+
--- a/libinterp/octave-value/ov.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave-value/ov.h	Mon Jan 12 09:17:35 2015 -0800
@@ -46,7 +46,6 @@
 class mxArray;
 class octave_map;
 class octave_scalar_map;
-class Octave_map;
 class octave_stream;
 class octave_function;
 class octave_user_function;
@@ -282,11 +281,12 @@
   octave_value (const Array<std::string>& cellstr);
   octave_value (const idx_vector& idx, bool lazy = true);
   octave_value (double base, double limit, double inc);
-  octave_value (const Range& r);
+  octave_value (const Range& r, bool force_range = false);
   octave_value (const octave_map& m);
   octave_value (const octave_scalar_map& m);
-  octave_value (const Octave_map& m);
-  octave_value (const Octave_map& m, const std::string& id,
+  octave_value (const octave_map& m, const std::string& id,
+                const std::list<std::string>& plist);
+  octave_value (const octave_scalar_map& m, const std::string& id,
                 const std::list<std::string>& plist);
   octave_value (const octave_value_list& m, bool = false);
   octave_value (octave_value::magic_colon);
@@ -572,6 +572,9 @@
   bool is_object (void) const
   { return rep->is_object (); }
 
+  bool is_classdef_object (void) const
+  { return rep->is_classdef_object (); }
+
   bool is_java (void) const
   { return rep->is_java (); }
 
@@ -915,6 +918,9 @@
   find_parent_class (const std::string& parent_class_name)
   { return rep->find_parent_class (parent_class_name); }
 
+  bool is_instance_of (const std::string& cls_name) const
+  { return rep->is_instance_of (cls_name); }
+
   octave_function *function_value (bool silent = false) const;
 
   octave_user_function *user_function_value (bool silent = false) const;
@@ -1017,7 +1023,7 @@
   bool print_as_scalar (void) const
   { return rep->print_as_scalar (); }
 
-  void print (std::ostream& os, bool pr_as_read_syntax = false) const
+  void print (std::ostream& os, bool pr_as_read_syntax = false)
   { rep->print (os, pr_as_read_syntax); }
 
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const
--- a/libinterp/octave.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/octave.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -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"
@@ -95,8 +96,7 @@
 static string_vector octave_argv;
 
 // The name used to invoke Octave.
-static std::string
-octave_program_invocation_name;
+static std::string octave_program_invocation_name;
 
 // The last component of octave_program_invocation_name.
 static std::string octave_program_name;
@@ -157,16 +157,19 @@
 // (--no-window-system, -W)
 static bool no_window_system = false;
 
-// The code to evaluate at startup (--eval CODE)
+// The code to evaluate at startup
+// (--eval CODE)
 static std::string code_to_eval;
 
 // If TRUE, don't exit after evaluating code given by --eval option.
+// (--persist)
 static bool persist = false;
 
 // If TRUE, the GUI should be started.
 static bool start_gui = false;
 
-// If TRUE use traditional settings (--traditional)
+// If TRUE use traditional (maximally MATLAB compatible) settings
+// (--traditional)
 static bool traditional = false;
 
 // Store the command-line options for later use.
@@ -256,10 +259,10 @@
             << std::endl;
 }
 
-// Execute commands from a file and catch potential exceptions in a
-// consistent way.  This function should be called anywhere we might
-// parse and execute commands from a file before before we have entered
-// the main loop in toplev.cc.
+// Execute commands from a file and catch potential exceptions in a consistent
+// way.  This function should be called anywhere we might parse and execute
+// commands from a file before before we have entered the main loop in
+// toplev.cc.
 
 static void
 safe_source_file (const std::string& file_name,
@@ -314,8 +317,8 @@
   if (read_init_files)
     {
       // Try to execute commands from $HOME/$OCTAVE_INITFILE and
-      // $OCTAVE_INITFILE.  If $OCTAVE_INITFILE is not set, .octaverc
-      // is assumed.
+      // $OCTAVE_INITFILE.  If $OCTAVE_INITFILE is not set, 
+      // .octaverc is assumed.
 
       bool home_rc_already_executed = false;
 
@@ -472,7 +475,7 @@
   set_liboctave_warning_with_id_handler (warning_with_id);
 }
 
-// What happens on --traditional.
+// What internal options get configured by --traditional.
 
 static void
 maximum_braindamage (void)
@@ -485,17 +488,19 @@
   Fbeep_on_error (octave_value (true));
   Fconfirm_recursive_rmdir (octave_value (false));
   Fcrash_dumps_octave_core (octave_value (false));
-  Fsave_default_options (octave_value ("-mat-binary"));
+  Fdisable_diagonal_matrix (octave_value (true));
+  Fdisable_permutation_matrix (octave_value (true));
+  Fdisable_range (octave_value (true));
   Ffixed_point_format (octave_value (true));
   Fhistory_timestamp_format_string (octave_value ("%%-- %D %I:%M %p --%%"));
   Fpage_screen_output (octave_value (false));
   Fprint_empty_dimensions (octave_value (false));
+  Fsave_default_options (octave_value ("-mat-binary"));
   Fstruct_levels_to_print (octave_value (0));
 
   disable_warning ("Octave:abbreviated-property-match");
-  disable_warning ("Octave:fopen-file-in-path");
+  disable_warning ("Octave:data-file-in-path");
   disable_warning ("Octave:function-name-clash");
-  disable_warning ("Octave:load-file-in-path");
   disable_warning ("Octave:possible-matlab-short-circuit-operator");
 }
 
@@ -534,9 +539,8 @@
       switch (optc)
         {
         case '?':
-          // Unrecognized option.  getopt_long already printed a
-          // message about that, so we will just print the usage string
-          // and exit.
+          // Unrecognized option.  getopt_long already printed a message about
+          // it, so we will just print the usage string and exit.
           octave_print_terse_usage_and_exit ();
           break;
 
@@ -681,21 +685,32 @@
           break;
 
         default:
-          // getopt_long should print a message about unrecognized
-          // options and return '?', which is handled above.  So if we
-          // end up here, it is because there was an option but we
-          // forgot to handle it.  That should be fatal.
+          // getopt_long should print a message about unrecognized options and
+          // return '?', which is handled above.  If we end up here, it is
+          // because there was an option but we forgot to handle it.
+          // That should be fatal.
           panic_impossible ();
           break;
         }
     }
 
+  // Check for various incompatible argument pairs
   if (force_gui_option && no_gui_option)
     {
-      error ("error: only one of --force-gui and --no-gui may be used");
+      error ("only one of --force-gui and --no-gui may be used");
 
       octave_print_terse_usage_and_exit ();
     }
+
+  bool script_file = (argc - optind) > 0;
+
+  if (! code_to_eval.empty () && script_file)
+    {
+      error ("--eval \"CODE\" and script file are mutually exclusive options");
+
+      octave_print_terse_usage_and_exit ();
+    }
+
 }
 
 // EMBEDDED is declared int instead of bool because this function is
@@ -719,8 +734,8 @@
 
   set_default_prompts ();
 
-  // Initialize default warning state before --traditional option may
-  // reset them.
+  // Initialize default warning state before --traditional option
+  // that may reset them.
 
   initialize_default_warning_state ();
 
@@ -731,10 +746,9 @@
 
   octave_ieee_init ();
 
-  // The idea here is to force xerbla to be referenced so that we will
-  // link to our own version instead of the one provided by the BLAS
-  // library.  But octave_NaN should never be -1, so we should never
-  // actually call xerbla.
+  // The idea here is to force xerbla to be referenced so that we will link to
+  // our own version instead of the one provided by the BLAS library.  But
+  // octave_NaN should never be -1, so we should never actually call xerbla.
 
   if (octave_NaN == -1)
     F77_FUNC (xerbla, XERBLA) ("octave", 13 F77_CHAR_ARG_LEN (6));
@@ -754,6 +768,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);
@@ -767,8 +783,7 @@
   if (no_window_system)
     display_info::no_window_system ();
 
-  // Is input coming from a terminal?  If so, we are probably
-  // interactive.
+  // Is input coming from a terminal?  If so, we are probably interactive.
 
   // If stdin is not a tty, then we are reading commands from a pipe or
   // a redirected file.
@@ -817,19 +832,12 @@
   if (! inhibit_startup_message && reading_startup_message_printed)
     std::cout << std::endl;
 
-  // If there is an extra argument, see if it names a file to read.
-  // Additional arguments are taken as command line options for the
-  // script.
-
-  int last_arg_idx = optind;
-
-  int remaining_args = octave_cmdline_argc - last_arg_idx;
-
+  // Execute any code specified with --eval 'CODE'
   if (! code_to_eval.empty ())
     {
       int parse_status = execute_eval_option_code (code_to_eval);
 
-      if (! (persist || remaining_args > 0))
+      if (! persist)
         {
           quitting_gracefully = true;
 
@@ -837,6 +845,12 @@
         }
     }
 
+  // If there is an extra argument, see if it names a file to read.
+  // Additional arguments are taken as command line options for the script.
+
+  int last_arg_idx = optind;
+  int remaining_args = octave_cmdline_argc - last_arg_idx;
+
   if (remaining_args > 0)
     {
       // If we are running an executable script (#! /bin/octave) then
@@ -861,23 +875,22 @@
   // Now argv should have the full set of args.
   intern_argv (octave_cmdline_argc, octave_cmdline_argv);
 
-  // Force input to be echoed if not really interactive, but the user
-  // has forced interactive behavior.
+  // Force input to be echoed if not really interactive,
+  // but the user has forced interactive behavior.
 
   if (! interactive && forced_interactive)
     {
       command_editor::blink_matching_paren (false);
 
       // FIXME: is this the right thing to do?
-
       Fecho_executing_commands (octave_value (ECHO_CMD_LINE));
     }
 
   if (octave_embedded)
     {
-      // FIXME: do we need to do any cleanup here before
-      // returning?  If we don't, what will happen to Octave functions
-      // that have been registered to execute with atexit, for example?
+      // FIXME: Do we need to do any cleanup here before returning?
+      // If we don't, what will happen to Octave functions that have been
+      // registered to execute with atexit, for example?
 
       return 1;
     }
@@ -915,17 +928,16 @@
   if (persist)
     return true;
 
-  // If stdin is not a tty, then assume we are reading commands from a
-  // pipe or a redirected file and the GUI should not start.  If this is
-  // not the case (for example, starting from a desktop "launcher" with
-  // no terminal) and you want to start the GUI, you may use the
-  // --force-gui option to start the GUI.
+  // If stdin is not a tty, then assume we are reading commands from a pipe or
+  // a redirected file and the GUI should not start.  If this is not the case
+  // (for example, starting from a desktop "launcher" with no terminal) and you
+  // want to start the GUI, you may use the --force-gui option to start the GUI.
 
   if (! gnulib::isatty (fileno (stdin)))
     return false;
 
-  // If we have code to eval or execute from a file, and we are going to
-  // exit immediately after executing it, don't start the gui.
+  // If we have code to eval or execute from a file, and we are going to exit
+  // immediately after executing it, don't start the gui.
 
   int last_arg_idx = optind;
   int remaining_args = octave_cmdline_argc - last_arg_idx;
@@ -936,8 +948,7 @@
   return true;
 }
 
-// Return int instead of bool because this function is declared
-// extern "C".
+// Return int instead of bool because this function is declared extern "C".
 
 int
 octave_starting_gui (void)
@@ -970,8 +981,9 @@
 DEFUN (argv, args, ,
        "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} argv ()\n\
-Return the command line arguments passed to Octave.  For example,\n\
-if you invoked Octave using the command\n\
+Return the command line arguments passed to Octave.\n\
+\n\
+For example, if you invoked Octave using the command\n\
 \n\
 @example\n\
 octave --no-line-editing --silent\n\
@@ -981,9 +993,9 @@
 @code{argv} would return a cell array of strings with the elements\n\
 @option{--no-line-editing} and @option{--silent}.\n\
 \n\
-If you write an executable Octave script, @code{argv} will return the\n\
-list of arguments passed to the script.  @xref{Executable Octave Programs},\n\
-for an example of how to create an executable Octave script.\n\
+If you write an executable Octave script, @code{argv} will return the list\n\
+of arguments passed to the script.  @xref{Executable Octave Programs}, for\n\
+an example of how to create an executable Octave script.\n\
 @end deftypefn")
 {
   octave_value retval;
--- a/libinterp/operators/op-b-b.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/operators/op-b-b.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -33,6 +33,7 @@
 #include "ov-float.h"
 #include "ov-re-mat.h"
 #include "ov-typeinfo.h"
+#include "ov-null-mat.h"
 #include "ops.h"
 #include "xdiv.h"
 #include "xpow.h"
@@ -92,4 +93,8 @@
   INSTALL_CATOP (octave_float_scalar, octave_bool, f_b);
 
   INSTALL_ASSIGNCONV (octave_bool, octave_bool, octave_bool_matrix);
+
+  INSTALL_ASSIGNCONV (octave_bool, octave_null_matrix, octave_bool_matrix);
+  INSTALL_ASSIGNCONV (octave_bool, octave_null_str, octave_bool_matrix);
+  INSTALL_ASSIGNCONV (octave_bool, octave_null_sq_str, octave_bool_matrix);
 }
--- a/libinterp/operators/op-cm-sm.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/operators/op-cm-sm.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -106,8 +106,8 @@
                    const octave_sparse_matrix&);
 
   return octave_value
-         (elem_xpow ( SparseComplexMatrix (v1.complex_matrix_value ()),
-                      v2.sparse_matrix_value ()));
+         (elem_xpow (SparseComplexMatrix (v1.complex_matrix_value ()),
+                     v2.sparse_matrix_value ()));
 }
 
 DEFBINOP (el_ldiv, complex_matrix, sparse_matrix)
--- a/libinterp/operators/op-dm-scm.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/operators/op-dm-scm.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -24,6 +24,15 @@
 #include <config.h>
 #endif
 
+#include "mx-cm-s.h"
+#include "mx-s-cm.h"
+
+#include "mx-dm-cs.h"
+#include "mx-cs-dm.h"
+
+#include "mx-m-cs.h"
+#include "mx-cs-m.h"
+
 #include "gripes.h"
 #include "oct-obj.h"
 #include "ov.h"
--- a/libinterp/operators/op-dm-template.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/operators/op-dm-template.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -24,6 +24,10 @@
 #include <config.h>
 #endif
 
+// FIXME: it might be nice to only include the declarations of the
+// operators that are actually needed instead of including all of them.
+#include "mx-ops.h"
+
 #include "ops.h"
 #include "xdiv.h"
 #include LINCLUDE
--- a/libinterp/operators/op-fcm-fs.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/operators/op-fcm-fs.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -24,8 +24,7 @@
 #include <config.h>
 #endif
 
-#include "mx-cm-s.h"
-#include "mx-cnda-s.h"
+#include "mx-fcnda-fs.h"
 
 #include "gripes.h"
 #include "oct-obj.h"
--- a/libinterp/operators/op-fcs-fm.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/operators/op-fcs-fm.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -24,10 +24,8 @@
 #include <config.h>
 #endif
 
-#include "mx-cs-nda.h"
-#include "mx-nda-cs.h"
-#include "mx-cs-nda.h"
-#include "mx-nda-cs.h"
+#include "mx-fcs-fnda.h"
+#include "mx-fnda-fcs.h"
 
 #include "gripes.h"
 #include "oct-obj.h"
--- a/libinterp/operators/op-i16-i16.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/operators/op-i16-i16.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -57,6 +57,15 @@
 #include "mx-i16-nda.h"
 #include "mx-nda-i16.h"
 
+#include "mx-i16nda-fs.h"
+#include "mx-fs-i16nda.h"
+
+#include "mx-i16nda-fnda.h"
+#include "mx-fnda-i16nda.h"
+
+#include "mx-i16-fnda.h"
+#include "mx-fnda-i16.h"
+
 #include "gripes.h"
 #include "oct-obj.h"
 #include "ov.h"
--- a/libinterp/operators/op-i32-i32.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/operators/op-i32-i32.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -57,6 +57,15 @@
 #include "mx-i32-nda.h"
 #include "mx-nda-i32.h"
 
+#include "mx-i32nda-fs.h"
+#include "mx-fs-i32nda.h"
+
+#include "mx-i32nda-fnda.h"
+#include "mx-fnda-i32nda.h"
+
+#include "mx-i32-fnda.h"
+#include "mx-fnda-i32.h"
+
 #include "gripes.h"
 #include "oct-obj.h"
 #include "ov.h"
--- a/libinterp/operators/op-i64-i64.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/operators/op-i64-i64.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -57,6 +57,15 @@
 #include "mx-i64-nda.h"
 #include "mx-nda-i64.h"
 
+#include "mx-i64nda-fs.h"
+#include "mx-fs-i64nda.h"
+
+#include "mx-i64nda-fnda.h"
+#include "mx-fnda-i64nda.h"
+
+#include "mx-i64-fnda.h"
+#include "mx-fnda-i64.h"
+
 #include "gripes.h"
 #include "oct-obj.h"
 #include "ov.h"
--- a/libinterp/operators/op-i8-i8.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/operators/op-i8-i8.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -57,6 +57,15 @@
 #include "mx-i8-nda.h"
 #include "mx-nda-i8.h"
 
+#include "mx-i8nda-fs.h"
+#include "mx-fs-i8nda.h"
+
+#include "mx-i8nda-fnda.h"
+#include "mx-fnda-i8nda.h"
+
+#include "mx-i8-fnda.h"
+#include "mx-fnda-i8.h"
+
 #include "gripes.h"
 #include "oct-obj.h"
 #include "ov.h"
--- a/libinterp/operators/op-int.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/operators/op-int.h	Mon Jan 12 09:17:35 2015 -0800
@@ -1160,7 +1160,10 @@
 #define OCTAVE_INSTALL_INT_NULL_ASSIGN_OPS(TYPE) \
   INSTALL_ASSIGNOP (op_asn_eq, octave_ ## TYPE ## _matrix, octave_null_matrix, TYPE ## null_assign) \
   INSTALL_ASSIGNOP (op_asn_eq, octave_ ## TYPE ## _matrix, octave_null_str, TYPE ## null_assign) \
-  INSTALL_ASSIGNOP (op_asn_eq, octave_ ## TYPE ## _matrix, octave_null_sq_str, TYPE ## null_assign)
+  INSTALL_ASSIGNOP (op_asn_eq, octave_ ## TYPE ## _matrix, octave_null_sq_str, TYPE ## null_assign) \
+  INSTALL_ASSIGNCONV (octave_ ## TYPE ## _scalar, octave_null_matrix, octave_ ## TYPE ## _matrix) \
+  INSTALL_ASSIGNCONV (octave_## TYPE ## _scalar, octave_null_str, octave_ ## TYPE ## _matrix) \
+  INSTALL_ASSIGNCONV (octave_## TYPE ## _scalar, octave_null_sq_str, octave_ ## TYPE ## _matrix)
 
 #define OCTAVE_INSTALL_INT_OPS(TYPE) \
   OCTAVE_INSTALL_SS_INT_OPS (TYPE) \
--- a/libinterp/operators/op-pm-sm.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/operators/op-pm-sm.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -44,12 +44,12 @@
 DEFUNOP (not, perm_matrix)
 {
   // Obviously negation of a permutation matrix destroys sparsity
-  return octave_value ( ! a.bool_array_value ());
+  return octave_value (! a.bool_array_value ());
 }
 
 DEFUNOP (uminus, perm_matrix)
 {
-  return octave_value ( - a.sparse_matrix_value ());
+  return octave_value (- a.sparse_matrix_value ());
 }
 
 // Most other logical operations cast to SparseBoolMatrix
--- a/libinterp/operators/op-pm-template.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/operators/op-pm-template.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -24,6 +24,10 @@
 #include <config.h>
 #endif
 
+// FIXME: it might be nice to only include the declarations of the
+// operators that are actually needed instead of including all of them.
+#include "mx-ops.h"
+
 #include "ov-perm.h"
 #include MINCLUDE
 #include "ops.h"
--- a/libinterp/operators/op-sbm-sbm.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/operators/op-sbm-sbm.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -49,7 +49,7 @@
 DEFUNOP (uminus, sparse_bool_matrix)
 {
   CAST_UNOP_ARG (const octave_sparse_bool_matrix&);
-  return octave_value ( - v.sparse_matrix_value ());
+  return octave_value (- v.sparse_matrix_value ());
 }
 
 DEFUNOP (transpose, sparse_bool_matrix)
--- a/libinterp/operators/op-ui16-ui16.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/operators/op-ui16-ui16.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -57,6 +57,15 @@
 #include "mx-ui16-nda.h"
 #include "mx-nda-ui16.h"
 
+#include "mx-ui16nda-fs.h"
+#include "mx-fs-ui16nda.h"
+
+#include "mx-ui16nda-fnda.h"
+#include "mx-fnda-ui16nda.h"
+
+#include "mx-ui16-fnda.h"
+#include "mx-fnda-ui16.h"
+
 #include "gripes.h"
 #include "oct-obj.h"
 #include "ov.h"
--- a/libinterp/operators/op-ui32-ui32.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/operators/op-ui32-ui32.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -57,6 +57,15 @@
 #include "mx-ui32-nda.h"
 #include "mx-nda-ui32.h"
 
+#include "mx-ui32nda-fs.h"
+#include "mx-fs-ui32nda.h"
+
+#include "mx-ui32nda-fnda.h"
+#include "mx-fnda-ui32nda.h"
+
+#include "mx-ui32-fnda.h"
+#include "mx-fnda-ui32.h"
+
 #include "gripes.h"
 #include "oct-obj.h"
 #include "ov.h"
--- a/libinterp/operators/op-ui64-ui64.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/operators/op-ui64-ui64.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -57,6 +57,15 @@
 #include "mx-ui64-nda.h"
 #include "mx-nda-ui64.h"
 
+#include "mx-ui64nda-fs.h"
+#include "mx-fs-ui64nda.h"
+
+#include "mx-ui64nda-fnda.h"
+#include "mx-fnda-ui64nda.h"
+
+#include "mx-ui64-fnda.h"
+#include "mx-fnda-ui64.h"
+
 #include "gripes.h"
 #include "oct-obj.h"
 #include "ov.h"
--- a/libinterp/operators/op-ui8-ui8.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/operators/op-ui8-ui8.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -57,6 +57,15 @@
 #include "mx-ui8-nda.h"
 #include "mx-nda-ui8.h"
 
+#include "mx-ui8nda-fs.h"
+#include "mx-fs-ui8nda.h"
+
+#include "mx-ui8nda-fnda.h"
+#include "mx-fnda-ui8nda.h"
+
+#include "mx-ui8-fnda.h"
+#include "mx-fnda-ui8.h"
+
 #include "gripes.h"
 #include "oct-obj.h"
 #include "ov.h"
--- a/libinterp/parse-tree/lex.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/parse-tree/lex.h	Mon Jan 12 09:17:35 2015 -0800
@@ -261,7 +261,9 @@
       looking_at_matrix_or_assign_lhs (false),
       looking_for_object_index (false),
       looking_at_indirect_ref (false), parsing_class_method (false),
-      maybe_classdef_get_set_method (false), parsing_classdef (false),
+      parsing_classdef (false), maybe_classdef_get_set_method (false),
+      parsing_classdef_get_method (false),
+      parsing_classdef_set_method (false), 
       quote_is_transpose (false), force_script (false),
       reading_fcn_file (false), reading_script_file (false),
       reading_classdef_file (false),
@@ -341,13 +343,19 @@
   // true means we are parsing a class method in function or classdef file.
   bool parsing_class_method;
 
+  // true means we are parsing a classdef file
+  bool parsing_classdef;
+
   // true means we are parsing a class method declaration line in a
   // classdef file and can accept a property get or set method name.
   // for example, "get.propertyname" is recognized as a function name.
   bool maybe_classdef_get_set_method;
 
-  // true means we are parsing a classdef file
-  bool parsing_classdef;
+  // TRUE means we are parsing a classdef get.method.
+  bool parsing_classdef_get_method;
+
+  // TRUE means we are parsing a classdef set.method.
+  bool parsing_classdef_set_method;
 
   // return transpose or start a string?
   bool quote_is_transpose;
@@ -572,6 +580,8 @@
 
   int is_keyword_token (const std::string& s);
 
+  bool fq_identifier_contains_keyword (const std::string& s);
+
   bool whitespace_is_significant (void);
 
   void handle_number (void);
@@ -590,6 +600,8 @@
 
   int handle_meta_identifier (void);
 
+  int handle_fq_identifier (void);
+
   int handle_identifier (void);
 
   void maybe_warn_separator_insert (char sep);
@@ -675,6 +687,8 @@
 
   int show_token (int tok);
 
+  void enable_fq_identifier (void);
+
 protected:
 
   std::stack<int> start_state_stack;
--- a/libinterp/parse-tree/lex.ll	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/parse-tree/lex.ll	Mon Jan 12 09:17:35 2015 -0800
@@ -54,6 +54,8 @@
 %x DQ_STRING_START
 %x SQ_STRING_START
 
+%x FQ_IDENT_START
+
 %{
 
 #include <cctype>
@@ -266,6 +268,43 @@
     } \
   while (0)
 
+#define HANDLE_IDENTIFIER(pattern, get_set) \
+  do \
+    { \
+      curr_lexer->lexer_debug (pattern); \
+ \
+      int tok = curr_lexer->previous_token_value (); \
+ \
+      if (curr_lexer->whitespace_is_significant () \
+          && curr_lexer->space_follows_previous_token () \
+          && ! (tok == '[' || tok == '{' \
+                || curr_lexer->previous_token_is_binop ())) \
+        { \
+          yyless (0); \
+          unput (','); \
+        } \
+      else \
+        { \
+          if (! curr_lexer->looking_at_decl_list \
+              && curr_lexer->previous_token_may_be_command ()) \
+            { \
+              yyless (0); \
+              curr_lexer->push_start_state (COMMAND_START); \
+            } \
+          else \
+            { \
+              if (get_set) \
+                curr_lexer->maybe_classdef_get_set_method = false; \
+ \
+              int id_tok = curr_lexer->handle_identifier (); \
+ \
+              if (id_tok >= 0) \
+                return curr_lexer->count_token_internal (id_tok); \
+            } \
+        } \
+    } \
+  while (0)
+
 static bool Vdisplay_tokens = false;
 
 static unsigned int Vtoken_count = 0;
@@ -273,11 +312,6 @@
 // Internal variable for lexer debugging state.
 static bool lexer_debug_flag = false;
 
-// Forward declarations for functions defined at the bottom of this
-// file that are needed inside the lexer actions.
-
-static std::string strip_trailing_whitespace (char *s);
-
 %}
 
 D       [0-9]
@@ -286,6 +320,7 @@
 Im      [iIjJ]
 CCHAR   [#%]
 IDENT   ([_$a-zA-Z][_$a-zA-Z0-9]*)
+FQIDENT ({IDENT}(\.{IDENT})*)
 EXPON   ([DdEe][+-]?{D}+)
 NUMBER  (({D}+\.?{D}*{EXPON}?)|(\.{D}+{EXPON}?)|(0[xX][0-9a-fA-F]+))
 
@@ -1018,6 +1053,35 @@
   }
 
 %{
+// Fully-qualified identifiers (used for classdef).
+%}
+
+<FQ_IDENT_START>{FQIDENT} {
+    curr_lexer->lexer_debug ("<FQ_IDENT_START>{FQIDENT}");
+    curr_lexer->pop_start_state ();
+
+    int id_tok = curr_lexer->handle_fq_identifier ();
+
+    if (id_tok >= 0)
+      {
+        curr_lexer->looking_for_object_index = true;
+
+        return curr_lexer->count_token_internal (id_tok);
+      }
+  }
+
+<FQ_IDENT_START>{S}+ {
+    curr_lexer->current_input_column += yyleng;
+
+    curr_lexer->mark_previous_token_trailing_space ();
+  }
+
+<FQ_IDENT_START>. {
+    yyless (0);
+    curr_lexer->pop_start_state ();
+  }
+
+%{
 // Imaginary numbers.
 %}
 
@@ -1138,46 +1202,25 @@
 
 %{
 // Identifiers.
+
+// Don't allow get and set to be recognized as keywords if they are
+// followed by "(".
 %}
 
+(set|get)/{S}*\( {
+    HANDLE_IDENTIFIER ("(set|get)/{S}*\\(", true);
+  }
+
 {IDENT} {
-    curr_lexer->lexer_debug ("{IDENT}");
-
-    int tok = curr_lexer->previous_token_value ();
-
-    if (curr_lexer->whitespace_is_significant ()
-        && curr_lexer->space_follows_previous_token ()
-        && ! (tok == '[' || tok == '{'
-              || curr_lexer->previous_token_is_binop ()))
-      {
-        yyless (0);
-        unput (',');
-      }
-    else
-      {
-        if (! curr_lexer->looking_at_decl_list
-            && curr_lexer->previous_token_may_be_command ())
-          {
-            yyless (0);
-            curr_lexer->push_start_state (COMMAND_START);
-          }
-        else
-          {
-            int id_tok = curr_lexer->handle_identifier ();
-
-            if (id_tok >= 0)
-              return curr_lexer->count_token_internal (id_tok);
-          }
-      }
+    HANDLE_IDENTIFIER ("{IDENT}", false);
   }
 
 %{
 // Superclass method identifiers.
 %}
 
-{IDENT}@{IDENT} |
-{IDENT}@{IDENT}.{IDENT} {
-    curr_lexer->lexer_debug ("{IDENT}@{IDENT}|{IDENT}@{IDENT}.{IDENT}");
+{IDENT}@{FQIDENT} {
+    curr_lexer->lexer_debug ("{IDENT}@{FQIDENT}");
 
     if (curr_lexer->previous_token_may_be_command ())
       {
@@ -1192,7 +1235,7 @@
           {
             curr_lexer->looking_for_object_index = true;
 
-            return curr_lexer->count_token_internal (SUPERCLASSREF);
+            return curr_lexer->count_token_internal (id_tok);
           }
       }
   }
@@ -1201,9 +1244,8 @@
 // Metaclass query
 %}
 
-\?{IDENT} |
-\?{IDENT}\.{IDENT} {
-    curr_lexer->lexer_debug ("\\?{IDENT}|\\?{IDENT}\\.{IDENT}");
+\?{FQIDENT} {
+    curr_lexer->lexer_debug ("\\?{FQIDENT}");
 
     if (curr_lexer->previous_token_may_be_command ()
         &&  curr_lexer->space_follows_previous_token ())
@@ -1219,7 +1261,7 @@
           {
             curr_lexer->looking_for_object_index = true;
 
-            return curr_lexer->count_token_internal (METAQUERY);
+            return curr_lexer->count_token_internal (id_tok);
           }
       }
   }
@@ -1887,21 +1929,6 @@
 
 */
 
-// Used to delete trailing white space from tokens.
-
-static std::string
-strip_trailing_whitespace (char *s)
-{
-  std::string retval = s;
-
-  size_t pos = retval.find_first_of (" \t");
-
-  if (pos != std::string::npos)
-    retval.resize (pos);
-
-  return retval;
-}
-
 DEFUN (__display_tokens__, args, nargout,
   "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} __display_tokens__ ()\n\
@@ -1967,8 +1994,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;
@@ -2370,20 +2399,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;
@@ -2396,10 +2411,9 @@
 
         case end_kw:
           if (inside_any_object_index ()
-              || (! reading_classdef_file
-                  && (defining_func
-                      && ! (looking_at_return_list
-                            || parsed_function_name.top ()))))
+              || (defining_func
+                  && ! (looking_at_return_list
+                        || parsed_function_name.top ())))
             {
               at_beginning_of_statement = previous_at_bos;
               return 0;
@@ -2585,6 +2599,34 @@
 }
 
 bool
+octave_base_lexer::fq_identifier_contains_keyword (const std::string& s)
+{
+  size_t p1 = 0;
+  size_t p2;
+
+  std::string s_part;
+
+  do
+    {
+      p2 = s.find ('.', p1);
+
+      if (p2 != std::string::npos)
+        {
+          s_part = s.substr (p1, p2 - p1);
+          p1 = p2 + 1;
+        }
+      else
+        s_part = s.substr (p1);
+
+      if (is_keyword_token (s_part))
+        return true;
+    }
+  while (p2 != std::string::npos);
+
+  return false;
+}
+
+bool
 octave_base_lexer::whitespace_is_significant (void)
 {
   return (nesting_level.is_bracket ()
@@ -2756,36 +2798,23 @@
 int
 octave_base_lexer::handle_superclass_identifier (void)
 {
-  std::string pkg;
-  char *yytxt = flex_yytext ();
-  std::string meth = strip_trailing_whitespace (yytxt);
+  std::string meth = flex_yytext ();
+
   size_t pos = meth.find ("@");
-  std::string cls = meth.substr (pos).substr (1);
-  meth = meth.substr (0, pos - 1);
-
-  pos = cls.find (".");
-  if (pos != std::string::npos)
-    {
-      pkg = cls.substr (pos).substr (1);
-      cls = cls.substr (0, pos - 1);
-    }
-
-  int kw_token = (is_keyword_token (meth) || is_keyword_token (cls)
-                  || is_keyword_token (pkg));
+  std::string cls = meth.substr (pos + 1);
+  meth = meth.substr (0, pos);
+
+  bool kw_token = (is_keyword_token (meth)
+                   || fq_identifier_contains_keyword (cls));
+
   if (kw_token)
     {
-      error ("method, class and package names may not be keywords");
+      error ("method, class, and package names may not be keywords");
       return LEXICAL_ERROR;
     }
 
-  symbol_table::scope_id sid = symtab_context.curr_scope ();
-
-  push_token (new token
-              (SUPERCLASSREF,
-               meth.empty () ? 0 : &(symbol_table::insert (meth, sid)),
-               cls.empty () ? 0 : &(symbol_table::insert (cls, sid)),
-               pkg.empty () ? 0 : &(symbol_table::insert (pkg, sid)),
-               input_line_number, current_input_column));
+  push_token (new token (SUPERCLASSREF, meth, cls,
+                         input_line_number, current_input_column));
 
   current_input_column += flex_yyleng ();
 
@@ -2795,37 +2824,41 @@
 int
 octave_base_lexer::handle_meta_identifier (void)
 {
-  std::string pkg;
-  char *yytxt = flex_yytext ();
-  std::string cls = strip_trailing_whitespace (yytxt).substr (1);
-  size_t pos = cls.find (".");
-
-  if (pos != std::string::npos)
+  std::string cls = std::string(flex_yytext ()).substr (1);
+
+  if (fq_identifier_contains_keyword (cls))
     {
-      pkg = cls.substr (pos).substr (1);
-      cls = cls.substr (0, pos - 1);
-    }
-
-  int kw_token = is_keyword_token (cls) || is_keyword_token (pkg);
-  if (kw_token)
-    {
-       error ("class and package names may not be keywords");
+      error ("class and package names may not be keywords");
       return LEXICAL_ERROR;
     }
 
-  symbol_table::scope_id sid = symtab_context.curr_scope ();
-
-  push_token (new token
-              (METAQUERY,
-               cls.empty () ? 0 : &(symbol_table::insert (cls, sid)),
-               pkg.empty () ? 0 : &(symbol_table::insert (pkg, sid)),
-               input_line_number, current_input_column));
+  push_token (new token (METAQUERY, cls, input_line_number,
+                         current_input_column));
 
   current_input_column += flex_yyleng ();
 
   return METAQUERY;
 }
 
+int
+octave_base_lexer::handle_fq_identifier (void)
+{
+  std::string tok = flex_yytext ();
+
+  if (fq_identifier_contains_keyword (tok))
+    {
+      error ("function, method, class, and package names may not be keywords");
+      return LEXICAL_ERROR;
+    }
+
+  push_token (new token (FQ_IDENT, tok, input_line_number,
+                         current_input_column));
+
+  current_input_column += flex_yyleng ();
+
+  return FQ_IDENT;
+}
+
 // Figure out exactly what kind of token to return when we have seen
 // an identifier.  Handles keywords.  Return -1 if the identifier
 // should be ignored.
@@ -3383,6 +3416,12 @@
   return tok;
 }
 
+void
+octave_base_lexer::enable_fq_identifier (void)
+{
+  push_start_state (FQ_IDENT_START);
+}
+
 int
 octave_lexer::fill_flex_buffer (char *buf, unsigned max_size)
 {
--- a/libinterp/parse-tree/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/parse-tree/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -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 12 09:13:19 2015 -0800
+++ b/libinterp/parse-tree/oct-parse.in.yy	Mon Jan 12 09:17:35 2015 -0800
@@ -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"
@@ -161,6 +163,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;
@@ -180,7 +184,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.
@@ -207,21 +228,22 @@
 %token <tok_val> TRY CATCH
 %token <tok_val> GLOBAL PERSISTENT
 %token <tok_val> FCN_HANDLE
+%token <tok_val> CLASSDEF
 %token <tok_val> PROPERTIES METHODS EVENTS ENUMERATION
 %token <tok_val> METAQUERY
 %token <tok_val> SUPERCLASSREF
+%token <tok_val> FQ_IDENT
 %token <tok_val> GET SET
 %token <tok_val> FCN
 
 // Other tokens.
 %token END_OF_INPUT LEXICAL_ERROR
-%token INPUT_FILE CLASSDEF
+%token INPUT_FILE
 // %token VARARGIN VARARGOUT
 
 // Nonterminals we construct.
-%type <tok_val> function_beg
-%type <comment_type> stash_comment classdef_beg
-%type <comment_type> properties_beg methods_beg events_beg enum_beg
+%type <comment_type> stash_comment
+%type <tok_val> function_beg classdef_beg
 %type <sep_type> sep_no_nl opt_sep_no_nl nl opt_nl sep opt_sep
 %type <tree_type> input
 %type <tree_constant_type> string constant magic_colon
@@ -233,18 +255,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
@@ -254,25 +277,27 @@
 %type <tree_decl_elt_type> decl2 param_list_elt
 %type <tree_decl_init_list_type> decl1
 %type <tree_decl_command_type> declaration
-%type <tree_statement_type> statement function_end classdef_end
+%type <tree_statement_type> statement function_end
 %type <tree_statement_list_type> simple_list simple_list1 list list1
 %type <tree_statement_list_type> opt_list
-// These types need to be specified.
-%type <dummy_type> attr
-%type <dummy_type> class_event
-%type <dummy_type> class_enum
-%type <dummy_type> class_property
-%type <dummy_type> properties_list
-%type <dummy_type> properties_block
-%type <dummy_type> methods_list
-%type <dummy_type> methods_block
-%type <dummy_type> opt_attr_list
-%type <dummy_type> attr_list
-%type <dummy_type> events_list
-%type <dummy_type> events_block
-%type <dummy_type> enum_list
-%type <dummy_type> enum_block
-%type <dummy_type> class_body
+%type <tree_classdef_attribute_type> attr
+%type <tree_classdef_attribute_list_type> attr_list opt_attr_list
+%type <tree_classdef_superclass_type> superclass
+%type <tree_classdef_superclass_list_type> superclass_list opt_superclass_list
+%type <tree_classdef_body_type> class_body
+%type <tree_classdef_property_type> class_property
+%type <tree_classdef_property_list_type> property_list
+%type <tree_classdef_properties_block_type> properties_block
+%type <tree_classdef_methods_list_type> methods_list
+%type <tree_classdef_methods_block_type> methods_block
+%type <tree_classdef_event_type> class_event
+%type <tree_classdef_events_list_type> events_list
+%type <tree_classdef_events_block_type> events_block
+%type <tree_classdef_enum_type> class_enum
+%type <tree_classdef_enum_list_type> enum_list
+%type <tree_classdef_enum_block_type> enum_block
+%type <tree_function_def_type> method_decl method
+%type <octave_user_function_type> method_decl1
 
 // Precedence and associativity.
 %right '=' ADD_EQ SUB_EQ MUL_EQ DIV_EQ LEFTDIV_EQ POW_EQ EMUL_EQ EDIV_EQ ELEFTDIV_EQ EPOW_EQ OR_EQ AND_EQ LSHIFT_EQ RSHIFT_EQ
@@ -309,6 +334,8 @@
 %destructor { delete $$; } <tree_expression_type> 
 %destructor { delete $$; } <tree_constant_type> 
 %destructor { delete $$; } <tree_fcn_handle_type> 
+%destructor { delete $$; } <tree_funcall>
+%destructor { delete $$; } <tree_function_def>
 %destructor { delete $$; } <tree_anon_fcn_handle_type> 
 %destructor { delete $$; } <tree_identifier_type> 
 %destructor { delete $$; } <tree_index_expression_type> 
@@ -329,6 +356,24 @@
 %destructor { delete $$; } <tree_statement_list_type> 
 %destructor { delete $$; } <octave_user_function_type> 
 
+%destructor { delete $$; } <tree_classdef_type>
+%destructor { delete $$; } <tree_classdef_attribute_type>
+%destructor { delete $$; } <tree_classdef_attribute_list_type>
+%destructor { delete $$; } <tree_classdef_superclass_type>
+%destructor { delete $$; } <tree_classdef_superclass_list_type>
+%destructor { delete $$; } <tree_classdef_body_type>
+%destructor { delete $$; } <tree_classdef_property_type>
+%destructor { delete $$; } <tree_classdef_property_list_type>
+%destructor { delete $$; } <tree_classdef_properties_block_type>
+%destructor { delete $$; } <tree_classdef_methods_list_type>
+%destructor { delete $$; } <tree_classdef_methods_block_type>
+%destructor { delete $$; } <tree_classdef_event_type>
+%destructor { delete $$; } <tree_classdef_events_list_type>
+%destructor { delete $$; } <tree_classdef_events_block_type>
+%destructor { delete $$; } <tree_classdef_enum_type>
+%destructor { delete $$; } <tree_classdef_enum_list_type>
+%destructor { delete $$; } <tree_classdef_enum_block_type>
+
 %destructor {
     warning_with_id
       ("Octave:parser-destructor",
@@ -436,11 +481,20 @@
 
 superclass_identifier
                 : SUPERCLASSREF
-                  { $$ = new tree_identifier ($1->line (), $1->column ()); }
+                  {
+                    std::string method_nm = $1->superclass_method_name ();
+                    std::string class_nm = $1->superclass_class_name ();
+
+                    $$ = parser.make_superclass_ref (method_nm, class_nm);
+                  }
                 ;
 
 meta_identifier : METAQUERY
-                  { $$ = new tree_identifier ($1->line (), $1->column ()); }
+                  {
+                    std::string class_nm = $1->text ();
+
+                    $$ = parser.make_meta_class_query (class_nm);
+                  }
                 ;
 
 string          : DQ_STRING
@@ -864,8 +918,6 @@
                   { $$ = $1; }
                 | file
                   { $$ = $1; }
-                | classdef
-                  { $$ = $1; }
                 ;
 
 // =====================
@@ -1291,6 +1343,13 @@
 
                     $$ = 0;
                   }
+                | INPUT_FILE opt_nl classdef opt_sep END_OF_INPUT
+                  {
+                    if (lexer.reading_classdef_file)
+                      parser.classdef_object = $3;
+
+                    $$ = 0;
+                  }
                 ;
 
 // ===================
@@ -1333,12 +1392,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;
                   }
                 ;
@@ -1349,6 +1410,14 @@
 
                     delete $1;
 
+                    if (lexer.parsing_classdef_get_method)
+                      fname.insert (0, "get.");
+                    else if (lexer.parsing_classdef_set_method)
+                      fname.insert (0, "set.");
+
+                    lexer.parsing_classdef_get_method = false;
+                    lexer.parsing_classdef_set_method = false;
+
                     $$ = parser.frob_function (fname, $2);
                   }
                 ;
@@ -1408,158 +1477,299 @@
 // Classdef
 // ========
 
-classdef_beg    : CLASSDEF stash_comment
+classdef_beg    : CLASSDEF
                   {
-                    $$ = 0;
+                    if (! lexer.reading_classdef_file)
+                      {
+                        parser.bison_error ("classdef must appear inside a file containing only a class definition");
+                        YYABORT;
+                      }
+
                     lexer.parsing_classdef = true;
+                    $$ = $1;
                   }
                 ;
 
-classdef_end    : END
+classdef        : classdef_beg stash_comment opt_attr_list identifier opt_superclass_list opt_sep class_body opt_sep END
                   {
                     lexer.parsing_classdef = false;
 
-                    if (parser.end_token_ok ($1, token::classdef_end))
-                      $$ = parser.make_end ("endclassdef", false,
-                                            $1->line (), $1->column ());
-                    else
-                      ABORT_PARSE;
+                    if (! ($$ = parser.make_classdef ($1, $3, $4, $5, $7, $9, $2)))
+                      {
+                        // make_classdef deleted $3, $4, $5, and $7.
+                        ABORT_PARSE;
+                      }
                   }
-                ;
-
-classdef1       : classdef_beg opt_attr_list identifier opt_superclasses
-                  { $$ = 0; }
-                ;
-
-classdef        : classdef1 opt_sep class_body opt_sep stash_comment classdef_end
-                  { $$ = 0; }
+                | classdef_beg stash_comment opt_attr_list identifier opt_superclass_list opt_sep END
+                  {
+                    lexer.parsing_classdef = false;
+
+                    if (! ($$ = parser.make_classdef ($1, $3, $4, $5, 0, $7, $2)))
+                      {
+                        // make_classdef deleted $3, $4, and $5.
+                        ABORT_PARSE;
+                      }
+                  }
                 ;
 
 opt_attr_list   : // empty
                   { $$ = 0; }
                 | '(' attr_list ')'
-                  { $$ = 0; }
+                  { $$ = $2; }
                 ;
 
 attr_list       : attr
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_attribute_list ($1); }
                 | attr_list ',' attr
-                  { $$ = 0; }
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
                 ;
 
 attr            : identifier
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_attribute ($1); }
                 | identifier '=' decl_param_init expression
-                  { $$ = 0; }
+                  {
+                    lexer.looking_at_initializer_expression = false;
+                    $$ = new tree_classdef_attribute ($1, $4);
+                  }
                 | EXPR_NOT identifier
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_attribute ($2, false); }
                 ;
 
-opt_superclasses
+opt_superclass_list
                 : // empty
                   { $$ = 0; }
-                | superclasses
-                  { $$ = 0; }
+                | superclass_list
+                  { $$ = $1; }
                 ;
 
-superclasses    : EXPR_LT identifier '.' identifier
-                  { $$ = 0; }
-                | EXPR_LT identifier
-                  { $$ = 0; }
-                | superclasses EXPR_AND identifier '.' identifier
-                  { $$ = 0; }
-                | superclasses EXPR_AND identifier
-                  { $$ = 0; }
+superclass_list : EXPR_LT
+                  { lexer.enable_fq_identifier (); }
+                  superclass
+                  { $$ = new tree_classdef_superclass_list ($3); }
+                | superclass_list EXPR_AND
+                  { lexer.enable_fq_identifier (); }
+                  superclass
+                  {
+                    $1->append ($4);
+                    $$ = $1;
+                  }
+                ;
+
+superclass      : FQ_IDENT
+                  { $$ = new tree_classdef_superclass ($1->text ()); }
                 ;
 
 class_body      : properties_block
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_body ($1); }
                 | methods_block
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_body ($1); }
                 | events_block
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_body ($1); }
                 | enum_block
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_body ($1); }
                 | class_body opt_sep properties_block
-                  { $$ = 0; }
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
                 | class_body opt_sep methods_block
-                  { $$ = 0; }
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
                 | class_body opt_sep events_block
-                  { $$ = 0; }
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
                 | class_body opt_sep enum_block
-                  { $$ = 0; }
-                ;
-
-properties_beg  : PROPERTIES stash_comment
-                  { $$ = 0; }
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
                 ;
 
 properties_block
-                : properties_beg opt_attr_list opt_sep properties_list opt_sep END
-                  { $$ = 0; }
+                : PROPERTIES stash_comment opt_attr_list opt_sep property_list opt_sep END
+                  {
+                    if (! ($$ = parser.make_classdef_properties_block
+                           ($1, $3, $5, $7, $2)))
+                      {
+                        // make_classdef_properties_block delete $3 and $5.
+                        ABORT_PARSE;
+                      }
+                  }
+                | PROPERTIES stash_comment opt_attr_list opt_sep END
+                  {
+                    if (! ($$ = parser.make_classdef_properties_block
+                           ($1, $3, 0, $5, $2)))
+                      {
+                        // make_classdef_properties_block delete $3.
+                        ABORT_PARSE;
+                      }
+                  }
                 ;
 
-properties_list
+property_list
                 : class_property
-                  { $$ = 0; }
-                | properties_list opt_sep class_property
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_property_list ($1); }
+                | property_list opt_sep class_property
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
                 ;
 
 class_property  : identifier
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_property ($1); }
                 | identifier '=' decl_param_init expression ';'
-                  { $$ = 0; }
+                  {
+                    lexer.looking_at_initializer_expression = false;
+                    $$ = new tree_classdef_property ($1, $4);
+                  }
                 ;
 
-methods_beg     : METHODS stash_comment
-                  { $$ = 0; }
+methods_block   : METHODS stash_comment opt_attr_list opt_sep methods_list opt_sep END
+                  {
+                    if (! ($$ = parser.make_classdef_methods_block
+                           ($1, $3, $5, $7, $2)))
+                      {
+                        // make_classdef_methods_block deleted $3 and $5.
+                        ABORT_PARSE;
+                      }
+                  }
+                | METHODS stash_comment opt_attr_list opt_sep END
+                  {
+                    if (! ($$ = parser.make_classdef_methods_block
+                           ($1, $3, 0, $5, $2)))
+                      {
+                        // make_classdef_methods_block deleted $3.
+                        ABORT_PARSE;
+                      }
+                  }
                 ;
-
-methods_block   : methods_beg opt_attr_list opt_sep methods_list opt_sep END
-                  { $$ = 0; }
+                ;
+
+method_decl1    : identifier
+                  {
+                    if (! ($$ = parser.start_classdef_external_method ($1, 0)))
+                      ABORT_PARSE;
+                  }
+                | identifier param_list
+                  {
+                    if (! ($$ = parser.start_classdef_external_method ($1, $2)))
+                      ABORT_PARSE;
+                  }
                 ;
 
-methods_list    : function
-                  { $$ = 0; }
-                | methods_list opt_sep function
-                  { $$ = 0; }
+method_decl     : stash_comment method_decl1
+                  { $$ = parser.finish_classdef_external_method ($2, 0, $1); }
+                | stash_comment return_list '='
+                  {
+                    lexer.defining_func++;
+                    lexer.parsed_function_name.push (false);
+                  }
+                  method_decl1
+                  {
+                    lexer.defining_func--;
+                    lexer.parsed_function_name.pop ();
+                    $$ = parser.finish_classdef_external_method ($5, $2, $1);
+                  }
+                ;
+
+method          : method_decl
+                  { $$ = $1; }
+                | function
+                  { $$ = $1; }
                 ;
 
-events_beg      : EVENTS stash_comment
-                  { $$ = 0; }
+methods_list    : method
+                  {
+                    octave_value fcn;
+                    if ($1)
+                      fcn = $1->function ();
+                    delete $1;
+                    $$ = new tree_classdef_methods_list (fcn);
+                  }
+                | methods_list opt_sep method
+                  {
+                    octave_value fcn;
+                    if ($3)
+                      fcn = $3->function ();
+                    delete $3;
+
+                    $1->append (fcn);
+                    $$ = $1;
+                  }
                 ;
 
-events_block    : events_beg opt_attr_list opt_sep events_list opt_sep END
-                  { $$ = 0; }
+events_block    : EVENTS stash_comment opt_attr_list opt_sep events_list opt_sep END
+                  {
+                    if (! ($$ = parser.make_classdef_events_block
+                           ($1, $3, $5, $7, $2)))
+                      {
+                        // make_classdef_events_block deleted $3 and $5.
+                        ABORT_PARSE;
+                      }
+                  }
+                | EVENTS stash_comment opt_attr_list opt_sep END
+                  {
+                    if (! ($$ = parser.make_classdef_events_block
+                           ($1, $3, 0, $5, $2)))
+                      {
+                        // make_classdef_events_block deleted $3.
+                        ABORT_PARSE;
+                      }
+                  }
                 ;
 
 events_list     : class_event
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_events_list ($1); }
                 | events_list opt_sep class_event
-                  { $$ = 0; }
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
                 ;
 
 class_event     : identifier
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_event ($1); }
                 ;
 
-enum_beg        : ENUMERATION stash_comment
-                  { $$ = 0; }
-                ;
-
-enum_block      : enum_beg opt_attr_list opt_sep enum_list opt_sep END
-                  { $$ = 0; }
+enum_block      : ENUMERATION stash_comment opt_attr_list opt_sep enum_list opt_sep END
+                  {
+                    if (! ($$ = parser.make_classdef_enum_block
+                           ($1, $3, $5, $7, $2)))
+                      {
+                        // make_classdef_enum_block deleted $3 and $5.
+                        ABORT_PARSE;
+                      }
+                  }
+                | ENUMERATION stash_comment opt_attr_list opt_sep END
+                  {
+                    if (! ($$ = parser.make_classdef_enum_block
+                           ($1, $3, 0, $5, $2)))
+                      {
+                        // make_classdef_enum_block deleted $3.
+                        ABORT_PARSE;
+                      }
+                  }
                 ;
 
 enum_list       : class_enum
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_enum_list ($1); }
                 | enum_list opt_sep class_enum
-                  { $$ = 0; }
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
                 ;
 
 class_enum      : identifier '(' expression ')'
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_enum ($1, $3); }
                 ;
 
 // =============
@@ -1657,6 +1867,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 ();
@@ -1828,95 +2039,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 *
@@ -1972,8 +2094,6 @@
           e->preserve_base ();
           delete e;
 
-          // FIXME -- need to attempt constant folding here
-          // too (we need a generic way to do that).
           retval = base;
         }
     }
@@ -2186,10 +2306,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.
@@ -2218,10 +2335,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.
@@ -2262,10 +2376,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.
@@ -2302,10 +2413,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.
@@ -2463,6 +2571,8 @@
 
   if (end_token_ok (end_tok, parfor ? token::parfor_end : token::for_end))
     {
+      expr->mark_as_for_cmd_expr ();
+
       octave_comment_list *tc = lexer.comment_buf.get_comment ();
 
       lexer.looping--;
@@ -2999,6 +3109,272 @@
   lexer.looking_at_parameter_list = false;
 }
 
+tree_funcall *
+octave_base_parser::make_superclass_ref (const std::string& method_nm,
+                                         const std::string& class_nm)
+{
+  octave_value_list args;
+
+  args(1) = class_nm;
+  args(0) = method_nm;
+
+  octave_value fcn
+    = symbol_table::find_built_in_function ("__superclass_reference__");
+
+  return new tree_funcall (fcn, args);
+}
+
+tree_funcall *
+octave_base_parser::make_meta_class_query (const std::string& class_nm)
+{
+  octave_value_list args;
+
+  args(0) = class_nm;
+
+  octave_value fcn
+    = symbol_table::find_built_in_function ("__meta_class_query__");
+
+  return new tree_funcall (fcn, args);
+}
+
+// A CLASSDEF block defines a class that has a constructor and other
+// methods, but it is not an executable command.  Parsing the block
+// makes some changes in the symbol table (inserting the constructor
+// and methods, and adding to the list of known objects) and creates
+// a parse tree containing meta information about the class.
+
+tree_classdef *
+octave_base_parser::make_classdef (token *tok_val,
+                                   tree_classdef_attribute_list *a,
+                                   tree_identifier *id,
+                                   tree_classdef_superclass_list *sc,
+                                   tree_classdef_body *body, token *end_tok,
+                                   octave_comment_list *lc)
+{
+  tree_classdef *retval = 0;
+
+  std::string cls_name = id->name ();
+
+  std::string nm = lexer.fcn_file_name;
+
+  size_t pos = nm.find_last_of (file_ops::dir_sep_chars ());
+
+  if (pos != std::string::npos)
+    nm = lexer.fcn_file_name.substr (pos+1);
+
+  if (nm != cls_name)
+    bison_error ("invalid classdef definition, the class name must match the file name");
+  else if (end_token_ok (end_tok, token::classdef_end))
+    {
+      octave_comment_list *tc = lexer.comment_buf.get_comment ();
+
+      int l = tok_val->line ();
+      int c = tok_val->column ();
+
+      if (! body)
+        body = new tree_classdef_body ();
+
+      retval = new tree_classdef (a, id, sc, body, lc, tc,
+                                  curr_package_name, l, c);
+    }
+
+  if (! retval)
+    {
+      delete a;
+      delete id;
+      delete sc;
+      delete body;
+    }
+
+  return retval;
+}
+
+tree_classdef_properties_block *
+octave_base_parser::make_classdef_properties_block (token *tok_val,
+                                                    tree_classdef_attribute_list *a,
+                                                    tree_classdef_property_list *plist,
+                                                    token *end_tok,
+                                                    octave_comment_list *lc)
+{
+  tree_classdef_properties_block *retval = 0;
+
+  if (end_token_ok (end_tok, token::properties_end))
+    {
+      octave_comment_list *tc = lexer.comment_buf.get_comment ();
+
+      int l = tok_val->line ();
+      int c = tok_val->column ();
+
+      if (! plist)
+        plist = new tree_classdef_property_list ();
+
+      retval = new tree_classdef_properties_block (a, plist, lc, tc, l, c);
+    }
+  else
+    {
+      delete a;
+      delete plist;
+    }
+
+  return retval;
+}
+
+tree_classdef_methods_block *
+octave_base_parser::make_classdef_methods_block (token *tok_val,
+                                                 tree_classdef_attribute_list *a,
+                                                 tree_classdef_methods_list *mlist,
+                                                 token *end_tok,
+                                                 octave_comment_list *lc)
+{
+  tree_classdef_methods_block *retval = 0;
+
+  if (end_token_ok (end_tok, token::methods_end))
+    {
+      octave_comment_list *tc = lexer.comment_buf.get_comment ();
+
+      int l = tok_val->line ();
+      int c = tok_val->column ();
+
+      if (! mlist)
+        mlist = new tree_classdef_methods_list ();
+
+      retval = new tree_classdef_methods_block (a, mlist, lc, tc, l, c);
+    }
+  else
+    {
+      delete a;
+      delete mlist;
+    }
+
+  return retval;
+}
+
+tree_classdef_events_block *
+octave_base_parser::make_classdef_events_block (token *tok_val,
+                                                tree_classdef_attribute_list *a,
+                                                tree_classdef_events_list *elist,
+                                                token *end_tok,
+                                                octave_comment_list *lc)
+{
+  tree_classdef_events_block *retval = 0;
+
+  if (end_token_ok (end_tok, token::events_end))
+    {
+      octave_comment_list *tc = lexer.comment_buf.get_comment ();
+
+      int l = tok_val->line ();
+      int c = tok_val->column ();
+
+      if (! elist)
+        elist = new tree_classdef_events_list ();
+
+      retval = new tree_classdef_events_block (a, elist, lc, tc, l, c);
+    }
+  else
+    {
+      delete a;
+      delete elist;
+    }
+
+  return retval;
+}
+
+tree_classdef_enum_block *
+octave_base_parser::make_classdef_enum_block (token *tok_val,
+                                              tree_classdef_attribute_list *a,
+                                              tree_classdef_enum_list *elist,
+                                              token *end_tok,
+                                              octave_comment_list *lc)
+{
+  tree_classdef_enum_block *retval = 0;
+
+  if (end_token_ok (end_tok, token::enumeration_end))
+    {
+      octave_comment_list *tc = lexer.comment_buf.get_comment ();
+
+      int l = tok_val->line ();
+      int c = tok_val->column ();
+
+      if (! elist)
+        elist = new tree_classdef_enum_list ();
+
+      retval = new tree_classdef_enum_block (a, elist, lc, tc, l, c);
+    }
+  else
+    {
+      delete a;
+      delete elist;
+    }
+
+  return retval;
+}
+
+octave_user_function*
+octave_base_parser::start_classdef_external_method (tree_identifier *id,
+                                                    tree_parameter_list *pl)
+{
+  octave_user_function* retval = 0;
+
+  // External methods are only allowed within @-folders. In this case,
+  // curr_class_name will be non-empty.
+
+  if (! curr_class_name.empty ())
+    {
+
+      std::string mname = id->name ();
+
+      // Methods that cannot be declared outside the classdef file:
+      // - methods with '.' character (e.g. property accessors)
+      // - class constructor
+      // - `delete'
+
+      if (mname.find_first_of (".") == std::string::npos
+          && mname != "delete"
+          && mname != curr_class_name)
+        {
+          // Create a dummy function that is used until the real method
+          // is loaded.
+
+          retval = new octave_user_function (-1, pl);
+
+          retval->stash_function_name (mname);
+
+          int l = id->line ();
+          int c = id->column ();
+
+          retval->stash_fcn_location (l, c);
+        }
+      else
+        bison_error ("invalid external method declaration, an external "
+                     "method cannot be the class constructor, `delete' "
+                     "or have a dot (.) character in its name");
+    }
+  else
+    bison_error ("external methods are only allowed in @-folders");
+
+  if (! retval)
+    delete id;
+
+  return retval;
+}
+
+tree_function_def *
+octave_base_parser::finish_classdef_external_method (octave_user_function *fcn,
+                                                     tree_parameter_list *ret_list,
+                                                     octave_comment_list *cl)
+{
+  if (ret_list)
+    fcn->define_ret_list (ret_list);
+
+  if (cl)
+    fcn->stash_leading_comment (cl);
+
+  int l = fcn->beginning_line ();
+  int c = fcn->beginning_column ();
+
+  return new tree_function_def (fcn, l, c);
+}
+
 // Make an index expression.
 
 tree_index_expression *
@@ -3021,7 +3397,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 ())
     {
@@ -3048,6 +3425,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);
@@ -3067,13 +3447,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);
@@ -3461,6 +3845,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)
 {
@@ -3494,6 +3879,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;
 
@@ -3508,20 +3894,37 @@
 
       fcn_ptr = parser.primary_fcn_ptr;
 
-      if (fcn_ptr)
+      if (status == 0)
         {
-          fcn_ptr->maybe_relocate_end ();
-
-          if (parser.parsing_subfunctions)
+          if (parser.lexer.reading_classdef_file
+              && parser.classdef_object)
             {
-              if (! parser.endfunction_found)
-                parser.subfunction_names.reverse ();
-
-              fcn_ptr->stash_subfunction_names (parser.subfunction_names);
+              // Convert parse tree for classdef object to
+              // meta.class info (and stash it in the symbol
+              // table?).  Return pointer to constructor?
+
+              if (fcn_ptr)
+                panic_impossible ();
+
+              bool is_at_folder = ! dispatch_type.empty ();
+
+              fcn_ptr =
+                parser.classdef_object->make_meta_class (is_at_folder);
+            }
+          else if (fcn_ptr)
+            {
+              fcn_ptr->maybe_relocate_end ();
+
+              if (parser.parsing_subfunctions)
+                {
+                  if (! parser.endfunction_found)
+                    parser.subfunction_names.reverse ();
+
+                  fcn_ptr->stash_subfunction_names (parser.subfunction_names);
+                }
             }
         }
-
-      if (status != 0)
+      else
         error ("parse error while reading file %s", full_file.c_str ());
     }
   else if (require_file)
@@ -3562,7 +3965,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)
         {
@@ -3626,6 +4030,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;
@@ -3673,7 +4078,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, "");
 
@@ -3685,13 +4091,14 @@
     }
   else if (len > 2)
     {
-      retval = parse_fcn_file (file, nm, dispatch_type, true, autoload,
-                               autoload, relative_lookup, "");
+      retval = parse_fcn_file (file, nm, dispatch_type, package_name, true,
+                               autoload, autoload, relative_lookup, "");
     }
 
   if (retval)
     {
       retval->stash_dir_name (dir_name);
+      retval->stash_package_name (package_name);
 
       if (retval->is_user_function ())
         {
@@ -3901,7 +4308,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)
@@ -4632,7 +5039,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 12 09:13:19 2015 -0800
+++ b/libinterp/parse-tree/octave.gperf	Mon Jan 12 09:17:35 2015 -0800
@@ -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 12 09:13:19 2015 -0800
+++ b/libinterp/parse-tree/parse.h	Mon Jan 12 09:17:35 2015 -0800
@@ -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,52 @@
   void
   recover_from_parsing_function (void);
 
+  tree_funcall *
+  make_superclass_ref (const std::string& method_nm,
+                       const std::string& class_nm);
+
+  tree_funcall *
+  make_meta_class_query (const std::string& class_nm);
+
+  tree_classdef *
+  make_classdef (token *tok_val, tree_classdef_attribute_list *a,
+                 tree_identifier *id, tree_classdef_superclass_list *sc,
+                 tree_classdef_body *body, token *end_tok,
+                 octave_comment_list *lc);
+
+  tree_classdef_properties_block *
+  make_classdef_properties_block (token *tok_val,
+                                  tree_classdef_attribute_list *a,
+                                  tree_classdef_property_list *plist,
+                                  token *end_tok, octave_comment_list *lc);
+
+  tree_classdef_methods_block *
+  make_classdef_methods_block (token *tok_val,
+                               tree_classdef_attribute_list *a,
+                               tree_classdef_methods_list *mlist,
+                               token *end_tok, octave_comment_list *lc);
+
+  tree_classdef_events_block *
+  make_classdef_events_block (token *tok_val,
+                              tree_classdef_attribute_list *a,
+                              tree_classdef_events_list *elist,
+                              token *end_tok, octave_comment_list *lc);
+
+  tree_classdef_enum_block *
+  make_classdef_enum_block (token *tok_val,
+                            tree_classdef_attribute_list *a,
+                            tree_classdef_enum_list *elist,
+                            token *end_tok, octave_comment_list *lc);
+
+  octave_user_function *
+  start_classdef_external_method (tree_identifier *id,
+                                  tree_parameter_list *pl);
+
+  tree_function_def *
+  finish_classdef_external_method (octave_user_function *fcn,
+                                   tree_parameter_list *ret_list,
+                                   octave_comment_list *cl);
+
   // Make an index expression.
   tree_index_expression *
   make_index_expression (tree_expression *expr,
@@ -372,6 +432,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 +449,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 12 09:13:19 2015 -0800
+++ b/libinterp/parse-tree/pt-all.h	Mon Jan 12 09:17:35 2015 -0800
@@ -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 12 09:13:19 2015 -0800
+++ b/libinterp/parse-tree/pt-bp.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -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 12 09:13:19 2015 -0800
+++ b/libinterp/parse-tree/pt-bp.h	Mon Jan 12 09:17:35 2015 -0800
@@ -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 12 09:13:19 2015 -0800
+++ b/libinterp/parse-tree/pt-cbinop.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -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-cell.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/parse-tree/pt-cell.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -44,7 +44,7 @@
 
   Cell val;
 
-  int i = 0;
+  octave_idx_type i = 0;
 
   for (iterator p = begin (); p != end (); p++)
     {
@@ -65,10 +65,15 @@
         {
           octave_idx_type this_nc = row.length ();
 
-          if (nc != this_nc)
+          if (this_nc != nc)
             {
-              ::error ("number of columns must match");
-              return retval;
+              if (this_nc == 0)
+                continue;  // blank line
+              else
+                {
+                  ::error ("number of columns must match");
+                  return retval;
+                }
             }
         }
 
@@ -78,6 +83,8 @@
       i++;
     }
 
+  if (i < nr)
+    val.resize (dim_vector (i, nc));  // there were blank rows
   retval = val;
 
   return retval;
--- a/libinterp/parse-tree/pt-check.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/parse-tree/pt-check.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -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 12 09:13:19 2015 -0800
+++ b/libinterp/parse-tree/pt-check.h	Mon Jan 12 09:17:35 2015 -0800
@@ -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 12 09:17:35 2015 -0800
@@ -0,0 +1,259 @@
+/*
+
+Copyright (C) 2012-2013 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "ov-classdef.h"
+#include "pt-classdef.h"
+
+// Classdef attribute
+
+void
+tree_classdef_attribute::accept (tree_walker& tw)
+{
+  tw.visit_classdef_attribute (*this);
+}
+
+// Classdef attribute_list
+
+tree_classdef_attribute_list::~tree_classdef_attribute_list (void)
+{
+  while (! empty ())
+    {
+      iterator p = begin ();
+      delete *p;
+      erase (p);
+    }
+}
+
+void
+tree_classdef_attribute_list::accept (tree_walker& tw)
+{
+  tw.visit_classdef_attribute_list (*this);
+}
+
+// Classdef superclass
+
+void
+tree_classdef_superclass::accept (tree_walker& tw)
+{
+  tw.visit_classdef_superclass (*this);
+}
+
+// Classdef superclass_list
+
+tree_classdef_superclass_list::~tree_classdef_superclass_list (void)
+{
+  while (! empty ())
+    {
+      iterator p = begin ();
+      delete *p;
+      erase (p);
+    }
+}
+
+void
+tree_classdef_superclass_list::accept (tree_walker& tw)
+{
+  tw.visit_classdef_superclass_list (*this);
+}
+
+// Classdef property
+
+void
+tree_classdef_property::accept (tree_walker& tw)
+{
+  tw.visit_classdef_property (*this);
+}
+
+// Classdef property_list
+
+tree_classdef_property_list::~tree_classdef_property_list (void)
+{
+  while (! empty ())
+    {
+      iterator p = begin ();
+      delete *p;
+      erase (p);
+    }
+}
+
+void
+tree_classdef_property_list::accept (tree_walker& tw)
+{
+  tw.visit_classdef_property_list (*this);
+}
+
+// Classdef properties_block
+
+void
+tree_classdef_properties_block::accept (tree_walker& tw)
+{
+  tw.visit_classdef_properties_block (*this);
+}
+
+// Classdef methods_list
+
+void
+tree_classdef_methods_list::accept (tree_walker& tw)
+{
+  tw.visit_classdef_methods_list (*this);
+}
+
+// Classdef methods_block
+
+void
+tree_classdef_methods_block::accept (tree_walker& tw)
+{
+  tw.visit_classdef_methods_block (*this);
+}
+
+// Classdef event
+
+void
+tree_classdef_event::accept (tree_walker& tw)
+{
+  tw.visit_classdef_event (*this);
+}
+
+// Classdef events_list
+
+tree_classdef_events_list::~tree_classdef_events_list (void)
+{
+  while (! empty ())
+    {
+      iterator p = begin ();
+      delete *p;
+      erase (p);
+    }
+}
+
+void
+tree_classdef_events_list::accept (tree_walker& tw)
+{
+  tw.visit_classdef_events_list (*this);
+}
+
+// Classdef events_block
+
+void
+tree_classdef_events_block::accept (tree_walker& tw)
+{
+  tw.visit_classdef_events_block (*this);
+}
+
+// Classdef enum
+
+void
+tree_classdef_enum::accept (tree_walker& tw)
+{
+  tw.visit_classdef_enum (*this);
+}
+
+// Classdef enum_list
+
+tree_classdef_enum_list::~tree_classdef_enum_list (void)
+{
+  while (! empty ())
+    {
+      iterator p = begin ();
+      delete *p;
+      erase (p);
+    }
+}
+
+void
+tree_classdef_enum_list::accept (tree_walker& tw)
+{
+  tw.visit_classdef_enum_list (*this);
+}
+
+// Classdef enum_block
+
+void
+tree_classdef_enum_block::accept (tree_walker& tw)
+{
+  tw.visit_classdef_enum_block (*this);
+}
+
+// Classdef body
+
+tree_classdef_body::~tree_classdef_body (void)
+{
+  while (! properties_lst.empty ())
+    {
+      properties_list_iterator p = properties_lst.begin ();
+      delete *p;
+      properties_lst.erase (p);
+    }
+
+  while (! methods_lst.empty ())
+    {
+      methods_list_iterator p = methods_lst.begin ();
+      delete *p;
+      methods_lst.erase (p);
+    }
+
+  while (! events_lst.empty ())
+    {
+      events_list_iterator p = events_lst.begin ();
+      delete *p;
+      events_lst.erase (p);
+    }
+
+  while (! enum_lst.empty ())
+    {
+      enum_list_iterator p = enum_lst.begin ();
+      delete *p;
+      enum_lst.erase (p);
+    }
+}
+
+// Classdef
+
+octave_function*
+tree_classdef::make_meta_class (bool is_at_folder)
+{
+  octave_value retval;
+  cdef_class cls = cdef_class::make_meta_class (this, is_at_folder);
+
+  if (cls.ok ())
+    return cls.get_constructor_function ();
+
+  return 0;
+}
+
+tree_classdef *
+tree_classdef::dup (symbol_table::scope_id,
+                    symbol_table::context_id) const
+{
+  // FIXME
+  return 0;
+}
+
+void
+tree_classdef::accept (tree_walker& tw)
+{
+  tw.visit_classdef (*this);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/parse-tree/pt-classdef.h	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,653 @@
+/*
+
+Copyright (C) 2012-2013 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_tree_classdef_h)
+#define octave_tree_classdef_h 1
+
+class octave_value;
+
+class tree_walker;
+
+#include "pt-cmd.h"
+#include "pt-exp.h"
+#include "pt-id.h"
+
+#include "base-list.h"
+
+#include <list>
+
+class tree_classdef_attribute
+{
+public:
+
+  tree_classdef_attribute (tree_identifier *i = 0, tree_expression *e = 0)
+    : id (i), expr (e), neg (false) { }
+
+  tree_classdef_attribute (tree_identifier *i, bool b)
+    : id (i), expr (0), neg (b) { }
+
+  ~tree_classdef_attribute (void)
+  {
+    delete id;
+    delete expr;
+  }
+
+  tree_identifier *ident (void) { return id; }
+
+  tree_expression *expression (void) { return expr; }
+
+  bool negate (void) { return neg; }
+
+  void accept (tree_walker&);
+
+private:
+  
+  tree_identifier *id;
+  tree_expression *expr;
+  bool neg;
+
+  // No copying!
+
+  tree_classdef_attribute (const tree_classdef_attribute&);
+
+  tree_classdef_attribute& operator = (const tree_classdef_attribute&);
+};
+
+class tree_classdef_attribute_list : public octave_base_list<tree_classdef_attribute *>
+{
+public:
+
+  tree_classdef_attribute_list (void) { }
+
+  tree_classdef_attribute_list (tree_classdef_attribute *a) { append (a); }
+
+  tree_classdef_attribute_list (const octave_base_list<tree_classdef_attribute *>& a)
+    : octave_base_list<tree_classdef_attribute *> (a) { }
+
+  ~tree_classdef_attribute_list (void);
+
+  void accept (tree_walker&);
+
+private:
+
+  // No copying!
+
+  tree_classdef_attribute_list (const tree_classdef_attribute_list&);
+
+  tree_classdef_attribute_list& operator = (const tree_classdef_attribute_list&);
+};
+
+class tree_classdef_superclass
+{
+public:
+
+  tree_classdef_superclass (const std::string& cname)
+    : cls_name (cname) { }
+
+  ~tree_classdef_superclass (void) { }
+
+  std::string class_name (void) { return cls_name; }
+
+  void accept (tree_walker&);
+
+private:
+
+  std::string cls_name;
+
+  // No copying!
+
+  tree_classdef_superclass (const tree_classdef_superclass&);
+
+  tree_classdef_superclass& operator = (const tree_classdef_superclass&);
+};
+
+class tree_classdef_superclass_list : public octave_base_list<tree_classdef_superclass *>
+{
+public:
+
+  tree_classdef_superclass_list (void) { }
+
+  tree_classdef_superclass_list (tree_classdef_superclass *sc) { append (sc); }
+
+  tree_classdef_superclass_list (const octave_base_list<tree_classdef_superclass *>& a)
+    : octave_base_list<tree_classdef_superclass *> (a) { }
+
+  ~tree_classdef_superclass_list (void);
+
+  void accept (tree_walker&);
+
+private:
+
+  // No copying!
+
+  tree_classdef_superclass_list (const tree_classdef_superclass_list&);
+
+  tree_classdef_superclass_list& operator = (const tree_classdef_superclass_list&);
+};
+
+template <typename T>
+class tree_classdef_element : public tree
+{
+public:
+
+  tree_classdef_element (tree_classdef_attribute_list *a,
+                         octave_base_list<T> *elist,
+                         octave_comment_list *lc, octave_comment_list *tc,
+                         int l = -1, int c = -1)
+    : tree (l, c), attr_list (a), elt_list (elist),
+      lead_comm (lc), trail_comm (tc)
+  { }
+
+  ~tree_classdef_element (void)
+  {
+    delete attr_list;
+    delete elt_list;
+    delete lead_comm;
+    delete trail_comm;
+  }
+
+  tree_classdef_attribute_list *attribute_list (void) { return attr_list; }
+
+  octave_base_list<T> *element_list (void) { return elt_list; }
+
+  octave_comment_list *leading_comment (void) { return lead_comm; }
+
+  octave_comment_list *trailing_comment (void) { return trail_comm; }
+
+  void accept (tree_walker&) { }
+
+private:
+
+  // List of attributes that apply to this class.
+  tree_classdef_attribute_list *attr_list;
+
+  // The list of objects contained in this block.
+  octave_base_list<T> *elt_list;
+  
+  // Comment preceding the token marking the beginning of the block.
+  octave_comment_list *lead_comm;
+
+  // Comment preceding END token.
+  octave_comment_list *trail_comm;
+
+  // No copying!
+
+  tree_classdef_element (const tree_classdef_element&);
+
+  tree_classdef_element& operator = (const tree_classdef_element&);
+};
+
+class tree_classdef_property
+{
+public:
+
+  tree_classdef_property (tree_identifier *i = 0, tree_expression *e = 0)
+    : id (i), expr (e) { }
+
+  ~tree_classdef_property (void)
+  {
+    delete id;
+    delete expr;
+  }
+
+  tree_identifier *ident (void) { return id; }
+
+  tree_expression *expression (void) { return expr; }
+
+  void accept (tree_walker&);
+
+private:
+
+  tree_identifier *id;
+  tree_expression *expr;
+
+  // No copying!
+
+  tree_classdef_property (const tree_classdef_property&);
+
+  tree_classdef_property& operator = (const tree_classdef_property&);
+};
+
+class tree_classdef_property_list : public octave_base_list<tree_classdef_property *>
+{
+public:
+
+  tree_classdef_property_list (void) { }
+
+  tree_classdef_property_list (tree_classdef_property* p) { append (p); }
+
+  tree_classdef_property_list (const octave_base_list<tree_classdef_property *>& a)
+    : octave_base_list<tree_classdef_property *> (a) { }
+
+  ~tree_classdef_property_list (void);
+
+  void accept (tree_walker&);
+
+private:
+
+  // No copying!
+
+  tree_classdef_property_list (const tree_classdef_property_list&);
+
+  tree_classdef_property_list& operator = (const tree_classdef_property_list&);
+};
+
+class tree_classdef_properties_block
+  : public tree_classdef_element<tree_classdef_property *>
+{
+public:
+
+  tree_classdef_properties_block (tree_classdef_attribute_list *a,
+                                  tree_classdef_property_list *plist,
+                                  octave_comment_list *lc,
+                                  octave_comment_list *tc,
+                                  int l = -1, int c = -1)
+    : tree_classdef_element<tree_classdef_property *> (a, plist, lc, tc, l, c) { }
+
+  ~tree_classdef_properties_block (void) { }
+
+  void accept (tree_walker&);
+
+private:
+
+  // No copying!
+
+  tree_classdef_properties_block (const tree_classdef_properties_block&);
+
+  tree_classdef_properties_block& operator = (const tree_classdef_properties_block&);
+};
+
+class tree_classdef_methods_list : public octave_base_list<octave_value>
+{
+public:
+
+  tree_classdef_methods_list (void) { }
+
+  tree_classdef_methods_list (const octave_value& f) { append (f); }
+
+  tree_classdef_methods_list (const octave_base_list<octave_value>& a)
+    : octave_base_list<octave_value> (a) { }
+
+  ~tree_classdef_methods_list (void) { }
+
+  void accept (tree_walker&);
+
+private:
+
+  // No copying!
+
+  tree_classdef_methods_list (const tree_classdef_methods_list&);
+
+  tree_classdef_methods_list& operator = (const tree_classdef_methods_list&);
+};
+
+class tree_classdef_methods_block : public tree_classdef_element<octave_value>
+{
+public:
+
+  tree_classdef_methods_block (tree_classdef_attribute_list *a,
+                               tree_classdef_methods_list *mlist,
+                               octave_comment_list *lc,
+                               octave_comment_list *tc, int l = -1, int c = -1)
+    : tree_classdef_element<octave_value> (a, mlist, lc, tc, l, c) { }
+
+  ~tree_classdef_methods_block (void) { }
+
+  void accept (tree_walker&);
+
+private:
+
+  // No copying!
+
+  tree_classdef_methods_block (const tree_classdef_methods_block&);
+
+  tree_classdef_methods_block& operator = (const tree_classdef_methods_block&);
+};
+
+class tree_classdef_event
+{
+public:
+
+  tree_classdef_event (tree_identifier *i = 0) : id (i) { }
+
+  ~tree_classdef_event (void)
+  {
+    delete id;
+  }
+
+  tree_identifier *ident (void) { return id; }
+
+  void accept (tree_walker&);
+
+private:
+
+  tree_identifier *id;
+
+  // No copying!
+
+  tree_classdef_event (const tree_classdef_event&);
+
+  tree_classdef_event& operator = (const tree_classdef_event&);
+};
+
+class tree_classdef_events_list : public octave_base_list<tree_classdef_event *>
+{
+public:
+
+  tree_classdef_events_list (void) { }
+
+  tree_classdef_events_list (tree_classdef_event *e) { append (e); }
+
+  tree_classdef_events_list (const octave_base_list<tree_classdef_event *>& a)
+    : octave_base_list<tree_classdef_event *> (a) { }
+
+  ~tree_classdef_events_list (void);
+
+  void accept (tree_walker&);
+
+private:
+
+  // No copying!
+
+  tree_classdef_events_list (const tree_classdef_events_list&);
+
+  tree_classdef_events_list& operator = (const tree_classdef_events_list&);
+};
+
+class tree_classdef_events_block
+  : public tree_classdef_element<tree_classdef_event *>
+{
+public:
+
+  tree_classdef_events_block (tree_classdef_attribute_list *a,
+                              tree_classdef_events_list *elist,
+                              octave_comment_list *lc,
+                              octave_comment_list *tc, int l = -1, int c = -1)
+    : tree_classdef_element<tree_classdef_event *> (a, elist, lc, tc, l, c) { }
+
+  ~tree_classdef_events_block (void) { }
+
+  void accept (tree_walker&);
+
+private:
+
+  // No copying!
+
+  tree_classdef_events_block (const tree_classdef_events_block&);
+
+  tree_classdef_events_block& operator = (const tree_classdef_events_block&);
+};
+
+class tree_classdef_enum
+{
+public:
+
+  tree_classdef_enum (void) : id (0), expr (0) { }
+
+  tree_classdef_enum (tree_identifier *i, tree_expression *e)
+    : id (i), expr (e) { }
+
+  ~tree_classdef_enum (void)
+  {
+    delete id;
+    delete expr;
+  }
+
+  tree_identifier *ident (void) { return id; }
+
+  tree_expression *expression (void) { return expr; }
+
+  void accept (tree_walker&);
+
+private:
+
+  tree_identifier *id;
+  tree_expression *expr;
+
+  // No copying!
+
+  tree_classdef_enum (const tree_classdef_enum&);
+
+  tree_classdef_enum& operator = (const tree_classdef_enum&);
+};
+
+class tree_classdef_enum_list : public octave_base_list<tree_classdef_enum *>
+{
+public:
+
+  tree_classdef_enum_list (void) { }
+
+  tree_classdef_enum_list (tree_classdef_enum *e) { append (e); }
+
+  tree_classdef_enum_list (const octave_base_list<tree_classdef_enum *>& a)
+    : octave_base_list<tree_classdef_enum *> (a) { }
+
+  ~tree_classdef_enum_list (void);
+
+  void accept (tree_walker&);
+
+private:
+
+  // No copying!
+
+  tree_classdef_enum_list (const tree_classdef_enum_list&);
+
+  tree_classdef_enum_list& operator = (const tree_classdef_enum_list&);
+};
+
+class tree_classdef_enum_block
+  : public tree_classdef_element<tree_classdef_enum *>
+{
+public:
+
+  tree_classdef_enum_block (tree_classdef_attribute_list *a,
+                            tree_classdef_enum_list *elist,
+                            octave_comment_list *lc,
+                            octave_comment_list *tc, int l = -1, int c = -1)
+    : tree_classdef_element<tree_classdef_enum *> (a, elist, lc, tc, l, c) { }
+
+  ~tree_classdef_enum_block (void) { }
+
+  void accept (tree_walker&);
+
+private:
+
+  // No copying!
+
+  tree_classdef_enum_block (const tree_classdef_enum_block&);
+
+  tree_classdef_enum_block& operator = (const tree_classdef_enum_block&);
+};
+
+class tree_classdef_body
+{
+public:
+
+  typedef std::list<tree_classdef_properties_block *>::iterator properties_list_iterator;
+  typedef std::list<tree_classdef_properties_block *>::const_iterator properties_list_const_iterator;
+
+  typedef std::list<tree_classdef_methods_block *>::iterator methods_list_iterator;
+  typedef std::list<tree_classdef_methods_block *>::const_iterator methods_list_const_iterator;
+
+  typedef std::list<tree_classdef_events_block *>::iterator events_list_iterator;
+  typedef std::list<tree_classdef_events_block *>::const_iterator events_list_const_iterator;
+
+  typedef std::list<tree_classdef_enum_block *>::iterator enum_list_iterator;
+  typedef std::list<tree_classdef_enum_block *>::const_iterator enum_list_const_iterator;
+
+  tree_classdef_body (void)
+    : properties_lst (), methods_lst (), events_lst (), enum_lst () { }
+
+  tree_classdef_body (tree_classdef_properties_block *pb)
+    : properties_lst (), methods_lst (), events_lst (), enum_lst ()
+  {
+    append (pb);
+  }
+
+  tree_classdef_body (tree_classdef_methods_block *mb)
+    : properties_lst (), methods_lst (), events_lst (), enum_lst ()
+  {
+    append (mb);
+  }
+
+  tree_classdef_body (tree_classdef_events_block *evb)
+    : properties_lst (), methods_lst (), events_lst (), enum_lst ()
+  {
+    append (evb);
+  }
+
+  tree_classdef_body (tree_classdef_enum_block *enb)
+    : properties_lst (), methods_lst (), events_lst (), enum_lst ()
+  {
+    append (enb);
+  }
+
+  ~tree_classdef_body (void);
+
+  void append (tree_classdef_properties_block *pb)
+  {
+    properties_lst.push_back (pb);
+  }
+
+  void append (tree_classdef_methods_block *mb)
+  {
+    methods_lst.push_back (mb);
+  }
+
+  void append (tree_classdef_events_block *evb)
+  {
+    events_lst.push_back (evb);
+  }
+
+  void append (tree_classdef_enum_block *enb)
+  {
+    enum_lst.push_back (enb);
+  }
+
+  std::list<tree_classdef_properties_block *> properties_list (void)
+  {
+    return properties_lst;
+  }
+
+  std::list<tree_classdef_methods_block *> methods_list (void)
+  {
+    return methods_lst;
+  }
+
+  std::list<tree_classdef_events_block *> events_list (void)
+  {
+    return events_lst;
+  }
+
+  std::list<tree_classdef_enum_block *> enum_list (void)
+  {
+    return enum_lst;
+  }
+
+  void accept (tree_walker&);
+
+private:
+
+  std::list<tree_classdef_properties_block *> properties_lst;
+
+  std::list<tree_classdef_methods_block *> methods_lst;
+
+  std::list<tree_classdef_events_block *> events_lst;
+
+  std::list<tree_classdef_enum_block *> enum_lst;
+
+  // No copying!
+
+  tree_classdef_body (const tree_classdef_body&);
+
+  tree_classdef_body& operator = (const tree_classdef_body&);
+};
+
+// Classdef definition.
+
+class tree_classdef : public tree_command
+{
+public:
+
+  tree_classdef (tree_classdef_attribute_list *a, tree_identifier *i,
+                 tree_classdef_superclass_list *sc,
+                 tree_classdef_body *b, octave_comment_list *lc,
+                 octave_comment_list *tc,
+                 const std::string& pn = std::string (), int l = -1,
+                 int c = -1)
+    : tree_command (l, c), attr_list (a), id (i),
+      supclass_list (sc), element_list (b), lead_comm (lc), trail_comm (tc),
+      pack_name (pn) { }
+
+  ~tree_classdef (void)
+  {
+    delete attr_list;
+    delete id;
+    delete supclass_list;
+    delete element_list;
+    delete lead_comm;
+    delete trail_comm;
+  }
+
+  tree_classdef_attribute_list *attribute_list (void) { return attr_list; }
+
+  tree_identifier *ident (void) { return id; }
+
+  tree_classdef_superclass_list *superclass_list (void) { return supclass_list; }
+
+  tree_classdef_body *body (void) { return element_list; }
+
+  octave_comment_list *leading_comment (void) { return lead_comm; }
+  octave_comment_list *trailing_comment (void) { return trail_comm; }
+
+  const std::string& package_name (void) const { return pack_name; }
+
+  octave_function* make_meta_class (bool is_at_folder = false);
+
+  tree_classdef *dup (symbol_table::scope_id scope,
+                      symbol_table::context_id context) const;
+
+  void accept (tree_walker& tw);
+
+private:
+
+  tree_classdef_attribute_list *attr_list;
+
+  tree_identifier *id;
+
+  tree_classdef_superclass_list *supclass_list;
+
+  tree_classdef_body *element_list;
+
+  octave_comment_list *lead_comm;
+  octave_comment_list *trail_comm;
+
+  std::string pack_name;
+
+  // No copying!
+
+  tree_classdef (const tree_classdef&);
+
+  tree_classdef& operator = (const tree_classdef&);
+};
+
+#endif
--- a/libinterp/parse-tree/pt-colon.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/parse-tree/pt-colon.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -96,7 +96,12 @@
     retval = Range ();
   else
     {
-      retval = Range (m_base(0), m_limit(0), m_increment(0));
+      Range r (m_base(0), m_limit(0), m_increment(0));
+
+      // For compatibility with Matlab, don't allow the range used in
+      // a FOR loop expression to be converted to a Matrix.
+
+      retval = octave_value (r, is_for_cmd_expr ());
 
       if (result_is_str)
         retval = retval.convert_to_str (false, true, dq_str ? '"' : '\'');
--- a/libinterp/parse-tree/pt-eval.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/parse-tree/pt-eval.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -370,7 +370,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)
           {
@@ -628,6 +629,12 @@
 }
 
 void
+tree_evaluator::visit_funcall (tree_funcall&)
+{
+  panic_impossible ();
+}
+
+void
 tree_evaluator::visit_parameter_list (tree_parameter_list&)
 {
   panic_impossible ();
@@ -1105,6 +1112,11 @@
   if (error_state)
     return;
 
+#if HAVE_LLVM
+  if (tree_jit::execute (cmd))
+    return;
+#endif
+
   unwind_protect frame;
 
   frame.protect_var (in_loop_command);
--- a/libinterp/parse-tree/pt-eval.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/parse-tree/pt-eval.h	Mon Jan 12 09:17:35 2015 -0800
@@ -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 12 09:13:19 2015 -0800
+++ b/libinterp/parse-tree/pt-exp.h	Mon Jan 12 09:17:35 2015 -0800
@@ -40,8 +40,8 @@
 public:
 
   tree_expression (int l = -1, int c = -1)
-    : tree (l, c), num_parens (0), postfix_indexed (false),
-      print_flag (false) { }
+    : tree (l, c), num_parens (0), postfix_index_type ('\0'),
+      for_cmd_expr (false), 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
@@ -102,15 +104,19 @@
 
   virtual void mark_braindead_shortcircuit (void) { }
 
+  void mark_as_for_cmd_expr (void) { for_cmd_expr = true; }
+
+  bool is_for_cmd_expr (void) const { return for_cmd_expr; }
+
   tree_expression *mark_in_parens (void)
   {
     num_parens++;
     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 +129,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 +143,14 @@
   //                  ==> 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;
+
+  // TRUE if this expression is the EXPR in for loop:
+  // FOR i = EXPR ... END
+  bool for_cmd_expr;
 
   // 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 12 09:17:35 2015 -0800
@@ -0,0 +1,110 @@
+/*
+
+Copyright (C) 2012-2013 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "ov-fcn.h"
+#include "pt-funcall.h"
+#include "pt-walk.h"
+
+// Function call objects.
+
+void
+tree_funcall::print (std::ostream& os, bool pr_as_read_syntax,
+                     bool pr_orig_text)
+{
+  print_raw (os, pr_as_read_syntax, pr_orig_text);
+}
+
+void
+tree_funcall::print_raw (std::ostream& os, bool pr_as_read_syntax,
+                         bool pr_orig_text)
+{
+  if (pr_orig_text)
+    {
+      os << original_text ();
+    }
+  else
+    {
+      octave_function *fp = fcn.function_value ();
+      std::string nm = fp ? fp->name () : std::string ("<invalid-function>");
+
+      os << nm << " (";
+
+      octave_idx_type len = args.length ();
+      for (octave_idx_type i = 0; i < len; i++)
+        {
+          args(i).print_raw (os, pr_as_read_syntax);
+
+          if (i < len - 1)
+            os << ", ";
+        }
+
+      os << ")";
+    }
+}
+
+tree_funcall *
+tree_funcall::dup (symbol_table::scope_id, symbol_table::context_id) const
+{
+  tree_funcall *new_fc = new tree_funcall (fcn, args, line (), column ());
+
+  new_fc->copy_base (*new_fc);
+
+  return new_fc;
+}
+
+void
+tree_funcall::accept (tree_walker& tw)
+{
+  tw.visit_funcall (*this);
+}
+
+octave_value_list
+tree_funcall::rvalue (int nargout)
+{
+  octave_value_list retval;
+
+  retval = feval (fcn.function_value (), args, nargout);
+
+  if (retval.length () == 1 && retval(0).is_function ())
+    {
+      // The return object is a function. We may need to re-index it using the
+      // same logic as for identifier. This is primarily used for superclass
+      // references in classdef.
+
+      octave_value val = retval(0);
+      octave_function *f = val.function_value (true);
+
+      if (f && ! (is_postfix_indexed ()
+                  && f->is_postfix_index_handled (postfix_index ())))
+        {
+          octave_value_list tmp_args;
+
+          retval = val.do_multi_index_op (nargout, tmp_args);
+        }
+    }
+
+  return retval;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/parse-tree/pt-funcall.h	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,98 @@
+/*
+
+Copyright (C) 2012-2013 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_tree_funcall_h)
+#define octave_tree_funcall_h 1
+
+#include "ov.h"
+#include "oct-obj.h"
+#include "parse.h"
+#include "pt-exp.h"
+
+// Function call.  This class only represents function calls that have
+// known functions (most useful for calls to built-in functions that
+// are generated by the parser) and fixed argument lists, known at
+// compile time.
+
+class
+tree_funcall : public tree_expression
+{
+public:
+
+  tree_funcall (const octave_value& f, const octave_value_list& a,
+                int l = -1, int c = -1)
+    : tree_expression (l, c), fcn (f), args (a)
+  {
+    if (! fcn.is_function ())
+      error ("tree_funcall: invalid function");
+  }
+
+  ~tree_funcall (void) { }
+
+  bool has_magic_end (void) const { return false; }
+
+  void print (std::ostream& os, bool pr_as_read_syntax = false,
+              bool pr_orig_txt = true);
+
+  void print_raw (std::ostream& os, bool pr_as_read_syntax = false,
+                  bool pr_orig_txt = true);
+
+  tree_funcall *dup (symbol_table::scope_id,
+                     symbol_table::context_id context) const;
+
+  octave_value rvalue1 (int nargout)
+  {
+    octave_value retval;
+
+    const octave_value_list tmp = rvalue (nargout);
+
+    if (! tmp.empty ())
+      retval = tmp(0);
+
+    return retval;
+  }
+
+  octave_value_list rvalue (int nargout);
+
+  octave_value function (void) const { return fcn; }
+
+  octave_value_list arguments (void) const { return args; }
+
+  void accept (tree_walker& tw);
+
+private:
+
+  // Function to call.  Error if not a valid function at time of
+  // construction.
+  octave_value fcn;
+
+  // Argument list.
+  octave_value_list args;
+
+  // No copying!
+
+  tree_funcall (const tree_funcall&);
+
+  tree_funcall& operator = (const tree_funcall&);
+};
+
+#endif
--- a/libinterp/parse-tree/pt-id.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/parse-tree/pt-id.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -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 12 09:13:19 2015 -0800
+++ b/libinterp/parse-tree/pt-id.h	Mon Jan 12 09:17:35 2015 -0800
@@ -32,6 +32,7 @@
 
 class tree_walker;
 
+#include "oct-lvalue.h"
 #include "pt-bp.h"
 #include "pt-exp.h"
 #include "symtab.h"
--- a/libinterp/parse-tree/pt-idx.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/parse-tree/pt-idx.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -220,7 +220,7 @@
               if (t.is_string () && t.rows () == 1)
                 fn = t.string_value ();
               else
-                error ("dynamic structure field names must be character strings");
+                error ("dynamic structure field names must be strings");
             }
         }
       else
@@ -363,7 +363,7 @@
                   // that argument list so we can pass the appropriate
                   // value to the built-in end function.
 
-                  const octave_value_list tmp_list
+                  octave_value_list tmp_list
                     = tmp.subsref (type.substr (tmpi, i - tmpi), idx, nargout);
 
                   tmp = tmp_list.length () ? tmp_list(0) : octave_value ();
@@ -375,6 +375,26 @@
 
                   if (error_state)
                     break;
+
+                  if (tmp.is_function ())
+                    {
+                      octave_function *fcn = tmp.function_value (true);
+
+                      if (fcn && ! fcn->is_postfix_index_handled (type[i]))
+                        {
+                          octave_value_list empty_args;
+
+                          tmp_list = tmp.do_multi_index_op (1, empty_args);
+                          tmp = (tmp_list.length ()
+                                 ? tmp_list(0) : octave_value ());
+
+                          if (tmp.is_cs_list ())
+                            gripe_indexed_cs_list ();
+
+                          if (error_state)
+                            break;
+                        }
+                    }
                 }
             }
 
@@ -412,8 +432,27 @@
         }
 
       if (! error_state)
-        retval = tmp.subsref (type.substr (tmpi, n - tmpi), idx, nargout,
-                              lvalue_list);
+        {
+          retval = tmp.subsref (type.substr (tmpi, n - tmpi), idx, nargout,
+                                lvalue_list);
+
+          octave_value val = retval.length () ? retval(0) : octave_value ();
+
+          if (! error_state && val.is_function ())
+            {
+              octave_function *fcn = val.function_value (true);
+
+              if (fcn)
+                {
+                  octave_value_list empty_args;
+
+                  retval = (lvalue_list
+                            ? val.do_multi_index_op (nargout, empty_args,
+                                                     lvalue_list)
+                            : val.do_multi_index_op (nargout, empty_args));
+                }
+            }
+        }
     }
 
   return retval;
--- a/libinterp/parse-tree/pt-mat.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/parse-tree/pt-mat.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -26,6 +26,7 @@
 
 #include <iostream>
 
+#include "oct-locbuf.h"
 #include "quit.h"
 
 #include "data.h"
@@ -387,27 +388,30 @@
 
   first_elem = true;
 
-  for (iterator p = begin (); p != end (); p++)
+  if (! error_state)
     {
-      octave_quit ();
-
-      octave_value val = *p;
-
-      dim_vector this_elt_dv = val.dims ();
-
-      if (! this_elt_dv.zero_by_zero ())
+      for (iterator p = begin (); p != end (); p++)
         {
-          all_mt = false;
+          octave_quit ();
+
+          octave_value val = *p;
 
-          if (first_elem)
+          dim_vector this_elt_dv = val.dims ();
+
+          if (! this_elt_dv.zero_by_zero ())
             {
-              first_elem = false;
-              dv = this_elt_dv;
-            }
-          else if ((! any_class) && (! dv.hvcat (this_elt_dv, 1)))
-            {
-              eval_error ("horizontal dimensions mismatch", dv, this_elt_dv);
-              break;
+              all_mt = false;
+
+              if (first_elem)
+                {
+                  first_elem = false;
+                  dv = this_elt_dv;
+                }
+              else if ((! any_class) && (! dv.hvcat (this_elt_dv, 1)))
+                {
+                  eval_error ("horizontal dimensions mismatch", dv, this_elt_dv);
+                  break;
+                }
             }
         }
     }
@@ -684,7 +688,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++)
     {
@@ -754,7 +759,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 ();
@@ -792,12 +798,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 ();
@@ -830,12 +838,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 12 09:13:19 2015 -0800
+++ b/libinterp/parse-tree/pt-pr-code.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -749,6 +749,18 @@
 }
 
 void
+tree_print_code::visit_funcall (tree_funcall& fc)
+{
+  indent ();
+
+  print_parens (fc, "(");
+
+  fc.print_raw (os, true, print_original_text);
+
+  print_parens (fc, ")");
+}
+
+void
 tree_print_code::visit_parameter_list (tree_parameter_list& lst)
 {
   tree_parameter_list::iterator p = lst.begin ();
@@ -1144,7 +1156,7 @@
 
   indent ();
 
-  os << "until";
+  os << "until ";
 
   tree_expression *expr = cmd.condition ();
 
@@ -1188,10 +1200,7 @@
     }
 }
 
-// Each print_code() function should call this before printing
-// anything.
-//
-// This doesn't need to be fast, but isn't there a better way?
+// Each print_code() function should call this before printing anything.
 
 void
 tree_print_code::indent (void)
@@ -1202,8 +1211,7 @@
     {
       os << prefix;
 
-      for (int i = 0; i < curr_print_indent_level; i++)
-        os << " ";
+      os << std::string (curr_print_indent_level, ' ');
 
       beginning_of_line = false;
     }
--- a/libinterp/parse-tree/pt-pr-code.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/parse-tree/pt-pr-code.h	Mon Jan 12 09:17:35 2015 -0800
@@ -109,6 +109,8 @@
 
   void visit_fcn_handle (tree_fcn_handle&);
 
+  void visit_funcall (tree_funcall&);
+
   void visit_parameter_list (tree_parameter_list&);
 
   void visit_postfix_expression (tree_postfix_expression&);
--- a/libinterp/parse-tree/pt-select.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/parse-tree/pt-select.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -123,7 +123,7 @@
 {
   octave_value label_value = label->rvalue1 ();
 
-  if (! error_state && label_value.is_defined () )
+  if (! error_state && label_value.is_defined ())
     {
       if (label_value.is_cell ())
         {
--- a/libinterp/parse-tree/pt-walk.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/parse-tree/pt-walk.h	Mon Jan 12 09:17:35 2015 -0800
@@ -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 12 09:13:19 2015 -0800
+++ b/libinterp/parse-tree/token.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -97,38 +97,29 @@
   sr = s;
 }
 
-token::token (int tv, symbol_table::symbol_record *cls,
-              symbol_table::symbol_record *pkg, int l, int c)
+token::token (int tv, const std::string& mth, const std::string& cls,
+              int l, int c)
 {
   maybe_cmd = false;
   tspc = false;
   line_num = l;
   column_num = c;
   tok_val = tv;
-  type_tag = meta_rec_token;
-  mc.cr = cls;
-  mc.pr = pkg;
-}
-
-token::token (int tv, symbol_table::symbol_record *mth,
-              symbol_table::symbol_record *cls,
-              symbol_table::symbol_record *pkg, int l, int c)
-{
-  maybe_cmd = false;
-  tspc = false;
-  line_num = l;
-  column_num = c;
-  tok_val = tv;
-  type_tag = scls_rec_token;
-  sc.mr = mth;
-  sc.cr = cls;
-  sc.pr = pkg;
+  type_tag = scls_name_token;
+  sc.method_nm = new std::string (mth);
+  sc.class_nm = new std::string (cls);
 }
 
 token::~token (void)
 {
   if (type_tag == string_token)
     delete str;
+
+  if (type_tag == scls_name_token)
+    {
+      delete sc.method_nm;
+      delete sc.class_nm;
+    }
 }
 
 std::string
@@ -172,39 +163,18 @@
   return sr;
 }
 
-symbol_table::symbol_record *
-token::method_rec (void)
+std::string
+token::superclass_method_name (void)
 {
-  assert (type_tag == scls_rec_token);
-  return sc.mr;
-}
-
-symbol_table::symbol_record *
-token::class_rec (void)
-{
-  assert (type_tag == scls_rec_token);
-  return sc.cr;
+  assert (type_tag == scls_name_token);
+  return *sc.method_nm;
 }
 
-symbol_table::symbol_record *
-token::package_rec (void)
-{
-  assert (type_tag == scls_rec_token);
-  return sc.pr;
-}
-
-symbol_table::symbol_record *
-token::meta_class_rec (void)
+std::string
+token::superclass_class_name (void)
 {
-  assert (type_tag == meta_rec_token);
-  return mc.cr;
-}
-
-symbol_table::symbol_record *
-token::meta_package_rec (void)
-{
-  assert (type_tag == meta_rec_token);
-  return mc.pr;
+  assert (type_tag == scls_name_token);
+  return *sc.class_nm;
 }
 
 std::string
--- a/libinterp/parse-tree/token.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/libinterp/parse-tree/token.h	Mon Jan 12 09:17:35 2015 -0800
@@ -40,8 +40,7 @@
     double_token,
     ettype_token,
     sym_rec_token,
-    scls_rec_token,
-    meta_rec_token
+    scls_name_token,
   };
 
   enum end_tok_type
@@ -69,11 +68,8 @@
          int l = -1, int c = -1);
   token (int tv, end_tok_type t, int l = -1, int c = -1);
   token (int tv, symbol_table::symbol_record *s, int l = -1, int c = -1);
-  token (int tv, symbol_table::symbol_record *cls,
-         symbol_table::symbol_record *pkg, int l = -1, int c = -1);
-  token (int tv, symbol_table::symbol_record *mth,
-         symbol_table::symbol_record *cls,
-         symbol_table::symbol_record *pkg, int l = -1, int c = -1);
+  token (int tv, const std::string& mth, const std::string& cls,
+         int l = -1, int c = -1);
 
   ~token (void);
 
@@ -106,12 +102,8 @@
   end_tok_type ettype (void) const;
   symbol_table::symbol_record *sym_rec (void);
 
-  symbol_table::symbol_record *method_rec (void);
-  symbol_table::symbol_record *class_rec (void);
-  symbol_table::symbol_record *package_rec (void);
-
-  symbol_table::symbol_record *meta_class_rec (void);
-  symbol_table::symbol_record *meta_package_rec (void);
+  std::string superclass_method_name (void);
+  std::string superclass_class_name (void);
 
   std::string text_rep (void);
 
@@ -137,15 +129,9 @@
     symbol_table::symbol_record *sr;
     struct
     {
-      symbol_table::symbol_record *mr;
-      symbol_table::symbol_record *cr;
-      symbol_table::symbol_record *pr;
+      std::string *method_nm;
+      std::string *class_nm;
     } sc;
-    struct
-    {
-      symbol_table::symbol_record *cr;
-      symbol_table::symbol_record *pr;
-    } mc;
   };
   std::string orig_text;
 };
--- a/liboctave/Makefile.am	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/Makefile.am	Mon Jan 12 09:17:35 2015 -0800
@@ -20,10 +20,6 @@
 
 include $(top_srcdir)/build-aux/common.mk
 
-## Run cruft dir with stand-alone Makefile.
-## Eventually this will use module.mk syntax.
-SUBDIRS = cruft
-
 ## Search local directories before those specified by the user.
 AM_CPPFLAGS = \
   -I$(srcdir)/array \
@@ -55,6 +51,7 @@
 
 octinclude_HEADERS = \
   $(ARRAY_INC) \
+  $(CRUFT_INC) \
   $(NUMERIC_INC) \
   $(OPERATORS_INC) \
   $(SYSTEM_INC) \
@@ -75,7 +72,10 @@
 
 ## A list of all files that could include tests
 
+liboctave_la_LIBADD =
+
 include array/module.mk
+include cruft/module.mk
 include numeric/module.mk
 include operators/module.mk
 include system/module.mk
@@ -92,14 +92,7 @@
 # Dummy C++ source to force C++ linking.
 nodist_EXTRA_liboctave_la_SOURCES = dummy.cc
 
-liboctave_la_LIBADD = \
-  array/libarray.la \
-  cruft/libcruft.la \
-  cruft/ranlib/libranlib.la \
-  numeric/libnumeric.la \
-  operators/liboperators.la \
-  system/libsystem.la \
-  util/libutil.la \
+liboctave_la_LIBADD += \
   $(top_builddir)/libgnu/libgnu.la \
   $(LIBOCTAVE_LINK_DEPS)
 
--- a/liboctave/array/Array-C.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/Array-C.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -88,7 +88,7 @@
   return result;
 }
 
-INSTANTIATE_ARRAY_SORT (Complex);
+template class OCTAVE_API octave_sort<Complex>;
 
 INSTANTIATE_ARRAY (Complex, OCTAVE_API);
 
--- a/liboctave/array/Array-b.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/Array-b.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -104,7 +104,7 @@
   do_bool_partition<true> (data, idx, nel);
 }
 
-INSTANTIATE_ARRAY_SORT (bool);
+template class OCTAVE_API octave_sort<bool>;
 
 INSTANTIATE_ARRAY (bool, OCTAVE_API);
 
--- a/liboctave/array/Array-ch.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/Array-ch.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -32,7 +32,7 @@
 #define INLINE_DESCENDING_SORT
 #include "oct-sort.cc"
 
-INSTANTIATE_ARRAY_SORT (char);
+template class OCTAVE_API octave_sort<char>;
 
 INSTANTIATE_ARRAY (char, OCTAVE_API);
 
--- a/liboctave/array/Array-d.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/Array-d.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -155,7 +155,7 @@
   return mode;
 }
 
-INSTANTIATE_ARRAY_SORT (double);
+template class OCTAVE_API octave_sort<double>;
 
 INSTANTIATE_ARRAY (double, OCTAVE_API);
 
--- a/liboctave/array/Array-f.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/Array-f.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -155,7 +155,7 @@
   return mode;
 }
 
-INSTANTIATE_ARRAY_SORT (float);
+template class OCTAVE_API octave_sort<float>;
 
 INSTANTIATE_ARRAY (float, OCTAVE_API);
 
--- a/liboctave/array/Array-fC.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/Array-fC.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -88,7 +88,7 @@
   return result;
 }
 
-INSTANTIATE_ARRAY_SORT (FloatComplex);
+template class OCTAVE_API octave_sort<FloatComplex>;
 
 INSTANTIATE_ARRAY (FloatComplex, OCTAVE_API);
 
--- a/liboctave/array/Array-i.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/Array-i.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -35,10 +35,10 @@
 #define INLINE_DESCENDING_SORT
 #include "oct-sort.cc"
 
-INSTANTIATE_ARRAY_SORT (int);
-INSTANTIATE_ARRAY_SORT (long);
+template class OCTAVE_API octave_sort<int>;
+template class OCTAVE_API octave_sort<long>;
 #if defined (HAVE_LONG_LONG_INT)
-INSTANTIATE_ARRAY_SORT (long long);
+template class OCTAVE_API octave_sort<long long>;
 #endif
 
 INSTANTIATE_ARRAY (int, OCTAVE_API);
@@ -47,20 +47,20 @@
 INSTANTIATE_ARRAY (long long, OCTAVE_API);
 #endif
 
-INSTANTIATE_ARRAY_SORT (octave_int8);
-INSTANTIATE_ARRAY_SORT (octave_int16);
-INSTANTIATE_ARRAY_SORT (octave_int32);
-INSTANTIATE_ARRAY_SORT (octave_int64);
+template class OCTAVE_API octave_sort<octave_int8>;
+template class OCTAVE_API octave_sort<octave_int16>;
+template class OCTAVE_API octave_sort<octave_int32>;
+template class OCTAVE_API octave_sort<octave_int64>;
 
 INSTANTIATE_ARRAY (octave_int8, OCTAVE_API);
 INSTANTIATE_ARRAY (octave_int16, OCTAVE_API);
 INSTANTIATE_ARRAY (octave_int32, OCTAVE_API);
 INSTANTIATE_ARRAY (octave_int64, OCTAVE_API);
 
-INSTANTIATE_ARRAY_SORT (octave_uint8);
-INSTANTIATE_ARRAY_SORT (octave_uint16);
-INSTANTIATE_ARRAY_SORT (octave_uint32);
-INSTANTIATE_ARRAY_SORT (octave_uint64);
+template class OCTAVE_API octave_sort<octave_uint8>;
+template class OCTAVE_API octave_sort<octave_uint16>;
+template class OCTAVE_API octave_sort<octave_uint32>;
+template class OCTAVE_API octave_sort<octave_uint64>;
 
 INSTANTIATE_ARRAY (octave_uint8, OCTAVE_API);
 INSTANTIATE_ARRAY (octave_uint16, OCTAVE_API);
--- a/liboctave/array/Array-s.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/Array-s.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -33,7 +33,7 @@
 #define INLINE_DESCENDING_SORT
 #include "oct-sort.cc"
 
-INSTANTIATE_ARRAY_SORT (short);
+template class OCTAVE_API octave_sort<short>;
 
 INSTANTIATE_ARRAY (short, OCTAVE_API);
 
--- a/liboctave/array/Array-str.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/Array-str.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -32,6 +32,6 @@
 #include "Array.cc"
 #include "oct-sort.cc"
 
-INSTANTIATE_ARRAY_SORT (std::string);
+template class OCTAVE_API octave_sort<std::string>;
 
 INSTANTIATE_ARRAY (std::string, OCTAVE_API);
--- a/liboctave/array/Array.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/Array.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -76,7 +76,7 @@
       slice_data = rep->data;
     }
   else
-    fill_or_memset (slice_len, val, slice_data);
+    std::fill_n (slice_data, slice_len, val);
 }
 
 template <class T>
@@ -399,7 +399,7 @@
         octave_idx_type len = dim[0];
         if (step == 1)
           {
-            copy_or_memcpy (len, src, dest);
+            std::copy (src, src + len, dest);
             dest += len;
           }
         else
@@ -683,18 +683,18 @@
   {
     if (lev == 0)
       {
-        copy_or_memcpy (cext[0], src, dest);
-        fill_or_memset (dext[0] - cext[0], rfv, dest + cext[0]);
+        std::copy (src, src+cext[0], dest);
+        std::fill_n (dest + cext[0], dext[0] - cext[0], rfv);
       }
     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);
 
-        fill_or_memset (dext[lev] - k * dd, rfv, dest + k * dd);
+        std::fill_n (dest + k * dd, dext[lev] - k * dd, rfv);
       }
   }
 
@@ -959,7 +959,7 @@
                   Array<T> tmp (Array<T> (dim_vector (nn, 1)), dv, 0, n);
                   T *dest = tmp.fortran_vec ();
 
-                  copy_or_memcpy (nx, data (), dest);
+                  std::copy (data (), data () + nx, dest);
                   dest[nx] = rfv;
 
                   *this = tmp;
@@ -972,8 +972,8 @@
 
               octave_idx_type n0 = std::min (n, nx);
               octave_idx_type n1 = n - n0;
-              copy_or_memcpy (n0, data (), dest);
-              fill_or_memset (n1, rfv, dest + n0);
+              std::copy (data (), data () + n0, dest);
+              std::fill_n (dest + n0, n1, rfv);
 
               *this = tmp;
             }
@@ -1003,22 +1003,22 @@
           const T *src = data ();
           if (r == rx)
             {
-              copy_or_memcpy (r * c0, src, dest);
+              std::copy (src, src + r * c0, dest);
               dest += r * c0;
             }
           else
             {
               for (octave_idx_type k = 0; k < c0; k++)
                 {
-                  copy_or_memcpy (r0, src, dest);
+                  std::copy (src, src + r0, dest);
                   src += rx;
                   dest += r0;
-                  fill_or_memset (r1, rfv, dest);
+                  std::fill_n (dest, r1, rfv);
                   dest += r1;
                 }
             }
 
-          fill_or_memset (r * c1, rfv, dest);
+          std::fill_n (dest, r * c1, rfv);
 
           *this = tmp;
         }
@@ -1416,8 +1416,8 @@
           Array<T> tmp (dim_vector (col_vec ? m : 1, !col_vec ? m : 1));
           const T *src = data ();
           T *dest = tmp.fortran_vec ();
-          copy_or_memcpy (l, src, dest);
-          copy_or_memcpy (n - u, src + u, dest + l);
+          std::copy (src, src + l, dest);
+          std::copy (src + u, src + n, dest + l);
           *this = tmp;
         }
       else
@@ -1469,9 +1469,9 @@
           l *= dl; u *= dl; n *= dl;
           for (octave_idx_type k = 0; k < du; k++)
             {
-              copy_or_memcpy (l, src, dest);
+              std::copy (src, src + l, dest);
               dest += l;
-              copy_or_memcpy (n - u, src + u, dest);
+              std::copy (src + u, src + n, dest);
               dest += n - u;
               src += n;
             }
@@ -2478,9 +2478,6 @@
   return m;
 }
 
-
-#define INSTANTIATE_ARRAY_SORT(T) template class OCTAVE_API octave_sort<T>;
-
 #define NO_INSTANTIATE_ARRAY_SORT(T) \
  \
 template <> Array<T>  \
@@ -2571,9 +2568,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/Array.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/Array.h	Mon Jan 12 09:17:35 2015 -0800
@@ -38,22 +38,16 @@
 #include "lo-utils.h"
 #include "oct-sort.h"
 #include "quit.h"
-#include "oct-mem.h"
 #include "oct-refcount.h"
 
-// One dimensional array class.  Handles the reference counting for
-// all the derived classes.
-
+//!Handles the reference counting for all the derived classes.
 template <class T>
 class
 Array
 {
 protected:
 
-  //--------------------------------------------------------------------
-  // The real representation of all arrays.
-  //--------------------------------------------------------------------
-
+  //! The real representation of all arrays.
   class ArrayRep
   {
   public:
@@ -63,14 +57,14 @@
     octave_refcount<int> count;
 
     ArrayRep (T *d, octave_idx_type l)
-      : data (no_ctor_new<T> (l)), len (l), count (1)
+      : data (new T [l]), len (l), count (1)
     {
-      copy_or_memcpy (l, d, data);
+      std::copy (d, d+l, data);
     }
 
     template <class U>
     ArrayRep (U *d, octave_idx_type l)
-      : data (no_ctor_new<T> (l)), len (l), count (1)
+      : data (new T [l]), len (l), count (1)
     {
       std::copy (d, d+l, data);
     }
@@ -78,21 +72,21 @@
     ArrayRep (void) : data (0), len (0), count (1) { }
 
     explicit ArrayRep (octave_idx_type n)
-      : data (no_ctor_new<T> (n)), len (n), count (1) { }
+      : data (new T [n]), len (n), count (1) { }
 
     explicit ArrayRep (octave_idx_type n, const T& val)
-      : data (no_ctor_new<T> (n)), len (n), count (1)
+      : data (new T [n]), len (n), count (1)
     {
-      fill_or_memset (n, val, data);
+      std::fill_n (data, n, val);
     }
 
     ArrayRep (const ArrayRep& a)
-      : data (no_ctor_new<T> (a.len)), len (a.len), count (1)
+      : data (new T [a.len]), len (a.len), count (1)
     {
-      copy_or_memcpy (a.len, a.data, data);
+      std::copy (a.data, a.data + a.len, data);
     }
 
-    ~ArrayRep (void) { no_ctor_delete<T> (data); }
+    ~ArrayRep (void) { delete [] data; }
 
     octave_idx_type length (void) const { return len; }
 
@@ -144,7 +138,7 @@
   T* slice_data;
   octave_idx_type slice_len;
 
-  // slice constructor
+  //! slice constructor
   Array (const Array<T>& a, const dim_vector& dv,
          octave_idx_type l, octave_idx_type u)
     : dimensions (dv), rep(a.rep), slice_data (a.slice_data+l), slice_len (u-l)
@@ -167,7 +161,7 @@
 
 protected:
 
-  // For jit support
+  //! For jit support
   Array (T *sdata, octave_idx_type slen, octave_idx_type *adims, void *arep)
     : dimensions (adims),
       rep (reinterpret_cast<typename Array<T>::ArrayRep *> (arep)),
@@ -175,8 +169,7 @@
 
 public:
 
-  // Empty ctor (0x0).
-
+  //! Empty ctor (0 by 0).
   Array (void)
     : dimensions (), rep (nil_rep ()), slice_data (rep->data),
       slice_len (rep->len)
@@ -184,21 +177,7 @@
     rep->count++;
   }
 
-  // Obsolete 1D ctor (there are no 1D arrays).
-  explicit Array (octave_idx_type n) GCC_ATTR_DEPRECATED
-    : dimensions (n, 1), rep (new typename Array<T>::ArrayRep (n)),
-      slice_data (rep->data), slice_len (rep->len)
-  { }
-
-  // Obsolete initialized 1D ctor (there are no 1D arrays).
-  explicit Array (octave_idx_type n, const T& val) GCC_ATTR_DEPRECATED
-    : dimensions (n, 1), rep (new typename Array<T>::ArrayRep (n)),
-      slice_data (rep->data), slice_len (rep->len)
-  {
-    fill (val);
-  }
-
-  // nD uninitialized ctor.
+  //! nD uninitialized ctor.
   explicit Array (const dim_vector& dv)
     : dimensions (dv),
       rep (new typename Array<T>::ArrayRep (dv.safe_numel ())),
@@ -207,7 +186,7 @@
     dimensions.chop_trailing_singletons ();
   }
 
-  // nD initialized ctor.
+  //! nD initialized ctor.
   explicit Array (const dim_vector& dv, const T& val)
     : dimensions (dv),
       rep (new typename Array<T>::ArrayRep (dv.safe_numel ())),
@@ -217,10 +196,10 @@
     dimensions.chop_trailing_singletons ();
   }
 
-  // Reshape constructor.
+  //! Reshape constructor.
   Array (const Array<T>& a, const dim_vector& dv);
 
-  // Type conversion case.
+  //! Type conversion case.
   template <class U>
   Array (const Array<U>& a)
     : dimensions (a.dims ()),
@@ -228,7 +207,7 @@
       slice_data (rep->data), slice_len (rep->len)
   { }
 
-  // No type conversion case.
+  //! No type conversion case.
   Array (const Array<T>& a)
     : dimensions (a.dimensions), rep (a.rep), slice_data (a.slice_data),
       slice_len (a.slice_len)
@@ -270,16 +249,15 @@
   void clear (octave_idx_type r, octave_idx_type c)
   { clear (dim_vector (r, c)); }
 
+  //@{
+  //! Number of elements in the array. These are all synonyms.
   octave_idx_type capacity (void) const { return slice_len; }
   octave_idx_type length (void) const { return capacity (); }
   octave_idx_type nelem (void) const { return capacity (); }
   octave_idx_type numel (void) const { return nelem (); }
+  //@}
 
-  octave_idx_type dim1 (void) const { return dimensions(0); }
-  octave_idx_type dim2 (void) const { return dimensions(1); }
-  octave_idx_type dim3 (void) const { return dimensions(2); }
-
-  // Return the array as a column vector.
+  //! Return the array as a column vector.
   Array<T> as_column (void) const
   {
     Array<T> retval (*this);
@@ -289,7 +267,7 @@
     return retval;
   }
 
-  // Return the array as a row vector.
+  //! Return the array as a row vector.
   Array<T> as_row (void) const
   {
     Array<T> retval (*this);
@@ -299,7 +277,7 @@
     return retval;
   }
 
-  // Return the array as a matrix.
+  //! Return the array as a matrix.
   Array<T> as_matrix (void) const
   {
     Array<T> retval (*this);
@@ -309,22 +287,40 @@
     return retval;
   }
 
+  //! @name First dimension
+  //!
+  //! Get the first dimension of the array (number of rows)
+  //@{
+  octave_idx_type dim1 (void) const { return dimensions(0); }
   octave_idx_type rows (void) const { return dim1 (); }
+  //@}
+
+  //! @name Second dimension
+  //!
+  //! Get the second dimension of the array (number of columns)
+  //@{
+  octave_idx_type dim2 (void) const { return dimensions(1); }
   octave_idx_type cols (void) const { return dim2 (); }
   octave_idx_type columns (void) const { return dim2 (); }
+  //@}
+
+  //! @name Third dimension
+  //!
+  //! Get the third dimension of the array (number of pages)
+  //@{
+  octave_idx_type dim3 (void) const { return dimensions(2); }
   octave_idx_type pages (void) const { return dim3 (); }
+  //@}
 
   size_t byte_size (void) const
   { return static_cast<size_t> (numel ()) * sizeof (T); }
 
-  // Return a const-reference so that dims ()(i) works efficiently.
+  //! Return a const-reference so that dims ()(i) works efficiently.
   const dim_vector& dims (void) const { return dimensions; }
 
+  //! Chop off leading singleton dimensions
   Array<T> squeeze (void) const;
 
-  void chop_trailing_singletons (void) GCC_ATTR_DEPRECATED
-  { dimensions.chop_trailing_singletons (); }
-
   octave_idx_type compute_index (octave_idx_type i, octave_idx_type j) const;
   octave_idx_type compute_index (octave_idx_type i, octave_idx_type j,
                                  octave_idx_type k) const;
@@ -434,13 +430,13 @@
   // Fast extractors. All of these produce shallow copies.
   // Warning: none of these do check bounds, unless BOUNDS_CHECKING is on!
 
-  // Extract column: A(:,k+1).
+  //! Extract column: A(:,k+1).
   Array<T> column (octave_idx_type k) const;
-  // Extract page: A(:,:,k+1).
+  //! Extract page: A(:,:,k+1).
   Array<T> page (octave_idx_type k) const;
 
-  // Extract a slice from this array as a column vector: A(:)(lo+1:up).
-  // Must be 0 <= lo && up <= numel. May be up < lo.
+  //! Extract a slice from this array as a column vector: A(:)(lo+1:up).
+  //! Must be 0 <= lo && up <= numel. May be up < lo.
   Array<T> linear_slice (octave_idx_type lo, octave_idx_type up) const;
 
   Array<T> reshape (octave_idx_type nr, octave_idx_type nc) const
@@ -472,41 +468,39 @@
 
   int ndims (void) const { return dimensions.length (); }
 
-  // Indexing without resizing.
-
+  //@{
+  //! Indexing without resizing.
   Array<T> index (const idx_vector& i) const;
 
   Array<T> index (const idx_vector& i, const idx_vector& j) const;
 
   Array<T> index (const Array<idx_vector>& ia) const;
+  //@}
 
   virtual T resize_fill_value (void) const;
 
-  // Resizing (with fill).
+  //@{
+  //! Resizing (with fill).
+  void resize2 (octave_idx_type nr, octave_idx_type nc, const T& rfv);
+  void resize2 (octave_idx_type nr, octave_idx_type nc)
+  {
+    resize2 (nr, nc, resize_fill_value ());
+  }
 
   void resize1 (octave_idx_type n, const T& rfv);
   void resize1 (octave_idx_type n) { resize1 (n, resize_fill_value ()); }
 
-  void resize (octave_idx_type n) GCC_ATTR_DEPRECATED { resize1 (n); }
-
-  void resize (octave_idx_type nr, octave_idx_type nc,
-               const T& rfv) GCC_ATTR_DEPRECATED
-  {
-    resize2 (nr, nc, rfv);
-  }
-
-  void resize (octave_idx_type nr, octave_idx_type nc) GCC_ATTR_DEPRECATED
-  {
-    resize2 (nr, nc, resize_fill_value ());
-  }
-
   void resize (const dim_vector& dv, const T& rfv);
   void resize (const dim_vector& dv) { resize (dv, resize_fill_value ()); }
+  //@}
 
-  // Indexing with possible resizing and fill
-  // FIXME: this is really a corner case, that should better be
+  //@{
+  //! Indexing with possible resizing and fill
+
+  // FIXME -- this is really a corner case, that should better be
   // handled directly in liboctinterp.
 
+
   Array<T> index (const idx_vector& i, bool resize_ok, const T& rfv) const;
   Array<T> index (const idx_vector& i, bool resize_ok) const
   {
@@ -527,9 +521,11 @@
   {
     return index (ia, resize_ok, resize_fill_value ());
   }
+  //@}
 
-  // Indexed assignment (always with resize & fill).
 
+  //@{
+  //! Indexed assignment (always with resize & fill).
   void assign (const idx_vector& i, const Array<T>& rhs, const T& rfv);
   void assign (const idx_vector& i, const Array<T>& rhs)
   {
@@ -548,25 +544,28 @@
   {
     assign (ia, rhs, resize_fill_value ());
   }
+  //@}
 
-  // Deleting elements.
+  //@{
+  //! Deleting elements.
 
-  // A(I) = [] (with a single subscript)
+  //! A(I) = [] (with a single subscript)
   void delete_elements (const idx_vector& i);
 
-  // A(:,...,I,...,:) = [] (>= 2 subscripts, one of them is non-colon)
+  //! A(:,...,I,...,:) = [] (>= 2 subscripts, one of them is non-colon)
   void delete_elements (int dim, const idx_vector& i);
 
-  // Dispatcher to the above two.
+  //! Dispatcher to the above two.
   void delete_elements (const Array<idx_vector>& ia);
+  //@}
 
-  // Insert an array into another at a specified position.
-  // If size (a) is [d1 d2 ... dN] and idx is [i1 i2 ... iN],
-  // this method is equivalent to
-  // x(i1:i1+d1-1, i2:i2+d2-1, ... , iN:iN+dN-1) = a.
+  //! Insert an array into another at a specified position. If
+  //! size (a) is [d1 d2 ... dN] and idx is [i1 i2 ... iN], this
+  //! method is equivalent to x(i1:i1+d1-1, i2:i2+d2-1, ... ,
+  //! iN:iN+dN-1) = a.
   Array<T>& insert (const Array<T>& a, const Array<octave_idx_type>& idx);
 
-  // This is just a special case for idx = [r c 0 ...]
+  //! This is just a special case for idx = [r c 0 ...]
   Array<T>& insert (const Array<T>& a, octave_idx_type r, octave_idx_type c);
 
   void maybe_economize (void)
@@ -582,54 +581,60 @@
 
   void print_info (std::ostream& os, const std::string& prefix) const;
 
-  // Unsafe.  This function exists to support the MEX interface.
-  // You should not use it anywhere else.
+  //! Give a pointer to the data in mex format. Unsafe. This function
+  //! exists to support the MEX interface. You should not use it
+  //! anywhere else.
   void *mex_get_data (void) const { return const_cast<T *> (data ()); }
 
   Array<T> sort (int dim = 0, sortmode mode = ASCENDING) const;
   Array<T> sort (Array<octave_idx_type> &sidx, int dim = 0,
                  sortmode mode = ASCENDING) const;
 
-  // Ordering is auto-detected or can be specified.
+  //! Ordering is auto-detected or can be specified.
   sortmode is_sorted (sortmode mode = UNSORTED) const;
 
-  // Sort by rows returns only indices.
+  //! Sort by rows returns only indices.
   Array<octave_idx_type> sort_rows_idx (sortmode mode = ASCENDING) const;
 
-  // Ordering is auto-detected or can be specified.
+  //! Ordering is auto-detected or can be specified.
   sortmode is_sorted_rows (sortmode mode = UNSORTED) const;
 
-  // Do a binary lookup in a sorted array. Must not contain NaNs.
-  // Mode can be specified or is auto-detected by comparing 1st and last element.
+  //! @brief Do a binary lookup in a sorted array. Must not contain NaNs.
+  //! Mode can be specified or is auto-detected by comparing 1st and last element.
   octave_idx_type lookup (const T& value, sortmode mode = UNSORTED) const;
 
-  // Ditto, but for an array of values, specializing on the case when values
-  // are sorted. NaNs get the value N.
+  //! Ditto, but for an array of values, specializing on the case when values
+  //! are sorted. NaNs get the value N.
   Array<octave_idx_type> lookup (const Array<T>& values,
                                  sortmode mode = UNSORTED) const;
 
-  // Count nonzero elements.
+  //! Count nonzero elements.
   octave_idx_type nnz (void) const;
 
-  // Find indices of (at most n) nonzero elements. If n is specified, backward
-  // specifies search from backward.
-  Array<octave_idx_type> find (octave_idx_type n = -1,
-                               bool backward = false) const;
+  //! Find indices of (at most n) nonzero elements. If n is specified,
+  //! backward specifies search from backward.
+  Array<octave_idx_type> find (octave_idx_type n = -1, bool backward = false) const;
 
-  // Returns the n-th element in increasing order, using the same ordering as
-  // used for sort. n can either be a scalar index or a contiguous range.
+  //! Returns the n-th element in increasing order, using the same
+  //! ordering as used for sort. n can either be a scalar index or a
+  //! contiguous range.
   Array<T> nth_element (const idx_vector& n, int dim = 0) const;
 
+  //! Get the kth super or subdiagonal. The zeroth diagonal is the
+  //! ordinary diagonal.
   Array<T> diag (octave_idx_type k = 0) const;
 
   Array<T> diag (octave_idx_type m, octave_idx_type n) const;
 
-  // Concatenation along a specified (0-based) dimension, equivalent to cat().
-  // dim = -1 corresponds to dim = 0 and dim = -2 corresponds to dim = 1,
-  // but apply the looser matching rules of vertcat/horzcat.
+  //! Concatenation along a specified (0-based) dimension, equivalent
+  //! to cat(). dim = -1 corresponds to dim = 0 and dim = -2
+  //! corresponds to dim = 1, but apply the looser matching rules of
+  //! vertcat/horzcat.
   static Array<T>
   cat (int dim, octave_idx_type n, const Array<T> *array_list);
 
+  //! Apply function fcn to each element of the Array<T>. This function
+  //! is optimised with a manually unrolled loop.
   template <class U, class F>
   Array<U>
   map (F fcn) const
@@ -660,7 +665,8 @@
     return result;
   }
 
-  // Overloads for function references.
+  //@{
+  //! Overloads for function references.
   template <class U>
   Array<U>
   map (U (&fcn) (T)) const
@@ -670,15 +676,17 @@
   Array<U>
   map (U (&fcn) (const T&)) const
   { return map<U, U (&) (const T&)> (fcn); }
+  //@}
 
-  // Generic any/all test functionality with arbitrary predicate.
+  //! Generic any/all test functionality with arbitrary predicate.
   template <class F, bool zero>
   bool test (F fcn) const
   {
     return any_all_test<F, T, zero> (fcn, data (), length ());
   }
 
-  // Simpler calls.
+  //@{
+  //! Simpler calls.
   template <class F>
   bool test_any (F fcn) const
   { return test<F, false> (fcn); }
@@ -686,8 +694,10 @@
   template <class F>
   bool test_all (F fcn) const
   { return test<F, true> (fcn); }
+  //@}
 
-  // Overloads for function references.
+  //@{
+  //! Overloads for function references.
   bool test_any (bool (&fcn) (T)) const
   { return test<bool (&) (T), false> (fcn); }
 
@@ -699,15 +709,17 @@
 
   bool test_all (bool (&fcn) (const T&)) const
   { return test<bool (&) (const T&), true> (fcn); }
+  //@}
 
   template <class U> friend class Array;
 
-  // Returns true if this->dims () == dv, and if so, replaces this->dimensions
-  // by a shallow copy of dv. This is useful for maintaining several arrays with
-  // supposedly equal dimensions (e.g. structs in the interpreter).
+  //! Returns true if this->dims () == dv, and if so, replaces this->dimensions
+  //! by a shallow copy of dv. This is useful for maintaining several arrays with
+  //! supposedly equal dimensions (e.g. structs in the interpreter).
   bool optimize_dimensions (const dim_vector& dv);
 
-  // WARNING: Only call these functions from jit
+  //@{
+  //! WARNING: Only call these functions from jit
 
   int *jit_ref_count (void) { return rep->count.get (); }
 
@@ -716,24 +728,17 @@
   octave_idx_type *jit_dimensions (void) const { return dimensions.to_jit (); }
 
   void *jit_array_rep (void) const { return rep; }
+  //@}
 
 private:
-
-  void resize2 (octave_idx_type nr, octave_idx_type nc, const T& rfv);
-  void resize2 (octave_idx_type nr, octave_idx_type nc)
-  {
-    resize2 (nr, nc, resize_fill_value ());
-  }
-
   static void instantiation_guard ();
 };
 
-// This is a simple wrapper template that will subclass an Array<T> type or any
-// later type derived from it and override the default non-const operator() to
-// not check for the array's uniqueness. It is, however, the user's
-// responsibility to ensure the array is actually unaliased whenever elements
-// are accessed.
-
+//! This is a simple wrapper template that will subclass an Array<T>
+//! type or any later type derived from it and override the default
+//! non-const operator() to not check for the array's uniqueness. It
+//! is, however, the user's responsibility to ensure the array is
+//! actually unaliased whenever elements are accessed.
 template<class ArrayClass>
 class NoAlias : public ArrayClass
 {
--- a/liboctave/array/Array2.h	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-// Template array classes
-/*
-
-Copyright (C) 1996-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_Array2_h)
-#define octave_Array2_h 1
-
-#include "Array.h"
-#define Array2 Array
-
-// If we're with GNU C++, issue a warning.
-#ifdef __GNUC__
-#warning Using Array2<T> is deprecated. Use Array<T> directly.
-#endif
-
-#endif
--- a/liboctave/array/Array3.h	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-// Template array classes
-/*
-
-Copyright (C) 1996-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_Array3_h)
-#define octave_Array3_h 1
-
-#include <cassert>
-#include <cstdlib>
-
-#include "Array.h"
-#include "lo-error.h"
-
-class idx_vector;
-
-// Three dimensional array class.
-
-template <class T>
-class
-Array3 : public Array<T>
-{
-public:
-
-  Array3 (void) : Array<T> (dim_vector (0, 0, 0)) { }
-
-  Array3 (octave_idx_type r, octave_idx_type c,
-          octave_idx_type p) : Array<T> (dim_vector (r, c, p)) { }
-
-  Array3 (octave_idx_type r, octave_idx_type c, octave_idx_type p, const T& val)
-    : Array<T> (dim_vector (r, c, p), val) { }
-
-  Array3 (const Array3<T>& a)
-    : Array<T> (a, a.dims ()) { }
-
-  Array3 (const Array<T>& a, octave_idx_type r, octave_idx_type c,
-          octave_idx_type p)
-    : Array<T> (a, dim_vector (r, c, p)) { }
-
-  ~Array3 (void) { }
-
-  Array3<T>& operator = (const Array3<T>& a)
-  {
-    if (this != &a)
-      Array<T>::operator = (a);
-
-    return *this;
-  }
-
-  void resize (octave_idx_type r, octave_idx_type c, octave_idx_type p)
-  { Array<T>::resize (dim_vector (r, c, p)); }
-
-  void resize (octave_idx_type r, octave_idx_type c, octave_idx_type p,
-               const T& val)
-  { Array<T>::resize (dim_vector (r, c, p), val); }
-
-  Array3<T> sort (octave_idx_type dim = 0, sortmode mode = ASCENDING) const
-  {
-    Array<T> tmp = Array<T>::sort (dim, mode);
-    return Array3<T> (tmp, tmp.rows (), tmp.columns (), tmp.pages ());
-  }
-
-  Array3<T> sort (Array<octave_idx_type> &sidx, octave_idx_type dim = 0,
-                  sortmode mode = ASCENDING) const
-  {
-    Array<T> tmp = Array<T>::sort (sidx, dim, mode);
-    return Array3<T> (tmp, tmp.rows (), tmp.columns (), tmp.pages ());
-  }
-};
-
-// If we're with GNU C++, issue a warning.
-#ifdef __GNUC__
-#warning Using Array3<T> is deprecated. Use Array<T> directly.
-#endif
-
-#endif
--- a/liboctave/array/ArrayN.h	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-// Template array classes
-/*
-
-Copyright (C) 2000-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_ArrayN_h)
-#define octave_ArrayN_h 1
-
-#include "Array.h"
-#define ArrayN Array
-
-// If we're with GNU C++, issue a warning.
-#ifdef __GNUC__
-#warning Using ArrayN<T> is deprecated. Use Array<T> directly.
-#endif
-
-#endif
--- a/liboctave/array/CDiagMatrix.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/CDiagMatrix.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -383,7 +383,7 @@
 }
 
 ComplexDiagMatrix
-ComplexDiagMatrix::pseudo_inverse (void) const
+ComplexDiagMatrix::pseudo_inverse (double tol) const
 {
   octave_idx_type r = rows ();
   octave_idx_type c = cols ();
@@ -393,10 +393,11 @@
 
   for (octave_idx_type i = 0; i < len; i++)
     {
-      if (elem (i, i) != 0.0)
+      double val = std::abs (elem (i, i));
+      if (val < tol || val == 0.0)
+        retval.elem (i, i) = 0.0;
+      else
         retval.elem (i, i) = 1.0 / elem (i, i);
-      else
-        retval.elem (i, i) = 0.0;
     }
 
   return retval;
--- a/liboctave/array/CDiagMatrix.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/CDiagMatrix.h	Mon Jan 12 09:17:35 2015 -0800
@@ -116,7 +116,7 @@
 
   ComplexDiagMatrix inverse (octave_idx_type& info) const;
   ComplexDiagMatrix inverse (void) const;
-  ComplexDiagMatrix pseudo_inverse (void) const;
+  ComplexDiagMatrix pseudo_inverse (double tol = 0.0) const;
 
   bool all_elements_are_real (void) const;
 
--- a/liboctave/array/CMatrix.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/CMatrix.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -36,8 +36,15 @@
 #include <sys/types.h>
 
 #include "Array-util.h"
+#include "boolMatrix.h"
+#include "chMatrix.h"
+#include "dMatrix.h"
 #include "CMatrix.h"
-#include "CmplxAEPBAL.h"
+#include "CNDArray.h"
+#include "CRowVector.h"
+#include "dRowVector.h"
+#include "CDiagMatrix.h"
+#include "dDiagMatrix.h"
 #include "CmplxCHOL.h"
 #include "CmplxSCHUR.h"
 #include "CmplxSVD.h"
@@ -48,7 +55,6 @@
 #include "lo-ieee.h"
 #include "lo-mappers.h"
 #include "lo-utils.h"
-#include "mx-base.h"
 #include "mx-cm-dm.h"
 #include "mx-cm-s.h"
 #include "mx-dm-cm.h"
@@ -262,39 +268,67 @@
 // Complex Matrix class
 
 ComplexMatrix::ComplexMatrix (const Matrix& a)
-  : MArray<Complex> (a)
+  : ComplexNDArray (a)
 {
 }
 
 ComplexMatrix::ComplexMatrix (const RowVector& rv)
-  : MArray<Complex> (rv)
+  : ComplexNDArray (rv)
 {
 }
 
 ComplexMatrix::ComplexMatrix (const ColumnVector& cv)
-  : MArray<Complex> (cv)
+  : ComplexNDArray (cv)
 {
 }
 
 ComplexMatrix::ComplexMatrix (const DiagMatrix& a)
-  : MArray<Complex> (a.dims (), 0.0)
+  : ComplexNDArray (a.dims (), 0.0)
+{
+  for (octave_idx_type i = 0; i < a.length (); i++)
+    elem (i, i) = a.elem (i, i);
+}
+
+ComplexMatrix::ComplexMatrix (const MDiagArray2<double>& a)
+  : ComplexNDArray (a.dims (), 0.0)
+{
+  for (octave_idx_type i = 0; i < a.length (); i++)
+    elem (i, i) = a.elem (i, i);
+}
+
+ComplexMatrix::ComplexMatrix (const DiagArray2<double>& a)
+  : ComplexNDArray (a.dims (), 0.0)
 {
   for (octave_idx_type i = 0; i < a.length (); i++)
     elem (i, i) = a.elem (i, i);
 }
 
 ComplexMatrix::ComplexMatrix (const ComplexRowVector& rv)
-  : MArray<Complex> (rv)
+  : ComplexNDArray (rv)
 {
 }
 
 ComplexMatrix::ComplexMatrix (const ComplexColumnVector& cv)
-  : MArray<Complex> (cv)
+  : ComplexNDArray (cv)
 {
 }
 
 ComplexMatrix::ComplexMatrix (const ComplexDiagMatrix& a)
-  : MArray<Complex> (a.dims (), 0.0)
+  : ComplexNDArray (a.dims (), 0.0)
+{
+  for (octave_idx_type i = 0; i < a.length (); i++)
+    elem (i, i) = a.elem (i, i);
+}
+
+ComplexMatrix::ComplexMatrix (const MDiagArray2<Complex>& a)
+  : ComplexNDArray (a.dims (), 0.0)
+{
+  for (octave_idx_type i = 0; i < a.length (); i++)
+    elem (i, i) = a.elem (i, i);
+}
+
+ComplexMatrix::ComplexMatrix (const DiagArray2<Complex>& a)
+  : ComplexNDArray (a.dims (), 0.0)
 {
   for (octave_idx_type i = 0; i < a.length (); i++)
     elem (i, i) = a.elem (i, i);
@@ -303,12 +337,12 @@
 // FIXME: could we use a templated mixed-type copy function here?
 
 ComplexMatrix::ComplexMatrix (const boolMatrix& a)
-  : MArray<Complex> (a)
+  : ComplexNDArray (a)
 {
 }
 
 ComplexMatrix::ComplexMatrix (const charMatrix& a)
-  : MArray<Complex> (a.dims (), 0.0)
+  : ComplexNDArray (a.dims (), 0.0)
 {
   for (octave_idx_type i = 0; i < a.rows (); i++)
     for (octave_idx_type j = 0; j < a.cols (); j++)
@@ -316,7 +350,7 @@
 }
 
 ComplexMatrix::ComplexMatrix (const Matrix& re, const Matrix& im)
-  : MArray<Complex> (re.dims ())
+  : ComplexNDArray (re.dims ())
 {
   if (im.rows () != rows () || im.cols () != cols ())
     (*current_liboctave_error_handler) ("complex: internal error");
@@ -463,7 +497,7 @@
 ComplexMatrix::insert (const ComplexMatrix& a,
                        octave_idx_type r, octave_idx_type c)
 {
-  Array<Complex>::insert (a, r, c);
+  ComplexNDArray::insert (a, r, c);
   return *this;
 }
 
@@ -1353,7 +1387,7 @@
 
   octave_idx_type nn = 4*npts+15;
 
-  Array<Complex> wsave (nn, 1);
+  Array<Complex> wsave (dim_vector (nn, 1));
   Complex *pwsave = wsave.fortran_vec ();
 
   retval = *this;
@@ -1394,7 +1428,7 @@
 
   octave_idx_type nn = 4*npts+15;
 
-  Array<Complex> wsave (nn, 1);
+  Array<Complex> wsave (dim_vector (nn, 1));
   Complex *pwsave = wsave.fortran_vec ();
 
   retval = *this;
@@ -1438,7 +1472,7 @@
 
   octave_idx_type nn = 4*npts+15;
 
-  Array<Complex> wsave (nn, 1);
+  Array<Complex> wsave (dim_vector (nn, 1));
   Complex *pwsave = wsave.fortran_vec ();
 
   retval = *this;
@@ -1460,7 +1494,7 @@
   wsave.resize (dim_vector (nn, 1));
   pwsave = wsave.fortran_vec ();
 
-  Array<Complex> tmp (npts, 1);
+  Array<Complex> tmp (dim_vector (npts, 1));
   Complex *prow = tmp.fortran_vec ();
 
   F77_FUNC (zffti, ZFFTI) (npts, pwsave);
@@ -1504,7 +1538,7 @@
 
   octave_idx_type nn = 4*npts+15;
 
-  Array<Complex> wsave (nn, 1);
+  Array<Complex> wsave (dim_vector (nn, 1));
   Complex *pwsave = wsave.fortran_vec ();
 
   retval = *this;
@@ -1529,7 +1563,7 @@
   wsave.resize (dim_vector (nn, 1));
   pwsave = wsave.fortran_vec ();
 
-  Array<Complex> tmp (npts, 1);
+  Array<Complex> tmp (dim_vector (npts, 1));
   Complex *prow = tmp.fortran_vec ();
 
   F77_FUNC (zffti, ZFFTI) (npts, pwsave);
@@ -1722,7 +1756,7 @@
 double
 ComplexMatrix::rcond (MatrixType &mattype) const
 {
-  double rcon;
+  double rcon = octave_NaN;
   octave_idx_type nr = rows ();
   octave_idx_type nc = cols ();
 
@@ -1920,11 +1954,27 @@
             {
               const Complex *tmp_data = fortran_vec ();
 
+              retval = b;
+              Complex *result = retval.fortran_vec ();
+
+              char uplo = 'U';
+              char trans = get_blas_char (transt);
+              char dia = 'N';
+
+              F77_XFCN (ztrtrs, ZTRTRS, (F77_CONST_CHAR_ARG2 (&uplo, 1),
+                                         F77_CONST_CHAR_ARG2 (&trans, 1),
+                                         F77_CONST_CHAR_ARG2 (&dia, 1),
+                                         nr, b_nc, tmp_data, nr,
+                                         result, nr, info
+                                         F77_CHAR_ARG_LEN (1)
+                                         F77_CHAR_ARG_LEN (1)
+                                         F77_CHAR_ARG_LEN (1)));
+
               if (calc_cond)
                 {
                   char norm = '1';
-                  char uplo = 'U';
-                  char dia = 'N';
+                  uplo = 'U';
+                  dia = 'N';
 
                   Array<Complex> z (dim_vector (2 * nc, 1));
                   Complex *pz = z.fortran_vec ();
@@ -1952,30 +2002,9 @@
                       if (sing_handler)
                         sing_handler (rcon);
                       else
-                        (*current_liboctave_error_handler)
-                          ("matrix singular to machine precision, rcond = %g",
-                           rcon);
+                        gripe_singular_matrix (rcon);
                     }
                 }
-
-              if (info == 0)
-                {
-                  retval = b;
-                  Complex *result = retval.fortran_vec ();
-
-                  char uplo = 'U';
-                  char trans = get_blas_char (transt);
-                  char dia = 'N';
-
-                  F77_XFCN (ztrtrs, ZTRTRS, (F77_CONST_CHAR_ARG2 (&uplo, 1),
-                                             F77_CONST_CHAR_ARG2 (&trans, 1),
-                                             F77_CONST_CHAR_ARG2 (&dia, 1),
-                                             nr, b_nc, tmp_data, nr,
-                                             result, nr, info
-                                             F77_CHAR_ARG_LEN (1)
-                                             F77_CHAR_ARG_LEN (1)
-                                             F77_CHAR_ARG_LEN (1)));
-                }
             }
         }
       else
@@ -2021,11 +2050,27 @@
             {
               const Complex *tmp_data = fortran_vec ();
 
+              retval = b;
+              Complex *result = retval.fortran_vec ();
+
+              char uplo = 'L';
+              char trans = get_blas_char (transt);
+              char dia = 'N';
+
+              F77_XFCN (ztrtrs, ZTRTRS, (F77_CONST_CHAR_ARG2 (&uplo, 1),
+                                         F77_CONST_CHAR_ARG2 (&trans, 1),
+                                         F77_CONST_CHAR_ARG2 (&dia, 1),
+                                         nr, b_nc, tmp_data, nr,
+                                         result, nr, info
+                                         F77_CHAR_ARG_LEN (1)
+                                         F77_CHAR_ARG_LEN (1)
+                                         F77_CHAR_ARG_LEN (1)));
+
               if (calc_cond)
                 {
                   char norm = '1';
-                  char uplo = 'L';
-                  char dia = 'N';
+                  uplo = 'L';
+                  dia = 'N';
 
                   Array<Complex> z (dim_vector (2 * nc, 1));
                   Complex *pz = z.fortran_vec ();
@@ -2053,30 +2098,9 @@
                       if (sing_handler)
                         sing_handler (rcon);
                       else
-                        (*current_liboctave_error_handler)
-                          ("matrix singular to machine precision, rcond = %g",
-                           rcon);
+                        gripe_singular_matrix (rcon);
                     }
                 }
-
-              if (info == 0)
-                {
-                  retval = b;
-                  Complex *result = retval.fortran_vec ();
-
-                  char uplo = 'L';
-                  char trans = get_blas_char (transt);
-                  char dia = 'N';
-
-                  F77_XFCN (ztrtrs, ZTRTRS, (F77_CONST_CHAR_ARG2 (&uplo, 1),
-                                             F77_CONST_CHAR_ARG2 (&trans, 1),
-                                             F77_CONST_CHAR_ARG2 (&dia, 1),
-                                             nr, b_nc, tmp_data, nr,
-                                             result, nr, info
-                                             F77_CHAR_ARG_LEN (1)
-                                             F77_CHAR_ARG_LEN (1)
-                                             F77_CHAR_ARG_LEN (1)));
-                }
             }
         }
       else
@@ -2159,9 +2183,7 @@
                       if (sing_handler)
                         sing_handler (rcon);
                       else
-                        (*current_liboctave_error_handler)
-                          ("matrix singular to machine precision, rcond = %g",
-                           rcon);
+                        gripe_singular_matrix (rcon);
                     }
                 }
 
@@ -2216,8 +2238,7 @@
               if (sing_handler)
                 sing_handler (rcon);
               else
-                (*current_liboctave_error_handler)
-                  ("matrix singular to machine precision");
+                gripe_singular_matrix ();
 
               mattype.mark_as_rectangular ();
             }
@@ -2245,9 +2266,7 @@
                       if (sing_handler)
                         sing_handler (rcon);
                       else
-                        (*current_liboctave_error_handler)
-                          ("matrix singular to machine precision, rcond = %g",
-                           rcon);
+                        gripe_singular_matrix (rcon);
                     }
                 }
 
@@ -2342,9 +2361,9 @@
 
   // Only calculate the condition number for LU/Cholesky
   if (typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper)
-    retval = utsolve (mattype, b, info, rcon, sing_handler, false, transt);
+    retval = utsolve (mattype, b, info, rcon, sing_handler, true, transt);
   else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower)
-    retval = ltsolve (mattype, b, info, rcon, sing_handler, false, transt);
+    retval = ltsolve (mattype, b, info, rcon, sing_handler, true, transt);
   else if (transt == blas_trans)
     return transpose ().solve (mattype, b, info, rcon, sing_handler,
                                singular_fallback);
@@ -3096,154 +3115,60 @@
   return *this;
 }
 
-// unary operations
-
-boolMatrix
-ComplexMatrix::operator ! (void) const
-{
-  if (any_element_is_nan ())
-    gripe_nan_to_logical_conversion ();
-
-  return do_mx_unary_op<bool, Complex> (*this, mx_inline_not);
-}
-
 // other operations
 
-bool
-ComplexMatrix::any_element_is_nan (void) const
-{
-  return do_mx_check<Complex> (*this, mx_inline_any_nan);
-}
-
-bool
-ComplexMatrix::any_element_is_inf_or_nan (void) const
-{
-  return ! do_mx_check<Complex> (*this, mx_inline_all_finite);
-}
-
-// Return true if no elements have imaginary components.
-
-bool
-ComplexMatrix::all_elements_are_real (void) const
-{
-  return do_mx_check<Complex> (*this, mx_inline_all_real);
-}
-
-// Return nonzero if any element of CM has a non-integer real or
-// imaginary part.  Also extract the largest and smallest (real or
-// imaginary) values and return them in MAX_VAL and MIN_VAL.
-
-bool
-ComplexMatrix::all_integers (double& max_val, double& min_val) const
-{
-  octave_idx_type nr = rows ();
-  octave_idx_type nc = cols ();
-
-  if (nr > 0 && nc > 0)
-    {
-      Complex val = elem (0, 0);
-
-      double r_val = std::real (val);
-      double i_val = std::imag (val);
-
-      max_val = r_val;
-      min_val = r_val;
-
-      if (i_val > max_val)
-        max_val = i_val;
-
-      if (i_val < max_val)
-        min_val = i_val;
-    }
-  else
-    return false;
-
-  for (octave_idx_type j = 0; j < nc; j++)
-    for (octave_idx_type i = 0; i < nr; i++)
-      {
-        Complex val = elem (i, j);
-
-        double r_val = std::real (val);
-        double i_val = std::imag (val);
-
-        if (r_val > max_val)
-          max_val = r_val;
-
-        if (i_val > max_val)
-          max_val = i_val;
-
-        if (r_val < min_val)
-          min_val = r_val;
-
-        if (i_val < min_val)
-          min_val = i_val;
-
-        if (D_NINT (r_val) != r_val || D_NINT (i_val) != i_val)
-          return false;
-      }
-
-  return true;
-}
-
-bool
-ComplexMatrix::too_large_for_float (void) const
-{
-  return test_any (xtoo_large_for_float);
-}
-
-// FIXME: Do these really belong here?  Maybe they should be in a base class?
-
 boolMatrix
 ComplexMatrix::all (int dim) const
 {
-  return do_mx_red_op<bool, Complex> (*this, dim, mx_inline_all);
+  return ComplexNDArray::all (dim);
 }
 
 boolMatrix
 ComplexMatrix::any (int dim) const
 {
-  return do_mx_red_op<bool, Complex> (*this, dim, mx_inline_any);
+  return ComplexNDArray::any (dim);
 }
 
 ComplexMatrix
 ComplexMatrix::cumprod (int dim) const
 {
-  return do_mx_cum_op<Complex, Complex> (*this, dim, mx_inline_cumprod);
+  return ComplexNDArray::cumprod (dim);
 }
 
 ComplexMatrix
 ComplexMatrix::cumsum (int dim) const
 {
-  return do_mx_cum_op<Complex, Complex> (*this, dim, mx_inline_cumsum);
+  return ComplexNDArray::cumsum (dim);
 }
 
 ComplexMatrix
 ComplexMatrix::prod (int dim) const
 {
-  return do_mx_red_op<Complex, Complex> (*this, dim, mx_inline_prod);
+  return ComplexNDArray::prod (dim);
 }
 
 ComplexMatrix
 ComplexMatrix::sum (int dim) const
 {
-  return do_mx_red_op<Complex, Complex> (*this, dim, mx_inline_sum);
+  return ComplexNDArray::sum (dim);
 }
 
 ComplexMatrix
 ComplexMatrix::sumsq (int dim) const
 {
-  return do_mx_red_op<double, Complex> (*this, dim, mx_inline_sumsq);
+  return ComplexNDArray::sumsq (dim);
 }
 
-Matrix ComplexMatrix::abs (void) const
+Matrix
+ComplexMatrix::abs (void) const
 {
-  return do_mx_unary_map<double, Complex, std::abs> (*this);
+  return ComplexNDArray::abs ();
 }
 
 ComplexMatrix
 ComplexMatrix::diag (octave_idx_type k) const
 {
-  return MArray<Complex>::diag (k);
+  return ComplexNDArray::diag (k);
 }
 
 ComplexDiagMatrix
@@ -3705,7 +3630,7 @@
 
   // FIXME: check info?
 
-  retval = -ua * cx * ub.hermitian ();
+  retval = ua * cx * ub.hermitian ();
 
   return retval;
 }
--- a/liboctave/array/CMatrix.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/CMatrix.h	Mon Jan 12 09:17:35 2015 -0800
@@ -26,6 +26,7 @@
 #include "MArray.h"
 #include "MDiagArray2.h"
 #include "MatrixType.h"
+#include "CNDArray.h"
 
 #include "mx-defs.h"
 #include "mx-op-decl.h"
@@ -34,7 +35,7 @@
 
 class
 OCTAVE_API
-ComplexMatrix : public MArray<Complex>
+ComplexMatrix : public ComplexNDArray
 {
 public:
 
@@ -43,26 +44,26 @@
 
   typedef void (*solve_singularity_handler) (double rcon);
 
-  ComplexMatrix (void) : MArray<Complex> () { }
+  ComplexMatrix (void) : ComplexNDArray () { }
 
   ComplexMatrix (octave_idx_type r, octave_idx_type c)
-    : MArray<Complex> (dim_vector (r, c)) { }
+    : ComplexNDArray (dim_vector (r, c)) { }
 
   ComplexMatrix (octave_idx_type r, octave_idx_type c, const Complex& val)
-    : MArray<Complex> (dim_vector (r, c), val) { }
+    : ComplexNDArray (dim_vector (r, c), val) { }
 
-  ComplexMatrix (const dim_vector& dv) : MArray<Complex> (dv.redim (2)) { }
+  ComplexMatrix (const dim_vector& dv) : ComplexNDArray (dv.redim (2)) { }
 
   ComplexMatrix (const dim_vector& dv, const Complex& val)
-    : MArray<Complex> (dv.redim (2), val) { }
+    : ComplexNDArray (dv.redim (2), val) { }
 
-  ComplexMatrix (const ComplexMatrix& a) : MArray<Complex> (a) { }
+  ComplexMatrix (const ComplexMatrix& a) : ComplexNDArray (a) { }
 
   template <class U>
-  ComplexMatrix (const MArray<U>& a) : MArray<Complex> (a.as_matrix ()) { }
+  ComplexMatrix (const MArray<U>& a) : ComplexNDArray (a.as_matrix ()) { }
 
   template <class U>
-  ComplexMatrix (const Array<U>& a) : MArray<Complex> (a.as_matrix ()) { }
+  ComplexMatrix (const Array<U>& a) : ComplexNDArray (a.as_matrix ()) { }
 
   ComplexMatrix (const Matrix& re, const Matrix& im);
 
@@ -74,22 +75,24 @@
 
   explicit ComplexMatrix (const DiagMatrix& a);
 
+  explicit ComplexMatrix (const MDiagArray2<double>& a);
+
+  explicit ComplexMatrix (const DiagArray2<double>& a);
+
   explicit ComplexMatrix (const ComplexRowVector& rv);
 
   explicit ComplexMatrix (const ComplexColumnVector& cv);
 
   explicit ComplexMatrix (const ComplexDiagMatrix& a);
 
+  explicit ComplexMatrix (const MDiagArray2<Complex>& a);
+
+  explicit ComplexMatrix (const DiagArray2<Complex>& a);
+
   explicit ComplexMatrix (const boolMatrix& a);
 
   explicit ComplexMatrix (const charMatrix& a);
 
-  ComplexMatrix& operator = (const ComplexMatrix& a)
-  {
-    MArray<Complex>::operator = (a);
-    return *this;
-  }
-
   bool operator == (const ComplexMatrix& a) const;
   bool operator != (const ComplexMatrix& a) const;
 
@@ -356,18 +359,8 @@
   ComplexMatrix& operator += (const Matrix& a);
   ComplexMatrix& operator -= (const Matrix& a);
 
-  // unary operations
-
-  boolMatrix operator ! (void) const;
-
   // other operations
 
-  bool any_element_is_nan (void) const;
-  bool any_element_is_inf_or_nan (void) const;
-  bool all_elements_are_real (void) const;
-  bool all_integers (double& max_val, double& min_val) const;
-  bool too_large_for_float (void) const;
-
   boolMatrix all (int dim = -1) const;
   boolMatrix any (int dim = -1) const;
 
--- a/liboctave/array/CNDArray.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/CNDArray.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -39,6 +39,7 @@
 #include "MArray-defs.h"
 #include "mx-base.h"
 #include "mx-op-defs.h"
+#include "mx-cnda-s.h"
 #include "oct-fftw.h"
 #include "oct-locbuf.h"
 
@@ -814,20 +815,6 @@
   return *this;
 }
 
-ComplexMatrix
-ComplexNDArray::matrix_value (void) const
-{
-  ComplexMatrix retval;
-
-  if (ndims () == 2)
-    retval = ComplexMatrix (Array<Complex> (*this));
-  else
-    (*current_liboctave_error_handler)
-      ("invalid conversion of ComplexNDArray to ComplexMatrix");
-
-  return retval;
-}
-
 void
 ComplexNDArray::increment_index (Array<octave_idx_type>& ra_idx,
                                  const dim_vector& dimensions,
--- a/liboctave/array/CNDArray.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/CNDArray.h	Mon Jan 12 09:17:35 2015 -0800
@@ -24,7 +24,6 @@
 #define octave_CNDArray_h 1
 
 #include "MArray.h"
-#include "CMatrix.h"
 
 #include "mx-defs.h"
 #include "mx-op-decl.h"
@@ -36,8 +35,6 @@
 {
 public:
 
-  typedef ComplexMatrix matrix_type;
-
   ComplexNDArray (void) : MArray<Complex> () { }
 
   ComplexNDArray (const dim_vector& dv) : MArray<Complex> (dv) { }
@@ -47,8 +44,6 @@
 
   ComplexNDArray (const ComplexNDArray& a) : MArray<Complex> (a) { }
 
-  ComplexNDArray (const ComplexMatrix& a) : MArray<Complex> (a) { }
-
   template <class U>
   ComplexNDArray (const MArray<U>& a) : MArray<Complex> (a) { }
 
@@ -124,8 +119,6 @@
   ComplexNDArray fourierNd (void) const;
   ComplexNDArray ifourierNd (void) const;
 
-  ComplexMatrix matrix_value (void) const;
-
   ComplexNDArray squeeze (void) const { return MArray<Complex>::squeeze (); }
 
   static void increment_index (Array<octave_idx_type>& ra_idx,
--- a/liboctave/array/CSparse.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/CSparse.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -36,6 +36,12 @@
 #include "lo-mappers.h"
 #include "f77-fcn.h"
 #include "dRowVector.h"
+#include "mx-m-cs.h"
+#include "mx-cs-m.h"
+#include "mx-cm-s.h"
+#include "mx-fcm-fs.h"
+#include "mx-s-cm.h"
+#include "mx-fs-fcm.h"
 #include "oct-locbuf.h"
 
 #include "dDiagMatrix.h"
@@ -51,10 +57,11 @@
 #include "SparseCmplxCHOL.h"
 #include "SparseCmplxQR.h"
 
+#include "Sparse-op-defs.h"
+
 #include "Sparse-diag-op-defs.h"
 
 #include "Sparse-perm-op-defs.h"
-#include "mx-inlines.cc"
 
 // Define whether to use a basic QR solver or one that uses a Dulmange
 // Mendelsohn factorization to seperate the problem into under-determined,
@@ -1118,7 +1125,6 @@
             {
               // Matrix is either singular or not positive definite
               mattype.mark_as_unsymmetric ();
-              typ = MatrixType::Full;
             }
         }
 
@@ -1798,9 +1804,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g",
-                   rcond);
+                gripe_singular_matrix (rcond);
             }
 
           volatile double rcond_plus_one = rcond + 1.0;
@@ -1815,9 +1819,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("matrix singular to machine precision, rcond = %g",
-                   rcond);
+                gripe_singular_matrix (rcond);
             }
         }
       else
@@ -1918,7 +1920,7 @@
                         }
                     }
 
-                  // Count non-zeros in work vector and adjust space in
+                  // Count nonzeros in work vector and adjust space in
                   // retval if needed
                   octave_idx_type new_nnz = 0;
                   for (octave_idx_type i = 0; i < nc; i++)
@@ -2014,7 +2016,7 @@
                         }
                     }
 
-                  // Count non-zeros in work vector and adjust space in
+                  // Count nonzeros in work vector and adjust space in
                   // retval if needed
                   octave_idx_type new_nnz = 0;
                   for (octave_idx_type i = 0; i < nc; i++)
@@ -2086,9 +2088,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g",
-                   rcond);
+                gripe_singular_matrix (rcond);
             }
 
           volatile double rcond_plus_one = rcond + 1.0;
@@ -2103,9 +2103,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("matrix singular to machine precision, rcond = %g",
-                   rcond);
+                gripe_singular_matrix (rcond);
             }
         }
       else
@@ -2321,9 +2319,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g",
-                   rcond);
+                gripe_singular_matrix (rcond);
             }
 
           volatile double rcond_plus_one = rcond + 1.0;
@@ -2338,9 +2334,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("matrix singular to machine precision, rcond = %g",
-                   rcond);
+                gripe_singular_matrix (rcond);
             }
         }
       else
@@ -2441,7 +2435,7 @@
                         }
                     }
 
-                  // Count non-zeros in work vector and adjust space in
+                  // Count nonzeros in work vector and adjust space in
                   // retval if needed
                   octave_idx_type new_nnz = 0;
                   for (octave_idx_type i = 0; i < nc; i++)
@@ -2537,7 +2531,7 @@
                         }
                     }
 
-                  // Count non-zeros in work vector and adjust space in
+                  // Count nonzeros in work vector and adjust space in
                   // retval if needed
                   octave_idx_type new_nnz = 0;
                   for (octave_idx_type i = 0; i < nc; i++)
@@ -2609,9 +2603,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g",
-                   rcond);
+                gripe_singular_matrix (rcond);
             }
 
           volatile double rcond_plus_one = rcond + 1.0;
@@ -2626,9 +2618,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("matrix singular to machine precision, rcond = %g",
-                   rcond);
+                gripe_singular_matrix (rcond);
             }
         }
       else
@@ -2865,9 +2855,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g",
-                   rcond);
+                gripe_singular_matrix (rcond);
             }
 
           volatile double rcond_plus_one = rcond + 1.0;
@@ -2882,9 +2870,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("matrix singular to machine precision, rcond = %g",
-                   rcond);
+                gripe_singular_matrix (rcond);
             }
         }
       else
@@ -2991,7 +2977,7 @@
                         }
                     }
 
-                  // Count non-zeros in work vector and adjust space in
+                  // Count nonzeros in work vector and adjust space in
                   // retval if needed
                   octave_idx_type new_nnz = 0;
                   for (octave_idx_type i = 0; i < nc; i++)
@@ -3100,7 +3086,7 @@
                         }
                     }
 
-                  // Count non-zeros in work vector and adjust space in
+                  // Count nonzeros in work vector and adjust space in
                   // retval if needed
                   octave_idx_type new_nnz = 0;
                   for (octave_idx_type i = 0; i < nc; i++)
@@ -3173,9 +3159,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g",
-                   rcond);
+                gripe_singular_matrix (rcond);
             }
 
           volatile double rcond_plus_one = rcond + 1.0;
@@ -3190,9 +3174,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("matrix singular to machine precision, rcond = %g",
-                   rcond);
+                gripe_singular_matrix (rcond);
             }
         }
       else
@@ -3433,9 +3415,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g",
-                   rcond);
+                gripe_singular_matrix (rcond);
             }
 
           volatile double rcond_plus_one = rcond + 1.0;
@@ -3450,9 +3430,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("matrix singular to machine precision, rcond = %g",
-                   rcond);
+                gripe_singular_matrix (rcond);
             }
         }
       else
@@ -3558,7 +3536,7 @@
                         }
                     }
 
-                  // Count non-zeros in work vector and adjust space in
+                  // Count nonzeros in work vector and adjust space in
                   // retval if needed
                   octave_idx_type new_nnz = 0;
                   for (octave_idx_type i = 0; i < nc; i++)
@@ -3667,7 +3645,7 @@
                         }
                     }
 
-                  // Count non-zeros in work vector and adjust space in
+                  // Count nonzeros in work vector and adjust space in
                   // retval if needed
                   octave_idx_type new_nnz = 0;
                   for (octave_idx_type i = 0; i < nc; i++)
@@ -3740,9 +3718,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g",
-                   rcond);
+                gripe_singular_matrix (rcond);
             }
 
           volatile double rcond_plus_one = rcond + 1.0;
@@ -3757,9 +3733,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("matrix singular to machine precision, rcond = %g",
-                   rcond);
+                gripe_singular_matrix (rcond);
             }
         }
       else
@@ -3906,8 +3880,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("matrix singular to machine precision");
+                gripe_singular_matrix ();
 
             }
           else
@@ -4004,9 +3977,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("matrix singular to machine precision");
-
+                gripe_singular_matrix ();
             }
           else
             {
@@ -4033,7 +4004,7 @@
                              work, b.rows (), err
                              F77_CHAR_ARG_LEN (1)));
 
-                  // Count non-zeros in work vector and adjust
+                  // Count nonzeros in work vector and adjust
                   // space in retval if needed
                   octave_idx_type new_nnz = 0;
                   for (octave_idx_type i = 0; i < nr; i++)
@@ -4208,8 +4179,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("matrix singular to machine precision");
+                gripe_singular_matrix ();
             }
         }
       else if (typ != MatrixType::Tridiagonal_Hermitian)
@@ -4304,8 +4274,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("matrix singular to machine precision");
+                gripe_singular_matrix ();
             }
           else
             {
@@ -4315,7 +4284,7 @@
               octave_idx_type b_nc = b.cols ();
               OCTAVE_LOCAL_BUFFER (Complex, Bx, b_nr);
 
-              // Take a first guess that the number of non-zero terms
+              // Take a first guess that the number of nonzero terms
               // will be as many as in b
               volatile octave_idx_type x_nz = b.nnz ();
               volatile octave_idx_type ii = 0;
@@ -4343,7 +4312,7 @@
                       break;
                     }
 
-                  // Count non-zeros in work vector and adjust
+                  // Count nonzeros in work vector and adjust
                   // space in retval if needed
                   octave_idx_type new_nnz = 0;
                   for (octave_idx_type i = 0; i < nr; i++)
@@ -4474,9 +4443,7 @@
                           mattype.mark_as_rectangular ();
                         }
                       else
-                        (*current_liboctave_error_handler)
-                          ("matrix singular to machine precision, rcond = %g",
-                           rcond);
+                        gripe_singular_matrix (rcond);
                     }
                 }
               else
@@ -4529,7 +4496,7 @@
               m_band(ridx (i) - j + n_lower + n_upper, j) = data (i);
 
           // Calculate the norm of the matrix, for later use.
-          double anorm;
+          double anorm = 0.0;
           if (calc_cond)
             {
               for (octave_idx_type j = 0; j < nr; j++)
@@ -4561,8 +4528,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("matrix singular to machine precision");
+                gripe_singular_matrix ();
             }
           else
             {
@@ -4595,9 +4561,7 @@
                           mattype.mark_as_rectangular ();
                         }
                       else
-                        (*current_liboctave_error_handler)
-                          ("matrix singular to machine precision, rcond = %g",
-                           rcond);
+                        gripe_singular_matrix (rcond);
                     }
                 }
               else
@@ -4721,9 +4685,7 @@
                           mattype.mark_as_rectangular ();
                         }
                       else
-                        (*current_liboctave_error_handler)
-                          ("matrix singular to machine precision, rcond = %g",
-                           rcond);
+                        gripe_singular_matrix (rcond);
                     }
                 }
               else
@@ -4735,7 +4697,7 @@
                   octave_idx_type b_nc = b.cols ();
                   OCTAVE_LOCAL_BUFFER (Complex, Bx, b_nr);
 
-                  // Take a first guess that the number of non-zero terms
+                  // Take a first guess that the number of nonzero terms
                   // will be as many as in b
                   volatile octave_idx_type x_nz = b.nnz ();
                   volatile octave_idx_type ii = 0;
@@ -4811,7 +4773,7 @@
               m_band(ridx (i) - j + n_lower + n_upper, j) = data (i);
 
           // Calculate the norm of the matrix, for later use.
-          double anorm;
+          double anorm = 0.0;
           if (calc_cond)
             {
               for (octave_idx_type j = 0; j < nr; j++)
@@ -4841,9 +4803,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("matrix singular to machine precision");
-
+                gripe_singular_matrix ();
             }
           else
             {
@@ -4876,9 +4836,7 @@
                           mattype.mark_as_rectangular ();
                         }
                       else
-                        (*current_liboctave_error_handler)
-                          ("matrix singular to machine precision, rcond = %g",
-                           rcond);
+                        gripe_singular_matrix (rcond);
                     }
                 }
               else
@@ -4909,7 +4867,7 @@
                                  ldm, pipvt, work, b.rows (), err
                                  F77_CHAR_ARG_LEN (1)));
 
-                      // Count non-zeros in work vector and adjust
+                      // Count nonzeros in work vector and adjust
                       // space in retval if needed
                       octave_idx_type new_nnz = 0;
                       for (octave_idx_type i = 0; i < nr; i++)
@@ -5041,9 +4999,7 @@
                           mattype.mark_as_rectangular ();
                         }
                       else
-                        (*current_liboctave_error_handler)
-                          ("matrix singular to machine precision, rcond = %g",
-                           rcond);
+                        gripe_singular_matrix (rcond);
                     }
                 }
               else
@@ -5096,7 +5052,7 @@
               m_band(ridx (i) - j + n_lower + n_upper, j) = data (i);
 
           // Calculate the norm of the matrix, for later use.
-          double anorm;
+          double anorm = 0.0;
           if (calc_cond)
             {
               for (octave_idx_type j = 0; j < nr; j++)
@@ -5126,8 +5082,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("matrix singular to machine precision");
+                gripe_singular_matrix ();
             }
           else
             {
@@ -5160,9 +5115,7 @@
                           mattype.mark_as_rectangular ();
                         }
                       else
-                        (*current_liboctave_error_handler)
-                          ("matrix singular to machine precision, rcond = %g",
-                           rcond);
+                        gripe_singular_matrix (rcond);
                     }
                 }
               else
@@ -5288,9 +5241,7 @@
                           mattype.mark_as_rectangular ();
                         }
                       else
-                        (*current_liboctave_error_handler)
-                          ("matrix singular to machine precision, rcond = %g",
-                           rcond);
+                        gripe_singular_matrix (rcond);
                     }
                 }
               else
@@ -5302,7 +5253,7 @@
                   octave_idx_type b_nc = b.cols ();
                   OCTAVE_LOCAL_BUFFER (Complex, Bx, b_nr);
 
-                  // Take a first guess that the number of non-zero terms
+                  // Take a first guess that the number of nonzero terms
                   // will be as many as in b
                   volatile octave_idx_type x_nz = b.nnz ();
                   volatile octave_idx_type ii = 0;
@@ -5329,7 +5280,7 @@
                           break;
                         }
 
-                      // Count non-zeros in work vector and adjust
+                      // Count nonzeros in work vector and adjust
                       // space in retval if needed
                       octave_idx_type new_nnz = 0;
                       for (octave_idx_type i = 0; i < nr; i++)
@@ -5383,7 +5334,7 @@
               m_band(ridx (i) - j + n_lower + n_upper, j) = data (i);
 
           // Calculate the norm of the matrix, for later use.
-          double anorm;
+          double anorm = 0.0;
           if (calc_cond)
             {
               for (octave_idx_type j = 0; j < nr; j++)
@@ -5413,9 +5364,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("matrix singular to machine precision");
-
+                gripe_singular_matrix ();
             }
           else
             {
@@ -5448,9 +5397,7 @@
                           mattype.mark_as_rectangular ();
                         }
                       else
-                        (*current_liboctave_error_handler)
-                          ("matrix singular to machine precision, rcond = %g",
-                           rcond);
+                        gripe_singular_matrix (rcond);
                     }
                 }
               else
@@ -5482,7 +5429,7 @@
                                  ldm, pipvt, Bx, b.rows (), err
                                  F77_CHAR_ARG_LEN (1)));
 
-                      // Count non-zeros in work vector and adjust
+                      // Count nonzeros in work vector and adjust
                       // space in retval if needed
                       octave_idx_type new_nnz = 0;
                       for (octave_idx_type i = 0; i < nr; i++)
@@ -5603,10 +5550,7 @@
           if (sing_handler)
             sing_handler (rcond);
           else
-            (*current_liboctave_error_handler)
-              ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g",
-               rcond);
-
+            gripe_singular_matrix (rcond);
         }
       else if (status < 0)
         {
@@ -5670,17 +5614,17 @@
           if (spu == 0.)
             {
               cm->print = -1;
-              cm->print_function = 0;
+              SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, 0);
             }
           else
             {
               cm->print = static_cast<int> (spu) + 2;
-              cm->print_function =&SparseCholPrint;
+              SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, &SparseCholPrint);
             }
 
           cm->error_handler = &SparseCholError;
-          cm->complex_divide = CHOLMOD_NAME(divcomplex);
-          cm->hypotenuse = CHOLMOD_NAME(hypot);
+          SUITESPARSE_ASSIGN_FPTR2 (divcomplex_func, cm->complex_divide, divcomplex);
+          SUITESPARSE_ASSIGN_FPTR2 (hypot_func, cm->hypotenuse, hypot);
 
           cm->final_ll = true;
 
@@ -5754,9 +5698,7 @@
                       mattype.mark_as_rectangular ();
                     }
                   else
-                    (*current_liboctave_error_handler)
-                      ("SparseMatrix::solve matrix singular to machine precision, rcond = %g",
-                       rcond);
+                    gripe_singular_matrix (rcond);
 
                   return retval;
                 }
@@ -5783,8 +5725,8 @@
               END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
             }
 #else
-          (*current_liboctave_warning_handler)
-            ("CHOLMOD not installed");
+          (*current_liboctave_warning_with_id_handler)
+            ("Octave:missing-dependency", "CHOLMOD not installed");
 
           mattype.mark_as_unsymmetric ();
           typ = MatrixType::Full;
@@ -5913,17 +5855,17 @@
           if (spu == 0.)
             {
               cm->print = -1;
-              cm->print_function = 0;
+              SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, 0);
             }
           else
             {
               cm->print = static_cast<int> (spu) + 2;
-              cm->print_function =&SparseCholPrint;
+              SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, &SparseCholPrint);
             }
 
           cm->error_handler = &SparseCholError;
-          cm->complex_divide = CHOLMOD_NAME(divcomplex);
-          cm->hypotenuse = CHOLMOD_NAME(hypot);
+          SUITESPARSE_ASSIGN_FPTR2 (divcomplex_func, cm->complex_divide, divcomplex);
+          SUITESPARSE_ASSIGN_FPTR2 (hypot_func, cm->hypotenuse, hypot);
 
           cm->final_ll = true;
 
@@ -6007,9 +5949,7 @@
                       mattype.mark_as_rectangular ();
                     }
                   else
-                    (*current_liboctave_error_handler)
-                      ("SparseMatrix::solve matrix singular to machine precision, rcond = %g",
-                       rcond);
+                    gripe_singular_matrix (rcond);
 
                   return retval;
                 }
@@ -6042,8 +5982,8 @@
               END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
             }
 #else
-          (*current_liboctave_warning_handler)
-            ("CHOLMOD not installed");
+          (*current_liboctave_warning_with_id_handler)
+            ("Octave:missing-dependency", "CHOLMOD not installed");
 
           mattype.mark_as_unsymmetric ();
           typ = MatrixType::Full;
@@ -6077,7 +6017,7 @@
               OCTAVE_LOCAL_BUFFER (Complex, Bz, b_nr);
 #endif
 
-              // Take a first guess that the number of non-zero terms
+              // Take a first guess that the number of nonzero terms
               // will be as many as in b
               octave_idx_type x_nz = b.nnz ();
               octave_idx_type ii = 0;
@@ -6204,17 +6144,17 @@
           if (spu == 0.)
             {
               cm->print = -1;
-              cm->print_function = 0;
+              SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, 0);
             }
           else
             {
               cm->print = static_cast<int> (spu) + 2;
-              cm->print_function =&SparseCholPrint;
+              SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, &SparseCholPrint);
             }
 
           cm->error_handler = &SparseCholError;
-          cm->complex_divide = CHOLMOD_NAME(divcomplex);
-          cm->hypotenuse = CHOLMOD_NAME(hypot);
+          SUITESPARSE_ASSIGN_FPTR2 (divcomplex_func, cm->complex_divide, divcomplex);
+          SUITESPARSE_ASSIGN_FPTR2 (hypot_func, cm->hypotenuse, hypot);
 
           cm->final_ll = true;
 
@@ -6288,9 +6228,7 @@
                       mattype.mark_as_rectangular ();
                     }
                   else
-                    (*current_liboctave_error_handler)
-                      ("SparseMatrix::solve matrix singular to machine precision, rcond = %g",
-                       rcond);
+                    gripe_singular_matrix (rcond);
 
                   return retval;
                 }
@@ -6317,8 +6255,8 @@
               END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
             }
 #else
-          (*current_liboctave_warning_handler)
-            ("CHOLMOD not installed");
+          (*current_liboctave_warning_with_id_handler)
+            ("Octave:missing-dependency", "CHOLMOD not installed");
 
           mattype.mark_as_unsymmetric ();
           typ = MatrixType::Full;
@@ -6426,17 +6364,17 @@
           if (spu == 0.)
             {
               cm->print = -1;
-              cm->print_function = 0;
+              SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, 0);
             }
           else
             {
               cm->print = static_cast<int> (spu) + 2;
-              cm->print_function =&SparseCholPrint;
+              SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, &SparseCholPrint);
             }
 
           cm->error_handler = &SparseCholError;
-          cm->complex_divide = CHOLMOD_NAME(divcomplex);
-          cm->hypotenuse = CHOLMOD_NAME(hypot);
+          SUITESPARSE_ASSIGN_FPTR2 (divcomplex_func, cm->complex_divide, divcomplex);
+          SUITESPARSE_ASSIGN_FPTR2 (hypot_func, cm->hypotenuse, hypot);
 
           cm->final_ll = true;
 
@@ -6520,9 +6458,7 @@
                       mattype.mark_as_rectangular ();
                     }
                   else
-                    (*current_liboctave_error_handler)
-                      ("SparseMatrix::solve matrix singular to machine precision, rcond = %g",
-                       rcond);
+                    gripe_singular_matrix (rcond);
 
                   return retval;
                 }
@@ -6555,8 +6491,8 @@
               END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
             }
 #else
-          (*current_liboctave_warning_handler)
-            ("CHOLMOD not installed");
+          (*current_liboctave_warning_with_id_handler)
+            ("Octave:missing-dependency", "CHOLMOD not installed");
 
           mattype.mark_as_unsymmetric ();
           typ = MatrixType::Full;
@@ -6583,7 +6519,7 @@
 
               OCTAVE_LOCAL_BUFFER (Complex, Bx, b_nr);
 
-              // Take a first guess that the number of non-zero terms
+              // Take a first guess that the number of nonzero terms
               // will be as many as in b
               octave_idx_type x_nz = b.nnz ();
               octave_idx_type ii = 0;
@@ -6651,10 +6587,7 @@
                   if (sing_handler)
                     sing_handler (rcond);
                   else
-                    (*current_liboctave_error_handler)
-                      ("SparseComplexMatrix::solve matrix singular to machine precision, rcond = %g",
-                       rcond);
-
+                    gripe_singular_matrix (rcond);
                 }
 
               UMFPACK_ZNAME (report_info) (control, info);
@@ -7688,87 +7621,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;
 }
@@ -7783,7 +7714,7 @@
 
   EMPTY_RETURN_CHECK (SparseComplexMatrix);
 
-  // Count the number of non-zero elements
+  // Count the number of nonzero elements
   if (xmax (c, 0.) != 0.)
     {
       result = SparseComplexMatrix (nr, nc, c);
@@ -7808,91 +7739,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/CSparse.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/CSparse.h	Mon Jan 12 09:17:35 2015 -0800
@@ -26,6 +26,7 @@
 
 #include "dMatrix.h"
 #include "dNDArray.h"
+#include "CMatrix.h"
 #include "CNDArray.h"
 #include "dColVector.h"
 #include "CColVector.h"
@@ -34,7 +35,9 @@
 #include "DET.h"
 #include "MSparse.h"
 #include "MSparse-defs.h"
-#include "Sparse-op-defs.h"
+
+#include "Sparse-op-decls.h"
+
 #include "MatrixType.h"
 
 class PermMatrix;
--- a/liboctave/array/DiagArray2.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/DiagArray2.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -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/MArray.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/MArray.h	Mon Jan 12 09:17:35 2015 -0800
@@ -49,12 +49,6 @@
 
   MArray (void) : Array<T> () { }
 
-  explicit MArray (octave_idx_type n) GCC_ATTR_DEPRECATED
-    : Array<T> (dim_vector (n, 1)) { }
-
-  MArray (octave_idx_type n, const T& val) GCC_ATTR_DEPRECATED
-    : Array<T> (dim_vector (n, 1), val) { }
-
   explicit MArray (const dim_vector& dv)
     : Array<T> (dv) { }
 
--- a/liboctave/array/MArray2.h	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-// Template array classes with like-type math ops
-/*
-
-Copyright (C) 1996-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_MArray2_h)
-#define octave_MArray2_h 1
-
-#include "MArray.h"
-#define MArray2 MArray
-
-// If we're with GNU C++, issue a warning.
-#ifdef __GNUC__
-#warning Using MArray2<T> is deprecated. Use MArray<T>.
-#endif
-
-
-
-#endif
--- a/liboctave/array/MArrayN.h	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-// Template array classes with like-type math ops
-/*
-
-Copyright (C) 1996-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_MArrayN_h)
-#define octave_MArrayN_h 1
-
-#include "MArray.h"
-#define MArrayN MArray
-
-// If we're with GNU C++, issue a warning.
-#ifdef __GNUC__
-#warning Using MArrayN<T> is deprecated. Use MArray<T>.
-#endif
-
-#endif
--- a/liboctave/array/MSparse.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/MSparse.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -68,7 +68,7 @@
           octave_idx_type  jb_max = b.cidx (i+1);
           bool jb_lt_max = jb < jb_max;
 
-          while (ja_lt_max || jb_lt_max )
+          while (ja_lt_max || jb_lt_max)
             {
               octave_quit ();
               if ((! jb_lt_max) ||
@@ -80,8 +80,8 @@
                   ja++;
                   ja_lt_max= ja < ja_max;
                 }
-              else if (( !ja_lt_max ) ||
-                       (jb_lt_max && (b.ridx (jb) < a.ridx (ja)) ) )
+              else if ((! ja_lt_max) ||
+                       (jb_lt_max && (b.ridx (jb) < a.ridx (ja))))
                 {
                   r.ridx (jx) = b.ridx (jb);
                   r.data (jx) = op (0., b.data (jb));
@@ -340,7 +340,7 @@
           octave_idx_type  jb_max = b.cidx (i+1);
           bool jb_lt_max = jb < jb_max;
 
-          while (ja_lt_max || jb_lt_max )
+          while (ja_lt_max || jb_lt_max)
             {
               octave_quit ();
               if ((! jb_lt_max) ||
@@ -352,8 +352,8 @@
                   ja++;
                   ja_lt_max= ja < ja_max;
                 }
-              else if (( !ja_lt_max ) ||
-                       (jb_lt_max && (b.ridx (jb) < a.ridx (ja)) ) )
+              else if ((! ja_lt_max) ||
+                       (jb_lt_max && (b.ridx (jb) < a.ridx (ja))))
                 {
                   r.ridx (jx) = b.ridx (jb);
                   r.data (jx) = op (0.,  b.data (jb));
@@ -462,7 +462,7 @@
           octave_idx_type  jb_max = b.cidx (i+1);
           bool jb_lt_max = jb < jb_max;
 
-          while (ja_lt_max || jb_lt_max )
+          while (ja_lt_max || jb_lt_max)
             {
               octave_quit ();
               if ((! jb_lt_max) ||
@@ -470,8 +470,8 @@
                 {
                   ja++; ja_lt_max= ja < ja_max;
                 }
-              else if (( !ja_lt_max ) ||
-                       (jb_lt_max && (b.ridx (jb) < a.ridx (ja)) ) )
+              else if ((! ja_lt_max) ||
+                       (jb_lt_max && (b.ridx (jb) < a.ridx (ja))))
                 {
                   jb++; jb_lt_max= jb < jb_max;
                 }
@@ -569,7 +569,7 @@
     gripe_nonconformant ("quotient", a_nr, a_nc, b_nr, b_nc);
   else
     {
-      r = MSparse<T>( a_nr, a_nc, (Zero / Zero));
+      r = MSparse<T> (a_nr, a_nc, (Zero / Zero));
 
       for (octave_idx_type i = 0 ; i < a_nc ; i++)
         {
@@ -581,7 +581,7 @@
           octave_idx_type  jb_max = b.cidx (i+1);
           bool jb_lt_max = jb < jb_max;
 
-          while (ja_lt_max || jb_lt_max )
+          while (ja_lt_max || jb_lt_max)
             {
               octave_quit ();
               if ((! jb_lt_max) ||
@@ -590,8 +590,8 @@
                   r.elem (a.ridx (ja),i) = a.data (ja) / Zero;
                   ja++; ja_lt_max= ja < ja_max;
                 }
-              else if (( !ja_lt_max ) ||
-                       (jb_lt_max && (b.ridx (jb) < a.ridx (ja)) ) )
+              else if ((! ja_lt_max) ||
+                       (jb_lt_max && (b.ridx (jb) < a.ridx (ja))))
                 {
                   r.elem (b.ridx (jb),i) = Zero / b.data (jb);
                   jb++; jb_lt_max= jb < jb_max;
--- a/liboctave/array/MatrixType.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/MatrixType.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -30,12 +30,35 @@
 
 #include "MatrixType.h"
 #include "dMatrix.h"
+#include "fMatrix.h"
 #include "CMatrix.h"
+#include "fCMatrix.h"
 #include "dSparse.h"
 #include "CSparse.h"
 #include "oct-spparms.h"
 #include "oct-locbuf.h"
 
+static void
+warn_cached (void)
+{
+  (*current_liboctave_warning_with_id_handler)
+    ("Octave:matrix-type-info", "using cached matrix type");
+}
+
+static void
+warn_invalid (void)
+{
+  (*current_liboctave_warning_with_id_handler)
+    ("Octave:matrix-type-info", "invalid matrix type");
+}
+
+static void
+warn_calculating_sparse_type (void)
+{
+  (*current_liboctave_warning_with_id_handler)
+    ("Octave:matrix-type-info", "calculating sparse matrix type");
+}
+
 // FIXME: There is a large code duplication here
 
 MatrixType::MatrixType (void)
@@ -119,7 +142,7 @@
 MatrixType::matrix_type
 matrix_complex_probe (const MArray<std::complex<T> >& a)
 {
-  MatrixType::matrix_type typ;
+  MatrixType::matrix_type typ = MatrixType::Unknown;
   octave_idx_type nrows = a.rows ();
   octave_idx_type ncols = a.cols ();
 
@@ -219,8 +242,7 @@
   octave_idx_type nnz = a.nnz ();
 
   if (octave_sparse_params::get_key ("spumoni") != 0.)
-    (*current_liboctave_warning_handler)
-      ("Calculating Sparse Matrix Type");
+    warn_calculating_sparse_type ();
 
   sp_bandden = octave_sparse_params::get_bandden ();
   bool maybe_hermitian = false;
@@ -538,8 +560,7 @@
   octave_idx_type nnz = a.nnz ();
 
   if (octave_sparse_params::get_key ("spumoni") != 0.)
-    (*current_liboctave_warning_handler)
-      ("Calculating Sparse Matrix Type");
+    warn_calculating_sparse_type ();
 
   sp_bandden = octave_sparse_params::get_bandden ();
   bool maybe_hermitian = false;
@@ -859,7 +880,7 @@
       || t == MatrixType::Rectangular)
     typ = t;
   else
-    (*current_liboctave_warning_handler) ("Invalid matrix type");
+    warn_invalid ();
 }
 
 MatrixType::MatrixType (const matrix_type t, const octave_idx_type np,
@@ -879,7 +900,7 @@
         perm[i] = p[i];
     }
   else
-    (*current_liboctave_warning_handler) ("Invalid matrix type");
+    warn_invalid ();
 }
 
 MatrixType::MatrixType (const matrix_type t, const octave_idx_type ku,
@@ -896,7 +917,7 @@
       lower_band = kl;
     }
   else
-    (*current_liboctave_warning_handler) ("Invalid sparse matrix type");
+    warn_invalid ();
 }
 
 MatrixType::~MatrixType (void)
@@ -946,16 +967,15 @@
     {
       if (!quiet &&
           octave_sparse_params::get_key ("spumoni") != 0.)
-        (*current_liboctave_warning_handler)
-          ("Using Cached Matrix Type");
+        warn_cached ();
 
       return typ;
     }
 
   if (typ != MatrixType::Unknown &&
       octave_sparse_params::get_key ("spumoni") != 0.)
-    (*current_liboctave_warning_handler)
-      ("Invalidating Matrix Type");
+    (*current_liboctave_warning_with_id_handler)
+      ("Octave:matrix-type-info", "invalidating matrix type");
 
   typ = MatrixType::Unknown;
 
@@ -969,8 +989,7 @@
       && (full || sp_bandden == octave_sparse_params::get_bandden ()))
     {
       if (octave_sparse_params::get_key ("spumoni") != 0.)
-        (*current_liboctave_warning_handler)
-          ("Using Cached Matrix Type");
+        warn_cached ();
 
       return typ;
     }
@@ -1002,8 +1021,7 @@
       && (full || sp_bandden == octave_sparse_params::get_bandden ()))
     {
       if (octave_sparse_params::get_key ("spumoni") != 0.)
-        (*current_liboctave_warning_handler)
-          ("Using Cached Matrix Type");
+        warn_cached ();
 
       return typ;
     }
@@ -1034,8 +1052,7 @@
   if (typ != MatrixType::Unknown)
     {
       if (octave_sparse_params::get_key ("spumoni") != 0.)
-        (*current_liboctave_warning_handler)
-          ("Using Cached Matrix Type");
+        warn_cached ();
 
       return typ;
     }
@@ -1061,8 +1078,7 @@
   if (typ != MatrixType::Unknown)
     {
       if (octave_sparse_params::get_key ("spumoni") != 0.)
-        (*current_liboctave_warning_handler)
-          ("Using Cached Matrix Type");
+        warn_cached ();
 
       return typ;
     }
@@ -1088,8 +1104,7 @@
   if (typ != MatrixType::Unknown)
     {
       if (octave_sparse_params::get_key ("spumoni") != 0.)
-        (*current_liboctave_warning_handler)
-          ("Using Cached Matrix Type");
+        warn_cached ();
 
       return typ;
     }
@@ -1115,8 +1130,7 @@
   if (typ != MatrixType::Unknown)
     {
       if (octave_sparse_params::get_key ("spumoni") != 0.)
-        (*current_liboctave_warning_handler)
-          ("Using Cached Matrix Type");
+        warn_cached ();
 
       return typ;
     }
@@ -1142,49 +1156,52 @@
   if (octave_sparse_params::get_key ("spumoni") != 0.)
     {
       if (typ == MatrixType::Unknown)
-        (*current_liboctave_warning_handler)
-          ("Unknown Matrix Type");
+        (*current_liboctave_warning_with_id_handler)
+          ("Octave:matrix-type-info", "unknown matrix type");
       else if (typ == MatrixType::Diagonal)
-        (*current_liboctave_warning_handler)
-          ("Diagonal Sparse Matrix");
+        (*current_liboctave_warning_with_id_handler)
+          ("Octave:matrix-type-info", "diagonal sparse matrix");
       else if (typ == MatrixType::Permuted_Diagonal)
-        (*current_liboctave_warning_handler)
-          ("Permuted Diagonal Sparse Matrix");
+        (*current_liboctave_warning_with_id_handler)
+          ("Octave:matrix-type-info", "permuted diagonal sparse matrix");
       else if (typ == MatrixType::Upper)
-        (*current_liboctave_warning_handler)
-          ("Upper Triangular Matrix");
+        (*current_liboctave_warning_with_id_handler)
+          ("Octave:matrix-type-info", "upper triangular matrix");
       else if (typ == MatrixType::Lower)
-        (*current_liboctave_warning_handler)
-          ("Lower Triangular Matrix");
+        (*current_liboctave_warning_with_id_handler)
+          ("Octave:matrix-type-info", "lower triangular matrix");
       else if (typ == MatrixType::Permuted_Upper)
-        (*current_liboctave_warning_handler)
-          ("Permuted Upper Triangular Matrix");
+        (*current_liboctave_warning_with_id_handler)
+          ("Octave:matrix-type-info", "permuted upper triangular matrix");
       else if (typ == MatrixType::Permuted_Lower)
-        (*current_liboctave_warning_handler)
-          ("Permuted Lower Triangular Matrix");
+        (*current_liboctave_warning_with_id_handler)
+          ("Octave:matrix-type-info", "permuted lower triangular Matrix");
       else if (typ == MatrixType::Banded)
-        (*current_liboctave_warning_handler)
-          ("Banded Sparse Matrix %d-1-%d (Density %f)", lower_band,
-           upper_band, bandden);
+        (*current_liboctave_warning_with_id_handler)
+          ("Octave:matrix-type-info",
+           "banded sparse matrix %d-1-%d (density %f)",
+           lower_band, upper_band, bandden);
       else if (typ == MatrixType::Banded_Hermitian)
-        (*current_liboctave_warning_handler)
-          ("Banded Hermitian/Symmetric Sparse Matrix %d-1-%d (Density %f)",
+        (*current_liboctave_warning_with_id_handler)
+          ("Octave:matrix-type-info",
+           "banded hermitian/symmetric sparse matrix %d-1-%d (density %f)",
            lower_band, upper_band, bandden);
       else if (typ == MatrixType::Hermitian)
-        (*current_liboctave_warning_handler)
-          ("Hermitian/Symmetric Matrix");
+        (*current_liboctave_warning_with_id_handler)
+          ("Octave:matrix-type-info", "hermitian/symmetric matrix");
       else if (typ == MatrixType::Tridiagonal)
-        (*current_liboctave_warning_handler)
-          ("Tridiagonal Sparse Matrix");
+        (*current_liboctave_warning_with_id_handler)
+          ("Octave:matrix-type-info", "tridiagonal sparse matrix");
       else if (typ == MatrixType::Tridiagonal_Hermitian)
-        (*current_liboctave_warning_handler)
-          ("Hermitian/Symmetric Tridiagonal Sparse Matrix");
+        (*current_liboctave_warning_with_id_handler)
+          ("Octave:matrix-type-info",
+           "hermitian/symmetric tridiagonal sparse matrix");
       else if (typ == MatrixType::Rectangular)
-        (*current_liboctave_warning_handler)
-          ("Rectangular/Singular Matrix");
+        (*current_liboctave_warning_with_id_handler)
+          ("Octave:matrix-type-info", "rectangular/singular matrix");
       else if (typ == MatrixType::Full)
-        (*current_liboctave_warning_handler)
-          ("Full Matrix");
+        (*current_liboctave_warning_with_id_handler)
+          ("Octave:matrix-type-info", "full matrix");
     }
 }
 
--- a/liboctave/array/PermMatrix.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/PermMatrix.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -36,8 +36,8 @@
     ("PermMatrix: invalid permutation vector");
 }
 
-PermMatrix::PermMatrix (const Array<octave_idx_type>& p, bool colp, bool check)
-  : Array<octave_idx_type> (p), _colp(colp)
+void
+PermMatrix::setup (const Array<octave_idx_type>& p, bool colp, bool check)
 {
   if (check)
     {
@@ -47,12 +47,28 @@
           Array<octave_idx_type>::operator = (Array<octave_idx_type> ());
         }
     }
+
+  if (!colp)
+    *this = this->transpose ();
+}
+
+PermMatrix::PermMatrix (const Array<octave_idx_type>& p)
+  : Array<octave_idx_type> (p)
+{
+  setup (p, false, true);
 }
 
-PermMatrix::PermMatrix (const idx_vector& idx, bool colp, octave_idx_type n)
-  : Array<octave_idx_type> (), _colp(colp)
+PermMatrix::PermMatrix (const Array<octave_idx_type>& p, bool colp, bool check)
+  : Array<octave_idx_type> (p)
+{
+  setup (p, colp, check);
+}
+
+void
+PermMatrix::setup (const idx_vector& idx, bool colp, octave_idx_type n)
 {
   octave_idx_type len = idx.length (n);
+
   if (! idx.is_permutation (len))
     gripe_invalid_permutation ();
   else
@@ -61,12 +77,28 @@
       for (octave_idx_type i = 0; i < len; i++) idxa(i) = idx(i);
       Array<octave_idx_type>::operator = (idxa);
     }
+
+  if (!colp)
+    *this = this->transpose ();
+}
+
+PermMatrix::PermMatrix (const idx_vector& idx)
+  : Array<octave_idx_type> ()
+{
+    setup (idx, false, 0);
+}
+
+PermMatrix::PermMatrix (const idx_vector& idx, bool colp, octave_idx_type n)
+  : Array<octave_idx_type> ()
+{
+    setup (idx, colp, n);
 }
 
 PermMatrix::PermMatrix (octave_idx_type n)
-  : Array<octave_idx_type> (dim_vector (n, 1)), _colp (false)
+  : Array<octave_idx_type> (dim_vector (n, 1))
 {
-  for (octave_idx_type i = 0; i < n; i++) xelem (i) = i;
+  for (octave_idx_type i = 0; i < n; i++)
+    xelem (i) = i;
 }
 
 octave_idx_type
@@ -86,8 +118,13 @@
 PermMatrix
 PermMatrix::transpose (void) const
 {
-  PermMatrix retval (*this);
-  retval._colp = ! retval._colp;
+  octave_idx_type len = Array<octave_idx_type>::length ();
+
+  PermMatrix retval (len);
+
+  for (octave_idx_type i = 0; i < len; ++i)
+    retval.xelem (xelem (i)) = i;
+
   return retval;
 }
 
@@ -133,17 +170,20 @@
 }
 
 PermMatrix
-PermMatrix::power (octave_idx_type m) const
+PermMatrix::power(octave_idx_type m) const
+{
+  if (m < 0)
+    return inverse ().pos_power (-m);
+  else if (m > 0)
+    return pos_power (m);
+  else
+    return PermMatrix (rows ());
+}
+
+PermMatrix
+PermMatrix::pos_power (octave_idx_type m) const
 {
   octave_idx_type n = rows ();
-  bool res_colp = _colp;
-  if (m < 0)
-    {
-      res_colp = ! res_colp;
-      m = -m;
-    }
-  else if (m == 0)
-    return PermMatrix (n);
 
   const octave_idx_type *p = data ();
   Array<octave_idx_type> res_pvec (dim_vector (n, 1), -1);
@@ -176,43 +216,29 @@
 
     }
 
-  return PermMatrix (res_pvec, res_colp, false);
+  return PermMatrix (res_pvec, true, false);
 }
 
 PermMatrix
 PermMatrix::eye (octave_idx_type n)
 {
-  Array<octave_idx_type> p (dim_vector (n, 1));
-  for (octave_idx_type i = 0; i < n; i++)
-    p(i) = i;
-
-  return PermMatrix (p, false, false);
+  return PermMatrix (n);
 }
 
 PermMatrix
 operator *(const PermMatrix& a, const PermMatrix& b)
 {
-  const Array<octave_idx_type> ia = a.pvec ();
-  const Array<octave_idx_type> ib = b.pvec ();
   PermMatrix r;
+
+  const Array<octave_idx_type> ia = a.col_perm_vec ();
+  const Array<octave_idx_type> ib = b.col_perm_vec ();
+
   octave_idx_type n = a.columns ();
+
   if (n != b.rows ())
     gripe_nonconformant ("operator *", n, n, b.rows (), b.rows ());
-  else if (a._colp == b._colp)
-    {
-      r = PermMatrix ((a._colp
-                       ? ia.index (idx_vector (ib))
-                       : ib.index (idx_vector (ia))), a._colp, false);
-    }
   else
-    {
-      Array<octave_idx_type> ra (dim_vector (n, 1));
-      if (a._colp)
-        ra.assign (idx_vector (ia), ib);
-      else
-        ra.assign (idx_vector (ib), ia);
-      r = PermMatrix (ra, a._colp, false);
-    }
+    r = PermMatrix (ia.index (idx_vector (ib)), true, false);
 
   return r;
 }
--- a/liboctave/array/PermMatrix.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/PermMatrix.h	Mon Jan 12 09:17:35 2015 -0800
@@ -31,20 +31,21 @@
 
 class OCTAVE_API PermMatrix : protected Array<octave_idx_type>
 {
-
 public:
 
-  PermMatrix (void) : Array<octave_idx_type> (), _colp (false) { }
+  PermMatrix (void) : Array<octave_idx_type> () { }
 
   PermMatrix (octave_idx_type n);
 
-  PermMatrix (const Array<octave_idx_type>& p, bool colp = false,
-              bool check = true);
+  PermMatrix (const Array<octave_idx_type>& p) GCC_ATTR_DEPRECATED;
+
+  PermMatrix (const Array<octave_idx_type>& p, bool colp, bool check = true);
 
-  PermMatrix (const PermMatrix& m)
-    : Array<octave_idx_type> (m), _colp(m._colp) { }
+  PermMatrix (const PermMatrix& m) : Array<octave_idx_type> (m) { }
 
-  PermMatrix (const idx_vector& idx, bool colp = false, octave_idx_type n = 0);
+  PermMatrix (const idx_vector& idx) GCC_ATTR_DEPRECATED;
+
+  PermMatrix (const idx_vector& idx, bool colp, octave_idx_type n = 0);
 
   octave_idx_type dim1 (void) const
   { return Array<octave_idx_type>::length (); }
@@ -68,15 +69,13 @@
 
   dim_vector dims (void) const { return dim_vector (dim1 (), dim2 ()); }
 
-  Array<octave_idx_type> pvec (void) const
+  const Array<octave_idx_type>& col_perm_vec (void) const
   { return *this; }
 
   octave_idx_type
   elem (octave_idx_type i, octave_idx_type j) const
   {
-    return (_colp
-            ? ((Array<octave_idx_type>::elem (j) == i) ? 1 : 0)
-              : ((Array<octave_idx_type>::elem (i) == j) ? 1 : 0));
+    return (Array<octave_idx_type>::elem (j) == i) ? 1 : 0;
   }
 
   octave_idx_type
@@ -102,20 +101,8 @@
   // Efficient integer power of a permutation.
   PermMatrix power (octave_idx_type n) const;
 
-  bool is_col_perm (void) const { return _colp; }
-  bool is_row_perm (void) const { return !_colp; }
-
-  friend OCTAVE_API PermMatrix operator *(const PermMatrix& a,
-                                          const PermMatrix& b);
-
-  const octave_idx_type *data (void) const
-  { return Array<octave_idx_type>::data (); }
-
-  const octave_idx_type *fortran_vec (void) const
-  { return Array<octave_idx_type>::fortran_vec (); }
-
-  octave_idx_type *fortran_vec (void)
-  { return Array<octave_idx_type>::fortran_vec (); }
+  bool is_col_perm (void) const { return true; }
+  bool is_row_perm (void) const { return false; }
 
   void print_info (std::ostream& os, const std::string& prefix) const
   { Array<octave_idx_type>::print_info (os, prefix); }
@@ -123,12 +110,17 @@
   static PermMatrix eye (octave_idx_type n);
 
 private:
-  bool _colp;
+
+  PermMatrix pos_power (octave_idx_type m) const;
+
+  void setup (const Array<octave_idx_type>& p, bool colp, bool check);
+
+  void setup (const idx_vector& idx, bool colp, octave_idx_type n);
 };
 
 // Multiplying permutations together.
 PermMatrix
 OCTAVE_API
-operator *(const PermMatrix& a, const PermMatrix& b);
+operator * (const PermMatrix& a, const PermMatrix& b);
 
 #endif
--- a/liboctave/array/Sparse.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/Sparse.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -61,18 +61,10 @@
   for (octave_idx_type i = 0; i <= n; i++)
     cidx (i) = i;
 
-  const Array<octave_idx_type> pv = a.pvec ();
-
-  if (a.is_row_perm ())
-    {
-      for (octave_idx_type i = 0; i < n; i++)
-        ridx (pv(i)) = i;
-    }
-  else
-    {
-      for (octave_idx_type i = 0; i < n; i++)
-        ridx (i) = pv(i);
-    }
+  const Array<octave_idx_type> pv = a.col_perm_vec ();
+
+  for (octave_idx_type i = 0; i < n; i++)
+    ridx (i) = pv(i);
 
   for (octave_idx_type i = 0; i < n; i++)
     data (i) = 1.0;
@@ -178,13 +170,13 @@
       octave_idx_type min_nzmx = std::min (nz, nzmx);
 
       octave_idx_type * new_ridx = new octave_idx_type [nz];
-      copy_or_memcpy (min_nzmx, r, new_ridx);
+      std::copy (r, r + min_nzmx, new_ridx);
 
       delete [] r;
       r = new_ridx;
 
       T * new_data = new T [nz];
-      copy_or_memcpy (min_nzmx, d, new_data);
+      std::copy (d, d + min_nzmx, new_data);
 
       delete [] d;
       d = new_data;
@@ -657,7 +649,7 @@
       octave_idx_type len = a.length ();
       octave_idx_type new_nzmx = 0;
 
-      // First count the number of non-zero terms
+      // First count the number of nonzero terms
       for (octave_idx_type i = 0; i < len; i++)
         if (a(i) != T ())
           new_nzmx++;
@@ -827,8 +819,9 @@
 
   if (dims2.length () > 2)
     {
-      (*current_liboctave_warning_handler)
-        ("reshape: sparse reshape to N-d array smashes dims");
+      (*current_liboctave_warning_with_id_handler)
+        ("Octave:reshape-smashes-dims",
+         "reshape: sparse reshape to N-d array smashes dims");
 
       for (octave_idx_type i = 2; i < dims2.length (); i++)
         dims2(1) *= dims2(i);
@@ -986,13 +979,13 @@
   if (c != rep->ncols)
     {
       octave_idx_type *new_cidx = new octave_idx_type [c+1];
-      copy_or_memcpy (std::min (c, rep->ncols)+1, rep->c, new_cidx);
+      std::copy (rep->c, rep->c + std::min (c, rep->ncols) + 1, new_cidx);
       delete [] rep->c;
       rep->c = new_cidx;
 
       if (c > rep->ncols)
-        fill_or_memset (c - rep->ncols, rep->c[rep->ncols],
-                        rep->c + rep->ncols + 1);
+        std::fill_n (rep->c + rep->ncols + 1, c - rep->ncols,
+          rep->c[rep->ncols]);
     }
 
   rep->ncols = dimensions(1) = c;
@@ -1188,9 +1181,9 @@
           // Copy data and adjust indices.
           octave_idx_type nz_new = nz - (ui - li);
           *this = Sparse<T> (nr - (ub - lb), 1, nz_new);
-          copy_or_memcpy (li, tmp.data (), data ());
-          copy_or_memcpy (li, tmp.ridx (), xridx ());
-          copy_or_memcpy (nz - ui, tmp.data () + ui, xdata () + li);
+          std::copy (tmp.data (), tmp.data () + li, data ());
+          std::copy (tmp.ridx (), tmp.ridx () + li, xridx ());
+          std::copy (tmp.data () + ui, tmp.data () + nz, xdata () + li);
           mx_inline_sub (nz - ui, xridx () + li, tmp.ridx () + ui, ub - lb);
           xcidx (1) = nz_new;
         }
@@ -1215,8 +1208,8 @@
             }
 
           *this = Sparse<T> (nr - sl, 1, nz_new);
-          copy_or_memcpy (nz_new, ridx_new, ridx ());
-          copy_or_memcpy (nz_new, data_new, xdata ());
+          std::copy (ridx_new, ridx_new + nz_new, ridx ());
+          std::copy (data_new, data_new + nz_new, xdata ());
           xcidx (1) = nz_new;
         }
     }
@@ -1231,10 +1224,10 @@
           octave_idx_type ubi = tmp.cidx (ub);
           octave_idx_type new_nz = nz - (ubi - lbi);
           *this = Sparse<T> (1, nc - (ub - lb), new_nz);
-          copy_or_memcpy (lbi, tmp.data (), data ());
-          copy_or_memcpy (nz - ubi, tmp.data () + ubi, xdata () + lbi);
-          fill_or_memset (new_nz, static_cast<octave_idx_type> (0), ridx ());
-          copy_or_memcpy (lb, tmp.cidx () + 1, cidx () + 1);
+          std::copy (tmp.data (), tmp.data () + lbi, data ());
+          std::copy (tmp.data () + ubi, tmp.data () + nz , xdata () + lbi);
+          std::fill_n (ridx (), new_nz, static_cast<octave_idx_type> (0));
+          std::copy (tmp.cidx () + 1, tmp.cidx () + 1 + lb, cidx () + 1);
           mx_inline_sub (nc - ub, xcidx () + 1, tmp.cidx () + ub + 1,
                          ubi - lbi);
         }
@@ -1290,11 +1283,11 @@
               octave_idx_type new_nz = nz - (ubi - lbi);
 
               *this = Sparse<T> (nr, nc - (ub - lb), new_nz);
-              copy_or_memcpy (lbi, tmp.data (), data ());
-              copy_or_memcpy (lbi, tmp.ridx (), ridx ());
-              copy_or_memcpy (nz - ubi, tmp.data () + ubi, xdata () + lbi);
-              copy_or_memcpy (nz - ubi, tmp.ridx () + ubi, xridx () + lbi);
-              copy_or_memcpy (lb, tmp.cidx () + 1, cidx () + 1);
+              std::copy (tmp.data (), tmp.data () + lbi, data ());
+              std::copy (tmp.ridx (), tmp.ridx () + lbi, ridx ());
+              std::copy (tmp.data () + ubi, tmp.data () + nz, xdata () + lbi);
+              std::copy (tmp.ridx () + ubi, tmp.ridx () + nz, xridx () + lbi);
+              std::copy (tmp.cidx () + 1, tmp.cidx () + 1 + lb, cidx () + 1);
               mx_inline_sub (nc - ub, xcidx () + lb + 1,
                              tmp.cidx () + ub + 1, ubi - lbi);
             }
@@ -1403,12 +1396,9 @@
 
   octave_idx_type nel = numel (); // Can throw.
 
-  const dim_vector idx_dims = idx.orig_dimensions ();
-
-  if (idx_dims.length () > 2)
-    (*current_liboctave_error_handler)
-      ("cannot index sparse matrix with an N-D Array");
-  else if (idx.is_colon ())
+  const dim_vector idx_dims = idx.orig_dimensions ().redim (2);
+
+  if (idx.is_colon ())
     {
       if (nc == 1)
         retval = *this;
@@ -1475,7 +1465,7 @@
           // Copy data and adjust indices.
           octave_idx_type nz_new = ui - li;
           retval = Sparse<T> (ub - lb, 1, nz_new);
-          copy_or_memcpy (nz_new, data () + li, retval.data ());
+          std::copy (data () + li, data () + li + nz_new, retval.data ());
           mx_inline_sub (nz_new, retval.xridx (), ridx () + li, lb);
           retval.xcidx (1) = nz_new;
         }
@@ -1488,7 +1478,7 @@
               for (octave_idx_type j = 0; j < nz; j++)
                 retval.ridx (j) = nr - ridx (nz - j - 1) - 1;
 
-              copy_or_memcpy (2, cidx (), retval.cidx ());
+              std::copy (cidx (), cidx () + 2, retval.cidx ());
               std::reverse_copy (data (), data () + nz, retval.data ());
             }
           else
@@ -1503,9 +1493,12 @@
           // If indexing a sparse column vector by a vector, the result is a
           // sparse column vector, otherwise it inherits the shape of index.
           // Vector transpose is cheap, so do it right here.
+
+          Array<octave_idx_type> tmp_idx = idx.as_array ().as_matrix ();
+
           const Array<octave_idx_type> idxa = (idx_dims(0) == 1
-                                               ? idx.as_array ().transpose ()
-                                               : idx.as_array ());
+                                               ? tmp_idx.transpose ()
+                                               : tmp_idx);
 
           octave_idx_type new_nr = idxa.rows ();
           octave_idx_type new_nc = idxa.cols ();
@@ -1560,9 +1553,8 @@
           octave_idx_type ubi = cidx (ub);
           octave_idx_type new_nz = ubi - lbi;
           retval = Sparse<T> (1, ub - lb, new_nz);
-          copy_or_memcpy (new_nz, data () + lbi, retval.data ());
-          fill_or_memset (new_nz, static_cast<octave_idx_type> (0),
-                          retval.ridx ());
+          std::copy (data () + lbi, data () + lbi + new_nz, retval.data ());
+          std::fill_n (retval.ridx (), new_nz, static_cast<octave_idx_type> (0));
           mx_inline_sub (ub - lb + 1, retval.cidx (), cidx () + lb, lbi);
         }
       else
@@ -1647,8 +1639,8 @@
           octave_idx_type ubi = cidx (ub);
           octave_idx_type new_nz = ubi - lbi;
           retval = Sparse<T> (nr, ub - lb, new_nz);
-          copy_or_memcpy (new_nz, data () + lbi, retval.data ());
-          copy_or_memcpy (new_nz, ridx () + lbi, retval.ridx ());
+          std::copy (data () + lbi, data () + lbi + new_nz, retval.data ());
+          std::copy (ridx () + lbi, ridx () + lbi + new_nz, retval.ridx ());
           mx_inline_sub (ub - lb + 1, retval.cidx (), cidx () + lb, lbi);
         }
       else
@@ -1670,8 +1662,8 @@
               octave_idx_type lj = retval.xcidx (j);
               octave_idx_type nzj = retval.xcidx (j+1) - lj;
 
-              copy_or_memcpy (nzj, data () + ljj, retval.data () + lj);
-              copy_or_memcpy (nzj, ridx () + ljj, retval.ridx () + lj);
+              std::copy (data () + ljj, data () + ljj + nzj, retval.data () + lj);
+              std::copy (ridx () + ljj, ridx () + ljj + nzj, retval.ridx () + lj);
             }
         }
     }
@@ -1901,7 +1893,7 @@
                     }
 
                   // Copy data and adjust indices from rhs.
-                  copy_or_memcpy (rnz, rhs.data (), data () + li);
+                  std::copy (rhs.data (), rhs.data () + rnz, data () + li);
                   mx_inline_add (rnz, ridx () + li, rhs.ridx (), lb);
                 }
               else
@@ -1912,17 +1904,17 @@
                   *this = Sparse<T> (nr, 1, new_nz);
 
                   // Head ...
-                  copy_or_memcpy (li, tmp.data (), data ());
-                  copy_or_memcpy (li, tmp.ridx (), ridx ());
+                  std::copy (tmp.data (), tmp.data () + li, data ());
+                  std::copy (tmp.ridx (), tmp.ridx () + li, ridx ());
 
                   // new stuff ...
-                  copy_or_memcpy (rnz, rhs.data (), data () + li);
+                  std::copy (rhs.data (), rhs.data () + rnz, data () + li);
                   mx_inline_add (rnz, ridx () + li, rhs.ridx (), lb);
 
                   // ...tail
-                  copy_or_memcpy (nz - ui, tmp.data () + ui,
+                  std::copy (tmp.data () + ui, tmp.data () + nz,
                                   data () + li + rnz);
-                  copy_or_memcpy (nz - ui, tmp.ridx () + ui,
+                  std::copy (tmp.ridx () + ui, tmp.ridx () + nz,
                                   ridx () + li + rnz);
                 }
 
@@ -1958,8 +1950,8 @@
               // Disassembly our matrix...
               Array<octave_idx_type> new_ri (dim_vector (new_nz, 1));
               Array<T> new_data (dim_vector (new_nz, 1));
-              copy_or_memcpy (nz, tmp.ridx (), new_ri.fortran_vec ());
-              copy_or_memcpy (nz, tmp.data (), new_data.fortran_vec ());
+              std::copy (tmp.ridx (), tmp.ridx () + nz, new_ri.fortran_vec ());
+              std::copy (tmp.data (), tmp.data () + nz, new_data.fortran_vec ());
               // ... insert new data (densified) ...
               idx.copy_data (new_ri.fortran_vec () + nz);
               new_data.assign (idx_vector (nz, new_nz), rhs.array_value ());
@@ -2085,8 +2077,8 @@
                     }
 
                   // Copy data and indices from rhs.
-                  copy_or_memcpy (rnz, rhs.data (), data () + li);
-                  copy_or_memcpy (rnz, rhs.ridx (), ridx () + li);
+                  std::copy (rhs.data (), rhs.data () + rnz, data () + li);
+                  std::copy (rhs.ridx (), rhs.ridx () + rnz, ridx () + li);
                   mx_inline_add (ub - lb, cidx () + lb + 1, rhs.cidx () + 1,
                                  li);
 
@@ -2100,20 +2092,20 @@
                   *this = Sparse<T> (nr, nc, new_nz);
 
                   // Head...
-                  copy_or_memcpy (li, tmp.data (), data ());
-                  copy_or_memcpy (li, tmp.ridx (), ridx ());
-                  copy_or_memcpy (lb, tmp.cidx () + 1, cidx () + 1);
+                  std::copy (tmp.data (), tmp.data () + li, data ());
+                  std::copy (tmp.ridx (), tmp.ridx () + li, ridx ());
+                  std::copy (tmp.cidx () + 1, tmp.cidx () + 1 + lb, cidx () + 1);
 
                   // new stuff...
-                  copy_or_memcpy (rnz, rhs.data (), data () + li);
-                  copy_or_memcpy (rnz, rhs.ridx (), ridx () + li);
+                  std::copy (rhs.data (), rhs.data () + rnz, data () + li);
+                  std::copy (rhs.ridx (), rhs.ridx () + rnz, ridx () + li);
                   mx_inline_add (ub - lb, cidx () + lb + 1, rhs.cidx () + 1,
                                  li);
 
                   // ...tail.
-                  copy_or_memcpy (nz - ui, tmp.data () + ui,
+                  std::copy (tmp.data () + ui, tmp.data () + nz,
                                   data () + li + rnz);
-                  copy_or_memcpy (nz - ui, tmp.ridx () + ui,
+                  std::copy (tmp.ridx () + ui, tmp.ridx () + nz,
                                   ridx () + li + rnz);
                   mx_inline_add (nc - ub, cidx () + ub + 1,
                                  tmp.cidx () + ub + 1, new_nz - nz);
@@ -2164,15 +2156,19 @@
                     {
                       // from rhs
                       octave_idx_type k = rhs.cidx (j);
-                      copy_or_memcpy (u - l, rhs.data () + k, xdata () + l);
-                      copy_or_memcpy (u - l, rhs.ridx () + k, xridx () + l);
+                      std::copy (rhs.data () + k, rhs.data () + k + u - l,
+                        xdata () + l);
+                      std::copy (rhs.ridx () + k, rhs.ridx () + k + u - l,
+                        xridx () + l);
                     }
                   else
                     {
                       // original
                       octave_idx_type k = tmp.cidx (i);
-                      copy_or_memcpy (u - l, tmp.data () + k, xdata () + l);
-                      copy_or_memcpy (u - l, tmp.ridx () + k, xridx () + l);
+                      std::copy (tmp.data () + k, tmp.data () + k + u - l,
+                        xdata () + l);
+                      std::copy (tmp.ridx () + k, tmp.ridx () + k + u - l,
+                        xridx () + l);
                     }
                 }
 
@@ -2431,7 +2427,7 @@
         {
           octave_idx_type ndiag = (nnr < nnc) ? nnr : nnc;
 
-          // Count the number of non-zero elements
+          // Count the number of nonzero elements
           octave_idx_type nel = 0;
           if (k > 0)
             {
@@ -2439,7 +2435,7 @@
                 if (elem (i, i+k) != 0.)
                   nel++;
             }
-          else if ( k < 0)
+          else if (k < 0)
             {
               for (octave_idx_type i = 0; i < ndiag; i++)
                 if (elem (i-k, i) != 0.)
@@ -2469,7 +2465,7 @@
                     }
                 }
             }
-          else if ( k < 0)
+          else if (k < 0)
             {
               for (octave_idx_type i = 0; i < ndiag; i++)
                 {
@@ -2495,8 +2491,15 @@
             }
         }
       else
-        (*current_liboctave_error_handler)
-          ("diag: requested diagonal out of range");
+        {
+          // Matlab returns [] 0x1 for out-of-range diagonal
+
+          octave_idx_type nr = 0;
+          octave_idx_type nc = 1;
+          octave_idx_type nz = 0;
+
+          d = Sparse<T> (nr, nc, nz);
+        }
     }
   else if (nnr != 0 && nnc != 0)
     {
--- a/liboctave/array/Sparse.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/Sparse.h	Mon Jan 12 09:17:35 2015 -0800
@@ -38,7 +38,6 @@
 #include "lo-utils.h"
 
 #include "oct-sort.h"
-#include "oct-mem.h"
 
 class idx_vector;
 class PermMatrix;
@@ -102,9 +101,9 @@
         nzmx (a.nzmx), nrows (a.nrows), ncols (a.ncols), count (1)
     {
       octave_idx_type nz = a.nnz ();
-      copy_or_memcpy (nz, a.d, d);
-      copy_or_memcpy (nz, a.r, r);
-      copy_or_memcpy (ncols + 1, a.c, c);
+      std::copy (a.d, a.d + nz, d);
+      std::copy (a.r, a.r + nz, r);
+      std::copy (a.c, a.c + ncols + 1, c);
     }
 
     ~SparseRep (void) { delete [] d; delete [] r; delete [] c; }
@@ -213,8 +212,8 @@
   {
     octave_idx_type nz = a.nnz ();
     std::copy (a.rep->d, a.rep->d + nz, rep->d);
-    copy_or_memcpy (nz, a.rep->r, rep->r);
-    copy_or_memcpy (rep->ncols + 1, a.rep->c, rep->c);
+    std::copy (a.rep->r, a.rep->r + nz, rep->r);
+    std::copy (a.rep->c, a.rep->c + rep->ncols + 1, rep->c);
   }
 
   // No type conversion case.
@@ -242,7 +241,7 @@
   Sparse<T>& operator = (const Sparse<T>& a);
 
   // Note that nzmax and capacity are the amount of storage for
-  // non-zero elements, while nnz is the actual number of non-zero
+  // nonzero elements, while nnz is the actual number of nonzero
   // terms.
   octave_idx_type nzmax (void) const { return rep->length (); }
   octave_idx_type capacity (void) const { return nzmax (); }
--- a/liboctave/array/boolMatrix.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/boolMatrix.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -29,9 +29,9 @@
 #include <iostream>
 
 #include "Array-util.h"
+#include "boolMatrix.h"
 #include "lo-error.h"
 #include "str-vec.h"
-#include "mx-base.h"
 #include "mx-inlines.cc"
 #include "mx-op-defs.h"
 
@@ -84,20 +84,6 @@
   return Array<bool>::diag (k);
 }
 
-// FIXME: Do these really belong here?  Maybe they should be in a base class?
-
-boolMatrix
-boolMatrix::all (int dim) const
-{
-  return do_mx_red_op<bool, bool> (*this, dim, mx_inline_all);
-}
-
-boolMatrix
-boolMatrix::any (int dim) const
-{
-  return do_mx_red_op<bool, bool> (*this, dim, mx_inline_any);
-}
-
 MM_BOOL_OPS (boolMatrix, boolMatrix)
 MS_BOOL_OPS (boolMatrix, bool)
 SM_BOOL_OPS (bool, boolMatrix)
--- a/liboctave/array/boolMatrix.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/boolMatrix.h	Mon Jan 12 09:17:35 2015 -0800
@@ -25,37 +25,33 @@
 #define octave_boolMatrix_h 1
 
 #include "Array.h"
+#include "boolNDArray.h"
 
 #include "mx-defs.h"
 #include "mx-op-decl.h"
 
 class
 OCTAVE_API
-boolMatrix : public Array<bool>
+boolMatrix : public boolNDArray
 {
 public:
 
-  boolMatrix (void) : Array<bool> () { }
+  boolMatrix (void) : boolNDArray () { }
 
   boolMatrix (octave_idx_type r, octave_idx_type c)
-    : Array<bool> (dim_vector (r, c)) { }
+    : boolNDArray (dim_vector (r, c)) { }
 
   boolMatrix (octave_idx_type r, octave_idx_type c, bool val)
-    : Array<bool> (dim_vector (r, c), val) { }
-
-  boolMatrix (const dim_vector& dv) : Array<bool> (dv) { }
+    : boolNDArray (dim_vector (r, c), val) { }
 
-  boolMatrix (const dim_vector& dv, bool val) : Array<bool> (dv, val) { }
-
-  boolMatrix (const Array<bool>& a) : Array<bool> (a.as_matrix ()) { }
+  boolMatrix (const dim_vector& dv) : boolNDArray (dv.redim (2)) { }
 
-  boolMatrix (const boolMatrix& a) : Array<bool> (a) { }
+  boolMatrix (const dim_vector& dv, bool val)
+    : boolNDArray (dv.redim (2), val) { }
 
-  boolMatrix& operator = (const boolMatrix& a)
-  {
-    Array<bool>::operator = (a);
-    return *this;
-  }
+  boolMatrix (const Array<bool>& a) : boolNDArray (a.as_matrix ()) { }
+
+  boolMatrix (const boolMatrix& a) : boolNDArray (a) { }
 
   bool operator == (const boolMatrix& a) const;
   bool operator != (const boolMatrix& a) const;
@@ -75,9 +71,6 @@
 
   boolMatrix diag (octave_idx_type k = 0) const;
 
-  boolMatrix all (int dim = -1) const;
-  boolMatrix any (int dim = -1) const;
-
 #if 0
   // i/o
 
--- a/liboctave/array/boolNDArray.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/boolNDArray.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -27,6 +27,7 @@
 #endif
 
 #include "Array-util.h"
+#include "boolNDArray.h"
 #include "CNDArray.h"
 #include "mx-base.h"
 #include "lo-ieee.h"
@@ -106,14 +107,6 @@
   return *this;
 }
 
-
-
-boolMatrix
-boolNDArray::matrix_value (void) const
-{
-  return *this;
-}
-
 void
 boolNDArray::increment_index (Array<octave_idx_type>& ra_idx,
                               const dim_vector& dimensions,
--- a/liboctave/array/boolNDArray.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/boolNDArray.h	Mon Jan 12 09:17:35 2015 -0800
@@ -29,9 +29,6 @@
 #include "mx-op-decl.h"
 #include "bsxfun-decl.h"
 
-#include "boolMatrix.h"
-
-
 class
 OCTAVE_API
 boolNDArray : public Array<bool>
@@ -49,8 +46,6 @@
 
   boolNDArray (const boolNDArray& a) : Array<bool> (a) { }
 
-  boolNDArray (const boolMatrix& a) : Array<bool> (a) { }
-
   boolNDArray (const Array<bool>& a) : Array<bool> (a) { }
 
   boolNDArray& operator = (const boolNDArray& a)
@@ -83,8 +78,6 @@
   boolNDArray& insert (const boolNDArray& a,
                        const Array<octave_idx_type>& ra_idx);
 
-  boolMatrix matrix_value (void) const;
-
   boolNDArray squeeze (void) const { return Array<bool>::squeeze (); }
 
   static void increment_index (Array<octave_idx_type>& ra_idx,
--- a/liboctave/array/boolSparse.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/boolSparse.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -35,9 +35,10 @@
 
 #include "boolSparse.h"
 #include "dSparse.h"
-#include "oct-mem.h"
 #include "oct-locbuf.h"
 
+#include "Sparse-op-defs.h"
+
 // SparseBoolMatrix class.
 
 bool
@@ -158,8 +159,8 @@
         retval.xcidx (i+1) = retval.xcidx (i) + (cidx (i+1) > cidx (i));
       octave_idx_type new_nz = retval.xcidx (nc);
       retval.change_capacity (new_nz);
-      fill_or_memset (new_nz, static_cast<octave_idx_type> (0), retval.ridx ());
-      fill_or_memset (new_nz, true, retval.data ());
+      std::fill_n (retval.ridx (), new_nz, static_cast<octave_idx_type> (0));
+      std::fill_n (retval.data (), new_nz, true);
     }
   else if (dim == 1)
     {
@@ -175,7 +176,7 @@
       else
         {
           Array<octave_idx_type> tmp (dim_vector (nz, 1));
-          copy_or_memcpy (nz, ridx (), tmp.fortran_vec ());
+          std::copy (ridx (), ridx () + nz, tmp.fortran_vec ());
           retval = Sparse<bool> (Array<bool> (dim_vector (1, 1), true),
                                  idx_vector (tmp),
                                  idx_vector (static_cast<octave_idx_type> (0)),
@@ -204,7 +205,7 @@
         retval.xcidx (i+1) = retval.xcidx (i) + (cidx (i+1) > cidx (i));
       octave_idx_type new_nz = retval.xcidx (nc);
       retval.change_capacity (new_nz);
-      fill_or_memset (new_nz, static_cast<octave_idx_type> (0), retval.ridx ());
+      std::fill_n (retval.ridx (), new_nz, static_cast<octave_idx_type> (0));
       for (octave_idx_type i = 0, k = 0; i < nc; i++)
         {
           octave_idx_type c = cidx (i+1) - cidx (i);
@@ -226,7 +227,7 @@
       else
         {
           Array<octave_idx_type> tmp (dim_vector (nz, 1));
-          copy_or_memcpy (nz, ridx (), tmp.fortran_vec ());
+          std::copy (ridx (), ridx () + nz, tmp.fortran_vec ());
           retval = Sparse<double> (Array<double> (dim_vector (1, 1), 1.0),
                                    idx_vector (tmp),
                                    idx_vector (static_cast<octave_idx_type> (0)),
--- a/liboctave/array/boolSparse.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/boolSparse.h	Mon Jan 12 09:17:35 2015 -0800
@@ -26,7 +26,12 @@
 
 #include "Sparse.h"
 #include "MSparse-defs.h"
-#include "Sparse-op-defs.h"
+
+#include "boolMatrix.h"
+#include "boolNDArray.h"
+#include "PermMatrix.h"
+
+#include "Sparse-op-decls.h"
 
 class SparseMatrix;
 
--- a/liboctave/array/chMatrix.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/chMatrix.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -39,55 +39,6 @@
 
 // charMatrix class.
 
-charMatrix::charMatrix (char c)
-  : Array<char> ()
-{
-  octave_idx_type nc = 1;
-  octave_idx_type nr = 1;
-
-  resize (nr, nc);
-
-  elem (0, 0) = c;
-}
-
-charMatrix::charMatrix (const char *s)
-  : Array<char> ()
-{
-  octave_idx_type nc = s ? strlen (s) : 0;
-  octave_idx_type nr = s && nc > 0 ? 1 : 0;
-
-  resize (nr, nc);
-
-  for (octave_idx_type i = 0; i < nc; i++)
-    elem (0, i) = s[i];
-}
-
-charMatrix::charMatrix (const std::string& s)
-  : Array<char> ()
-{
-  octave_idx_type nc = s.length ();
-  octave_idx_type nr = nc > 0 ? 1 : 0;
-
-  resize (nr, nc);
-
-  for (octave_idx_type i = 0; i < nc; i++)
-    elem (0, i) = s[i];
-}
-
-charMatrix::charMatrix (const string_vector& s, char fill_value)
-  : Array<char> (dim_vector (s.length (), s.max_length ()), fill_value)
-{
-  octave_idx_type nr = rows ();
-
-  for (octave_idx_type i = 0; i < nr; i++)
-    {
-      const std::string si = s(i);
-      octave_idx_type nc = si.length ();
-      for (octave_idx_type j = 0; j < nc; j++)
-        elem (i, j) = si[j];
-    }
-}
-
 bool
 charMatrix::operator == (const charMatrix& a) const
 {
@@ -185,26 +136,6 @@
   return result;
 }
 
-charMatrix
-charMatrix::diag (octave_idx_type k) const
-{
-  return Array<char>::diag (k);
-}
-
-// FIXME: Do these really belong here?  Maybe they should be in a base class?
-
-boolMatrix
-charMatrix::all (int dim) const
-{
-  return do_mx_red_op<bool, char> (*this, dim, mx_inline_all);
-}
-
-boolMatrix
-charMatrix::any (int dim) const
-{
-  return do_mx_red_op<bool, char> (*this, dim, mx_inline_any);
-}
-
 MS_CMP_OPS (charMatrix, char)
 MS_BOOL_OPS (charMatrix, char)
 
--- a/liboctave/array/chMatrix.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/chMatrix.h	Mon Jan 12 09:17:35 2015 -0800
@@ -27,6 +27,7 @@
 #include <string>
 
 #include "Array.h"
+#include "chNDArray.h"
 
 #include "mx-defs.h"
 #include "mx-op-decl.h"
@@ -34,41 +35,37 @@
 
 class
 OCTAVE_API
-charMatrix : public Array<char>
+charMatrix : public charNDArray
 {
   friend class ComplexMatrix;
 
 public:
 
-  charMatrix (void) : Array<char> () { }
+  charMatrix (void) : charNDArray () { }
 
   charMatrix (octave_idx_type r, octave_idx_type c)
-    : Array<char> (dim_vector (r, c)) { }
+    : charNDArray (dim_vector (r, c)) { }
 
   charMatrix (octave_idx_type r, octave_idx_type c, char val)
-    : Array<char> (dim_vector (r, c), val) { }
+    : charNDArray (dim_vector (r, c), val) { }
 
-  charMatrix (const dim_vector& dv) : Array<char> (dv) { }
-
-  charMatrix (const dim_vector& dv, char val) : Array<char> (dv, val) { }
+  charMatrix (const dim_vector& dv) : charNDArray (dv.redim (2)) { }
 
-  charMatrix (const Array<char>& a) : Array<char> (a.as_matrix ()) { }
+  charMatrix (const dim_vector& dv, char val)
+    : charNDArray (dv.redim (2), val) { }
 
-  charMatrix (const charMatrix& a) : Array<char> (a) { }
-
-  charMatrix (char c);
+  charMatrix (const Array<char>& a) : charNDArray (a.as_matrix ()) { }
 
-  charMatrix (const char *s);
+  charMatrix (const charMatrix& a) : charNDArray (a) { }
 
-  charMatrix (const std::string& s);
-
-  charMatrix (const string_vector& s, char fill_value = '\0');
+  charMatrix (char c) : charNDArray (c) {}
 
-  charMatrix& operator = (const charMatrix& a)
-  {
-    Array<char>::operator = (a);
-    return *this;
-  }
+  charMatrix (const char *s) : charNDArray (s) {}
+
+  charMatrix (const std::string& s) : charNDArray (s) {}
+
+  charMatrix (const string_vector& s, char fill_value = '\0')
+    : charNDArray (s, fill_value) {}
 
   bool operator == (const charMatrix& a) const;
   bool operator != (const charMatrix& a) const;
@@ -93,11 +90,6 @@
     Array<char>::resize (dim_vector (nr, nc), rfv);
   }
 
-  charMatrix diag (octave_idx_type k = 0) const;
-
-  boolMatrix all (int dim = -1) const;
-  boolMatrix any (int dim = -1) const;
-
 #if 0
   // i/o
 
--- a/liboctave/array/chNDArray.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/chNDArray.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -25,15 +25,64 @@
 #include <config.h>
 #endif
 
+#include <string>
+
 #include "Array-util.h"
 #include "chNDArray.h"
 #include "mx-base.h"
 #include "lo-ieee.h"
 #include "lo-mappers.h"
 #include "mx-op-defs.h"
+#include "str-vec.h"
 
 #include "bsxfun-defs.cc"
 
+charNDArray::charNDArray (char c)
+  : Array<char> ()
+{
+  octave_idx_type n = 1;
+
+  resize1 (n);
+
+  elem (0) = c;
+}
+
+charNDArray::charNDArray (const char *s)
+  : Array<char> ()
+{
+  octave_idx_type n = s ? strlen (s) : 0;
+
+  resize1 (n);
+
+  for (octave_idx_type i = 0; i < n; i++)
+    elem (i) = s[i];
+}
+
+charNDArray::charNDArray (const std::string& s)
+  : Array<char> ()
+{
+  octave_idx_type n = s.length ();
+
+  resize1 (n);
+
+  for (octave_idx_type i = 0; i < n; i++)
+    elem (i) = s[i];
+}
+
+charNDArray::charNDArray (const string_vector& s, char fill_value)
+  : Array<char> (dim_vector (s.length (), s.max_length ()), fill_value)
+{
+  octave_idx_type nr = rows ();
+
+  for (octave_idx_type i = 0; i < nr; i++)
+    {
+      const std::string si = s(i);
+      octave_idx_type nc = si.length ();
+      for (octave_idx_type j = 0; j < nc; j++)
+        elem (i, j) = si[j];
+    }
+}
+
 // FIXME: this is not quite the right thing.
 
 boolNDArray
@@ -130,12 +179,6 @@
   return *this;
 }
 
-charMatrix
-charNDArray::matrix_value (void) const
-{
-  return *this;
-}
-
 void
 charNDArray::increment_index (Array<octave_idx_type>& ra_idx,
                               const dim_vector& dimensions,
--- a/liboctave/array/chNDArray.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/chNDArray.h	Mon Jan 12 09:17:35 2015 -0800
@@ -23,12 +23,14 @@
 #if !defined (octave_chNDArray_h)
 #define octave_chNDArray_h 1
 
+#include <string>
+
 #include "Array.h"
-#include "chMatrix.h"
 
 #include "mx-defs.h"
 #include "mx-op-decl.h"
 #include "bsxfun-decl.h"
+#include "str-vec.h"
 
 class
 OCTAVE_API
@@ -46,17 +48,15 @@
 
   charNDArray (const charNDArray& a) : Array<char> (a) { }
 
-  charNDArray (const charMatrix& a) : Array<char> (a) { }
+  charNDArray (const Array<char>& a) : Array<char> (a) { }
 
-  charNDArray (char c) : Array<char> (charMatrix (c)) { }
-
-  charNDArray (const char *s) : Array<char> (charMatrix (s)) { }
+  charNDArray (char c);
 
-  charNDArray (const std::string& s) : Array<char> (charMatrix (s)) { }
+  charNDArray (const char *s);
 
-  charNDArray (const string_vector& s) : Array<char> (charMatrix (s)) { }
+  charNDArray (const std::string& s);
 
-  charNDArray (const Array<char>& a) : Array<char> (a) { }
+  charNDArray (const string_vector& s, char fill_value = '\0');
 
   charNDArray& operator = (const charNDArray& a)
   {
@@ -84,8 +84,6 @@
   charNDArray& insert (const charNDArray& a,
                        const Array<octave_idx_type>& ra_idx);
 
-  charMatrix matrix_value (void) const;
-
   charNDArray squeeze (void) const { return Array<char>::squeeze (); }
 
   static void increment_index (Array<octave_idx_type>& ra_idx,
--- a/liboctave/array/dDiagMatrix.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/dDiagMatrix.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -292,7 +292,7 @@
 }
 
 DiagMatrix
-DiagMatrix::pseudo_inverse (void) const
+DiagMatrix::pseudo_inverse (double tol) const
 {
   octave_idx_type r = rows ();
   octave_idx_type c = cols ();
@@ -302,10 +302,11 @@
 
   for (octave_idx_type i = 0; i < len; i++)
     {
-      if (elem (i, i) != 0.0)
+      double val = std::abs (elem (i, i));
+      if (val < tol || val == 0.0)
+        retval.elem (i, i) = 0.0;
+      else
         retval.elem (i, i) = 1.0 / elem (i, i);
-      else
-        retval.elem (i, i) = 0.0;
     }
 
   return retval;
--- a/liboctave/array/dDiagMatrix.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/dDiagMatrix.h	Mon Jan 12 09:17:35 2015 -0800
@@ -98,7 +98,7 @@
 
   DiagMatrix inverse (void) const;
   DiagMatrix inverse (octave_idx_type& info) const;
-  DiagMatrix pseudo_inverse (void) const;
+  DiagMatrix pseudo_inverse (double tol = 0.0) const;
 
   // other operations
 
--- a/liboctave/array/dMatrix.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/dMatrix.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -34,8 +34,15 @@
 
 #include "Array-util.h"
 #include "byte-swap.h"
+#include "boolMatrix.h"
+#include "chMatrix.h"
 #include "dMatrix.h"
-#include "dbleAEPBAL.h"
+#include "dDiagMatrix.h"
+#include "CMatrix.h"
+#include "dColVector.h"
+#include "dRowVector.h"
+#include "CColVector.h"
+#include "PermMatrix.h"
 #include "DET.h"
 #include "dbleSCHUR.h"
 #include "dbleSVD.h"
@@ -47,7 +54,6 @@
 #include "lo-ieee.h"
 #include "lo-mappers.h"
 #include "lo-utils.h"
-#include "mx-base.h"
 #include "mx-m-dm.h"
 #include "mx-dm-m.h"
 #include "mx-inlines.cc"
@@ -240,44 +246,54 @@
 // Matrix class.
 
 Matrix::Matrix (const RowVector& rv)
-  : MArray<double> (rv)
+  : NDArray (rv)
 {
 }
 
 Matrix::Matrix (const ColumnVector& cv)
-  : MArray<double> (cv)
+  : NDArray (cv)
 {
 }
 
 Matrix::Matrix (const DiagMatrix& a)
-  : MArray<double> (a.dims (), 0.0)
+  : NDArray (a.dims (), 0.0)
+{
+  for (octave_idx_type i = 0; i < a.length (); i++)
+    elem (i, i) = a.elem (i, i);
+}
+
+Matrix::Matrix (const MDiagArray2<double>& a)
+  : NDArray (a.dims (), 0.0)
+{
+  for (octave_idx_type i = 0; i < a.length (); i++)
+    elem (i, i) = a.elem (i, i);
+}
+
+Matrix::Matrix (const DiagArray2<double>& a)
+  : NDArray (a.dims (), 0.0)
 {
   for (octave_idx_type i = 0; i < a.length (); i++)
     elem (i, i) = a.elem (i, i);
 }
 
 Matrix::Matrix (const PermMatrix& a)
-  : MArray<double> (a.dims (), 0.0)
+  : NDArray (a.dims (), 0.0)
 {
-  const Array<octave_idx_type> ia (a.pvec ());
+  const Array<octave_idx_type> ia (a.col_perm_vec ());
   octave_idx_type len = a.rows ();
-  if (a.is_col_perm ())
-    for (octave_idx_type i = 0; i < len; i++)
-      elem (ia(i), i) = 1.0;
-  else
-    for (octave_idx_type i = 0; i < len; i++)
-      elem (i, ia(i)) = 1.0;
+  for (octave_idx_type i = 0; i < len; i++)
+    elem (ia(i), i) = 1.0;
 }
 
 // FIXME: could we use a templated mixed-type copy function here?
 
 Matrix::Matrix (const boolMatrix& a)
-  : MArray<double> (a)
+  : NDArray (a)
 {
 }
 
 Matrix::Matrix (const charMatrix& a)
-  : MArray<double> (a.dims ())
+  : NDArray (a.dims ())
 {
   for (octave_idx_type i = 0; i < a.rows (); i++)
     for (octave_idx_type j = 0; j < a.cols (); j++)
@@ -1382,7 +1398,7 @@
 double
 Matrix::rcond (MatrixType &mattype) const
 {
-  double rcon;
+  double rcon = octave_NaN;
   octave_idx_type nr = rows ();
   octave_idx_type nc = cols ();
 
@@ -1577,11 +1593,27 @@
             {
               const double *tmp_data = fortran_vec ();
 
+              retval = b;
+              double *result = retval.fortran_vec ();
+
+              char uplo = 'U';
+              char trans = get_blas_char (transt);
+              char dia = 'N';
+
+              F77_XFCN (dtrtrs, DTRTRS, (F77_CONST_CHAR_ARG2 (&uplo, 1),
+                                         F77_CONST_CHAR_ARG2 (&trans, 1),
+                                         F77_CONST_CHAR_ARG2 (&dia, 1),
+                                         nr, b_nc, tmp_data, nr,
+                                         result, nr, info
+                                         F77_CHAR_ARG_LEN (1)
+                                         F77_CHAR_ARG_LEN (1)
+                                         F77_CHAR_ARG_LEN (1)));
+
               if (calc_cond)
                 {
                   char norm = '1';
-                  char uplo = 'U';
-                  char dia = 'N';
+                  uplo = 'U';
+                  dia = 'N';
 
                   Array<double> z (dim_vector (3 * nc, 1));
                   double *pz = z.fortran_vec ();
@@ -1609,30 +1641,9 @@
                       if (sing_handler)
                         sing_handler (rcon);
                       else
-                        (*current_liboctave_error_handler)
-                          ("matrix singular to machine precision, rcond = %g",
-                           rcon);
+                        gripe_singular_matrix (rcon);
                     }
                 }
-
-              if (info == 0)
-                {
-                  retval = b;
-                  double *result = retval.fortran_vec ();
-
-                  char uplo = 'U';
-                  char trans = get_blas_char (transt);
-                  char dia = 'N';
-
-                  F77_XFCN (dtrtrs, DTRTRS, (F77_CONST_CHAR_ARG2 (&uplo, 1),
-                                             F77_CONST_CHAR_ARG2 (&trans, 1),
-                                             F77_CONST_CHAR_ARG2 (&dia, 1),
-                                             nr, b_nc, tmp_data, nr,
-                                             result, nr, info
-                                             F77_CHAR_ARG_LEN (1)
-                                             F77_CHAR_ARG_LEN (1)
-                                             F77_CHAR_ARG_LEN (1)));
-                }
             }
         }
       else
@@ -1677,11 +1688,27 @@
             {
               const double *tmp_data = fortran_vec ();
 
+              retval = b;
+              double *result = retval.fortran_vec ();
+
+              char uplo = 'L';
+              char trans = get_blas_char (transt);
+              char dia = 'N';
+
+              F77_XFCN (dtrtrs, DTRTRS, (F77_CONST_CHAR_ARG2 (&uplo, 1),
+                                         F77_CONST_CHAR_ARG2 (&trans, 1),
+                                         F77_CONST_CHAR_ARG2 (&dia, 1),
+                                         nr, b_nc, tmp_data, nr,
+                                         result, nr, info
+                                         F77_CHAR_ARG_LEN (1)
+                                         F77_CHAR_ARG_LEN (1)
+                                         F77_CHAR_ARG_LEN (1)));
+
               if (calc_cond)
                 {
                   char norm = '1';
-                  char uplo = 'L';
-                  char dia = 'N';
+                  uplo = 'L';
+                  dia = 'N';
 
                   Array<double> z (dim_vector (3 * nc, 1));
                   double *pz = z.fortran_vec ();
@@ -1709,30 +1736,9 @@
                       if (sing_handler)
                         sing_handler (rcon);
                       else
-                        (*current_liboctave_error_handler)
-                          ("matrix singular to machine precision, rcond = %g",
-                           rcon);
+                        gripe_singular_matrix (rcon);
                     }
                 }
-
-              if (info == 0)
-                {
-                  retval = b;
-                  double *result = retval.fortran_vec ();
-
-                  char uplo = 'L';
-                  char trans = get_blas_char (transt);
-                  char dia = 'N';
-
-                  F77_XFCN (dtrtrs, DTRTRS, (F77_CONST_CHAR_ARG2 (&uplo, 1),
-                                             F77_CONST_CHAR_ARG2 (&trans, 1),
-                                             F77_CONST_CHAR_ARG2 (&dia, 1),
-                                             nr, b_nc, tmp_data, nr,
-                                             result, nr, info
-                                             F77_CHAR_ARG_LEN (1)
-                                             F77_CHAR_ARG_LEN (1)
-                                             F77_CHAR_ARG_LEN (1)));
-                }
             }
         }
       else
@@ -1813,9 +1819,7 @@
                       if (sing_handler)
                         sing_handler (rcon);
                       else
-                        (*current_liboctave_error_handler)
-                          ("matrix singular to machine precision, rcond = %g",
-                           rcon);
+                        gripe_singular_matrix (rcon);
                     }
                 }
 
@@ -1868,8 +1872,7 @@
               if (sing_handler)
                 sing_handler (rcon);
               else
-                (*current_liboctave_error_handler)
-                  ("matrix singular to machine precision");
+                gripe_singular_matrix ();
 
               mattype.mark_as_rectangular ();
             }
@@ -1897,9 +1900,7 @@
                       if (sing_handler)
                         sing_handler (rcon);
                       else
-                        (*current_liboctave_error_handler)
-                          ("matrix singular to machine precision, rcond = %g",
-                           rcon);
+                        gripe_singular_matrix (rcon);
                     }
                 }
 
@@ -1962,9 +1963,9 @@
 
   // Only calculate the condition number for LU/Cholesky
   if (typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper)
-    retval = utsolve (mattype, b, info, rcon, sing_handler, false, transt);
+    retval = utsolve (mattype, b, info, rcon, sing_handler, true, transt);
   else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower)
-    retval = ltsolve (mattype, b, info, rcon, sing_handler, false, transt);
+    retval = ltsolve (mattype, b, info, rcon, sing_handler, true, transt);
   else if (transt == blas_trans || transt == blas_conj_trans)
     return transpose ().solve (mattype, b, info, rcon, sing_handler,
                                singular_fallback);
@@ -2630,15 +2631,6 @@
 
 // unary operations
 
-boolMatrix
-Matrix::operator ! (void) const
-{
-  if (any_element_is_nan ())
-    gripe_nan_to_logical_conversion ();
-
-  return do_mx_unary_op<bool, double> (*this, mx_inline_not);
-}
-
 // column vector by row vector -> matrix operations
 
 Matrix
@@ -2668,137 +2660,60 @@
 
 // other operations.
 
-bool
-Matrix::any_element_is_negative (bool neg_zero) const
-{
-  return (neg_zero ? test_all (xnegative_sign)
-          : do_mx_check<double> (*this, mx_inline_any_negative));
-}
-
-bool
-Matrix::any_element_is_positive (bool neg_zero) const
-{
-  return (neg_zero ? test_all (xpositive_sign)
-          : do_mx_check<double> (*this, mx_inline_any_positive));
-}
-
-bool
-Matrix::any_element_is_nan (void) const
-{
-  return do_mx_check<double> (*this, mx_inline_any_nan);
-}
-
-bool
-Matrix::any_element_is_inf_or_nan (void) const
-{
-  return ! do_mx_check<double> (*this, mx_inline_all_finite);
-}
-
-bool
-Matrix::any_element_not_one_or_zero (void) const
-{
-  return ! test_all (xis_one_or_zero);
-}
-
-bool
-Matrix::all_elements_are_int_or_inf_or_nan (void) const
-{
-  return test_all (xis_int_or_inf_or_nan);
-}
-
-// Return nonzero if any element of M is not an integer.  Also extract
-// the largest and smallest values and return them in MAX_VAL and MIN_VAL.
-
-bool
-Matrix::all_integers (double& max_val, double& min_val) const
-{
-  octave_idx_type nel = nelem ();
-
-  if (nel > 0)
-    {
-      max_val = elem (0);
-      min_val = elem (0);
-    }
-  else
-    return false;
-
-  for (octave_idx_type i = 0; i < nel; i++)
-    {
-      double val = elem (i);
-
-      if (val > max_val)
-        max_val = val;
-
-      if (val < min_val)
-        min_val = val;
-
-      if (! xisinteger (val))
-        return false;
-    }
-
-  return true;
-}
-
-bool
-Matrix::too_large_for_float (void) const
-{
-  return test_any (xtoo_large_for_float);
-}
-
 // FIXME: Do these really belong here?  Maybe they should be in a base class?
 
 boolMatrix
 Matrix::all (int dim) const
 {
-  return do_mx_red_op<bool, double> (*this, dim, mx_inline_all);
+  return NDArray::all (dim);
 }
 
 boolMatrix
 Matrix::any (int dim) const
 {
-  return do_mx_red_op<bool, double> (*this, dim, mx_inline_any);
+  return NDArray::any (dim);
 }
 
 Matrix
 Matrix::cumprod (int dim) const
 {
-  return do_mx_cum_op<double, double> (*this, dim, mx_inline_cumprod);
+  return NDArray::cumprod (dim);
 }
 
 Matrix
 Matrix::cumsum (int dim) const
 {
-  return do_mx_cum_op<double, double> (*this, dim, mx_inline_cumsum);
+  return NDArray::cumsum (dim);
 }
 
 Matrix
 Matrix::prod (int dim) const
 {
-  return do_mx_red_op<double, double> (*this, dim, mx_inline_prod);
+  return NDArray::prod (dim);
 }
 
 Matrix
 Matrix::sum (int dim) const
 {
-  return do_mx_red_op<double, double> (*this, dim, mx_inline_sum);
+  return NDArray::sum (dim);
 }
 
 Matrix
 Matrix::sumsq (int dim) const
 {
-  return do_mx_red_op<double, double> (*this, dim, mx_inline_sumsq);
+  return NDArray::sumsq (dim);
 }
 
 Matrix
 Matrix::abs (void) const
 {
-  return do_mx_unary_map<double, double, std::abs> (*this);
+  return NDArray::abs ();
 }
 
 Matrix
 Matrix::diag (octave_idx_type k) const
 {
-  return MArray<double>::diag (k);
+  return NDArray::diag (k);
 }
 
 DiagMatrix
@@ -3139,7 +3054,7 @@
 
   // FIXME: check info?
 
-  retval = -ua*cx*ub.transpose ();
+  retval = ua*cx*ub.transpose ();
 
   return retval;
 }
--- a/liboctave/array/dMatrix.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/dMatrix.h	Mon Jan 12 09:17:35 2015 -0800
@@ -23,6 +23,7 @@
 #if !defined (octave_dMatrix_h)
 #define octave_dMatrix_h 1
 
+#include "dNDArray.h"
 #include "MArray.h"
 #include "MDiagArray2.h"
 #include "MatrixType.h"
@@ -33,7 +34,7 @@
 
 class
 OCTAVE_API
-Matrix : public MArray<double>
+Matrix : public NDArray
 {
 public:
 
@@ -42,26 +43,26 @@
 
   typedef void (*solve_singularity_handler) (double rcon);
 
-  Matrix (void) : MArray<double> () { }
+  Matrix (void) : NDArray () { }
 
   Matrix (octave_idx_type r, octave_idx_type c)
-    : MArray<double> (dim_vector (r, c)) { }
+    : NDArray (dim_vector (r, c)) { }
 
   Matrix (octave_idx_type r, octave_idx_type c, double val)
-    : MArray<double> (dim_vector (r, c), val) { }
+    : NDArray (dim_vector (r, c), val) { }
 
-  Matrix (const dim_vector& dv) : MArray<double> (dv.redim (2)) { }
+  Matrix (const dim_vector& dv) : NDArray (dv.redim (2)) { }
 
   Matrix (const dim_vector& dv, double val)
-    : MArray<double> (dv.redim (2), val) { }
+    : NDArray (dv.redim (2), val) { }
 
-  Matrix (const Matrix& a) : MArray<double> (a) { }
+  Matrix (const Matrix& a) : NDArray (a) { }
 
   template <class U>
-  Matrix (const MArray<U>& a) : MArray<double> (a.as_matrix ()) { }
+  Matrix (const MArray<U>& a) : NDArray (a.as_matrix ()) { }
 
   template <class U>
-  Matrix (const Array<U>& a) : MArray<double> (a.as_matrix ()) { }
+  Matrix (const Array<U>& a) : NDArray (a.as_matrix ()) { }
 
   explicit Matrix (const RowVector& rv);
 
@@ -69,18 +70,16 @@
 
   explicit Matrix (const DiagMatrix& a);
 
+  explicit Matrix (const MDiagArray2<double>& a);
+
+  explicit Matrix (const DiagArray2<double>& a);
+
   explicit Matrix (const PermMatrix& a);
 
   explicit Matrix (const boolMatrix& a);
 
   explicit Matrix (const charMatrix& a);
 
-  Matrix& operator = (const Matrix& a)
-  {
-    MArray<double>::operator = (a);
-    return *this;
-  }
-
   bool operator == (const Matrix& a) const;
   bool operator != (const Matrix& a) const;
 
@@ -303,19 +302,8 @@
 
   // unary operations
 
-  boolMatrix operator ! (void) const;
-
   // other operations
 
-  bool any_element_is_negative (bool = false) const;
-  bool any_element_is_positive (bool = false) const;
-  bool any_element_is_nan (void) const;
-  bool any_element_is_inf_or_nan (void) const;
-  bool any_element_not_one_or_zero (void) const;
-  bool all_elements_are_int_or_inf_or_nan (void) const;
-  bool all_integers (double& max_val, double& min_val) const;
-  bool too_large_for_float (void) const;
-
   boolMatrix all (int dim = -1) const;
   boolMatrix any (int dim = -1) const;
 
--- a/liboctave/array/dNDArray.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/dNDArray.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -257,7 +257,7 @@
   ComplexNDArray retval (dv);
   octave_idx_type npts = dv(dim);
   octave_idx_type nn = 4*npts+15;
-  Array<Complex> wsave (nn);
+  Array<Complex> wsave (dim_vector (nn, 1));
   Complex *pwsave = wsave.fortran_vec ();
 
   OCTAVE_LOCAL_BUFFER (Complex, tmp, npts);
@@ -304,7 +304,7 @@
   ComplexNDArray retval (dv);
   octave_idx_type npts = dv(dim);
   octave_idx_type nn = 4*npts+15;
-  Array<Complex> wsave (nn);
+  Array<Complex> wsave (dim_vector (nn, 1));
   Complex *pwsave = wsave.fortran_vec ();
 
   OCTAVE_LOCAL_BUFFER (Complex, tmp, npts);
@@ -354,9 +354,9 @@
     {
       octave_idx_type npts = dv2(i);
       octave_idx_type nn = 4*npts+15;
-      Array<Complex> wsave (nn);
+      Array<Complex> wsave (dim_vector (nn, 1));
       Complex *pwsave = wsave.fortran_vec ();
-      Array<Complex> row (npts);
+      Array<Complex> row (dim_vector (npts, 1));
       Complex *prow = row.fortran_vec ();
 
       octave_idx_type howmany = numel () / npts;
@@ -402,9 +402,9 @@
     {
       octave_idx_type npts = dv2(i);
       octave_idx_type nn = 4*npts+15;
-      Array<Complex> wsave (nn);
+      Array<Complex> wsave (dim_vector (nn, 1));
       Complex *pwsave = wsave.fortran_vec ();
-      Array<Complex> row (npts);
+      Array<Complex> row (dim_vector (npts, 1));
       Complex *prow = row.fortran_vec ();
 
       octave_idx_type howmany = numel () / npts;
@@ -450,9 +450,9 @@
     {
       octave_idx_type npts = dv(i);
       octave_idx_type nn = 4*npts+15;
-      Array<Complex> wsave (nn);
+      Array<Complex> wsave (dim_vector (nn, 1));
       Complex *pwsave = wsave.fortran_vec ();
-      Array<Complex> row (npts);
+      Array<Complex> row (dim_vector (npts, 1));
       Complex *prow = row.fortran_vec ();
 
       octave_idx_type howmany = numel () / npts;
@@ -497,9 +497,9 @@
     {
       octave_idx_type npts = dv(i);
       octave_idx_type nn = 4*npts+15;
-      Array<Complex> wsave (nn);
+      Array<Complex> wsave (dim_vector (nn, 1));
       Complex *pwsave = wsave.fortran_vec ();
-      Array<Complex> row (npts);
+      Array<Complex> row (dim_vector (npts, 1));
       Complex *prow = row.fortran_vec ();
 
       octave_idx_type howmany = numel () / npts;
@@ -841,20 +841,6 @@
   return do_mx_unary_map<bool, double, xfinite> (*this);
 }
 
-Matrix
-NDArray::matrix_value (void) const
-{
-  Matrix retval;
-
-  if (ndims () == 2)
-    retval = Matrix (Array<double> (*this));
-  else
-    (*current_liboctave_error_handler)
-      ("invalid conversion of NDArray to Matrix");
-
-  return retval;
-}
-
 void
 NDArray::increment_index (Array<octave_idx_type>& ra_idx,
                           const dim_vector& dimensions,
--- a/liboctave/array/dNDArray.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/dNDArray.h	Mon Jan 12 09:17:35 2015 -0800
@@ -24,7 +24,6 @@
 #define octave_dNDArray_h 1
 
 #include "MArray.h"
-#include "dMatrix.h"
 #include "intNDArray.h"
 
 #include "mx-defs.h"
@@ -37,8 +36,6 @@
 {
 public:
 
-  typedef Matrix matrix_type;
-
   NDArray (void) : MArray<double> () { }
 
   NDArray (const dim_vector& dv) : MArray<double> (dv) { }
@@ -48,8 +45,6 @@
 
   NDArray (const NDArray& a) : MArray<double> (a) { }
 
-  NDArray (const Matrix& a) : MArray<double> (a) { }
-
   NDArray (const Array<octave_idx_type>& a, bool zero_based = false,
            bool negative_to_nan = false);
 
@@ -141,8 +136,6 @@
 
   friend class ComplexNDArray;
 
-  Matrix matrix_value (void) const;
-
   NDArray squeeze (void) const { return MArray<double>::squeeze (); }
 
   static void increment_index (Array<octave_idx_type>& ra_idx,
--- a/liboctave/array/dSparse.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/dSparse.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -52,6 +52,8 @@
 #include "SparsedbleCHOL.h"
 #include "SparseQR.h"
 
+#include "Sparse-op-defs.h"
+
 #include "Sparse-diag-op-defs.h"
 
 #include "Sparse-perm-op-defs.h"
@@ -777,7 +779,7 @@
               octave_idx_type  jb_max = y.cidx (i+1);
               bool jb_lt_max = jb < jb_max;
 
-              while (ja_lt_max || jb_lt_max )
+              while (ja_lt_max || jb_lt_max)
                 {
                   octave_quit ();
                   if ((! jb_lt_max) ||
@@ -789,8 +791,8 @@
                       ja++;
                       ja_lt_max= ja < ja_max;
                     }
-                  else if (( !ja_lt_max ) ||
-                           (jb_lt_max && (y.ridx (jb) < x.ridx (ja)) ) )
+                  else if ((! ja_lt_max) ||
+                           (jb_lt_max && (y.ridx (jb) < x.ridx (ja))))
                     {
                       jb++;
                       jb_lt_max= jb < jb_max;
@@ -1216,7 +1218,6 @@
             {
               // Matrix is either singular or not positive definite
               mattype.mark_as_unsymmetric ();
-              typ = MatrixType::Full;
             }
         }
 
@@ -1885,9 +1886,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("SparseMatrix::solve matrix singular to machine precision, rcond = %g",
-                   rcond);
+                gripe_singular_matrix (rcond);
             }
 
           volatile double rcond_plus_one = rcond + 1.0;
@@ -1902,9 +1901,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("matrix singular to machine precision, rcond = %g",
-                   rcond);
+                gripe_singular_matrix (rcond);
             }
         }
       else
@@ -2005,7 +2002,7 @@
                         }
                     }
 
-                  // Count non-zeros in work vector and adjust space in
+                  // Count nonzeros in work vector and adjust space in
                   // retval if needed
                   octave_idx_type new_nnz = 0;
                   for (octave_idx_type i = 0; i < nc; i++)
@@ -2101,7 +2098,7 @@
                         }
                     }
 
-                  // Count non-zeros in work vector and adjust space in
+                  // Count nonzeros in work vector and adjust space in
                   // retval if needed
                   octave_idx_type new_nnz = 0;
                   for (octave_idx_type i = 0; i < nc; i++)
@@ -2173,9 +2170,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("SparseMatrix::solve matrix singular to machine precision, rcond = %g",
-                   rcond);
+                gripe_singular_matrix (rcond);
             }
 
           volatile double rcond_plus_one = rcond + 1.0;
@@ -2190,9 +2185,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("matrix singular to machine precision, rcond = %g",
-                   rcond);
+                gripe_singular_matrix (rcond);
             }
         }
       else
@@ -2410,9 +2403,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("SparseMatrix::solve matrix singular to machine precision, rcond = %g",
-                   rcond);
+                gripe_singular_matrix (rcond);
             }
 
           volatile double rcond_plus_one = rcond + 1.0;
@@ -2427,9 +2418,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("matrix singular to machine precision, rcond = %g",
-                   rcond);
+                gripe_singular_matrix (rcond);
             }
         }
       else
@@ -2530,7 +2519,7 @@
                         }
                     }
 
-                  // Count non-zeros in work vector and adjust space in
+                  // Count nonzeros in work vector and adjust space in
                   // retval if needed
                   octave_idx_type new_nnz = 0;
                   for (octave_idx_type i = 0; i < nc; i++)
@@ -2627,7 +2616,7 @@
                         }
                     }
 
-                  // Count non-zeros in work vector and adjust space in
+                  // Count nonzeros in work vector and adjust space in
                   // retval if needed
                   octave_idx_type new_nnz = 0;
                   for (octave_idx_type i = 0; i < nc; i++)
@@ -2700,9 +2689,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("SparseMatrix::solve matrix singular to machine precision, rcond = %g",
-                   rcond);
+                gripe_singular_matrix (rcond);
             }
 
           volatile double rcond_plus_one = rcond + 1.0;
@@ -2717,9 +2704,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("matrix singular to machine precision, rcond = %g",
-                   rcond);
+                gripe_singular_matrix (rcond);
             }
         }
       else
@@ -2960,9 +2945,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("SparseMatrix::solve matrix singular to machine precision, rcond = %g",
-                   rcond);
+                gripe_singular_matrix (rcond);
             }
 
           volatile double rcond_plus_one = rcond + 1.0;
@@ -2977,9 +2960,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("matrix singular to machine precision, rcond = %g",
-                   rcond);
+                gripe_singular_matrix (rcond);
             }
         }
       else
@@ -3085,7 +3066,7 @@
                         }
                     }
 
-                  // Count non-zeros in work vector and adjust space in
+                  // Count nonzeros in work vector and adjust space in
                   // retval if needed
                   octave_idx_type new_nnz = 0;
                   for (octave_idx_type i = 0; i < nc; i++)
@@ -3194,7 +3175,7 @@
                         }
                     }
 
-                  // Count non-zeros in work vector and adjust space in
+                  // Count nonzeros in work vector and adjust space in
                   // retval if needed
                   octave_idx_type new_nnz = 0;
                   for (octave_idx_type i = 0; i < nc; i++)
@@ -3267,9 +3248,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("SparseMatrix::solve matrix singular to machine precision, rcond = %g",
-                   rcond);
+                gripe_singular_matrix (rcond);
             }
 
           volatile double rcond_plus_one = rcond + 1.0;
@@ -3284,9 +3263,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("matrix singular to machine precision, rcond = %g",
-                   rcond);
+                gripe_singular_matrix (rcond);
             }
         }
       else
@@ -3528,9 +3505,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("SparseMatrix::solve matrix singular to machine precision, rcond = %g",
-                   rcond);
+                gripe_singular_matrix (rcond);
             }
 
           volatile double rcond_plus_one = rcond + 1.0;
@@ -3545,9 +3520,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("matrix singular to machine precision, rcond = %g",
-                   rcond);
+                gripe_singular_matrix (rcond);
             }
         }
       else
@@ -3653,7 +3626,7 @@
                         }
                     }
 
-                  // Count non-zeros in work vector and adjust space in
+                  // Count nonzeros in work vector and adjust space in
                   // retval if needed
                   octave_idx_type new_nnz = 0;
                   for (octave_idx_type i = 0; i < nc; i++)
@@ -3763,7 +3736,7 @@
                         }
                     }
 
-                  // Count non-zeros in work vector and adjust space in
+                  // Count nonzeros in work vector and adjust space in
                   // retval if needed
                   octave_idx_type new_nnz = 0;
                   for (octave_idx_type i = 0; i < nc; i++)
@@ -3837,9 +3810,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("SparseMatrix::solve matrix singular to machine precision, rcond = %g",
-                   rcond);
+                gripe_singular_matrix (rcond);
             }
 
           volatile double rcond_plus_one = rcond + 1.0;
@@ -3854,9 +3825,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("matrix singular to machine precision, rcond = %g",
-                   rcond);
+                gripe_singular_matrix (rcond);
             }
         }
       else
@@ -4003,9 +3972,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("matrix singular to machine precision");
-
+                gripe_singular_matrix ();
             }
           else
             rcond = 1.;
@@ -4101,9 +4068,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("matrix singular to machine precision");
-
+                gripe_singular_matrix ();
             }
           else
             {
@@ -4130,7 +4095,7 @@
                              work, b.rows (), err
                              F77_CHAR_ARG_LEN (1)));
 
-                  // Count non-zeros in work vector and adjust
+                  // Count nonzeros in work vector and adjust
                   // space in retval if needed
                   octave_idx_type new_nnz = 0;
                   for (octave_idx_type i = 0; i < nr; i++)
@@ -4305,8 +4270,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("matrix singular to machine precision");
+                gripe_singular_matrix ();
             }
         }
       else if (typ != MatrixType::Tridiagonal_Hermitian)
@@ -4400,8 +4364,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("matrix singular to machine precision");
+                gripe_singular_matrix ();
             }
           else
             {
@@ -4412,7 +4375,7 @@
               OCTAVE_LOCAL_BUFFER (double, Bx, b_nr);
               OCTAVE_LOCAL_BUFFER (double, Bz, b_nr);
 
-              // Take a first guess that the number of non-zero terms
+              // Take a first guess that the number of nonzero terms
               // will be as many as in b
               volatile octave_idx_type x_nz = b.nnz ();
               volatile octave_idx_type ii = 0;
@@ -4459,7 +4422,7 @@
                       break;
                     }
 
-                  // Count non-zeros in work vector and adjust
+                  // Count nonzeros in work vector and adjust
                   // space in retval if needed
                   octave_idx_type new_nnz = 0;
                   for (octave_idx_type i = 0; i < nr; i++)
@@ -4591,9 +4554,7 @@
                           mattype.mark_as_rectangular ();
                         }
                       else
-                        (*current_liboctave_error_handler)
-                          ("matrix singular to machine precision, rcond = %g",
-                           rcond);
+                        gripe_singular_matrix (rcond);
                     }
                 }
               else
@@ -4646,7 +4607,7 @@
               m_band(ridx (i) - j + n_lower + n_upper, j) = data (i);
 
           // Calculate the norm of the matrix, for later use.
-          double anorm;
+          double anorm = 0.0;
           if (calc_cond)
             {
               for (octave_idx_type j = 0; j < nr; j++)
@@ -4678,9 +4639,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("matrix singular to machine precision");
-
+                gripe_singular_matrix ();
             }
           else
             {
@@ -4713,9 +4672,7 @@
                           mattype.mark_as_rectangular ();
                         }
                       else
-                        (*current_liboctave_error_handler)
-                          ("matrix singular to machine precision, rcond = %g",
-                           rcond);
+                        gripe_singular_matrix (rcond);
                     }
                 }
               else
@@ -4839,9 +4796,7 @@
                           mattype.mark_as_rectangular ();
                         }
                       else
-                        (*current_liboctave_error_handler)
-                          ("matrix singular to machine precision, rcond = %g",
-                           rcond);
+                        gripe_singular_matrix (rcond);
                     }
                 }
               else
@@ -4853,7 +4808,7 @@
                   octave_idx_type b_nc = b.cols ();
                   OCTAVE_LOCAL_BUFFER (double, Bx, b_nr);
 
-                  // Take a first guess that the number of non-zero terms
+                  // Take a first guess that the number of nonzero terms
                   // will be as many as in b
                   volatile octave_idx_type x_nz = b.nnz ();
                   volatile octave_idx_type ii = 0;
@@ -4959,9 +4914,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("matrix singular to machine precision");
-
+                gripe_singular_matrix ();
             }
           else
             {
@@ -4994,9 +4947,7 @@
                           mattype.mark_as_rectangular ();
                         }
                       else
-                        (*current_liboctave_error_handler)
-                          ("matrix singular to machine precision, rcond = %g",
-                           rcond);
+                        gripe_singular_matrix (rcond);
                     }
                 }
               else
@@ -5027,7 +4978,7 @@
                                  ldm, pipvt, work, b.rows (), err
                                  F77_CHAR_ARG_LEN (1)));
 
-                      // Count non-zeros in work vector and adjust
+                      // Count nonzeros in work vector and adjust
                       // space in retval if needed
                       octave_idx_type new_nnz = 0;
                       for (octave_idx_type i = 0; i < nr; i++)
@@ -5159,9 +5110,7 @@
                           mattype.mark_as_rectangular ();
                         }
                       else
-                        (*current_liboctave_error_handler)
-                          ("matrix singular to machine precision, rcond = %g",
-                           rcond);
+                        gripe_singular_matrix (rcond);
                     }
                 }
               else
@@ -5275,9 +5224,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("matrix singular to machine precision");
-
+                gripe_singular_matrix ();
             }
           else
             {
@@ -5310,9 +5257,7 @@
                           mattype.mark_as_rectangular ();
                         }
                       else
-                        (*current_liboctave_error_handler)
-                          ("matrix singular to machine precision, rcond = %g",
-                           rcond);
+                        gripe_singular_matrix (rcond);
                     }
                 }
               else
@@ -5459,9 +5404,7 @@
                           mattype.mark_as_rectangular ();
                         }
                       else
-                        (*current_liboctave_error_handler)
-                          ("matrix singular to machine precision, rcond = %g",
-                           rcond);
+                        gripe_singular_matrix (rcond);
                     }
                 }
               else
@@ -5474,7 +5417,7 @@
                   OCTAVE_LOCAL_BUFFER (double, Bx, b_nr);
                   OCTAVE_LOCAL_BUFFER (double, Bz, b_nr);
 
-                  // Take a first guess that the number of non-zero terms
+                  // Take a first guess that the number of nonzero terms
                   // will be as many as in b
                   volatile octave_idx_type x_nz = b.nnz ();
                   volatile octave_idx_type ii = 0;
@@ -5520,7 +5463,7 @@
                           break;
                         }
 
-                      // Count non-zeros in work vector and adjust
+                      // Count nonzeros in work vector and adjust
                       // space in retval if needed
                       octave_idx_type new_nnz = 0;
                       for (octave_idx_type i = 0; i < nr; i++)
@@ -5605,9 +5548,7 @@
                   mattype.mark_as_rectangular ();
                 }
               else
-                (*current_liboctave_error_handler)
-                  ("matrix singular to machine precision");
-
+                gripe_singular_matrix ();
             }
           else
             {
@@ -5640,9 +5581,7 @@
                           mattype.mark_as_rectangular ();
                         }
                       else
-                        (*current_liboctave_error_handler)
-                          ("matrix singular to machine precision, rcond = %g",
-                           rcond);
+                        gripe_singular_matrix (rcond);
                     }
                 }
               else
@@ -5687,7 +5626,7 @@
                                  ldm, pipvt, Bz, b.rows (), err
                                  F77_CHAR_ARG_LEN (1)));
 
-                      // Count non-zeros in work vector and adjust
+                      // Count nonzeros in work vector and adjust
                       // space in retval if needed
                       octave_idx_type new_nnz = 0;
                       for (octave_idx_type i = 0; i < nr; i++)
@@ -5804,10 +5743,7 @@
           if (sing_handler)
             sing_handler (rcond);
           else
-            (*current_liboctave_error_handler)
-              ("SparseMatrix::solve matrix singular to machine precision, rcond = %g",
-               rcond);
-
+            gripe_singular_matrix (rcond);
         }
       else if (status < 0)
         {
@@ -5872,17 +5808,17 @@
           if (spu == 0.)
             {
               cm->print = -1;
-              cm->print_function = 0;
+              SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, 0);
             }
           else
             {
               cm->print = static_cast<int> (spu) + 2;
-              cm->print_function =&SparseCholPrint;
+              SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, &SparseCholPrint);
             }
 
           cm->error_handler = &SparseCholError;
-          cm->complex_divide = CHOLMOD_NAME(divcomplex);
-          cm->hypotenuse = CHOLMOD_NAME(hypot);
+          SUITESPARSE_ASSIGN_FPTR2 (divcomplex_func, cm->complex_divide, divcomplex);
+          SUITESPARSE_ASSIGN_FPTR2 (hypot_func, cm->hypotenuse, hypot);
 
           cm->final_ll = true;
 
@@ -5957,9 +5893,7 @@
                       mattype.mark_as_rectangular ();
                     }
                   else
-                    (*current_liboctave_error_handler)
-                      ("SparseMatrix::solve matrix singular to machine precision, rcond = %g",
-                       rcond);
+                    gripe_singular_matrix (rcond);
 
                   return retval;
                 }
@@ -5986,8 +5920,8 @@
               END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
             }
 #else
-          (*current_liboctave_warning_handler)
-            ("CHOLMOD not installed");
+          (*current_liboctave_warning_with_id_handler)
+            ("Octave:missing-dependency", "CHOLMOD not installed");
 
           mattype.mark_as_unsymmetric ();
           typ = MatrixType::Full;
@@ -6089,17 +6023,17 @@
           if (spu == 0.)
             {
               cm->print = -1;
-              cm->print_function = 0;
+              SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, 0);
             }
           else
             {
               cm->print = static_cast<int> (spu) + 2;
-              cm->print_function =&SparseCholPrint;
+              SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, &SparseCholPrint);
             }
 
           cm->error_handler = &SparseCholError;
-          cm->complex_divide = CHOLMOD_NAME(divcomplex);
-          cm->hypotenuse = CHOLMOD_NAME(hypot);
+          SUITESPARSE_ASSIGN_FPTR2 (divcomplex_func, cm->complex_divide, divcomplex);
+          SUITESPARSE_ASSIGN_FPTR2 (hypot_func, cm->hypotenuse, hypot);
 
           cm->final_ll = true;
 
@@ -6183,9 +6117,7 @@
                       mattype.mark_as_rectangular ();
                     }
                   else
-                    (*current_liboctave_error_handler)
-                      ("SparseMatrix::solve matrix singular to machine precision, rcond = %g",
-                       rcond);
+                    gripe_singular_matrix (rcond);
 
                   return retval;
                 }
@@ -6217,8 +6149,8 @@
               END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
             }
 #else
-          (*current_liboctave_warning_handler)
-            ("CHOLMOD not installed");
+          (*current_liboctave_warning_with_id_handler)
+            ("Octave:missing-dependency", "CHOLMOD not installed");
 
           mattype.mark_as_unsymmetric ();
           typ = MatrixType::Full;
@@ -6246,7 +6178,7 @@
               OCTAVE_LOCAL_BUFFER (double, Bx, b_nr);
               OCTAVE_LOCAL_BUFFER (double, Xx, b_nr);
 
-              // Take a first guess that the number of non-zero terms
+              // Take a first guess that the number of nonzero terms
               // will be as many as in b
               octave_idx_type x_nz = b.nnz ();
               octave_idx_type ii = 0;
@@ -6351,17 +6283,17 @@
           if (spu == 0.)
             {
               cm->print = -1;
-              cm->print_function = 0;
+              SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, 0);
             }
           else
             {
               cm->print = static_cast<int> (spu) + 2;
-              cm->print_function =&SparseCholPrint;
+              SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, &SparseCholPrint);
             }
 
           cm->error_handler = &SparseCholError;
-          cm->complex_divide = CHOLMOD_NAME(divcomplex);
-          cm->hypotenuse = CHOLMOD_NAME(hypot);
+          SUITESPARSE_ASSIGN_FPTR2 (divcomplex_func, cm->complex_divide, divcomplex);
+          SUITESPARSE_ASSIGN_FPTR2 (hypot_func, cm->hypotenuse, hypot);
 
           cm->final_ll = true;
 
@@ -6435,9 +6367,7 @@
                       mattype.mark_as_rectangular ();
                     }
                   else
-                    (*current_liboctave_error_handler)
-                      ("SparseMatrix::solve matrix singular to machine precision, rcond = %g",
-                       rcond);
+                    gripe_singular_matrix (rcond);
 
                   return retval;
                 }
@@ -6464,8 +6394,8 @@
               END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
             }
 #else
-          (*current_liboctave_warning_handler)
-            ("CHOLMOD not installed");
+          (*current_liboctave_warning_with_id_handler)
+            ("Octave:missing-dependency", "CHOLMOD not installed");
 
           mattype.mark_as_unsymmetric ();
           typ = MatrixType::Full;
@@ -6585,17 +6515,17 @@
           if (spu == 0.)
             {
               cm->print = -1;
-              cm->print_function = 0;
+              SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, 0);
             }
           else
             {
               cm->print = static_cast<int> (spu) + 2;
-              cm->print_function =&SparseCholPrint;
+              SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, &SparseCholPrint);
             }
 
           cm->error_handler = &SparseCholError;
-          cm->complex_divide = CHOLMOD_NAME(divcomplex);
-          cm->hypotenuse = CHOLMOD_NAME(hypot);
+          SUITESPARSE_ASSIGN_FPTR2 (divcomplex_func, cm->complex_divide, divcomplex);
+          SUITESPARSE_ASSIGN_FPTR2 (hypot_func, cm->hypotenuse, hypot);
 
           cm->final_ll = true;
 
@@ -6679,9 +6609,7 @@
                       mattype.mark_as_rectangular ();
                     }
                   else
-                    (*current_liboctave_error_handler)
-                      ("SparseMatrix::solve matrix singular to machine precision, rcond = %g",
-                       rcond);
+                    gripe_singular_matrix (rcond);
 
                   return retval;
                 }
@@ -6714,8 +6642,8 @@
               END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
             }
 #else
-          (*current_liboctave_warning_handler)
-            ("CHOLMOD not installed");
+          (*current_liboctave_warning_with_id_handler)
+            ("Octave:missing-dependency", "CHOLMOD not installed");
 
           mattype.mark_as_unsymmetric ();
           typ = MatrixType::Full;
@@ -6743,7 +6671,7 @@
               OCTAVE_LOCAL_BUFFER (double, Bx, b_nr);
               OCTAVE_LOCAL_BUFFER (double, Bz, b_nr);
 
-              // Take a first guess that the number of non-zero terms
+              // Take a first guess that the number of nonzero terms
               // will be as many as in b
               octave_idx_type x_nz = b.nnz ();
               octave_idx_type ii = 0;
@@ -7743,7 +7671,7 @@
 
   EMPTY_RETURN_CHECK (SparseMatrix);
 
-  // Count the number of non-zero elements
+  // Count the number of nonzero elements
   if (d < 0.)
     {
       result = SparseMatrix (nr, nc, d);
@@ -7801,84 +7729,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;
 }
@@ -7893,7 +7822,7 @@
 
   EMPTY_RETURN_CHECK (SparseMatrix);
 
-  // Count the number of non-zero elements
+  // Count the number of nonzero elements
   if (d > 0.)
     {
       result = SparseMatrix (nr, nc, d);
@@ -7951,84 +7880,85 @@
 {
   SparseMatrix r;
 
-  if ((a.rows () == b.rows ()) && (a.cols () == b.cols ()))
+  octave_idx_type a_nr = a.rows ();
+  octave_idx_type a_nc = a.cols ();
+  octave_idx_type b_nr = b.rows ();
+  octave_idx_type b_nc = b.cols ();
+
+  if (a_nr == b_nr && a_nc == b_nc)
     {
-      octave_idx_type a_nr = a.rows ();
-      octave_idx_type a_nc = a.cols ();
-
-      octave_idx_type b_nr = b.rows ();
-      octave_idx_type b_nc = b.cols ();
-
-      if (a_nr != b_nr || a_nc != b_nc)
-        gripe_nonconformant ("min", a_nr, a_nc, b_nr, b_nc);
-      else
+      r = SparseMatrix (a_nr, a_nc, (a.nnz () + b.nnz ()));
+
+      octave_idx_type jx = 0;
+      r.cidx (0) = 0;
+      for (octave_idx_type i = 0 ; i < a_nc ; i++)
         {
-          r = SparseMatrix (a_nr, a_nc, (a.nnz () + b.nnz ()));
-
-          octave_idx_type jx = 0;
-          r.cidx (0) = 0;
-          for (octave_idx_type i = 0 ; i < a_nc ; i++)
-            {
-              octave_idx_type  ja = a.cidx (i);
-              octave_idx_type  ja_max = a.cidx (i+1);
-              bool ja_lt_max= ja < ja_max;
-
-              octave_idx_type  jb = b.cidx (i);
-              octave_idx_type  jb_max = b.cidx (i+1);
-              bool jb_lt_max = jb < jb_max;
-
-              while (ja_lt_max || jb_lt_max )
-                {
-                  octave_quit ();
-                  if ((! jb_lt_max) ||
-                      (ja_lt_max && (a.ridx (ja) < b.ridx (jb))))
+          octave_idx_type  ja = a.cidx (i);
+          octave_idx_type  ja_max = a.cidx (i+1);
+          bool ja_lt_max= ja < ja_max;
+
+          octave_idx_type  jb = b.cidx (i);
+          octave_idx_type  jb_max = b.cidx (i+1);
+          bool jb_lt_max = jb < jb_max;
+
+          while (ja_lt_max || jb_lt_max)
+            {
+              octave_quit ();
+              if ((! jb_lt_max) ||
+                  (ja_lt_max && (a.ridx (ja) < b.ridx (jb))))
+                {
+                  double tmp = xmax (a.data (ja), 0.);
+                  if (tmp != 0.)
                     {
-                      double tmp = xmax (a.data (ja), 0.);
-                      if (tmp != 0.)
-                        {
-                          r.ridx (jx) = a.ridx (ja);
-                          r.data (jx) = tmp;
-                          jx++;
-                        }
-                      ja++;
-                      ja_lt_max= ja < ja_max;
+                      r.ridx (jx) = a.ridx (ja);
+                      r.data (jx) = tmp;
+                      jx++;
                     }
-                  else if (( !ja_lt_max ) ||
-                           (jb_lt_max && (b.ridx (jb) < a.ridx (ja)) ) )
+                  ja++;
+                  ja_lt_max= ja < ja_max;
+                }
+              else if ((! ja_lt_max) ||
+                       (jb_lt_max && (b.ridx (jb) < a.ridx (ja))))
+                {
+                  double tmp = xmax (0., b.data (jb));
+                  if (tmp != 0.)
                     {
-                      double tmp = xmax (0., b.data (jb));
-                      if (tmp != 0.)
-                        {
-                          r.ridx (jx) = b.ridx (jb);
-                          r.data (jx) = tmp;
-                          jx++;
-                        }
-                      jb++;
-                      jb_lt_max= jb < jb_max;
+                      r.ridx (jx) = b.ridx (jb);
+                      r.data (jx) = tmp;
+                      jx++;
                     }
-                  else
+                  jb++;
+                  jb_lt_max= jb < jb_max;
+                }
+              else
+                {
+                  double tmp = xmax (a.data (ja), b.data (jb));
+                  if (tmp != 0.)
                     {
-                      double tmp = xmax (a.data (ja), b.data (jb));
-                      if (tmp != 0.)
-                        {
-                          r.data (jx) = tmp;
-                          r.ridx (jx) = a.ridx (ja);
-                          jx++;
-                        }
-                      ja++;
-                      ja_lt_max= ja < ja_max;
-                      jb++;
-                      jb_lt_max= jb < jb_max;
+                      r.data (jx) = tmp;
+                      r.ridx (jx) = a.ridx (ja);
+                      jx++;
                     }
-                }
-              r.cidx (i+1) = jx;
-            }
-
-          r.maybe_compress ();
+                  ja++;
+                  ja_lt_max= ja < ja_max;
+                  jb++;
+                  jb_lt_max= jb < jb_max;
+                }
+            }
+          r.cidx (i+1) = jx;
         }
+
+      r.maybe_compress ();
     }
   else
-    (*current_liboctave_error_handler) ("matrix size mismatch");
+    {
+      if (a_nr == 0 || a_nc == 0)
+        r.resize (a_nr, a_nc);
+      else if (b_nr == 0 || b_nc == 0)
+        r.resize (b_nr, b_nc);
+      else
+        gripe_nonconformant ("max", a_nr, a_nc, b_nr, b_nc);
+    }
 
   return r;
 }
--- a/liboctave/array/dSparse.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/dSparse.h	Mon Jan 12 09:17:35 2015 -0800
@@ -33,7 +33,9 @@
 #include "DET.h"
 #include "MSparse.h"
 #include "MSparse-defs.h"
-#include "Sparse-op-defs.h"
+
+#include "Sparse-op-decls.h"
+
 #include "MatrixType.h"
 
 class PermMatrix;
--- a/liboctave/array/dim-vector.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/dim-vector.h	Mon Jan 12 09:17:35 2015 -0800
@@ -62,7 +62,7 @@
 
   octave_idx_type& count (void) const { return rep[-2]; }
 
-  // Construct a new rep with count = 1 and ndims given.
+  //! Construct a new rep with count = 1 and ndims given.
 
   static octave_idx_type *newrep (int ndims)
   {
@@ -74,7 +74,7 @@
     return r;
   }
 
-  // Clone this->rep.
+  //! Clone this->rep.
 
   octave_idx_type *clonerep (void)
   {
@@ -91,7 +91,7 @@
     return r;
   }
 
-  // Clone and resize this->rep to length n, filling by given value.
+  //! Clone and resize this->rep to length n, filling by given value.
 
   octave_idx_type *resizerep (int n, octave_idx_type fill_value)
   {
@@ -117,7 +117,7 @@
     return r;
   }
 
-  // Free the rep.
+  //! Free the rep.
 
   void freerep (void)
   {
@@ -140,27 +140,6 @@
 
 public:
 
-  // The constructor
-  //
-  //   dim_vector (n)
-  //
-  // creates an dimension vector with N rows and 1 column.  It is
-  // deprecated because of the potentiol for confusion that it causes.
-  // Additional constructors of the form
-  //
-  //   dim_vector (r, c)
-  //   dim_vector (r, c, p)
-  //   dim_vector (d1, d2, d3, d4, ...)
-  //
-  // are available for up to 7 dimensions.
-
-  explicit dim_vector (octave_idx_type n) GCC_ATTR_DEPRECATED
-    : rep (newrep (2))
-  {
-    rep[0] = n;
-    rep[1] = 1;
-  }
-
 #define ASSIGN_REP(i) rep[i] = d ## i;
 #define DIM_VECTOR_CTOR(N) \
   dim_vector (OCT_MAKE_DECL_LIST (octave_idx_type, d, N)) \
@@ -337,9 +316,12 @@
     return (num_ones () == length ());
   }
 
-  // Return the number of elements that a matrix with this dimension
-  // vector would have, NOT the number of dimensions (elements in the
-  // dimension vector).
+  //! Number of elements that a matrix with this dimensions would have.
+   /*!
+      Return the number of elements that a matrix with this dimension
+      vector would have, NOT the number of dimensions (elements in the
+      dimension vector).
+  */
 
   octave_idx_type numel (int n = 0) const
   {
@@ -353,13 +335,15 @@
     return retval;
   }
 
-  // The following function will throw a std::bad_alloc ()
-  // exception if the requested size is larger than can be indexed by
-  // octave_idx_type. This may be smaller than the actual amount of
-  // memory that can be safely allocated on a system.  However, if we
-  // don't fail here, we can end up with a mysterious crash inside a
-  // function that is iterating over an array using octave_idx_type
-  // indices.
+   /*!
+      The following function will throw a std::bad_alloc ()
+      exception if the requested size is larger than can be indexed by
+      octave_idx_type. This may be smaller than the actual amount of
+      memory that can be safely allocated on a system.  However, if we
+      don't fail here, we can end up with a mysterious crash inside a
+      function that is iterating over an array using octave_idx_type
+      indices.
+  */
 
   octave_idx_type safe_numel (void) const;
 
@@ -377,18 +361,19 @@
 
   dim_vector squeeze (void) const;
 
-  // This corresponds to cat().
+  //! This corresponds to cat().
   bool concat (const dim_vector& dvb, int dim);
 
-  // This corresponds to [,] (horzcat, dim = 0) and [;] (vertcat, dim = 1).
+  //! This corresponds to [,] (horzcat, dim = 0) and [;] (vertcat, dim = 1).
   // The rules are more relaxed here.
   bool hvcat (const dim_vector& dvb, int dim);
 
-  // Force certain dimensionality, preserving numel ().  Missing
-  // dimensions are set to 1, redundant are folded into the trailing
-  // one.  If n = 1, the result is 2d and the second dim is 1
-  // (dim_vectors are always at least 2D).
-
+  /*!
+      Force certain dimensionality, preserving numel ().  Missing
+      dimensions are set to 1, redundant are folded into the trailing
+      one.  If n = 1, the result is 2d and the second dim is 1
+      (dim_vectors are always at least 2D).
+  */
   dim_vector redim (int n) const;
 
   dim_vector as_column (void) const
@@ -423,7 +408,7 @@
     return def;
   }
 
-  // Compute a linear index from an index tuple.
+  //! Compute a linear index from an index tuple.
 
   octave_idx_type compute_index (const octave_idx_type *idx) const
   {
@@ -434,7 +419,7 @@
     return k;
   }
 
-  // Ditto, but the tuple may be incomplete (nidx < length ()).
+  //! Ditto, but the tuple may be incomplete (nidx < length ()).
 
   octave_idx_type compute_index (const octave_idx_type *idx, int nidx) const
   {
@@ -445,9 +430,11 @@
     return k;
   }
 
-  // Increment a multi-dimensional index tuple, optionally starting
-  // from an offset position and return the index of the last index
-  // position that was changed, or length () if just cycled over.
+  /*/!
+      Increment a multi-dimensional index tuple, optionally starting
+      from an offset position and return the index of the last index
+      position that was changed, or length () if just cycled over.
+  */
 
   int increment_index (octave_idx_type *idx, int start = 0) const
   {
@@ -462,7 +449,7 @@
     return i;
   }
 
-  // Return cumulative dimensions.
+  //! Return cumulative dimensions.
 
   dim_vector cumulative (void) const
   {
@@ -476,8 +463,8 @@
     return retval;
   }
 
-  // Compute a linear index from an index tuple.  Dimensions are
-  // required to be cumulative.
+  //! Compute a linear index from an index tuple.  Dimensions are
+  //! required to be cumulative.
 
   octave_idx_type cum_compute_index (const octave_idx_type *idx) const
   {
--- a/liboctave/array/fCDiagMatrix.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/fCDiagMatrix.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -387,7 +387,7 @@
 }
 
 FloatComplexDiagMatrix
-FloatComplexDiagMatrix::pseudo_inverse (void) const
+FloatComplexDiagMatrix::pseudo_inverse (float tol) const
 {
   octave_idx_type r = rows ();
   octave_idx_type c = cols ();
@@ -397,10 +397,11 @@
 
   for (octave_idx_type i = 0; i < len; i++)
     {
-      if (elem (i, i) != 0.0f)
+      float val = std::abs (elem (i, i));
+      if (val < tol || val == 0.0f)
+        retval.elem (i, i) = 0.0f;
+      else
         retval.elem (i, i) = 1.0f / elem (i, i);
-      else
-        retval.elem (i, i) = 0.0f;
     }
 
   return retval;
--- a/liboctave/array/fCDiagMatrix.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/fCDiagMatrix.h	Mon Jan 12 09:17:35 2015 -0800
@@ -122,7 +122,7 @@
 
   FloatComplexDiagMatrix inverse (octave_idx_type& info) const;
   FloatComplexDiagMatrix inverse (void) const;
-  FloatComplexDiagMatrix pseudo_inverse (void) const;
+  FloatComplexDiagMatrix pseudo_inverse (float tol = 0.0f) const;
 
   bool all_elements_are_real (void) const;
 
--- a/liboctave/array/fCMatrix.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/fCMatrix.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -38,7 +38,13 @@
 #include "Array-util.h"
 #include "DET.h"
 #include "f77-fcn.h"
+#include "boolMatrix.h"
+#include "chMatrix.h"
 #include "fCMatrix.h"
+#include "fCNDArray.h"
+#include "fCDiagMatrix.h"
+#include "fCColVector.h"
+#include "fCRowVector.h"
 #include "fCmplxCHOL.h"
 #include "fCmplxSCHUR.h"
 #include "fCmplxSVD.h"
@@ -47,7 +53,6 @@
 #include "lo-ieee.h"
 #include "lo-mappers.h"
 #include "lo-utils.h"
-#include "mx-base.h"
 #include "mx-fcm-fdm.h"
 #include "mx-fcm-fs.h"
 #include "mx-fdm-fcm.h"
@@ -264,39 +269,67 @@
 // FloatComplex Matrix class
 
 FloatComplexMatrix::FloatComplexMatrix (const FloatMatrix& a)
-  : MArray<FloatComplex> (a)
+  : FloatComplexNDArray (a)
 {
 }
 
 FloatComplexMatrix::FloatComplexMatrix (const FloatRowVector& rv)
-  : MArray<FloatComplex> (rv)
+  : FloatComplexNDArray (rv)
 {
 }
 
 FloatComplexMatrix::FloatComplexMatrix (const FloatColumnVector& cv)
-  : MArray<FloatComplex> (cv)
+  : FloatComplexNDArray (cv)
 {
 }
 
 FloatComplexMatrix::FloatComplexMatrix (const FloatDiagMatrix& a)
-  : MArray<FloatComplex> (a.dims (), 0.0)
+  : FloatComplexNDArray (a.dims (), 0.0)
+{
+  for (octave_idx_type i = 0; i < a.length (); i++)
+    elem (i, i) = a.elem (i, i);
+}
+
+FloatComplexMatrix::FloatComplexMatrix (const MDiagArray2<float>& a)
+  : FloatComplexNDArray (a.dims (), 0.0)
+{
+  for (octave_idx_type i = 0; i < a.length (); i++)
+    elem (i, i) = a.elem (i, i);
+}
+
+FloatComplexMatrix::FloatComplexMatrix (const DiagArray2<float>& a)
+  : FloatComplexNDArray (a.dims (), 0.0)
 {
   for (octave_idx_type i = 0; i < a.length (); i++)
     elem (i, i) = a.elem (i, i);
 }
 
 FloatComplexMatrix::FloatComplexMatrix (const FloatComplexRowVector& rv)
-  : MArray<FloatComplex> (rv)
+  : FloatComplexNDArray (rv)
 {
 }
 
 FloatComplexMatrix::FloatComplexMatrix (const FloatComplexColumnVector& cv)
-  : MArray<FloatComplex> (cv)
+  : FloatComplexNDArray (cv)
 {
 }
 
 FloatComplexMatrix::FloatComplexMatrix (const FloatComplexDiagMatrix& a)
-  : MArray<FloatComplex> (a.dims (), 0.0)
+  : FloatComplexNDArray (a.dims (), 0.0)
+{
+  for (octave_idx_type i = 0; i < a.length (); i++)
+    elem (i, i) = a.elem (i, i);
+}
+
+FloatComplexMatrix::FloatComplexMatrix (const MDiagArray2<FloatComplex>& a)
+  : FloatComplexNDArray (a.dims (), 0.0)
+{
+  for (octave_idx_type i = 0; i < a.length (); i++)
+    elem (i, i) = a.elem (i, i);
+}
+
+FloatComplexMatrix::FloatComplexMatrix (const DiagArray2<FloatComplex>& a)
+  : FloatComplexNDArray (a.dims (), 0.0)
 {
   for (octave_idx_type i = 0; i < a.length (); i++)
     elem (i, i) = a.elem (i, i);
@@ -306,12 +339,12 @@
 // here?
 
 FloatComplexMatrix::FloatComplexMatrix (const boolMatrix& a)
-  : MArray<FloatComplex> (a)
+  : FloatComplexNDArray (a)
 {
 }
 
 FloatComplexMatrix::FloatComplexMatrix (const charMatrix& a)
-  : MArray<FloatComplex> (a.dims (), 0.0)
+  : FloatComplexNDArray (a.dims (), 0.0)
 {
   for (octave_idx_type i = 0; i < a.rows (); i++)
     for (octave_idx_type j = 0; j < a.cols (); j++)
@@ -320,7 +353,7 @@
 
 FloatComplexMatrix::FloatComplexMatrix (const FloatMatrix& re,
                                         const FloatMatrix& im)
-  : MArray<FloatComplex> (re.dims ())
+  : FloatComplexNDArray (re.dims ())
 {
   if (im.rows () != rows () || im.cols () != cols ())
     (*current_liboctave_error_handler) ("complex: internal error");
@@ -1727,7 +1760,7 @@
 float
 FloatComplexMatrix::rcond (MatrixType &mattype) const
 {
-  float rcon;
+  float rcon = octave_NaN;
   octave_idx_type nr = rows ();
   octave_idx_type nc = cols ();
 
@@ -1925,11 +1958,27 @@
             {
               const FloatComplex *tmp_data = fortran_vec ();
 
+              retval = b;
+              FloatComplex *result = retval.fortran_vec ();
+
+              char uplo = 'U';
+              char trans = get_blas_char (transt);
+              char dia = 'N';
+
+              F77_XFCN (ctrtrs, CTRTRS, (F77_CONST_CHAR_ARG2 (&uplo, 1),
+                                         F77_CONST_CHAR_ARG2 (&trans, 1),
+                                         F77_CONST_CHAR_ARG2 (&dia, 1),
+                                         nr, b_nc, tmp_data, nr,
+                                         result, nr, info
+                                         F77_CHAR_ARG_LEN (1)
+                                         F77_CHAR_ARG_LEN (1)
+                                         F77_CHAR_ARG_LEN (1)));
+
               if (calc_cond)
                 {
                   char norm = '1';
-                  char uplo = 'U';
-                  char dia = 'N';
+                  uplo = 'U';
+                  dia = 'N';
 
                   Array<FloatComplex> z (dim_vector (2 * nc, 1));
                   FloatComplex *pz = z.fortran_vec ();
@@ -1957,30 +2006,9 @@
                       if (sing_handler)
                         sing_handler (rcon);
                       else
-                        (*current_liboctave_error_handler)
-                          ("matrix singular to machine precision, rcond = %g",
-                           rcon);
+                        gripe_singular_matrix (rcon);
                     }
                 }
-
-              if (info == 0)
-                {
-                  retval = b;
-                  FloatComplex *result = retval.fortran_vec ();
-
-                  char uplo = 'U';
-                  char trans = get_blas_char (transt);
-                  char dia = 'N';
-
-                  F77_XFCN (ctrtrs, CTRTRS, (F77_CONST_CHAR_ARG2 (&uplo, 1),
-                                             F77_CONST_CHAR_ARG2 (&trans, 1),
-                                             F77_CONST_CHAR_ARG2 (&dia, 1),
-                                             nr, b_nc, tmp_data, nr,
-                                             result, nr, info
-                                             F77_CHAR_ARG_LEN (1)
-                                             F77_CHAR_ARG_LEN (1)
-                                             F77_CHAR_ARG_LEN (1)));
-                }
             }
         }
       else
@@ -2026,11 +2054,27 @@
             {
               const FloatComplex *tmp_data = fortran_vec ();
 
+              retval = b;
+              FloatComplex *result = retval.fortran_vec ();
+
+              char uplo = 'L';
+              char trans = get_blas_char (transt);
+              char dia = 'N';
+
+              F77_XFCN (ctrtrs, CTRTRS, (F77_CONST_CHAR_ARG2 (&uplo, 1),
+                                         F77_CONST_CHAR_ARG2 (&trans, 1),
+                                         F77_CONST_CHAR_ARG2 (&dia, 1),
+                                         nr, b_nc, tmp_data, nr,
+                                         result, nr, info
+                                         F77_CHAR_ARG_LEN (1)
+                                         F77_CHAR_ARG_LEN (1)
+                                         F77_CHAR_ARG_LEN (1)));
+
               if (calc_cond)
                 {
                   char norm = '1';
-                  char uplo = 'L';
-                  char dia = 'N';
+                  uplo = 'L';
+                  dia = 'N';
 
                   Array<FloatComplex> z (dim_vector (2 * nc, 1));
                   FloatComplex *pz = z.fortran_vec ();
@@ -2058,30 +2102,9 @@
                       if (sing_handler)
                         sing_handler (rcon);
                       else
-                        (*current_liboctave_error_handler)
-                          ("matrix singular to machine precision, rcond = %g",
-                           rcon);
+                        gripe_singular_matrix (rcon);
                     }
                 }
-
-              if (info == 0)
-                {
-                  retval = b;
-                  FloatComplex *result = retval.fortran_vec ();
-
-                  char uplo = 'L';
-                  char trans = get_blas_char (transt);
-                  char dia = 'N';
-
-                  F77_XFCN (ctrtrs, CTRTRS, (F77_CONST_CHAR_ARG2 (&uplo, 1),
-                                             F77_CONST_CHAR_ARG2 (&trans, 1),
-                                             F77_CONST_CHAR_ARG2 (&dia, 1),
-                                             nr, b_nc, tmp_data, nr,
-                                             result, nr, info
-                                             F77_CHAR_ARG_LEN (1)
-                                             F77_CHAR_ARG_LEN (1)
-                                             F77_CHAR_ARG_LEN (1)));
-                }
             }
         }
       else
@@ -2164,9 +2187,7 @@
                       if (sing_handler)
                         sing_handler (rcon);
                       else
-                        (*current_liboctave_error_handler)
-                          ("matrix singular to machine precision, rcond = %g",
-                           rcon);
+                        gripe_singular_matrix (rcon);
                     }
                 }
 
@@ -2221,8 +2242,7 @@
               if (sing_handler)
                 sing_handler (rcon);
               else
-                (*current_liboctave_error_handler)
-                  ("matrix singular to machine precision");
+                gripe_singular_matrix ();
 
               mattype.mark_as_rectangular ();
             }
@@ -2250,9 +2270,7 @@
                       if (sing_handler)
                         sing_handler (rcon);
                       else
-                        (*current_liboctave_error_handler)
-                          ("matrix singular to machine precision, rcond = %g",
-                           rcon);
+                        gripe_singular_matrix (rcon);
                     }
                 }
 
@@ -2349,9 +2367,9 @@
 
   // Only calculate the condition number for LU/Cholesky
   if (typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper)
-    retval = utsolve (mattype, b, info, rcon, sing_handler, false, transt);
+    retval = utsolve (mattype, b, info, rcon, sing_handler, true, transt);
   else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower)
-    retval = ltsolve (mattype, b, info, rcon, sing_handler, false, transt);
+    retval = ltsolve (mattype, b, info, rcon, sing_handler, true, transt);
   else if (transt == blas_trans)
     return transpose ().solve (mattype, b, info, rcon, sing_handler,
                                singular_fallback);
@@ -3118,154 +3136,56 @@
 // unary operations
 
 boolMatrix
-FloatComplexMatrix::operator ! (void) const
-{
-  if (any_element_is_nan ())
-    gripe_nan_to_logical_conversion ();
-
-  return do_mx_unary_op<bool, FloatComplex> (*this, mx_inline_not);
-}
-
-// other operations
-
-bool
-FloatComplexMatrix::any_element_is_nan (void) const
-{
-  return do_mx_check<FloatComplex> (*this, mx_inline_any_nan);
-}
-
-bool
-FloatComplexMatrix::any_element_is_inf_or_nan (void) const
-{
-  return ! do_mx_check<FloatComplex> (*this, mx_inline_all_finite);
-}
-
-// Return true if no elements have imaginary components.
-
-bool
-FloatComplexMatrix::all_elements_are_real (void) const
-{
-  return do_mx_check<FloatComplex> (*this, mx_inline_all_real);
-}
-
-// Return nonzero if any element of CM has a non-integer real or
-// imaginary part.  Also extract the largest and smallest (real or
-// imaginary) values and return them in MAX_VAL and MIN_VAL.
-
-bool
-FloatComplexMatrix::all_integers (float& max_val, float& min_val) const
-{
-  octave_idx_type nr = rows ();
-  octave_idx_type nc = cols ();
-
-  if (nr > 0 && nc > 0)
-    {
-      FloatComplex val = elem (0, 0);
-
-      float r_val = std::real (val);
-      float i_val = std::imag (val);
-
-      max_val = r_val;
-      min_val = r_val;
-
-      if (i_val > max_val)
-        max_val = i_val;
-
-      if (i_val < max_val)
-        min_val = i_val;
-    }
-  else
-    return false;
-
-  for (octave_idx_type j = 0; j < nc; j++)
-    for (octave_idx_type i = 0; i < nr; i++)
-      {
-        FloatComplex val = elem (i, j);
-
-        float r_val = std::real (val);
-        float i_val = std::imag (val);
-
-        if (r_val > max_val)
-          max_val = r_val;
-
-        if (i_val > max_val)
-          max_val = i_val;
-
-        if (r_val < min_val)
-          min_val = r_val;
-
-        if (i_val < min_val)
-          min_val = i_val;
-
-        if (D_NINT (r_val) != r_val || D_NINT (i_val) != i_val)
-          return false;
-      }
-
-  return true;
-}
-
-bool
-FloatComplexMatrix::too_large_for_float (void) const
-{
-  return false;
-}
-
-// FIXME: Do these really belong here?  Maybe they should be
-// in a base class?
-
-boolMatrix
 FloatComplexMatrix::all (int dim) const
 {
-  return do_mx_red_op<bool, FloatComplex> (*this, dim, mx_inline_all);
+  return FloatComplexNDArray::all (dim);
 }
 
 boolMatrix
 FloatComplexMatrix::any (int dim) const
 {
-  return do_mx_red_op<bool, FloatComplex> (*this, dim, mx_inline_any);
+  return FloatComplexNDArray::any (dim);
 }
 
 FloatComplexMatrix
 FloatComplexMatrix::cumprod (int dim) const
 {
-  return do_mx_cum_op<FloatComplex, FloatComplex> (*this, dim,
-                                                   mx_inline_cumprod);
+  return FloatComplexNDArray::cumprod (dim);
 }
 
 FloatComplexMatrix
 FloatComplexMatrix::cumsum (int dim) const
 {
-  return do_mx_cum_op<FloatComplex, FloatComplex> (*this, dim,
-                                                   mx_inline_cumsum);
+  return FloatComplexNDArray::cumsum (dim);
 }
 
 FloatComplexMatrix
 FloatComplexMatrix::prod (int dim) const
 {
-  return do_mx_red_op<FloatComplex, FloatComplex> (*this, dim, mx_inline_prod);
+  return FloatComplexNDArray::prod (dim);
 }
 
 FloatComplexMatrix
 FloatComplexMatrix::sum (int dim) const
 {
-  return do_mx_red_op<FloatComplex, FloatComplex> (*this, dim, mx_inline_sum);
+  return FloatComplexNDArray::sum (dim);
 }
 
 FloatComplexMatrix
 FloatComplexMatrix::sumsq (int dim) const
 {
-  return do_mx_red_op<float, FloatComplex> (*this, dim, mx_inline_sumsq);
+  return FloatComplexNDArray::sumsq (dim);
 }
 
 FloatMatrix FloatComplexMatrix::abs (void) const
 {
-  return do_mx_unary_map<float, FloatComplex, std::abs> (*this);
+  return FloatComplexNDArray::abs ();
 }
 
 FloatComplexMatrix
 FloatComplexMatrix::diag (octave_idx_type k) const
 {
-  return MArray<FloatComplex>::diag (k);
+  return FloatComplexNDArray::diag (k);
 }
 
 FloatComplexDiagMatrix
@@ -3729,7 +3649,7 @@
 
   // FIXME: check info?
 
-  retval = -ua * cx * ub.hermitian ();
+  retval = ua * cx * ub.hermitian ();
 
   return retval;
 }
--- a/liboctave/array/fCMatrix.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/fCMatrix.h	Mon Jan 12 09:17:35 2015 -0800
@@ -23,6 +23,7 @@
 #if !defined (octave_fCMatrix_h)
 #define octave_fCMatrix_h 1
 
+#include "fCNDArray.h"
 #include "MArray.h"
 #include "MDiagArray2.h"
 #include "MatrixType.h"
@@ -34,7 +35,7 @@
 
 class
 OCTAVE_API
-FloatComplexMatrix : public MArray<FloatComplex>
+FloatComplexMatrix : public FloatComplexNDArray
 {
 public:
 
@@ -43,31 +44,31 @@
 
   typedef void (*solve_singularity_handler) (float rcon);
 
-  FloatComplexMatrix (void) : MArray<FloatComplex> () { }
+  FloatComplexMatrix (void) : FloatComplexNDArray () { }
 
   FloatComplexMatrix (octave_idx_type r, octave_idx_type c)
-    : MArray<FloatComplex> (dim_vector (r, c)) { }
+    : FloatComplexNDArray (dim_vector (r, c)) { }
 
   FloatComplexMatrix (octave_idx_type r, octave_idx_type c,
                       const FloatComplex& val)
-    : MArray<FloatComplex> (dim_vector (r, c), val) { }
+    : FloatComplexNDArray (dim_vector (r, c), val) { }
 
   FloatComplexMatrix (const dim_vector& dv)
-    : MArray<FloatComplex> (dv.redim (2)) { }
+    : FloatComplexNDArray (dv.redim (2)) { }
 
   FloatComplexMatrix (const dim_vector& dv, const FloatComplex& val)
-    : MArray<FloatComplex> (dv.redim (2), val) { }
+    : FloatComplexNDArray (dv.redim (2), val) { }
 
   FloatComplexMatrix (const FloatComplexMatrix& a)
-    : MArray<FloatComplex> (a) { }
+    : FloatComplexNDArray (a) { }
 
   template <class U>
   FloatComplexMatrix (const MArray<U>& a)
-    : MArray<FloatComplex> (a.as_matrix ()) { }
+    : FloatComplexNDArray (a.as_matrix ()) { }
 
   template <class U>
   FloatComplexMatrix (const Array<U>& a)
-    : MArray<FloatComplex> (a.as_matrix ()) { }
+    : FloatComplexNDArray (a.as_matrix ()) { }
 
   explicit FloatComplexMatrix (const FloatMatrix& a);
 
@@ -77,24 +78,26 @@
 
   explicit FloatComplexMatrix (const FloatDiagMatrix& a);
 
+  explicit FloatComplexMatrix (const MDiagArray2<float>& a);
+
+  explicit FloatComplexMatrix (const DiagArray2<float>& a);
+
   explicit FloatComplexMatrix (const FloatComplexRowVector& rv);
 
   explicit FloatComplexMatrix (const FloatComplexColumnVector& cv);
 
   explicit FloatComplexMatrix (const FloatComplexDiagMatrix& a);
 
+  explicit FloatComplexMatrix (const MDiagArray2<FloatComplex>& a);
+
+  explicit FloatComplexMatrix (const DiagArray2<FloatComplex>& a);
+
   explicit FloatComplexMatrix (const boolMatrix& a);
 
   explicit FloatComplexMatrix (const charMatrix& a);
 
   FloatComplexMatrix (const FloatMatrix& re, const FloatMatrix& im);
 
-  FloatComplexMatrix& operator = (const FloatComplexMatrix& a)
-  {
-    MArray<FloatComplex>::operator = (a);
-    return *this;
-  }
-
   bool operator == (const FloatComplexMatrix& a) const;
   bool operator != (const FloatComplexMatrix& a) const;
 
@@ -380,12 +383,6 @@
 
   // other operations
 
-  bool any_element_is_nan (void) const;
-  bool any_element_is_inf_or_nan (void) const;
-  bool all_elements_are_real (void) const;
-  bool all_integers (float& max_val, float& min_val) const;
-  bool too_large_for_float (void) const;
-
   boolMatrix all (int dim = -1) const;
   boolMatrix any (int dim = -1) const;
 
--- a/liboctave/array/fCNDArray.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/fCNDArray.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -39,6 +39,7 @@
 #include "MArray-defs.h"
 #include "mx-base.h"
 #include "mx-op-defs.h"
+#include "mx-fcnda-fs.h"
 #include "oct-fftw.h"
 #include "oct-locbuf.h"
 
@@ -213,7 +214,7 @@
   FloatComplexNDArray retval (dv);
   octave_idx_type npts = dv(dim);
   octave_idx_type nn = 4*npts+15;
-  Array<FloatComplex> wsave (nn, 1);
+  Array<FloatComplex> wsave (dim_vector (nn, 1));
   FloatComplex *pwsave = wsave.fortran_vec ();
 
   OCTAVE_LOCAL_BUFFER (FloatComplex, tmp, npts);
@@ -260,7 +261,7 @@
   FloatComplexNDArray retval (dv);
   octave_idx_type npts = dv(dim);
   octave_idx_type nn = 4*npts+15;
-  Array<FloatComplex> wsave (nn, 1);
+  Array<FloatComplex> wsave (dim_vector (nn, 1));
   FloatComplex *pwsave = wsave.fortran_vec ();
 
   OCTAVE_LOCAL_BUFFER (FloatComplex, tmp, npts);
@@ -310,9 +311,9 @@
     {
       octave_idx_type npts = dv2(i);
       octave_idx_type nn = 4*npts+15;
-      Array<FloatComplex> wsave (nn, 1);
+      Array<FloatComplex> wsave (dim_vector (nn, 1));
       FloatComplex *pwsave = wsave.fortran_vec ();
-      Array<FloatComplex> row (npts, 1);
+      Array<FloatComplex> row (dim_vector (npts, 1));
       FloatComplex *prow = row.fortran_vec ();
 
       octave_idx_type howmany = numel () / npts;
@@ -358,9 +359,9 @@
     {
       octave_idx_type npts = dv2(i);
       octave_idx_type nn = 4*npts+15;
-      Array<FloatComplex> wsave (nn, 1);
+      Array<FloatComplex> wsave (dim_vector (nn, 1));
       FloatComplex *pwsave = wsave.fortran_vec ();
-      Array<FloatComplex> row (npts, 1);
+      Array<FloatComplex> row (dim_vector (npts, 1));
       FloatComplex *prow = row.fortran_vec ();
 
       octave_idx_type howmany = numel () / npts;
@@ -406,9 +407,9 @@
     {
       octave_idx_type npts = dv(i);
       octave_idx_type nn = 4*npts+15;
-      Array<FloatComplex> wsave (nn, 1);
+      Array<FloatComplex> wsave (dim_vector (nn, 1));
       FloatComplex *pwsave = wsave.fortran_vec ();
-      Array<FloatComplex> row (npts, 1);
+      Array<FloatComplex> row (dim_vector (npts, 1));
       FloatComplex *prow = row.fortran_vec ();
 
       octave_idx_type howmany = numel () / npts;
@@ -453,9 +454,9 @@
     {
       octave_idx_type npts = dv(i);
       octave_idx_type nn = 4*npts+15;
-      Array<FloatComplex> wsave (nn, 1);
+      Array<FloatComplex> wsave (dim_vector (nn, 1));
       FloatComplex *pwsave = wsave.fortran_vec ();
-      Array<FloatComplex> row (npts, 1);
+      Array<FloatComplex> row (dim_vector (npts, 1));
       FloatComplex *prow = row.fortran_vec ();
 
       octave_idx_type howmany = numel () / npts;
@@ -616,6 +617,12 @@
   return do_mx_red_op<FloatComplex, FloatComplex> (*this, dim, mx_inline_prod);
 }
 
+ComplexNDArray
+FloatComplexNDArray::dprod (int dim) const
+{
+  return do_mx_red_op<Complex, FloatComplex> (*this, dim, mx_inline_dprod);
+}
+
 FloatComplexNDArray
 FloatComplexNDArray::sum (int dim) const
 {
@@ -819,20 +826,6 @@
   return *this;
 }
 
-FloatComplexMatrix
-FloatComplexNDArray::matrix_value (void) const
-{
-  FloatComplexMatrix retval;
-
-  if (ndims () == 2)
-    retval = FloatComplexMatrix (Array<FloatComplex> (*this));
-  else
-    (*current_liboctave_error_handler)
-      ("invalid conversion of FloatComplexNDArray to FloatComplexMatrix");
-
-  return retval;
-}
-
 void
 FloatComplexNDArray::increment_index (Array<octave_idx_type>& ra_idx,
                                       const dim_vector& dimensions,
--- a/liboctave/array/fCNDArray.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/fCNDArray.h	Mon Jan 12 09:17:35 2015 -0800
@@ -24,7 +24,6 @@
 #define octave_fCNDArray_h 1
 
 #include "MArray.h"
-#include "fCMatrix.h"
 
 #include "mx-defs.h"
 #include "mx-op-decl.h"
@@ -36,8 +35,6 @@
 {
 public:
 
-  typedef FloatComplexMatrix matrix_type;
-
   FloatComplexNDArray (void) : MArray<FloatComplex> () { }
 
   FloatComplexNDArray (const dim_vector& dv) : MArray<FloatComplex> (dv) { }
@@ -48,9 +45,6 @@
   FloatComplexNDArray (const FloatComplexNDArray& a)
     : MArray<FloatComplex> (a) { }
 
-  FloatComplexNDArray (const FloatComplexMatrix& a)
-    : MArray<FloatComplex> (a) { }
-
   template <class U>
   FloatComplexNDArray (const MArray<U>& a) : MArray<FloatComplex> (a) { }
 
@@ -83,6 +77,7 @@
   FloatComplexNDArray cumprod (int dim = -1) const;
   FloatComplexNDArray cumsum (int dim = -1) const;
   FloatComplexNDArray prod (int dim = -1) const;
+  ComplexNDArray dprod (int dim = -1) const;
   FloatComplexNDArray sum (int dim = -1) const;
   ComplexNDArray dsum (int dim = -1) const;
   FloatComplexNDArray sumsq (int dim = -1) const;
@@ -128,8 +123,6 @@
   FloatComplexNDArray fourierNd (void) const;
   FloatComplexNDArray ifourierNd (void) const;
 
-  FloatComplexMatrix matrix_value (void) const;
-
   FloatComplexNDArray squeeze (void) const
   { return MArray<FloatComplex>::squeeze (); }
 
--- a/liboctave/array/fDiagMatrix.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/fDiagMatrix.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -292,7 +292,7 @@
 }
 
 FloatDiagMatrix
-FloatDiagMatrix::pseudo_inverse (void) const
+FloatDiagMatrix::pseudo_inverse (float tol) const
 {
   octave_idx_type r = rows ();
   octave_idx_type c = cols ();
@@ -302,10 +302,11 @@
 
   for (octave_idx_type i = 0; i < len; i++)
     {
-      if (elem (i, i) != 0.0f)
+      float val = std::abs (elem (i, i));
+      if (val < tol || val == 0.0f)
+        retval.elem (i, i) = 0.0f;
+      else
         retval.elem (i, i) = 1.0f / elem (i, i);
-      else
-        retval.elem (i, i) = 0.0f;
     }
 
   return retval;
--- a/liboctave/array/fDiagMatrix.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/fDiagMatrix.h	Mon Jan 12 09:17:35 2015 -0800
@@ -99,7 +99,7 @@
 
   FloatDiagMatrix inverse (void) const;
   FloatDiagMatrix inverse (octave_idx_type& info) const;
-  FloatDiagMatrix pseudo_inverse (void) const;
+  FloatDiagMatrix pseudo_inverse (float tol = 0.0f) const;
 
   // other operations
 
--- a/liboctave/array/fMatrix.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/fMatrix.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -32,7 +32,17 @@
 #include <iostream>
 #include <vector>
 
+#include "fNDArray.h"
 #include "Array-util.h"
+#include "boolMatrix.h"
+#include "chMatrix.h"
+#include "fMatrix.h"
+#include "fDiagMatrix.h"
+#include "fCMatrix.h"
+#include "fColVector.h"
+#include "fRowVector.h"
+#include "fCColVector.h"
+#include "PermMatrix.h"
 #include "DET.h"
 #include "byte-swap.h"
 #include "f77-fcn.h"
@@ -45,7 +55,6 @@
 #include "lo-ieee.h"
 #include "lo-mappers.h"
 #include "lo-utils.h"
-#include "mx-base.h"
 #include "mx-fdm-fm.h"
 #include "mx-fm-fdm.h"
 #include "mx-inlines.cc"
@@ -240,44 +249,54 @@
 // Matrix class.
 
 FloatMatrix::FloatMatrix (const FloatRowVector& rv)
-  : MArray<float> (rv)
+  : FloatNDArray (rv)
 {
 }
 
 FloatMatrix::FloatMatrix (const FloatColumnVector& cv)
-  : MArray<float> (cv)
+  : FloatNDArray (cv)
 {
 }
 
 FloatMatrix::FloatMatrix (const FloatDiagMatrix& a)
-  : MArray<float> (a.dims (), 0.0)
+  : FloatNDArray (a.dims (), 0.0)
+{
+  for (octave_idx_type i = 0; i < a.length (); i++)
+    elem (i, i) = a.elem (i, i);
+}
+
+FloatMatrix::FloatMatrix (const MDiagArray2<float>& a)
+  : FloatNDArray (a.dims (), 0.0)
+{
+  for (octave_idx_type i = 0; i < a.length (); i++)
+    elem (i, i) = a.elem (i, i);
+}
+
+FloatMatrix::FloatMatrix (const DiagArray2<float>& a)
+  : FloatNDArray (a.dims (), 0.0)
 {
   for (octave_idx_type i = 0; i < a.length (); i++)
     elem (i, i) = a.elem (i, i);
 }
 
 FloatMatrix::FloatMatrix (const PermMatrix& a)
-  : MArray<float> (a.dims (), 0.0)
+  : FloatNDArray (a.dims (), 0.0)
 {
-  const Array<octave_idx_type> ia (a.pvec ());
+  const Array<octave_idx_type> ia (a.col_perm_vec ());
   octave_idx_type len = a.rows ();
-  if (a.is_col_perm ())
-    for (octave_idx_type i = 0; i < len; i++)
-      elem (ia(i), i) = 1.0;
-  else
-    for (octave_idx_type i = 0; i < len; i++)
-      elem (i, ia(i)) = 1.0;
+  for (octave_idx_type i = 0; i < len; i++)
+    elem (ia(i), i) = 1.0;
 }
 
 // FIXME: could we use a templated mixed-type copy function here?
 
 FloatMatrix::FloatMatrix (const boolMatrix& a)
-  : MArray<float> (a)
+  : FloatNDArray (a)
 {
 }
 
 FloatMatrix::FloatMatrix (const charMatrix& a)
-  : MArray<float> (a.dims ())
+  : FloatNDArray (a.dims ())
 {
   for (octave_idx_type i = 0; i < a.rows (); i++)
     for (octave_idx_type j = 0; j < a.cols (); j++)
@@ -319,7 +338,7 @@
 FloatMatrix::insert (const FloatMatrix& a,
                      octave_idx_type r, octave_idx_type c)
 {
-  Array<float>::insert (a, r, c);
+  FloatNDArray::insert (a, r, c);
   return *this;
 }
 
@@ -1390,7 +1409,7 @@
 float
 FloatMatrix::rcond (MatrixType &mattype) const
 {
-  float rcon;
+  float rcon = octave_NaN;
   octave_idx_type nr = rows ();
   octave_idx_type nc = cols ();
 
@@ -1586,11 +1605,27 @@
             {
               const float *tmp_data = fortran_vec ();
 
+              retval = b;
+              float *result = retval.fortran_vec ();
+
+              char uplo = 'U';
+              char trans = get_blas_char (transt);
+              char dia = 'N';
+
+              F77_XFCN (strtrs, STRTRS, (F77_CONST_CHAR_ARG2 (&uplo, 1),
+                                         F77_CONST_CHAR_ARG2 (&trans, 1),
+                                         F77_CONST_CHAR_ARG2 (&dia, 1),
+                                         nr, b_nc, tmp_data, nr,
+                                         result, nr, info
+                                         F77_CHAR_ARG_LEN (1)
+                                         F77_CHAR_ARG_LEN (1)
+                                         F77_CHAR_ARG_LEN (1)));
+
               if (calc_cond)
                 {
                   char norm = '1';
-                  char uplo = 'U';
-                  char dia = 'N';
+                  uplo = 'U';
+                  dia = 'N';
 
                   Array<float> z (dim_vector (3 * nc, 1));
                   float *pz = z.fortran_vec ();
@@ -1618,30 +1653,10 @@
                       if (sing_handler)
                         sing_handler (rcon);
                       else
-                        (*current_liboctave_error_handler)
-                          ("matrix singular to machine precision, rcond = %g",
-                           rcon);
+                        gripe_singular_matrix (rcon);
                     }
                 }
 
-              if (info == 0)
-                {
-                  retval = b;
-                  float *result = retval.fortran_vec ();
-
-                  char uplo = 'U';
-                  char trans = get_blas_char (transt);
-                  char dia = 'N';
-
-                  F77_XFCN (strtrs, STRTRS, (F77_CONST_CHAR_ARG2 (&uplo, 1),
-                                             F77_CONST_CHAR_ARG2 (&trans, 1),
-                                             F77_CONST_CHAR_ARG2 (&dia, 1),
-                                             nr, b_nc, tmp_data, nr,
-                                             result, nr, info
-                                             F77_CHAR_ARG_LEN (1)
-                                             F77_CHAR_ARG_LEN (1)
-                                             F77_CHAR_ARG_LEN (1)));
-                }
             }
         }
       else
@@ -1687,11 +1702,27 @@
             {
               const float *tmp_data = fortran_vec ();
 
+              retval = b;
+              float *result = retval.fortran_vec ();
+
+              char uplo = 'L';
+              char trans = get_blas_char (transt);
+              char dia = 'N';
+
+              F77_XFCN (strtrs, STRTRS, (F77_CONST_CHAR_ARG2 (&uplo, 1),
+                                         F77_CONST_CHAR_ARG2 (&trans, 1),
+                                         F77_CONST_CHAR_ARG2 (&dia, 1),
+                                         nr, b_nc, tmp_data, nr,
+                                         result, nr, info
+                                         F77_CHAR_ARG_LEN (1)
+                                         F77_CHAR_ARG_LEN (1)
+                                         F77_CHAR_ARG_LEN (1)));
+
               if (calc_cond)
                 {
                   char norm = '1';
-                  char uplo = 'L';
-                  char dia = 'N';
+                  uplo = 'L';
+                  dia = 'N';
 
                   Array<float> z (dim_vector (3 * nc, 1));
                   float *pz = z.fortran_vec ();
@@ -1719,30 +1750,9 @@
                       if (sing_handler)
                         sing_handler (rcon);
                       else
-                        (*current_liboctave_error_handler)
-                          ("matrix singular to machine precision, rcond = %g",
-                           rcon);
+                        gripe_singular_matrix (rcon);
                     }
                 }
-
-              if (info == 0)
-                {
-                  retval = b;
-                  float *result = retval.fortran_vec ();
-
-                  char uplo = 'L';
-                  char trans = get_blas_char (transt);
-                  char dia = 'N';
-
-                  F77_XFCN (strtrs, STRTRS, (F77_CONST_CHAR_ARG2 (&uplo, 1),
-                                             F77_CONST_CHAR_ARG2 (&trans, 1),
-                                             F77_CONST_CHAR_ARG2 (&dia, 1),
-                                             nr, b_nc, tmp_data, nr,
-                                             result, nr, info
-                                             F77_CHAR_ARG_LEN (1)
-                                             F77_CHAR_ARG_LEN (1)
-                                             F77_CHAR_ARG_LEN (1)));
-                }
             }
         }
       else
@@ -1824,9 +1834,7 @@
                       if (sing_handler)
                         sing_handler (rcon);
                       else
-                        (*current_liboctave_error_handler)
-                          ("matrix singular to machine precision, rcond = %g",
-                           rcon);
+                        gripe_singular_matrix (rcon);
                     }
                 }
 
@@ -1879,8 +1887,7 @@
               if (sing_handler)
                 sing_handler (rcon);
               else
-                (*current_liboctave_error_handler)
-                  ("matrix singular to machine precision");
+                gripe_singular_matrix ();
 
               mattype.mark_as_rectangular ();
             }
@@ -1908,9 +1915,7 @@
                       if (sing_handler)
                         sing_handler (rcon);
                       else
-                        (*current_liboctave_error_handler)
-                          ("matrix singular to machine precision, rcond = %g",
-                           rcon);
+                        gripe_singular_matrix (rcon);
                     }
                 }
 
@@ -1975,9 +1980,9 @@
 
   // Only calculate the condition number for LU/Cholesky
   if (typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper)
-    retval = utsolve (mattype, b, info, rcon, sing_handler, false, transt);
+    retval = utsolve (mattype, b, info, rcon, sing_handler, true, transt);
   else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower)
-    retval = ltsolve (mattype, b, info, rcon, sing_handler, false, transt);
+    retval = ltsolve (mattype, b, info, rcon, sing_handler, true, transt);
   else if (transt == blas_trans || transt == blas_conj_trans)
     return transpose ().solve (mattype, b, info, rcon, sing_handler,
                                singular_fallback);
@@ -2649,17 +2654,6 @@
   return *this;
 }
 
-// unary operations
-
-boolMatrix
-FloatMatrix::operator ! (void) const
-{
-  if (any_element_is_nan ())
-    gripe_nan_to_logical_conversion ();
-
-  return do_mx_unary_op<bool, float> (*this, mx_inline_not);
-}
-
 // column vector by row vector -> matrix operations
 
 FloatMatrix
@@ -2687,139 +2681,48 @@
   return retval;
 }
 
-// other operations.
-
-bool
-FloatMatrix::any_element_is_negative (bool neg_zero) const
-{
-  return (neg_zero ? test_all (xnegative_sign)
-          : do_mx_check<float> (*this, mx_inline_any_negative));
-}
-
-bool
-FloatMatrix::any_element_is_positive (bool neg_zero) const
-{
-  return (neg_zero ? test_all (xpositive_sign)
-          : do_mx_check<float> (*this, mx_inline_any_positive));
-}
-
-bool
-FloatMatrix::any_element_is_nan (void) const
-{
-  return do_mx_check<float> (*this, mx_inline_any_nan);
-}
-
-bool
-FloatMatrix::any_element_is_inf_or_nan (void) const
-{
-  return ! do_mx_check<float> (*this, mx_inline_all_finite);
-}
-
-bool
-FloatMatrix::any_element_not_one_or_zero (void) const
-{
-  return ! test_all (xis_one_or_zero);
-}
-
-bool
-FloatMatrix::all_elements_are_int_or_inf_or_nan (void) const
-{
-  return test_all (xis_int_or_inf_or_nan);
-}
-
-// Return nonzero if any element of M is not an integer.  Also extract
-// the largest and smallest values and return them in MAX_VAL and MIN_VAL.
-
-bool
-FloatMatrix::all_integers (float& max_val, float& min_val) const
-{
-  octave_idx_type nel = nelem ();
-
-  if (nel > 0)
-    {
-      max_val = elem (0);
-      min_val = elem (0);
-    }
-  else
-    return false;
-
-  for (octave_idx_type i = 0; i < nel; i++)
-    {
-      float val = elem (i);
-
-      if (val > max_val)
-        max_val = val;
-
-      if (val < min_val)
-        min_val = val;
-
-      if (! xisinteger (val))
-        return false;
-    }
-
-  return true;
-}
-
-bool
-FloatMatrix::too_large_for_float (void) const
-{
-  return false;
-}
-
 // FIXME: Do these really belong here?  Maybe they should be in a base class?
 
-boolMatrix
-FloatMatrix::all (int dim) const
-{
-  return do_mx_red_op<bool, float> (*this, dim, mx_inline_all);
-}
-
-boolMatrix
-FloatMatrix::any (int dim) const
-{
-  return do_mx_red_op<bool, float> (*this, dim, mx_inline_any);
-}
-
 FloatMatrix
 FloatMatrix::cumprod (int dim) const
 {
-  return do_mx_cum_op<float, float> (*this, dim, mx_inline_cumprod);
+  return FloatNDArray::cumprod (dim);
 }
 
 FloatMatrix
 FloatMatrix::cumsum (int dim) const
 {
-  return do_mx_cum_op<float, float> (*this, dim, mx_inline_cumsum);
+  return FloatNDArray::cumsum (dim);
 }
 
 FloatMatrix
 FloatMatrix::prod (int dim) const
 {
-  return do_mx_red_op<float, float> (*this, dim, mx_inline_prod);
+  return FloatNDArray::prod (dim);
 }
 
 FloatMatrix
 FloatMatrix::sum (int dim) const
 {
-  return do_mx_red_op<float, float> (*this, dim, mx_inline_sum);
+  return FloatNDArray::sum (dim);
 }
 
 FloatMatrix
 FloatMatrix::sumsq (int dim) const
 {
-  return do_mx_red_op<float, float> (*this, dim, mx_inline_sumsq);
+  return FloatNDArray::sumsq (dim);
 }
 
 FloatMatrix
 FloatMatrix::abs (void) const
 {
-  return do_mx_unary_map<float, float, std::abs> (*this);
+  return FloatNDArray::abs ();
 }
 
 FloatMatrix
 FloatMatrix::diag (octave_idx_type k) const
 {
-  return MArray<float>::diag (k);
+  return FloatNDArray::diag (k);
 }
 
 FloatDiagMatrix
@@ -3161,7 +3064,7 @@
 
   // FIXME: check info?
 
-  retval = -ua*cx*ub.transpose ();
+  retval = ua*cx*ub.transpose ();
 
   return retval;
 }
--- a/liboctave/array/fMatrix.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/fMatrix.h	Mon Jan 12 09:17:35 2015 -0800
@@ -23,6 +23,7 @@
 #if !defined (octave_fMatrix_h)
 #define octave_fMatrix_h 1
 
+#include "fNDArray.h"
 #include "MArray.h"
 #include "MDiagArray2.h"
 #include "MatrixType.h"
@@ -33,7 +34,7 @@
 
 class
 OCTAVE_API
-FloatMatrix : public MArray<float>
+FloatMatrix : public FloatNDArray
 {
 public:
 
@@ -42,26 +43,26 @@
 
   typedef void (*solve_singularity_handler) (float rcon);
 
-  FloatMatrix (void) : MArray<float> () { }
+  FloatMatrix (void) : FloatNDArray () { }
 
   FloatMatrix (octave_idx_type r, octave_idx_type c)
-    : MArray<float> (dim_vector (r, c)) { }
+    : FloatNDArray (dim_vector (r, c)) { }
 
   FloatMatrix (octave_idx_type r, octave_idx_type c, float val)
-    : MArray<float> (dim_vector (r, c), val) { }
+    : FloatNDArray (dim_vector (r, c), val) { }
 
-  FloatMatrix (const dim_vector& dv) : MArray<float> (dv.redim (2)) { }
+  FloatMatrix (const dim_vector& dv) : FloatNDArray (dv.redim (2)) { }
 
   FloatMatrix (const dim_vector& dv, float val)
-    : MArray<float> (dv.redim (2), val) { }
+    : FloatNDArray (dv.redim (2), val) { }
 
-  FloatMatrix (const FloatMatrix& a) : MArray<float> (a) { }
+  FloatMatrix (const FloatMatrix& a) : FloatNDArray (a) { }
 
   template <class U>
-  FloatMatrix (const MArray<U>& a) : MArray<float> (a.as_matrix ()) { }
+  FloatMatrix (const MArray<U>& a) : FloatNDArray (a.as_matrix ()) { }
 
   template <class U>
-  FloatMatrix (const Array<U>& a) : MArray<float> (a.as_matrix ()) { }
+  FloatMatrix (const Array<U>& a) : FloatNDArray (a.as_matrix ()) { }
 
   explicit FloatMatrix (const FloatRowVector& rv);
 
@@ -69,19 +70,16 @@
 
   explicit FloatMatrix (const FloatDiagMatrix& a);
 
+  explicit FloatMatrix (const MDiagArray2<float>& a);
+
+  explicit FloatMatrix (const DiagArray2<float>& a);
+
   explicit FloatMatrix (const PermMatrix& a);
 
   explicit FloatMatrix (const boolMatrix& a);
 
   explicit FloatMatrix (const charMatrix& a);
 
-
-  FloatMatrix& operator = (const FloatMatrix& a)
-  {
-    MArray<float>::operator = (a);
-    return *this;
-  }
-
   bool operator == (const FloatMatrix& a) const;
   bool operator != (const FloatMatrix& a) const;
 
@@ -323,24 +321,6 @@
   FloatMatrix& operator += (const FloatDiagMatrix& a);
   FloatMatrix& operator -= (const FloatDiagMatrix& a);
 
-  // unary operations
-
-  boolMatrix operator ! (void) const;
-
-  // other operations
-
-  bool any_element_is_negative (bool = false) const;
-  bool any_element_is_positive (bool = false) const;
-  bool any_element_is_nan (void) const;
-  bool any_element_is_inf_or_nan (void) const;
-  bool any_element_not_one_or_zero (void) const;
-  bool all_elements_are_int_or_inf_or_nan (void) const;
-  bool all_integers (float& max_val, float& min_val) const;
-  bool too_large_for_float (void) const;
-
-  boolMatrix all (int dim = -1) const;
-  boolMatrix any (int dim = -1) const;
-
   FloatMatrix cumprod (int dim = -1) const;
   FloatMatrix cumsum (int dim = -1) const;
   FloatMatrix prod (int dim = -1) const;
--- a/liboctave/array/fNDArray.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/fNDArray.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -217,7 +217,7 @@
   FloatComplexNDArray retval (dv);
   octave_idx_type npts = dv(dim);
   octave_idx_type nn = 4*npts+15;
-  Array<FloatComplex> wsave (nn);
+  Array<FloatComplex> wsave (dim_vector (nn, 1));
   FloatComplex *pwsave = wsave.fortran_vec ();
 
   OCTAVE_LOCAL_BUFFER (FloatComplex, tmp, npts);
@@ -264,7 +264,7 @@
   FloatComplexNDArray retval (dv);
   octave_idx_type npts = dv(dim);
   octave_idx_type nn = 4*npts+15;
-  Array<FloatComplex> wsave (nn);
+  Array<FloatComplex> wsave (dim_vector (nn, 1));
   FloatComplex *pwsave = wsave.fortran_vec ();
 
   OCTAVE_LOCAL_BUFFER (FloatComplex, tmp, npts);
@@ -314,9 +314,9 @@
     {
       octave_idx_type npts = dv2(i);
       octave_idx_type nn = 4*npts+15;
-      Array<FloatComplex> wsave (nn);
+      Array<FloatComplex> wsave (dim_vector (nn, 1));
       FloatComplex *pwsave = wsave.fortran_vec ();
-      Array<FloatComplex> row (npts);
+      Array<FloatComplex> row (dim_vector (npts, 1));
       FloatComplex *prow = row.fortran_vec ();
 
       octave_idx_type howmany = numel () / npts;
@@ -362,9 +362,9 @@
     {
       octave_idx_type npts = dv2(i);
       octave_idx_type nn = 4*npts+15;
-      Array<FloatComplex> wsave (nn);
+      Array<FloatComplex> wsave (dim_vector (nn, 1));
       FloatComplex *pwsave = wsave.fortran_vec ();
-      Array<FloatComplex> row (npts);
+      Array<FloatComplex> row (dim_vector (npts, 1));
       FloatComplex *prow = row.fortran_vec ();
 
       octave_idx_type howmany = numel () / npts;
@@ -410,9 +410,9 @@
     {
       octave_idx_type npts = dv(i);
       octave_idx_type nn = 4*npts+15;
-      Array<FloatComplex> wsave (nn);
+      Array<FloatComplex> wsave (dim_vector (nn, 1));
       FloatComplex *pwsave = wsave.fortran_vec ();
-      Array<FloatComplex> row (npts);
+      Array<FloatComplex> row (dim_vector (npts, 1));
       FloatComplex *prow = row.fortran_vec ();
 
       octave_idx_type howmany = numel () / npts;
@@ -457,9 +457,9 @@
     {
       octave_idx_type npts = dv(i);
       octave_idx_type nn = 4*npts+15;
-      Array<FloatComplex> wsave (nn);
+      Array<FloatComplex> wsave (dim_vector (nn, 1));
       FloatComplex *pwsave = wsave.fortran_vec ();
-      Array<FloatComplex> row (npts);
+      Array<FloatComplex> row (dim_vector (npts, 1));
       FloatComplex *prow = row.fortran_vec ();
 
       octave_idx_type howmany = numel () / npts;
@@ -627,6 +627,12 @@
   return do_mx_red_op<float, float> (*this, dim, mx_inline_prod);
 }
 
+NDArray
+FloatNDArray::dprod (int dim) const
+{
+  return do_mx_red_op<double, float> (*this, dim, mx_inline_dprod);
+}
+
 FloatNDArray
 FloatNDArray::sum (int dim) const
 {
@@ -806,20 +812,6 @@
   return do_mx_unary_map<bool, float, xfinite> (*this);
 }
 
-FloatMatrix
-FloatNDArray::matrix_value (void) const
-{
-  FloatMatrix retval;
-
-  if (ndims () == 2)
-    retval = FloatMatrix (Array<float> (*this));
-  else
-    (*current_liboctave_error_handler)
-      ("invalid conversion of FloatNDArray to FloatMatrix");
-
-  return retval;
-}
-
 void
 FloatNDArray::increment_index (Array<octave_idx_type>& ra_idx,
                                const dim_vector& dimensions,
--- a/liboctave/array/fNDArray.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/fNDArray.h	Mon Jan 12 09:17:35 2015 -0800
@@ -24,7 +24,6 @@
 #define octave_fNDArray_h 1
 
 #include "MArray.h"
-#include "fMatrix.h"
 #include "intNDArray.h"
 
 #include "mx-defs.h"
@@ -37,8 +36,6 @@
 {
 public:
 
-  typedef FloatMatrix matrix_type;
-
   FloatNDArray (void) : MArray<float> () { }
 
   FloatNDArray (const dim_vector& dv) : MArray<float> (dv) { }
@@ -48,8 +45,6 @@
 
   FloatNDArray (const FloatNDArray& a) : MArray<float> (a) { }
 
-  FloatNDArray (const FloatMatrix& a) : MArray<float> (a) { }
-
   template <class U>
   FloatNDArray (const MArray<U>& a) : MArray<float> (a) { }
 
@@ -90,6 +85,7 @@
   FloatNDArray cumprod (int dim = -1) const;
   FloatNDArray cumsum (int dim = -1) const;
   FloatNDArray prod (int dim = -1) const;
+  NDArray dprod (int dim = -1) const;
   FloatNDArray sum (int dim = -1) const;
   NDArray dsum (int dim = -1) const;
   FloatNDArray sumsq (int dim = -1) const;
@@ -136,8 +132,6 @@
 
   friend class FloatComplexNDArray;
 
-  FloatMatrix matrix_value (void) const;
-
   FloatNDArray squeeze (void) const { return MArray<float>::squeeze (); }
 
   static void increment_index (Array<octave_idx_type>& ra_idx,
--- a/liboctave/array/idx-vector.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/idx-vector.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -1093,7 +1093,7 @@
       {
         idx_vector_rep * r = dynamic_cast<idx_vector_rep *> (rep);
         const octave_idx_type *rdata = r->get_data ();
-        copy_or_memcpy (len, rdata, data);
+        std::copy (rdata, rdata + len, data);
       }
       break;
 
--- a/liboctave/array/idx-vector.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/idx-vector.h	Mon Jan 12 09:17:35 2015 -0800
@@ -26,6 +26,7 @@
 #define octave_idx_vector_h 1
 
 #include <cassert>
+#include <cstring>
 
 #include <algorithm>
 #include <iosfwd>
@@ -34,7 +35,6 @@
 #include "dim-vector.h"
 #include "oct-inttypes.h"
 #include "oct-alloc.h"
-#include "oct-mem.h"
 #include "oct-refcount.h"
 
 template<class T> class Array;
@@ -631,7 +631,7 @@
     switch (rep->idx_class ())
       {
       case class_colon:
-        copy_or_memcpy (len, src, dest);
+        std::copy (src, src + len, dest);
         break;
 
       case class_range:
@@ -641,7 +641,7 @@
           octave_idx_type step = r->get_step ();
           const T *ssrc = src + start;
           if (step == 1)
-            copy_or_memcpy (len, ssrc, dest);
+            std::copy (ssrc, ssrc + len, dest);
           else if (step == -1)
             std::reverse_copy (ssrc - len + 1, ssrc + 1, dest);
           else if (step == 0)
@@ -705,7 +705,7 @@
     switch (rep->idx_class ())
       {
       case class_colon:
-        copy_or_memcpy (len, src, dest);
+        std::copy (src, src + len, dest);
         break;
 
       case class_range:
@@ -715,7 +715,7 @@
           octave_idx_type step = r->get_step ();
           T *sdest = dest + start;
           if (step == 1)
-            copy_or_memcpy (len, src, sdest);
+            std::copy (src, src + len, sdest);
           else if (step == -1)
             std::reverse_copy (src, src + len, sdest - len + 1);
           else
--- a/liboctave/array/intNDArray.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/intNDArray.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -213,6 +213,13 @@
 
 template <class T>
 intNDArray<T>
+intNDArray<T>::prod (int dim) const
+{
+  return do_mx_red_op<T, T> (*this, dim, mx_inline_prod);
+}
+
+template <class T>
+intNDArray<T>
 intNDArray<T>::sum (int dim) const
 {
   return do_mx_red_op<T, T> (*this, dim, mx_inline_sum);
--- a/liboctave/array/intNDArray.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/intNDArray.h	Mon Jan 12 09:17:35 2015 -0800
@@ -89,6 +89,7 @@
   intNDArray cummin (int dim = -1) const;
   intNDArray cummin (Array<octave_idx_type>& index, int dim = -1) const;
 
+  intNDArray prod (int dim) const;
   intNDArray sum (int dim) const;
   NDArray dsum (int dim) const;
   intNDArray cumsum (int dim) const;
--- a/liboctave/array/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/array/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -2,10 +2,7 @@
   array/module.mk
 
 ARRAY_INC = \
-  array/Array2.h \
-  array/Array3.h \
   array/Array.h \
-  array/ArrayN.h \
   array/Array-util.h \
   array/boolMatrix.h \
   array/boolNDArray.h \
@@ -42,11 +39,9 @@
   array/int64NDArray.h \
   array/int8NDArray.h \
   array/intNDArray.h \
-  array/MArray2.h \
   array/MArray-decl.h \
   array/MArray-defs.h \
   array/MArray.h \
-  array/MArrayN.h \
   array/Matrix.h \
   array/MatrixType.h \
   array/MDiagArray2.h \
@@ -139,5 +134,7 @@
 array_libarray_la_SOURCES = $(ARRAY_SRC)
 array_libarray_la_CPPFLAGS = \
   $(liboctave_la_CPPFLAGS) \
+  $(FFTW_XCPPFLAGS) \
   $(SPARSE_XCPPFLAGS)
 
+liboctave_la_LIBADD += array/libarray.la
--- a/liboctave/cruft/Faddeeva/Faddeeva.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/cruft/Faddeeva/Faddeeva.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -565,8 +565,8 @@
  taylor_realaxis:
   {
     double x2 = x*x;
+    double y2 = y*y;
     if (x2 > 1600) { // |x| > 40
-      double y2 = y*y;
       if (x2 > 25e14) {// |x| > 5e7
         double xy2 = (x*y)*(x*y);
         return C((0.5 + y2 * (0.5 + 0.25*y2
@@ -584,7 +584,6 @@
     }
     else {
       double D = spi2 * FADDEEVA(w_im)(x);
-      double x2 = x*x, y2 = y*y;
       return C
         (D + y2 * (D + x - 2*D*x2)
          + y2*y2 * (D * (0.5 - x2 * (2 - 0.66666666666666666667*x2))
@@ -694,7 +693,7 @@
   else {
     const double pi = 3.14159265358979323846264338327950288419716939937510582;
     if (relerr > 0.1) relerr = 0.1; // not sensible to compute < 1 digit
-    a = pi / sqrt(-log(relerr*0.5));
+    a = pi / sqrt(-gnulib::log(relerr*0.5));
     c = (2/pi)*a;
     a2 = a*a;
   }
@@ -1010,7 +1009,7 @@
    compared to fitting the whole [0,1] interval with a single polynomial. */
 static double erfcx_y100(double y100)
 {
-  switch ((int) y100) {
+  switch (static_cast<int> (y100)) {
 case 0: {
 double t = 2*y100 - 1;
 return 0.70878032454106438663e-3 + (0.71234091047026302958e-3 + (0.35779077297597742384e-5 + (0.17403143962587937815e-7 + (0.81710660047307788845e-10 + (0.36885022360434957634e-12 + 0.15917038551111111111e-14 * t) * t) * t) * t) * t) * t;
@@ -1454,7 +1453,7 @@
    the Chebyshev polynomials to be of significantly lower degree (about 1/30)
    compared to fitting the whole [0,1] interval with a single polynomial. */
 static double w_im_y100(double y100, double x) {
-  switch ((int) y100) {
+  switch (static_cast<int> (y100)) {
     case 0: {
       double t = 2*y100 - 1;
       return 0.28351593328822191546e-2 + (0.28494783221378400759e-2 + (0.14427470563276734183e-4 + (0.10939723080231588129e-6 + (0.92474307943275042045e-9 + (0.89128907666450075245e-11 + 0.92974121935111111110e-13 * t) * t) * t) * t) * t) * t;
--- a/liboctave/cruft/Faddeeva/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/cruft/Faddeeva/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -1,3 +1,5 @@
-EXTRA_DIST += Faddeeva/module.mk
+EXTRA_DIST += cruft/Faddeeva/module.mk
 
-libcruft_la_SOURCES += Faddeeva/Faddeeva.cc Faddeeva/Faddeeva.hh
+CRUFT_SOURCES += \
+  cruft/Faddeeva/Faddeeva.cc \
+  cruft/Faddeeva/Faddeeva.hh
--- a/liboctave/cruft/Makefile.am	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-# Makefile for Octave's liboctave/cruft directory
-#
-# Copyright (C) 1993-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/>.
-
-include $(top_srcdir)/build-aux/common.mk
-
-## Search local directories before those specified by the user.
-AM_CPPFLAGS = \
-  -I$(top_builddir)/libgnu -I$(top_srcdir)/libgnu
-
-EXTRA_DIST = mkf77def.in
-
-noinst_LTLIBRARIES = libcruft.la
-
-libcruft_la_SOURCES =
-
-nodist_libcruft_la_SOURCES =
-
-libcruft_la_FFLAGS = $(F77_INTEGER_8_FLAG)
-
-libcruft_la_CPPFLAGS = @CRUFT_DLL_DEFS@ $(AM_CPPFLAGS)
-
-libcruft_la_DEPENDENCIES = cruft.def
-
-octinclude_HEADERS =
-
-include amos/module.mk
-include blas-xtra/module.mk
-include daspk/module.mk
-include dasrt/module.mk
-include dassl/module.mk
-include Faddeeva/module.mk
-include fftpack/module.mk
-include lapack-xtra/module.mk
-include misc/module.mk
-include odepack/module.mk
-include ordered-qz/module.mk
-include quadpack/module.mk
-include ranlib/module.mk
-include slatec-err/module.mk
-include slatec-fn/module.mk
-
-## Special rules for files which must be built before compilation
-cruft.def: $(libcruft_la_SOURCES) mkf77def
-	chmod a+rx mkf77def
-	./mkf77def $(srcdir) $(libcruft_la_SOURCES) > $@-t
-	mv $@-t $@
-
-DISTCLEANFILES = \
-  cruft.def \
-  ranlib/ranlib.def \
-  $(nodist_libcruft_la_SOURCES)
-
--- a/liboctave/cruft/amos/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/cruft/amos/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -1,69 +1,69 @@
-EXTRA_DIST += amos/module.mk
+EXTRA_DIST += cruft/amos/module.mk
 
-libcruft_la_SOURCES += \
-  amos/cacai.f \
-  amos/cacon.f \
-  amos/cbesh.f \
-  amos/cbesi.f \
-  amos/cbesj.f \
-  amos/cbesk.f \
-  amos/cbesy.f \
-  amos/cbinu.f \
-  amos/cbuni.f \
-  amos/cbunk.f \
-  amos/cunk1.f \
-  amos/cunk2.f \
-  amos/crati.f \
-  amos/cshch.f \
-  amos/cuni1.f \
-  amos/cuoik.f \
-  amos/cairy.f \
-  amos/cbiry.f \
-  amos/ckscl.f \
-  amos/cs1s2.f \
-  amos/cuchk.f \
-  amos/cuni2.f \
-  amos/cwrsk.f \
-  amos/casyi.f \
-  amos/cbknu.f \
-  amos/cmlri.f \
-  amos/cseri.f \
-  amos/cunhj.f \
-  amos/cunik.f \
-  amos/dgamln.f \
-  amos/gamln.f \
-  amos/xzabs.f \
-  amos/xzexp.f \
-  amos/xzlog.f \
-  amos/xzsqrt.f \
-  amos/zacai.f \
-  amos/zacon.f \
-  amos/zairy.f \
-  amos/zasyi.f \
-  amos/zbesh.f \
-  amos/zbesi.f \
-  amos/zbesj.f \
-  amos/zbesk.f \
-  amos/zbesy.f \
-  amos/zbinu.f \
-  amos/zbiry.f \
-  amos/zbknu.f \
-  amos/zbuni.f \
-  amos/zbunk.f \
-  amos/zdiv.f \
-  amos/zkscl.f \
-  amos/zmlri.f \
-  amos/zmlt.f \
-  amos/zrati.f \
-  amos/zs1s2.f \
-  amos/zseri.f \
-  amos/zshch.f \
-  amos/zuchk.f \
-  amos/zunhj.f \
-  amos/zuni1.f \
-  amos/zuni2.f \
-  amos/zunik.f \
-  amos/zunk1.f \
-  amos/zunk2.f \
-  amos/zuoik.f \
-  amos/zwrsk.f
+CRUFT_SOURCES += \
+  cruft/amos/cacai.f \
+  cruft/amos/cacon.f \
+  cruft/amos/cbesh.f \
+  cruft/amos/cbesi.f \
+  cruft/amos/cbesj.f \
+  cruft/amos/cbesk.f \
+  cruft/amos/cbesy.f \
+  cruft/amos/cbinu.f \
+  cruft/amos/cbuni.f \
+  cruft/amos/cbunk.f \
+  cruft/amos/cunk1.f \
+  cruft/amos/cunk2.f \
+  cruft/amos/crati.f \
+  cruft/amos/cshch.f \
+  cruft/amos/cuni1.f \
+  cruft/amos/cuoik.f \
+  cruft/amos/cairy.f \
+  cruft/amos/cbiry.f \
+  cruft/amos/ckscl.f \
+  cruft/amos/cs1s2.f \
+  cruft/amos/cuchk.f \
+  cruft/amos/cuni2.f \
+  cruft/amos/cwrsk.f \
+  cruft/amos/casyi.f \
+  cruft/amos/cbknu.f \
+  cruft/amos/cmlri.f \
+  cruft/amos/cseri.f \
+  cruft/amos/cunhj.f \
+  cruft/amos/cunik.f \
+  cruft/amos/dgamln.f \
+  cruft/amos/gamln.f \
+  cruft/amos/xzabs.f \
+  cruft/amos/xzexp.f \
+  cruft/amos/xzlog.f \
+  cruft/amos/xzsqrt.f \
+  cruft/amos/zacai.f \
+  cruft/amos/zacon.f \
+  cruft/amos/zairy.f \
+  cruft/amos/zasyi.f \
+  cruft/amos/zbesh.f \
+  cruft/amos/zbesi.f \
+  cruft/amos/zbesj.f \
+  cruft/amos/zbesk.f \
+  cruft/amos/zbesy.f \
+  cruft/amos/zbinu.f \
+  cruft/amos/zbiry.f \
+  cruft/amos/zbknu.f \
+  cruft/amos/zbuni.f \
+  cruft/amos/zbunk.f \
+  cruft/amos/zdiv.f \
+  cruft/amos/zkscl.f \
+  cruft/amos/zmlri.f \
+  cruft/amos/zmlt.f \
+  cruft/amos/zrati.f \
+  cruft/amos/zs1s2.f \
+  cruft/amos/zseri.f \
+  cruft/amos/zshch.f \
+  cruft/amos/zuchk.f \
+  cruft/amos/zunhj.f \
+  cruft/amos/zuni1.f \
+  cruft/amos/zuni2.f \
+  cruft/amos/zunik.f \
+  cruft/amos/zunk1.f \
+  cruft/amos/zunk2.f \
+  cruft/amos/zuoik.f \
+  cruft/amos/zwrsk.f
--- a/liboctave/cruft/blas-xtra/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/cruft/blas-xtra/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -1,28 +1,28 @@
-EXTRA_DIST += blas-xtra/module.mk
+EXTRA_DIST += cruft/blas-xtra/module.mk
 
-libcruft_la_SOURCES += \
-  blas-xtra/ddot3.f \
-  blas-xtra/zdotc3.f \
-  blas-xtra/sdot3.f \
-  blas-xtra/cdotc3.f \
-  blas-xtra/dmatm3.f \
-  blas-xtra/zmatm3.f \
-  blas-xtra/smatm3.f \
-  blas-xtra/cmatm3.f \
-  blas-xtra/xddot.f \
-  blas-xtra/xdnrm2.f \
-  blas-xtra/xdznrm2.f \
-  blas-xtra/xzdotc.f \
-  blas-xtra/xzdotu.f \
-  blas-xtra/xsdot.f \
-  blas-xtra/xsnrm2.f \
-  blas-xtra/xscnrm2.f \
-  blas-xtra/xcdotc.f \
-  blas-xtra/xcdotu.f \
-  blas-xtra/xerbla.f \
-  blas-xtra/cconv2.f \
-  blas-xtra/csconv2.f \
-  blas-xtra/dconv2.f \
-  blas-xtra/sconv2.f \
-  blas-xtra/zconv2.f \
-  blas-xtra/zdconv2.f
+CRUFT_SOURCES += \
+  cruft/blas-xtra/ddot3.f \
+  cruft/blas-xtra/zdotc3.f \
+  cruft/blas-xtra/sdot3.f \
+  cruft/blas-xtra/cdotc3.f \
+  cruft/blas-xtra/dmatm3.f \
+  cruft/blas-xtra/zmatm3.f \
+  cruft/blas-xtra/smatm3.f \
+  cruft/blas-xtra/cmatm3.f \
+  cruft/blas-xtra/xddot.f \
+  cruft/blas-xtra/xdnrm2.f \
+  cruft/blas-xtra/xdznrm2.f \
+  cruft/blas-xtra/xzdotc.f \
+  cruft/blas-xtra/xzdotu.f \
+  cruft/blas-xtra/xsdot.f \
+  cruft/blas-xtra/xsnrm2.f \
+  cruft/blas-xtra/xscnrm2.f \
+  cruft/blas-xtra/xcdotc.f \
+  cruft/blas-xtra/xcdotu.f \
+  cruft/blas-xtra/xerbla.f \
+  cruft/blas-xtra/cconv2.f \
+  cruft/blas-xtra/csconv2.f \
+  cruft/blas-xtra/dconv2.f \
+  cruft/blas-xtra/sconv2.f \
+  cruft/blas-xtra/zconv2.f \
+  cruft/blas-xtra/zdconv2.f
--- a/liboctave/cruft/daspk/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/cruft/daspk/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -1,31 +1,31 @@
-EXTRA_DIST += daspk/module.mk
+EXTRA_DIST += cruft/daspk/module.mk
 
-libcruft_la_SOURCES += \
-  daspk/datv.f \
-  daspk/dcnst0.f \
-  daspk/dcnstr.f \
-  daspk/ddasic.f \
-  daspk/ddasid.f \
-  daspk/ddasik.f \
-  daspk/ddaspk.f \
-  daspk/ddstp.f \
-  daspk/ddwnrm.f \
-  daspk/dfnrmd.f \
-  daspk/dfnrmk.f \
-  daspk/dhels.f \
-  daspk/dheqr.f \
-  daspk/dinvwt.f \
-  daspk/dlinsd.f \
-  daspk/dlinsk.f \
-  daspk/dmatd.f \
-  daspk/dnedd.f \
-  daspk/dnedk.f \
-  daspk/dnsd.f \
-  daspk/dnsid.f \
-  daspk/dnsik.f \
-  daspk/dnsk.f \
-  daspk/dorth.f \
-  daspk/dslvd.f \
-  daspk/dslvk.f \
-  daspk/dspigm.f \
-  daspk/dyypnw.f
+CRUFT_SOURCES += \
+  cruft/daspk/datv.f \
+  cruft/daspk/dcnst0.f \
+  cruft/daspk/dcnstr.f \
+  cruft/daspk/ddasic.f \
+  cruft/daspk/ddasid.f \
+  cruft/daspk/ddasik.f \
+  cruft/daspk/ddaspk.f \
+  cruft/daspk/ddstp.f \
+  cruft/daspk/ddwnrm.f \
+  cruft/daspk/dfnrmd.f \
+  cruft/daspk/dfnrmk.f \
+  cruft/daspk/dhels.f \
+  cruft/daspk/dheqr.f \
+  cruft/daspk/dinvwt.f \
+  cruft/daspk/dlinsd.f \
+  cruft/daspk/dlinsk.f \
+  cruft/daspk/dmatd.f \
+  cruft/daspk/dnedd.f \
+  cruft/daspk/dnedk.f \
+  cruft/daspk/dnsd.f \
+  cruft/daspk/dnsid.f \
+  cruft/daspk/dnsik.f \
+  cruft/daspk/dnsk.f \
+  cruft/daspk/dorth.f \
+  cruft/daspk/dslvd.f \
+  cruft/daspk/dslvk.f \
+  cruft/daspk/dspigm.f \
+  cruft/daspk/dyypnw.f
--- a/liboctave/cruft/dasrt/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/cruft/dasrt/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -1,6 +1,6 @@
-EXTRA_DIST += dasrt/module.mk
+EXTRA_DIST += cruft/dasrt/module.mk
 
-libcruft_la_SOURCES += \
-  dasrt/ddasrt.f \
-  dasrt/drchek.f \
-  dasrt/droots.f
+CRUFT_SOURCES += \
+  cruft/dasrt/ddasrt.f \
+  cruft/dasrt/drchek.f \
+  cruft/dasrt/droots.f
--- a/liboctave/cruft/dassl/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/cruft/dassl/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -1,11 +1,11 @@
-EXTRA_DIST += dassl/module.mk
+EXTRA_DIST += cruft/dassl/module.mk
 
-libcruft_la_SOURCES += \
-  dassl/ddaini.f \
-  dassl/ddajac.f \
-  dassl/ddanrm.f \
-  dassl/ddaslv.f \
-  dassl/ddassl.f \
-  dassl/ddastp.f \
-  dassl/ddatrp.f \
-  dassl/ddawts.f
+CRUFT_SOURCES += \
+  cruft/dassl/ddaini.f \
+  cruft/dassl/ddajac.f \
+  cruft/dassl/ddanrm.f \
+  cruft/dassl/ddaslv.f \
+  cruft/dassl/ddassl.f \
+  cruft/dassl/ddastp.f \
+  cruft/dassl/ddatrp.f \
+  cruft/dassl/ddawts.f
--- a/liboctave/cruft/fftpack/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/cruft/fftpack/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -1,43 +1,43 @@
 EXTRA_DIST += \
-  fftpack/module.mk \
-  fftpack/fftpack.doc
+  cruft/fftpack/module.mk \
+  cruft/fftpack/fftpack.doc
 
 FFTPACK_SRC = \
-  fftpack/cfftb.f \
-  fftpack/cfftb1.f \
-  fftpack/cfftf.f \
-  fftpack/cfftf1.f \
-  fftpack/cffti.f \
-  fftpack/cffti1.f \
-  fftpack/passb.f \
-  fftpack/passb2.f \
-  fftpack/passb3.f \
-  fftpack/passb4.f \
-  fftpack/passb5.f \
-  fftpack/passf.f \
-  fftpack/passf2.f \
-  fftpack/passf3.f \
-  fftpack/passf4.f \
-  fftpack/passf5.f \
-  fftpack/zfftb.f \
-  fftpack/zfftb1.f \
-  fftpack/zfftf.f \
-  fftpack/zfftf1.f \
-  fftpack/zffti.f \
-  fftpack/zffti1.f \
-  fftpack/zpassb.f \
-  fftpack/zpassb2.f \
-  fftpack/zpassb3.f \
-  fftpack/zpassb4.f \
-  fftpack/zpassb5.f \
-  fftpack/zpassf.f \
-  fftpack/zpassf2.f \
-  fftpack/zpassf3.f \
-  fftpack/zpassf4.f \
-  fftpack/zpassf5.f
+  cruft/fftpack/cfftb.f \
+  cruft/fftpack/cfftb1.f \
+  cruft/fftpack/cfftf.f \
+  cruft/fftpack/cfftf1.f \
+  cruft/fftpack/cffti.f \
+  cruft/fftpack/cffti1.f \
+  cruft/fftpack/passb.f \
+  cruft/fftpack/passb2.f \
+  cruft/fftpack/passb3.f \
+  cruft/fftpack/passb4.f \
+  cruft/fftpack/passb5.f \
+  cruft/fftpack/passf.f \
+  cruft/fftpack/passf2.f \
+  cruft/fftpack/passf3.f \
+  cruft/fftpack/passf4.f \
+  cruft/fftpack/passf5.f \
+  cruft/fftpack/zfftb.f \
+  cruft/fftpack/zfftb1.f \
+  cruft/fftpack/zfftf.f \
+  cruft/fftpack/zfftf1.f \
+  cruft/fftpack/zffti.f \
+  cruft/fftpack/zffti1.f \
+  cruft/fftpack/zpassb.f \
+  cruft/fftpack/zpassb2.f \
+  cruft/fftpack/zpassb3.f \
+  cruft/fftpack/zpassb4.f \
+  cruft/fftpack/zpassb5.f \
+  cruft/fftpack/zpassf.f \
+  cruft/fftpack/zpassf2.f \
+  cruft/fftpack/zpassf3.f \
+  cruft/fftpack/zpassf4.f \
+  cruft/fftpack/zpassf5.f
 
 if AMCOND_HAVE_FFTW
   EXTRA_DIST += $(FFTPACK_SRC)
 else
-  libcruft_la_SOURCES += $(FFTPACK_SRC)
+  CRUFT_SOURCES += $(FFTPACK_SRC)
 endif
--- a/liboctave/cruft/lapack-xtra/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/cruft/lapack-xtra/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -1,12 +1,12 @@
-EXTRA_DIST += lapack-xtra/module.mk
+EXTRA_DIST += cruft/lapack-xtra/module.mk
 
-libcruft_la_SOURCES += \
-  lapack-xtra/xclange.f \
-  lapack-xtra/xdlamch.f \
-  lapack-xtra/xdlange.f \
-  lapack-xtra/xilaenv.f \
-  lapack-xtra/xslamch.f \
-  lapack-xtra/xslange.f \
-  lapack-xtra/xzlange.f \
-  lapack-xtra/zrsf2csf.f \
-  lapack-xtra/crsf2csf.f
+CRUFT_SOURCES += \
+  cruft/lapack-xtra/xclange.f \
+  cruft/lapack-xtra/xdlamch.f \
+  cruft/lapack-xtra/xdlange.f \
+  cruft/lapack-xtra/xilaenv.f \
+  cruft/lapack-xtra/xslamch.f \
+  cruft/lapack-xtra/xslange.f \
+  cruft/lapack-xtra/xzlange.f \
+  cruft/lapack-xtra/zrsf2csf.f \
+  cruft/lapack-xtra/crsf2csf.f
--- a/liboctave/cruft/misc/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/cruft/misc/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -1,19 +1,19 @@
 EXTRA_DIST += \
-  misc/module.mk \
-  misc/d1mach-tst.for 
+  cruft/misc/module.mk \
+  cruft/misc/d1mach-tst.for 
 
-libcruft_la_SOURCES += \
-  misc/blaswrap.c \
-  misc/cquit.c \
-  misc/d1mach.f \
-  misc/f77-extern.cc \
-  misc/f77-fcn.c \
-  misc/i1mach.f \
-  misc/lo-error.c \
-  misc/quit.cc \
-  misc/r1mach.f
+CRUFT_SOURCES += \
+  cruft/misc/blaswrap.c \
+  cruft/misc/cquit.c \
+  cruft/misc/d1mach.f \
+  cruft/misc/f77-extern.cc \
+  cruft/misc/f77-fcn.c \
+  cruft/misc/i1mach.f \
+  cruft/misc/lo-error.c \
+  cruft/misc/quit.cc \
+  cruft/misc/r1mach.f
 
-octinclude_HEADERS += \
-  misc/f77-fcn.h \
-  misc/lo-error.h \
-  misc/quit.h
+CRUFT_INC += \
+  cruft/misc/f77-fcn.h \
+  cruft/misc/lo-error.h \
+  cruft/misc/quit.h
--- a/liboctave/cruft/misc/quit.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/cruft/misc/quit.h	Mon Jan 12 09:17:35 2015 -0800
@@ -23,16 +23,16 @@
 #if !defined (octave_quit_h)
 #define octave_quit_h 1
 
+#include <stdio.h>
+
+#include <signal.h>
+#include <setjmp.h>
+
 #ifdef __cplusplus
 #include <new>
 extern "C" {
 #endif
 
-#include <stdio.h>
-
-#include <signal.h>
-#include <setjmp.h>
-
 #if defined (__WIN32__) && ! defined (_POSIX_VERSION)
 
 #define WIN32_LEAN_AND_MEAN
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/liboctave/cruft/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,47 @@
+EXTRA_DIST += cruft/mkf77def.in
+
+nodist_cruft_libcruft_la_SOURCES =
+
+cruft_libcruft_la_FFLAGS = $(F77_INTEGER_8_FLAG)
+
+cruft_libcruft_la_DEPENDENCIES = cruft/cruft.def
+
+CRUFT_INC =
+
+CRUFT_SOURCES =
+
+include cruft/amos/module.mk
+include cruft/blas-xtra/module.mk
+include cruft/daspk/module.mk
+include cruft/dasrt/module.mk
+include cruft/dassl/module.mk
+include cruft/Faddeeva/module.mk
+include cruft/fftpack/module.mk
+include cruft/lapack-xtra/module.mk
+include cruft/misc/module.mk
+include cruft/odepack/module.mk
+include cruft/ordered-qz/module.mk
+include cruft/quadpack/module.mk
+include cruft/ranlib/module.mk
+include cruft/slatec-err/module.mk
+include cruft/slatec-fn/module.mk
+
+## Special rules for files which must be built before compilation
+cruft/cruft.def: $(cruft_libcruft_la_SOURCES) cruft/mkf77def
+	chmod a+rx cruft/mkf77def
+	./cruft/mkf77def $(srcdir) $(cruft_libcruft_la_SOURCES) > $@-t
+	mv $@-t $@
+
+DISTCLEANFILES += \
+  cruft/cruft.def \
+  cruft/mkf77def \
+  cruft/ranlib/ranlib.def \
+  $(nodist_cruft_libcruft_la_SOURCES)
+
+noinst_LTLIBRARIES += cruft/libcruft.la
+
+cruft_libcruft_la_SOURCES = $(CRUFT_SOURCES)
+cruft_libcruft_la_CPPFLAGS = \
+  $(liboctave_la_CPPFLAGS)
+
+liboctave_la_LIBADD += cruft/libcruft.la
--- a/liboctave/cruft/odepack/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/cruft/odepack/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -1,19 +1,19 @@
-EXTRA_DIST += odepack/module.mk
+EXTRA_DIST += cruft/odepack/module.mk
 
-libcruft_la_SOURCES += \
-  odepack/cfode.f \
-  odepack/dlsode.f \
-  odepack/ewset.f \
-  odepack/intdy.f \
-  odepack/prepj.f \
-  odepack/solsy.f \
-  odepack/stode.f \
-  odepack/vnorm.f \
-  odepack/scfode.f \
-  odepack/sewset.f \
-  odepack/sintdy.f \
-  odepack/slsode.f \
-  odepack/sprepj.f \
-  odepack/ssolsy.f \
-  odepack/sstode.f \
-  odepack/svnorm.f
+CRUFT_SOURCES += \
+  cruft/odepack/cfode.f \
+  cruft/odepack/dlsode.f \
+  cruft/odepack/ewset.f \
+  cruft/odepack/intdy.f \
+  cruft/odepack/prepj.f \
+  cruft/odepack/solsy.f \
+  cruft/odepack/stode.f \
+  cruft/odepack/vnorm.f \
+  cruft/odepack/scfode.f \
+  cruft/odepack/sewset.f \
+  cruft/odepack/sintdy.f \
+  cruft/odepack/slsode.f \
+  cruft/odepack/sprepj.f \
+  cruft/odepack/ssolsy.f \
+  cruft/odepack/sstode.f \
+  cruft/odepack/svnorm.f
--- a/liboctave/cruft/ordered-qz/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/cruft/ordered-qz/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -1,7 +1,7 @@
-EXTRA_DIST += ordered-qz/module.mk
+EXTRA_DIST += cruft/ordered-qz/module.mk
 
-libcruft_la_SOURCES += \
-  ordered-qz/dsubsp.f \
-  ordered-qz/exchqz.f \
-  ordered-qz/ssubsp.f \
-  ordered-qz/sexchqz.f
+CRUFT_SOURCES += \
+  cruft/ordered-qz/dsubsp.f \
+  cruft/ordered-qz/exchqz.f \
+  cruft/ordered-qz/ssubsp.f \
+  cruft/ordered-qz/sexchqz.f
--- a/liboctave/cruft/quadpack/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/cruft/quadpack/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -1,20 +1,20 @@
-EXTRA_DIST += quadpack/module.mk
+EXTRA_DIST += cruft/quadpack/module.mk
 
-libcruft_la_SOURCES += \
-  quadpack/dqagi.f \
-  quadpack/dqagie.f \
-  quadpack/dqagp.f \
-  quadpack/dqagpe.f \
-  quadpack/dqelg.f \
-  quadpack/dqk15i.f \
-  quadpack/dqk21.f \
-  quadpack/dqpsrt.f \
-  quadpack/qagie.f \
-  quadpack/qagi.f \
-  quadpack/qagpe.f \
-  quadpack/qagp.f \
-  quadpack/qelg.f \
-  quadpack/qk15i.f \
-  quadpack/qk21.f \
-  quadpack/qpsrt.f \
-  quadpack/xerror.f
+CRUFT_SOURCES += \
+  cruft/quadpack/dqagi.f \
+  cruft/quadpack/dqagie.f \
+  cruft/quadpack/dqagp.f \
+  cruft/quadpack/dqagpe.f \
+  cruft/quadpack/dqelg.f \
+  cruft/quadpack/dqk15i.f \
+  cruft/quadpack/dqk21.f \
+  cruft/quadpack/dqpsrt.f \
+  cruft/quadpack/qagie.f \
+  cruft/quadpack/qagi.f \
+  cruft/quadpack/qagpe.f \
+  cruft/quadpack/qagp.f \
+  cruft/quadpack/qelg.f \
+  cruft/quadpack/qk15i.f \
+  cruft/quadpack/qk21.f \
+  cruft/quadpack/qpsrt.f \
+  cruft/quadpack/xerror.f
--- a/liboctave/cruft/ranlib/ignpoi.f	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/cruft/ranlib/ignpoi.f	Mon Jan 12 09:17:35 2015 -0800
@@ -99,7 +99,7 @@
 C     JJV added this for case: mu unchanged
 C     .. Save statement ..
       SAVE s, d, l, ll, omega, c3, c2, c1, c0, c, m, p, q, p0,
-     +     a0, a1, a2, a3, a4, a5, a6, a7, fact, muprev, muold
+     +     a0, a1, a2, a3, a4, a5, a6, a7, fact, pp, muprev, muold
 C     ..
 C     JJV end addition - I am including vars in Data statements
 C     .. Data statements ..
@@ -110,6 +110,7 @@
       DATA a0,a1,a2,a3,a4,a5,a6,a7/-.5,.3333333,-.2500068,.2000118,
      +     -.1661269,.1421878,-.1384794,.1250060/
       DATA fact/1.,1.,2.,6.,24.,120.,720.,5040.,40320.,362880./
+      DATA pp/35*0.0/
 C     ..
 C     .. Executable Statements ..
 
--- a/liboctave/cruft/ranlib/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/cruft/ranlib/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -1,64 +1,65 @@
 EXTRA_DIST += \
-  ranlib/module.mk \
-  ranlib/Basegen.doc \
-  ranlib/HOWTOGET \
-  ranlib/README \
-  ranlib/randlib.chs \
-  ranlib/randlib.fdoc \
-  ranlib/tstbot.for \
-  ranlib/tstgmn.for \
-  ranlib/tstmid.for
+  cruft/ranlib/module.mk \
+  cruft/ranlib/Basegen.doc \
+  cruft/ranlib/HOWTOGET \
+  cruft/ranlib/README \
+  cruft/ranlib/randlib.chs \
+  cruft/ranlib/randlib.fdoc \
+  cruft/ranlib/tstbot.for \
+  cruft/ranlib/tstgmn.for \
+  cruft/ranlib/tstmid.for
 
 RANLIB_SRC = \
-  ranlib/advnst.f \
-  ranlib/genbet.f \
-  ranlib/genchi.f \
-  ranlib/genexp.f \
-  ranlib/genf.f \
-  ranlib/gengam.f \
-  ranlib/genmn.f \
-  ranlib/genmul.f \
-  ranlib/gennch.f \
-  ranlib/gennf.f \
-  ranlib/gennor.f \
-  ranlib/genprm.f \
-  ranlib/genunf.f \
-  ranlib/getcgn.f \
-  ranlib/getsd.f \
-  ranlib/ignbin.f \
-  ranlib/ignlgi.f \
-  ranlib/ignnbn.f \
-  ranlib/ignpoi.f \
-  ranlib/ignuin.f \
-  ranlib/initgn.f \
-  ranlib/inrgcm.f \
-  ranlib/lennob.f \
-  ranlib/mltmod.f \
-  ranlib/phrtsd.f \
-  ranlib/qrgnin.f \
-  ranlib/ranf.f \
-  ranlib/setall.f \
-  ranlib/setant.f \
-  ranlib/setgmn.f \
-  ranlib/setsd.f \
-  ranlib/sexpo.f \
-  ranlib/sgamma.f \
-  ranlib/snorm.f \
-  ranlib/wrap.f
+  cruft/ranlib/advnst.f \
+  cruft/ranlib/genbet.f \
+  cruft/ranlib/genchi.f \
+  cruft/ranlib/genexp.f \
+  cruft/ranlib/genf.f \
+  cruft/ranlib/gengam.f \
+  cruft/ranlib/genmn.f \
+  cruft/ranlib/genmul.f \
+  cruft/ranlib/gennch.f \
+  cruft/ranlib/gennf.f \
+  cruft/ranlib/gennor.f \
+  cruft/ranlib/genprm.f \
+  cruft/ranlib/genunf.f \
+  cruft/ranlib/getcgn.f \
+  cruft/ranlib/getsd.f \
+  cruft/ranlib/ignbin.f \
+  cruft/ranlib/ignlgi.f \
+  cruft/ranlib/ignnbn.f \
+  cruft/ranlib/ignpoi.f \
+  cruft/ranlib/ignuin.f \
+  cruft/ranlib/initgn.f \
+  cruft/ranlib/inrgcm.f \
+  cruft/ranlib/lennob.f \
+  cruft/ranlib/mltmod.f \
+  cruft/ranlib/phrtsd.f \
+  cruft/ranlib/qrgnin.f \
+  cruft/ranlib/ranf.f \
+  cruft/ranlib/setall.f \
+  cruft/ranlib/setant.f \
+  cruft/ranlib/setgmn.f \
+  cruft/ranlib/setsd.f \
+  cruft/ranlib/sexpo.f \
+  cruft/ranlib/sgamma.f \
+  cruft/ranlib/snorm.f \
+  cruft/ranlib/wrap.f
 
-noinst_LTLIBRARIES += ranlib/libranlib.la
+noinst_LTLIBRARIES += cruft/ranlib/libranlib.la
 
-ranlib_libranlib_la_SOURCES = $(RANLIB_SRC)
+cruft_ranlib_libranlib_la_SOURCES = $(RANLIB_SRC)
 
-ranlib_libranlib_la_DEPENDENCIES = ranlib/ranlib.def
+cruft_ranlib_libranlib_la_DEPENDENCIES = cruft/ranlib/ranlib.def
 
 ## Special rules for files which must be built before compilation
 ## ranlib directory may not exist in VPATH build; create it if necessary.
-ranlib/ranlib.def: $(RANLIB_SRC) mkf77def
-	@-if ! test -d ranlib; then \
-		mkdir ranlib ; \
+cruft/ranlib/ranlib.def: $(RANLIB_SRC) cruft/mkf77def
+	@-if ! test -d cruft/ranlib; then \
+		mkdir cruft/ranlib ; \
 	fi
-	chmod a+rx mkf77def
-	./mkf77def $(srcdir) $(RANLIB_SRC) > $@-t
+	chmod a+rx cruft/mkf77def
+	./cruft/mkf77def $(srcdir) $(RANLIB_SRC) > $@-t
 	mv $@-t $@
 
+liboctave_la_LIBADD += cruft/ranlib/libranlib.la
--- a/liboctave/cruft/slatec-err/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/cruft/slatec-err/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -1,17 +1,17 @@
-EXTRA_DIST += slatec-err/module.mk
+EXTRA_DIST += cruft/slatec-err/module.mk
 
-libcruft_la_SOURCES += \
-  slatec-err/fdump.f \
-  slatec-err/ixsav.f \
-  slatec-err/j4save.f \
-  slatec-err/xerclr.f \
-  slatec-err/xercnt.f \
-  slatec-err/xerhlt.f \
-  slatec-err/xermsg.f \
-  slatec-err/xerprn.f \
-  slatec-err/xerrwd.f \
-  slatec-err/xersve.f \
-  slatec-err/xgetf.f \
-  slatec-err/xgetua.f \
-  slatec-err/xsetf.f \
-  slatec-err/xsetua.f
+CRUFT_SOURCES += \
+  cruft/slatec-err/fdump.f \
+  cruft/slatec-err/ixsav.f \
+  cruft/slatec-err/j4save.f \
+  cruft/slatec-err/xerclr.f \
+  cruft/slatec-err/xercnt.f \
+  cruft/slatec-err/xerhlt.f \
+  cruft/slatec-err/xermsg.f \
+  cruft/slatec-err/xerprn.f \
+  cruft/slatec-err/xerrwd.f \
+  cruft/slatec-err/xersve.f \
+  cruft/slatec-err/xgetf.f \
+  cruft/slatec-err/xgetua.f \
+  cruft/slatec-err/xsetf.f \
+  cruft/slatec-err/xsetua.f
--- a/liboctave/cruft/slatec-fn/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/cruft/slatec-fn/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -1,88 +1,88 @@
 EXTRA_DIST += \
-  slatec-fn/module.mk \
-  slatec-fn/derfc.in.f \
-  slatec-fn/erfc.in.f
+  cruft/slatec-fn/module.mk \
+  cruft/slatec-fn/derfc.in.f \
+  cruft/slatec-fn/erfc.in.f
 
-libcruft_la_SOURCES += \
-  slatec-fn/albeta.f \
-  slatec-fn/alngam.f \
-  slatec-fn/alnrel.f \
-  slatec-fn/algams.f \
-  slatec-fn/acosh.f \
-  slatec-fn/asinh.f \
-  slatec-fn/atanh.f \
-  slatec-fn/betai.f \
-  slatec-fn/csevl.f \
-  slatec-fn/d9gmit.f \
-  slatec-fn/d9lgic.f \
-  slatec-fn/d9lgit.f \
-  slatec-fn/d9lgmc.f \
-  slatec-fn/dacosh.f \
-  slatec-fn/dasinh.f \
-  slatec-fn/datanh.f \
-  slatec-fn/dbetai.f \
-  slatec-fn/dcsevl.f \
-  slatec-fn/derf.f \
-  slatec-fn/dgami.f \
-  slatec-fn/dgamit.f \
-  slatec-fn/dgamlm.f \
-  slatec-fn/dgamma.f \
-  slatec-fn/dgamr.f \
-  slatec-fn/dlbeta.f \
-  slatec-fn/dlgams.f \
-  slatec-fn/dlngam.f \
-  slatec-fn/dlnrel.f \
-  slatec-fn/dpchim.f \
-  slatec-fn/dpchst.f \
-  slatec-fn/erf.f \
-  slatec-fn/gami.f \
-  slatec-fn/gamit.f \
-  slatec-fn/gamlim.f \
-  slatec-fn/gamma.f \
-  slatec-fn/gamr.f \
-  slatec-fn/initds.f \
-  slatec-fn/inits.f \
-  slatec-fn/pchim.f \
-  slatec-fn/pchst.f \
-  slatec-fn/r9lgmc.f \
-  slatec-fn/r9lgit.f \
-  slatec-fn/r9gmit.f \
-  slatec-fn/r9lgic.f \
-  slatec-fn/xdacosh.f \
-  slatec-fn/xdasinh.f \
-  slatec-fn/xdatanh.f \
-  slatec-fn/xdbetai.f \
-  slatec-fn/xderf.f \
-  slatec-fn/xderfc.f \
-  slatec-fn/xdgami.f \
-  slatec-fn/xdgamit.f \
-  slatec-fn/xdgamma.f \
-  slatec-fn/xgmainc.f \
-  slatec-fn/xacosh.f \
-  slatec-fn/xasinh.f \
-  slatec-fn/xatanh.f \
-  slatec-fn/xerf.f \
-  slatec-fn/xerfc.f \
-  slatec-fn/xsgmainc.f \
-  slatec-fn/xgamma.f \
-  slatec-fn/xbetai.f
+CRUFT_SOURCES += \
+  cruft/slatec-fn/albeta.f \
+  cruft/slatec-fn/alngam.f \
+  cruft/slatec-fn/alnrel.f \
+  cruft/slatec-fn/algams.f \
+  cruft/slatec-fn/acosh.f \
+  cruft/slatec-fn/asinh.f \
+  cruft/slatec-fn/atanh.f \
+  cruft/slatec-fn/betai.f \
+  cruft/slatec-fn/csevl.f \
+  cruft/slatec-fn/d9gmit.f \
+  cruft/slatec-fn/d9lgic.f \
+  cruft/slatec-fn/d9lgit.f \
+  cruft/slatec-fn/d9lgmc.f \
+  cruft/slatec-fn/dacosh.f \
+  cruft/slatec-fn/dasinh.f \
+  cruft/slatec-fn/datanh.f \
+  cruft/slatec-fn/dbetai.f \
+  cruft/slatec-fn/dcsevl.f \
+  cruft/slatec-fn/derf.f \
+  cruft/slatec-fn/dgami.f \
+  cruft/slatec-fn/dgamit.f \
+  cruft/slatec-fn/dgamlm.f \
+  cruft/slatec-fn/dgamma.f \
+  cruft/slatec-fn/dgamr.f \
+  cruft/slatec-fn/dlbeta.f \
+  cruft/slatec-fn/dlgams.f \
+  cruft/slatec-fn/dlngam.f \
+  cruft/slatec-fn/dlnrel.f \
+  cruft/slatec-fn/dpchim.f \
+  cruft/slatec-fn/dpchst.f \
+  cruft/slatec-fn/erf.f \
+  cruft/slatec-fn/gami.f \
+  cruft/slatec-fn/gamit.f \
+  cruft/slatec-fn/gamlim.f \
+  cruft/slatec-fn/gamma.f \
+  cruft/slatec-fn/gamr.f \
+  cruft/slatec-fn/initds.f \
+  cruft/slatec-fn/inits.f \
+  cruft/slatec-fn/pchim.f \
+  cruft/slatec-fn/pchst.f \
+  cruft/slatec-fn/r9lgmc.f \
+  cruft/slatec-fn/r9lgit.f \
+  cruft/slatec-fn/r9gmit.f \
+  cruft/slatec-fn/r9lgic.f \
+  cruft/slatec-fn/xdacosh.f \
+  cruft/slatec-fn/xdasinh.f \
+  cruft/slatec-fn/xdatanh.f \
+  cruft/slatec-fn/xdbetai.f \
+  cruft/slatec-fn/xderf.f \
+  cruft/slatec-fn/xderfc.f \
+  cruft/slatec-fn/xdgami.f \
+  cruft/slatec-fn/xdgamit.f \
+  cruft/slatec-fn/xdgamma.f \
+  cruft/slatec-fn/xgmainc.f \
+  cruft/slatec-fn/xacosh.f \
+  cruft/slatec-fn/xasinh.f \
+  cruft/slatec-fn/xatanh.f \
+  cruft/slatec-fn/xerf.f \
+  cruft/slatec-fn/xerfc.f \
+  cruft/slatec-fn/xsgmainc.f \
+  cruft/slatec-fn/xgamma.f \
+  cruft/slatec-fn/xbetai.f
 
-nodist_libcruft_la_SOURCES += \
-  slatec-fn/derfc.f \
-  slatec-fn/erfc.f
+nodist_cruft_libcruft_la_SOURCES += \
+  cruft/slatec-fn/derfc.f \
+  cruft/slatec-fn/erfc.f
 
 ## slatec-fn directory may not exist in VPATH build; create it if necessary.
 
-slatec-fn/erfc.f: slatec-fn/erfc.in.f Makefile
-	@-if ! test -d slatec-fn; then \
-		mkdir slatec-fn ; \
+cruft/slatec-fn/erfc.f: cruft/slatec-fn/erfc.in.f Makefile
+	@-if ! test -d cruft/slatec-fn; then \
+		mkdir cruft/slatec-fn ; \
 	fi
 	$(SED) -e "${F77_ISNAN_MACRO}" < $< > $@-t
 	mv $@-t $@
 
-slatec-fn/derfc.f: slatec-fn/derfc.in.f Makefile
-	@-if ! test -d slatec-fn; then \
-		mkdir slatec-fn ; \
+cruft/slatec-fn/derfc.f: cruft/slatec-fn/derfc.in.f Makefile
+	@-if ! test -d cruft/slatec-fn; then \
+		mkdir cruft/slatec-fn ; \
 	fi
 	$(SED) -e "${F77_ISNAN_MACRO}" < $< > $@-t
 	mv $@-t $@
--- a/liboctave/numeric/CmplxQR.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/numeric/CmplxQR.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -549,7 +549,7 @@
                           octave_idx_type i, octave_idx_type j)
 {
   octave_idx_type n = a.columns ();
-  Array<octave_idx_type> p (n);
+  Array<octave_idx_type> p (dim_vector (n, 1));
   for (octave_idx_type k = 0; k < n; k++) p(k) = k;
   if (i < j)
     {
@@ -618,7 +618,6 @@
 {
   warn_qrupdate_once ();
 
-  octave_idx_type m = q.rows ();
   octave_idx_type n = r.columns ();
 
   if (j < 0 || j > n-1)
@@ -634,7 +633,6 @@
 {
   warn_qrupdate_once ();
 
-  octave_idx_type m = q.rows ();
   octave_idx_type n = r.columns ();
 
   Array<octave_idx_type> jsi;
@@ -681,7 +679,6 @@
   warn_qrupdate_once ();
 
   octave_idx_type m = r.rows ();
-  octave_idx_type n = r.columns ();
 
   if (! q.is_square ())
     (*current_liboctave_error_handler) ("qrdelete: dimensions mismatch");
@@ -698,7 +695,6 @@
 {
   warn_qrupdate_once ();
 
-  octave_idx_type m = q.rows ();
   octave_idx_type n = r.columns ();
 
   if (i < 0 || i > n-1 || j < 0 || j > n-1)
--- a/liboctave/numeric/CmplxQRP.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/numeric/CmplxQRP.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -103,7 +103,7 @@
 RowVector
 ComplexQRP::Pvec (void) const
 {
-  Array<double> pa (p.pvec ());
+  Array<double> pa (p.col_perm_vec ());
   RowVector pv (MArray<double> (pa) + 1.0);
   return pv;
 }
--- a/liboctave/numeric/DASPK-opts.in	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/numeric/DASPK-opts.in	Mon Jan 12 09:17:35 2015 -0800
@@ -209,7 +209,7 @@
 A vector of the same length as the state vector.  A nonzero element
 indicates that the corresponding element of the state vector is an
 algebraic variable (i.e., its derivative does not appear explicitly
-in the equation set.
+in the equation set).
 
 This option is required by the
 @qcode{\"compute consistent initial condition\"} and
--- a/liboctave/numeric/base-lu.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/numeric/base-lu.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -30,7 +30,7 @@
 template <class lu_type>
 base_lu<lu_type>::base_lu (const lu_type& l, const lu_type& u,
                            const PermMatrix& p)
-  : a_fact (u), l_fact (l), ipvt (p.pvec ())
+  : a_fact (u), l_fact (l), ipvt (p.transpose ().col_perm_vec ())
 {
   if (l.columns () != u.rows ())
     (*current_liboctave_error_handler) ("lu: dimension mismatch");
--- a/liboctave/numeric/bsxfun.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/numeric/bsxfun.h	Mon Jan 12 09:17:35 2015 -0800
@@ -41,7 +41,7 @@
       octave_idx_type xk = dx(i);
       octave_idx_type yk = dy(i);
       // Check the three conditions for valid bsxfun dims
-      if (! ( (xk == yk) || (xk == 1 && yk > 1) || (xk > 1 && yk == 1)))
+      if (! ((xk == yk) || (xk == 1 && yk > 1) || (xk > 1 && yk == 1)))
         return false;
     }
 
@@ -71,7 +71,7 @@
       octave_idx_type xk = dx(i);
 
       // Only two valid canditions to check; can't stretch rk
-      if (! ( (rk == xk) || (rk > 1 && xk == 1)))
+      if (! ((rk == xk) || (rk > 1 && xk == 1)))
         return false;
     }
 
--- a/liboctave/numeric/dbleQR.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/numeric/dbleQR.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -544,7 +544,7 @@
                    octave_idx_type i, octave_idx_type j)
 {
   octave_idx_type n = a.columns ();
-  Array<octave_idx_type> p (n);
+  Array<octave_idx_type> p (dim_vector (n, 1));
   for (octave_idx_type k = 0; k < n; k++) p(k) = k;
   if (i < j)
     {
@@ -613,7 +613,6 @@
 {
   warn_qrupdate_once ();
 
-  octave_idx_type m = q.rows ();
   octave_idx_type n = r.columns ();
 
   if (j < 0 || j > n-1)
@@ -629,7 +628,6 @@
 {
   warn_qrupdate_once ();
 
-  octave_idx_type m = q.rows ();
   octave_idx_type n = r.columns ();
 
   Array<octave_idx_type> jsi;
@@ -674,7 +672,6 @@
 QR::delete_row (octave_idx_type j)
 {
   octave_idx_type m = r.rows ();
-  octave_idx_type n = r.columns ();
 
   if (! q.is_square ())
     (*current_liboctave_error_handler) ("qrdelete: dimensions mismatch");
@@ -691,7 +688,6 @@
 {
   warn_qrupdate_once ();
 
-  octave_idx_type m = q.rows ();
   octave_idx_type n = r.columns ();
 
   if (i < 0 || i > n-1 || j < 0 || j > n-1)
@@ -707,11 +703,13 @@
   static bool warned = false;
   if (! warned)
     {
-      (*current_liboctave_warning_handler)
-        ("In this version of Octave, QR & Cholesky updating routines\n"
-         "simply update the matrix and recalculate factorizations.\n"
-         "To use fast algorithms, link Octave with the qrupdate library.\n"
-         "See <http://sourceforge.net/projects/qrupdate>.\n");
+      (*current_liboctave_warning_with_id_handler)
+        ("Octave:missing-dependency",
+         "In this version of Octave, QR & Cholesky updating routines "
+         "simply update the matrix and recalculate factorizations. "
+         "To use fast algorithms, link Octave with the qrupdate library. "
+         "See <http://sourceforge.net/projects/qrupdate>.");
+
       warned = true;
     }
 }
--- a/liboctave/numeric/dbleQRP.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/numeric/dbleQRP.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -100,7 +100,7 @@
 RowVector
 QRP::Pvec (void) const
 {
-  Array<double> pa (p.pvec ());
+  Array<double> pa (p.col_perm_vec ());
   RowVector pv (MArray<double> (pa) + 1.0);
   return pv;
 }
--- a/liboctave/numeric/eigs-base.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/numeric/eigs-base.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -30,6 +30,7 @@
 #include <iostream>
 
 #include "f77-fcn.h"
+#include "oct-locbuf.h"
 #include "quit.h"
 #include "SparsedbleLU.h"
 #include "SparseCmplxLU.h"
@@ -206,6 +207,15 @@
 
 #endif
 
+static void
+warn_convergence (void)
+{
+  (*current_liboctave_warning_with_id_handler)
+    ("Octave:convergence",
+     "eigs: 'A - sigma*B' is singular, indicating sigma is exactly "
+     "an eigenvalue so convergence is not guaranteed");
+}
+
 template <class M, class SM>
 static octave_idx_type
 lusolve (const SM& L, const SM& U, M& m)
@@ -507,12 +517,7 @@
   volatile double rcond_plus_one = rcond + 1.0;
 
   if (rcond_plus_one == 1.0 || xisnan (rcond))
-    {
-      (*current_liboctave_warning_handler)
-        ("eigs: 'A - sigma*B' is singular, indicating sigma is exactly");
-      (*current_liboctave_warning_handler)
-        ("       an eigenvalue. Convergence is not guaranteed");
-    }
+    warn_convergence ();
 
   return true;
 }
@@ -584,12 +589,7 @@
   volatile double rcond_plus_one = rcond + 1.0;
 
   if (rcond_plus_one == 1.0 || xisnan (rcond))
-    {
-      (*current_liboctave_warning_handler)
-        ("eigs: 'A - sigma*B' is singular, indicating sigma is exactly");
-      (*current_liboctave_warning_handler)
-        ("       an eigenvalue. Convergence is not guaranteed");
-    }
+    warn_convergence ();
 
   return true;
 }
@@ -681,12 +681,7 @@
   volatile double rcond_plus_one = rcond + 1.0;
 
   if (rcond_plus_one == 1.0 || xisnan (rcond))
-    {
-      (*current_liboctave_warning_handler)
-        ("eigs: 'A - sigma*B' is singular, indicating sigma is exactly");
-      (*current_liboctave_warning_handler)
-        ("       an eigenvalue. Convergence is not guaranteed");
-    }
+    warn_convergence ();
 
   return true;
 }
@@ -758,12 +753,7 @@
   volatile double rcond_plus_one = rcond + 1.0;
 
   if (rcond_plus_one == 1.0 || xisnan (rcond))
-    {
-      (*current_liboctave_warning_handler)
-        ("eigs: 'A - sigma*B' is singular, indicating sigma is exactly");
-      (*current_liboctave_warning_handler)
-        ("       an eigenvalue. Convergence is not guaranteed");
-    }
+    warn_convergence ();
 
   return true;
 }
--- a/liboctave/numeric/fCmplxQR.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/numeric/fCmplxQR.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -557,7 +557,7 @@
                                octave_idx_type i, octave_idx_type j)
 {
   octave_idx_type n = a.columns ();
-  Array<octave_idx_type> p (n);
+  Array<octave_idx_type> p (dim_vector (n, 1));
   for (octave_idx_type k = 0; k < n; k++) p(k) = k;
   if (i < j)
     {
@@ -628,7 +628,6 @@
 {
   warn_qrupdate_once ();
 
-  octave_idx_type m = q.rows ();
   octave_idx_type n = r.columns ();
 
   if (j < 0 || j > n-1)
@@ -644,7 +643,6 @@
 {
   warn_qrupdate_once ();
 
-  octave_idx_type m = q.rows ();
   octave_idx_type n = r.columns ();
 
   Array<octave_idx_type> jsi;
@@ -691,7 +689,6 @@
   warn_qrupdate_once ();
 
   octave_idx_type m = r.rows ();
-  octave_idx_type n = r.columns ();
 
   if (! q.is_square ())
     (*current_liboctave_error_handler) ("qrdelete: dimensions mismatch");
@@ -708,7 +705,6 @@
 {
   warn_qrupdate_once ();
 
-  octave_idx_type m = q.rows ();
   octave_idx_type n = r.columns ();
 
   if (i < 0 || i > n-1 || j < 0 || j > n-1)
--- a/liboctave/numeric/fCmplxQRP.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/numeric/fCmplxQRP.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -103,7 +103,7 @@
 FloatRowVector
 FloatComplexQRP::Pvec (void) const
 {
-  Array<float> pa (p.pvec ());
+  Array<float> pa (p.col_perm_vec ());
   FloatRowVector pv (MArray<float> (pa) + 1.0f);
   return pv;
 }
--- a/liboctave/numeric/floatQR.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/numeric/floatQR.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -542,7 +542,7 @@
                         octave_idx_type i, octave_idx_type j)
 {
   octave_idx_type n = a.columns ();
-  Array<octave_idx_type> p (n);
+  Array<octave_idx_type> p (dim_vector (n, 1));
   for (octave_idx_type k = 0; k < n; k++) p(k) = k;
   if (i < j)
     {
@@ -611,7 +611,6 @@
 {
   warn_qrupdate_once ();
 
-  octave_idx_type m = q.rows ();
   octave_idx_type n = r.columns ();
 
   if (j < 0 || j > n-1)
@@ -627,7 +626,6 @@
 {
   warn_qrupdate_once ();
 
-  octave_idx_type m = q.rows ();
   octave_idx_type n = r.columns ();
 
   Array<octave_idx_type> jsi;
@@ -674,7 +672,6 @@
   warn_qrupdate_once ();
 
   octave_idx_type m = r.rows ();
-  octave_idx_type n = r.columns ();
 
   if (! q.is_square ())
     (*current_liboctave_error_handler) ("qrdelete: dimensions mismatch");
@@ -691,7 +688,6 @@
 {
   warn_qrupdate_once ();
 
-  octave_idx_type m = q.rows ();
   octave_idx_type n = r.columns ();
 
   if (i < 0 || i > n-1 || j < 0 || j > n-1)
--- a/liboctave/numeric/floatQRP.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/numeric/floatQRP.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -100,7 +100,7 @@
 FloatRowVector
 FloatQRP::Pvec (void) const
 {
-  Array<float> pa (p.pvec ());
+  Array<float> pa (p.col_perm_vec ());
   FloatRowVector pv (MArray<float> (pa) + 1.0f);
   return pv;
 }
--- a/liboctave/numeric/lo-mappers.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/numeric/lo-mappers.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -101,7 +101,7 @@
 #if defined (M_LN2)
   static double ln2 = M_LN2;
 #else
-  static double ln2 = log (2);
+  static double ln2 = gnulib::log (2);
 #endif
 
   return std::log (x) / ln2;
@@ -116,7 +116,7 @@
 #if defined (M_LN2)
   static double ln2 = M_LN2;
 #else
-  static double ln2 = log (2);
+  static double ln2 = gnulib::log (2);
 #endif
 
   return exp (x * ln2);
@@ -169,12 +169,6 @@
   return lo_ieee_is_NA (x);
 }
 
-bool
-octave_is_NaN_or_NA (double x)
-{
-  return lo_ieee_isnan (x);
-}
-
 // (double, double) -> double mappers.
 
 // complex -> complex mappers.
@@ -184,7 +178,20 @@
 {
   static Complex i (0, 1);
 
-  return -i * (log (x + i * (sqrt (1.0 - x*x))));
+  Complex tmp;
+
+  if (imag (x) == 0.0)
+    {
+      // If the imaginary part of X is 0, then avoid generating an
+      // imaginary part of -0 for the expression 1-x*x.
+      // This effectively chooses the same phase of the branch cut as Matlab.
+      double xr = real (x);
+      tmp = Complex (1.0 - xr*xr);
+    }
+  else
+    tmp = 1.0 - x*x;
+
+  return -i * log (x + i * sqrt (tmp));
 }
 
 Complex
@@ -198,7 +205,20 @@
 {
   static Complex i (0, 1);
 
-  return -i * log (i*x + sqrt (1.0 - x*x));
+  Complex tmp;
+
+  if (imag (x) == 0.0)
+    {
+      // If the imaginary part of X is 0, then avoid generating an
+      // imaginary part of -0 for the expression 1-x*x.
+      // This effectively chooses the same phase of the branch cut as Matlab.
+      double xr = real (x);
+      tmp = Complex (1.0 - xr*xr);
+    }
+  else
+    tmp = 1.0 - x*x;
+
+  return -i * log (i*x + sqrt (tmp));
 }
 
 Complex
@@ -386,12 +406,6 @@
   return lo_ieee_is_NA (x);
 }
 
-bool
-octave_is_NaN_or_NA (float x)
-{
-  return lo_ieee_isnan (x);
-}
-
 // (float, float) -> float mappers.
 
 // complex -> complex mappers.
@@ -401,7 +415,20 @@
 {
   static FloatComplex i (0, 1);
 
-  return -i * (log (x + i * (sqrt (static_cast<float>(1.0) - x*x))));
+  FloatComplex tmp;
+
+  if (imag (x) == 0.0f)
+    {
+      // If the imaginary part of X is 0, then avoid generating an
+      // imaginary part of -0 for the expression 1-x*x.
+      // This effectively chooses the same phase of the branch cut as Matlab.
+      float xr = real (x);
+      tmp = FloatComplex (1.0f - xr*xr);
+    }
+  else
+    tmp = 1.0f - x*x;
+
+  return -i * log (x + i * sqrt (tmp));
 }
 
 FloatComplex
@@ -415,7 +442,20 @@
 {
   static FloatComplex i (0, 1);
 
-  return -i * log (i*x + sqrt (static_cast<float>(1.0) - x*x));
+  FloatComplex tmp;
+
+  if (imag (x) == 0.0f)
+    {
+      // If the imaginary part of X is 0, then avoid generating an
+      // imaginary part of -0 for the expression 1-x*x.
+      // This effectively chooses the same phase of the branch cut as Matlab.
+      float xr = real (x);
+      tmp = FloatComplex (1.0f - xr*xr);
+    }
+  else
+    tmp = 1.0f - x*x;
+
+  return -i * log (i*x + sqrt (tmp));
 }
 
 FloatComplex
--- a/liboctave/numeric/lo-mappers.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/numeric/lo-mappers.h	Mon Jan 12 09:17:35 2015 -0800
@@ -72,7 +72,6 @@
 #endif
 
 extern OCTAVE_API bool octave_is_NA (double x);
-extern OCTAVE_API bool octave_is_NaN_or_NA (double x) GCC_ATTR_DEPRECATED;
 
 // Generic xmin, xmax definitions
 template <class T>
@@ -154,7 +153,6 @@
 #endif
 
 extern OCTAVE_API bool octave_is_NA (float x);
-extern OCTAVE_API bool octave_is_NaN_or_NA (float x) GCC_ATTR_DEPRECATED;
 
 inline float
 xmin (float x, float y)
--- a/liboctave/numeric/lo-specfun.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/numeric/lo-specfun.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -2580,12 +2580,8 @@
   err = false;
 
   if (a < 0.0 || x < 0.0)
-    {
-      (*current_liboctave_error_handler)
-        ("gammainc: A and X must be non-negative");
-
-      err = true;
-    }
+    (*current_liboctave_error_handler)
+      ("gammainc: A and X must be non-negative");
   else
     F77_XFCN (xgammainc, XGAMMAINC, (a, x, retval));
 
@@ -2785,12 +2781,8 @@
   err = false;
 
   if (a < 0.0 || x < 0.0)
-    {
-      (*current_liboctave_error_handler)
-        ("gammainc: A and X must be non-negative");
-
-      err = true;
-    }
+    (*current_liboctave_error_handler)
+      ("gammainc: A and X must be non-negative");
   else
     F77_XFCN (xsgammainc, XSGAMMAINC, (a, x, retval));
 
@@ -3422,7 +3414,8 @@
         }
 
       xin = value;
-      ycur = (ycur - a) * exp (beta + r * gnulib::log (xin) + t * gnulib::log (1.0 - xin));
+      ycur = (ycur - a) * exp (beta + r * gnulib::log (xin)
+                               + t * gnulib::log (1.0 - xin));
 
       if (ycur * yprev <= 0.0)
         {
@@ -3643,16 +3636,18 @@
 
   if (m < 0 || m > 1)
     {
-      (*current_liboctave_warning_handler)
-        ("ellipj: expecting 0 <= M <= 1");
+      (*current_liboctave_warning_with_id_handler)
+        ("Octave:ellipj-invalid-m", "ellipj: expecting 0 <= M <= 1");
+
       sn = cn = dn = lo_ieee_nan_value ();
+
       return;
     }
 
   double sqrt_eps = sqrt (std::numeric_limits<double>::epsilon ());
   if (m < sqrt_eps)
     {
-      // For small m, ( Abramowitz and Stegun, Section 16.13 )
+      // For small m, (Abramowitz and Stegun, Section 16.13)
       si_u = sin (u);
       co_u = cos (u);
       t = 0.25*m*(u - si_u*co_u);
@@ -3662,7 +3657,7 @@
     }
   else if ((1 - m) < sqrt_eps)
     {
-      // For m1 = (1-m) small ( Abramowitz and Stegun, Section 16.15 )
+      // For m1 = (1-m) small (Abramowitz and Stegun, Section 16.15)
       m1 = 1 - m;
       si_u = sinh (u);
       co_u = cosh (u);
@@ -3674,8 +3669,8 @@
     }
   else
     {
-      //  Arithmetic-Geometric Mean (AGM) algorithm
-      //    ( Abramowitz and Stegun, Section 16.4 )
+      // Arithmetic-Geometric Mean (AGM) algorithm
+      //   (Abramowitz and Stegun, Section 16.4)
       a[0] = 1;
       b    = sqrt (1 - m);
       c[0] = sqrt (m);
@@ -3696,12 +3691,11 @@
       phi = ii*a[Nn]*u;
       for (n = Nn; n > 0; --n)
         {
-          t = phi;
           phi = (asin ((c[n]/a[n])* sin (phi)) + phi)/2;
         }
       sn = sin (phi);
       cn = cos (phi);
-      dn = cn/cos (t - phi);
+      dn = sqrt (1 - m*sn*sn);
     }
 }
 
--- a/liboctave/numeric/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/numeric/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -180,8 +180,8 @@
 numeric_libnumeric_la_SOURCES = $(NUMERIC_SRC)
 numeric_libnumeric_la_CPPFLAGS = \
   $(liboctave_la_CPPFLAGS) \
-  $(ARPACK_CPPFLAGS) \
   -I$(srcdir)/cruft/Faddeeva \
   $(FFTW_XCPPFLAGS) \
   $(SPARSE_XCPPFLAGS)
 
+liboctave_la_LIBADD += numeric/libnumeric.la
--- a/liboctave/numeric/oct-norm.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/numeric/oct-norm.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -36,6 +36,10 @@
 #include "oct-cmplx.h"
 #include "lo-error.h"
 #include "lo-ieee.h"
+#include "mx-cm-s.h"
+#include "mx-s-cm.h"
+#include "mx-fcm-fs.h"
+#include "mx-fs-fcm.h"
 #include "Array.h"
 #include "Array-util.h"
 #include "CMatrix.h"
--- a/liboctave/numeric/randmtzig.c	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/numeric/randmtzig.c	Mon Jan 12 09:17:35 2015 -0800
@@ -249,7 +249,7 @@
         }
     }
 
-  state[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */
+  state[0] = 0x80000000UL; /* MSB is 1; assuring nonzero initial array */
   left = 1;
   initf = 1;
 }
--- a/liboctave/numeric/sparse-base-chol.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/numeric/sparse-base-chol.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -105,17 +105,17 @@
   if (spu == 0.)
     {
       cm->print = -1;
-      cm->print_function = 0;
+      SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, 0);
     }
   else
     {
       cm->print = static_cast<int> (spu) + 2;
-      cm->print_function =&SparseCholPrint;
+      SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, &SparseCholPrint);
     }
 
   cm->error_handler = &SparseCholError;
-  cm->complex_divide = CHOLMOD_NAME(divcomplex);
-  cm->hypotenuse = CHOLMOD_NAME(hypot);
+  SUITESPARSE_ASSIGN_FPTR2 (divcomplex_func, cm->complex_divide, divcomplex);
+  SUITESPARSE_ASSIGN_FPTR2 (hypot_func, cm->hypotenuse, hypot);
 
   cm->final_asis = false;
   cm->final_super = false;
--- a/liboctave/numeric/sparse-base-lu.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/numeric/sparse-base-lu.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -27,6 +27,8 @@
 
 #include "sparse-base-lu.h"
 
+#include "PermMatrix.h"
+
 template <class lu_type, class lu_elt_type, class p_type, class p_elt_type>
 lu_type
 sparse_base_lu <lu_type, lu_elt_type, p_type, p_elt_type> :: Y (void) const
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/liboctave/operators/Sparse-op-decls.h	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,184 @@
+/*
+
+Copyright (C) 2004-2013 David Bateman
+Copyright (C) 1998-2004 Andy Adler
+Copyright (C) 2008 Jaroslav Hajek
+
+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_Sparse_op_decls_h)
+#define octave_Sparse_op_decls_h 1
+
+class SparseBoolMatrix;
+
+#define SPARSE_BIN_OP_DECL(R, OP, X, Y, API) \
+  extern API R OP (const X&, const Y&)
+
+#define SPARSE_CMP_OP_DECL(OP, X, Y, API) \
+  extern API SparseBoolMatrix OP (const X&, const Y&)
+
+#define SPARSE_BOOL_OP_DECL(OP, X, Y, API) \
+  extern API SparseBoolMatrix OP (const X&, const Y&)
+
+// sparse matrix by scalar operations.
+
+#define SPARSE_SMS_BIN_OP_DECLS(R1, R2, M, S, API)  \
+  SPARSE_BIN_OP_DECL (R1, operator +, M, S, API); \
+  SPARSE_BIN_OP_DECL (R1, operator -, M, S, API); \
+  SPARSE_BIN_OP_DECL (R2, operator *, M, S, API); \
+  SPARSE_BIN_OP_DECL (R2, operator /, M, S, API);
+
+#define SPARSE_SMS_CMP_OP_DECLS(M, S, API) \
+  SPARSE_CMP_OP_DECL (mx_el_lt, M, S, API); \
+  SPARSE_CMP_OP_DECL (mx_el_le, M, S, API); \
+  SPARSE_CMP_OP_DECL (mx_el_ge, M, S, API); \
+  SPARSE_CMP_OP_DECL (mx_el_gt, M, S, API); \
+  SPARSE_CMP_OP_DECL (mx_el_eq, M, S, API); \
+  SPARSE_CMP_OP_DECL (mx_el_ne, M, S, API);
+
+#define SPARSE_SMS_EQNE_OP_DECLS(M, S, API) \
+  SPARSE_CMP_OP_DECL (mx_el_eq, M, S, API); \
+  SPARSE_CMP_OP_DECL (mx_el_ne, M, S, API);
+
+#define SPARSE_SMS_BOOL_OP_DECLS(M, S, API) \
+  SPARSE_BOOL_OP_DECL (mx_el_and, M, S, API); \
+  SPARSE_BOOL_OP_DECL (mx_el_or,  M, S, API);
+
+#define SPARSE_SMS_OP_DECLS(R1, R2, M, S, API) \
+  SPARSE_SMS_BIN_OP_DECLS (R1, R2, M, S, API)    \
+  SPARSE_SMS_CMP_OP_DECLS (M, S, API) \
+  SPARSE_SMS_BOOL_OP_DECLS (M, S, API)
+
+// scalar by sparse matrix operations.
+
+#define SPARSE_SSM_BIN_OP_DECLS(R1, R2, S, M, API)    \
+  SPARSE_BIN_OP_DECL (R1, operator +, S, M, API); \
+  SPARSE_BIN_OP_DECL (R1, operator -, S, M, API); \
+  SPARSE_BIN_OP_DECL (R2, operator *, S, M, API); \
+  SPARSE_BIN_OP_DECL (R2, operator /, S, M, API);
+
+#define SPARSE_SSM_CMP_OP_DECLS(S, M, API) \
+  SPARSE_CMP_OP_DECL (mx_el_lt, S, M, API); \
+  SPARSE_CMP_OP_DECL (mx_el_le, S, M, API); \
+  SPARSE_CMP_OP_DECL (mx_el_ge, S, M, API); \
+  SPARSE_CMP_OP_DECL (mx_el_gt, S, M, API); \
+  SPARSE_CMP_OP_DECL (mx_el_eq, S, M, API); \
+  SPARSE_CMP_OP_DECL (mx_el_ne, S, M, API);
+
+#define SPARSE_SSM_EQNE_OP_DECLS(S, M, API) \
+  SPARSE_CMP_OP_DECL (mx_el_eq, S, M, API); \
+  SPARSE_CMP_OP_DECL (mx_el_ne, S, M, API);
+
+#define SPARSE_SSM_BOOL_OP_DECLS(S, M, API) \
+  SPARSE_BOOL_OP_DECL (mx_el_and, S, M, API); \
+  SPARSE_BOOL_OP_DECL (mx_el_or,  S, M, API); \
+
+#define SPARSE_SSM_OP_DECLS(R1, R2, S, M, API) \
+  SPARSE_SSM_BIN_OP_DECLS (R1, R2, S, M, API)    \
+  SPARSE_SSM_CMP_OP_DECLS (S, M, API) \
+  SPARSE_SSM_BOOL_OP_DECLS (S, M, API) \
+
+// sparse matrix by sparse matrix operations.
+
+#define SPARSE_SMSM_BIN_OP_DECLS(R1, R2, M1, M2, API)   \
+  SPARSE_BIN_OP_DECL (R1, operator +, M1, M2, API); \
+  SPARSE_BIN_OP_DECL (R1, operator -, M1, M2, API); \
+  SPARSE_BIN_OP_DECL (R2, product,    M1, M2, API); \
+  SPARSE_BIN_OP_DECL (R2, quotient,   M1, M2, API);
+
+#define SPARSE_SMSM_CMP_OP_DECLS(M1, M2, API) \
+  SPARSE_CMP_OP_DECL (mx_el_lt, M1, M2, API); \
+  SPARSE_CMP_OP_DECL (mx_el_le, M1, M2, API); \
+  SPARSE_CMP_OP_DECL (mx_el_ge, M1, M2, API); \
+  SPARSE_CMP_OP_DECL (mx_el_gt, M1, M2, API); \
+  SPARSE_CMP_OP_DECL (mx_el_eq, M1, M2, API); \
+  SPARSE_CMP_OP_DECL (mx_el_ne, M1, M2, API);
+
+#define SPARSE_SMSM_EQNE_OP_DECLS(M1, M2, API) \
+  SPARSE_CMP_OP_DECL (mx_el_eq, M1, M2, API); \
+  SPARSE_CMP_OP_DECL (mx_el_ne, M1, M2, API);
+
+#define SPARSE_SMSM_BOOL_OP_DECLS(M1, M2, API) \
+  SPARSE_BOOL_OP_DECL (mx_el_and, M1, M2, API); \
+  SPARSE_BOOL_OP_DECL (mx_el_or,  M1, M2, API);
+
+#define SPARSE_SMSM_OP_DECLS(R1, R2, M1, M2, API) \
+  SPARSE_SMSM_BIN_OP_DECLS (R1, R2, M1, M2, API) \
+  SPARSE_SMSM_CMP_OP_DECLS (M1, M2, API) \
+  SPARSE_SMSM_BOOL_OP_DECLS (M1, M2, API)
+
+// matrix by sparse matrix operations.
+
+#define SPARSE_MSM_BIN_OP_DECLS(R1, R2, M1, M2, API)    \
+  SPARSE_BIN_OP_DECL (R1, operator +, M1, M2, API); \
+  SPARSE_BIN_OP_DECL (R1, operator -, M1, M2, API); \
+  SPARSE_BIN_OP_DECL (R2, product,    M1, M2, API); \
+  SPARSE_BIN_OP_DECL (R2, quotient,   M1, M2, API);
+
+#define SPARSE_MSM_CMP_OP_DECLS(M1, M2, API) \
+  SPARSE_CMP_OP_DECL (mx_el_lt, M1, M2, API); \
+  SPARSE_CMP_OP_DECL (mx_el_le, M1, M2, API); \
+  SPARSE_CMP_OP_DECL (mx_el_ge, M1, M2, API); \
+  SPARSE_CMP_OP_DECL (mx_el_gt, M1, M2, API); \
+  SPARSE_CMP_OP_DECL (mx_el_eq, M1, M2, API); \
+  SPARSE_CMP_OP_DECL (mx_el_ne, M1, M2, API);
+
+#define SPARSE_MSM_EQNE_OP_DECLS(M1, M2, API) \
+  SPARSE_CMP_OP_DECL (mx_el_eq, M1, M2, API); \
+  SPARSE_CMP_OP_DECL (mx_el_ne, M1, M2, API);
+
+#define SPARSE_MSM_BOOL_OP_DECLS(M1, M2, API) \
+  SPARSE_BOOL_OP_DECL (mx_el_and, M1, M2, API); \
+  SPARSE_BOOL_OP_DECL (mx_el_or,  M1, M2, API);
+
+#define SPARSE_MSM_OP_DECLS(R1, R2, M1, M2, API) \
+  SPARSE_MSM_BIN_OP_DECLS (R1, R2, M1, M2, API) \
+  SPARSE_MSM_CMP_OP_DECLS (M1, M2, API) \
+  SPARSE_MSM_BOOL_OP_DECLS (M1, M2, API)
+
+// sparse matrix by matrix operations.
+
+#define SPARSE_SMM_BIN_OP_DECLS(R1, R2, M1, M2, API)    \
+  SPARSE_BIN_OP_DECL (R1, operator +, M1, M2, API); \
+  SPARSE_BIN_OP_DECL (R1, operator -, M1, M2, API); \
+  SPARSE_BIN_OP_DECL (R2, product,    M1, M2, API); \
+  SPARSE_BIN_OP_DECL (R2, quotient,   M1, M2, API);
+
+#define SPARSE_SMM_CMP_OP_DECLS(M1, M2, API) \
+  SPARSE_CMP_OP_DECL (mx_el_lt, M1, M2, API); \
+  SPARSE_CMP_OP_DECL (mx_el_le, M1, M2, API); \
+  SPARSE_CMP_OP_DECL (mx_el_ge, M1, M2, API); \
+  SPARSE_CMP_OP_DECL (mx_el_gt, M1, M2, API); \
+  SPARSE_CMP_OP_DECL (mx_el_eq, M1, M2, API); \
+  SPARSE_CMP_OP_DECL (mx_el_ne, M1, M2, API);
+
+#define SPARSE_SMM_EQNE_OP_DECLS(M1, M2, API) \
+  SPARSE_CMP_OP_DECL (mx_el_eq, M1, M2, API); \
+  SPARSE_CMP_OP_DECL (mx_el_ne, M1, M2, API);
+
+#define SPARSE_SMM_BOOL_OP_DECLS(M1, M2, API) \
+  SPARSE_BOOL_OP_DECL (mx_el_and, M1, M2, API); \
+  SPARSE_BOOL_OP_DECL (mx_el_or,  M1, M2, API);
+
+#define SPARSE_SMM_OP_DECLS(R1, R2, M1, M2, API) \
+  SPARSE_SMM_BIN_OP_DECLS (R1, R2, M1, M2, API) \
+  SPARSE_SMM_CMP_OP_DECLS (M1, M2, API) \
+  SPARSE_SMM_BOOL_OP_DECLS (M1, M2, API)
+
+#endif
--- a/liboctave/operators/Sparse-op-defs.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/operators/Sparse-op-defs.h	Mon Jan 12 09:17:35 2015 -0800
@@ -26,26 +26,10 @@
 #define octave_Sparse_op_defs_h 1
 
 #include "Array-util.h"
-#include "mx-ops.h"
 #include "oct-locbuf.h"
 #include "mx-inlines.cc"
 
-#define SPARSE_BIN_OP_DECL(R, OP, X, Y, API) \
-  extern API R OP (const X&, const Y&)
-
-#define SPARSE_CMP_OP_DECL(OP, X, Y, API) \
-  extern API SparseBoolMatrix OP (const X&, const Y&)
-
-#define SPARSE_BOOL_OP_DECL(OP, X, Y, API) \
-  extern API SparseBoolMatrix OP (const X&, const Y&)
-
-// matrix by scalar operations.
-
-#define SPARSE_SMS_BIN_OP_DECLS(R1, R2, M, S, API)  \
-  SPARSE_BIN_OP_DECL (R1, operator +, M, S, API); \
-  SPARSE_BIN_OP_DECL (R1, operator -, M, S, API); \
-  SPARSE_BIN_OP_DECL (R2, operator *, M, S, API); \
-  SPARSE_BIN_OP_DECL (R2, operator /, M, S, API);
+// sparse matrix by scalar operations.
 
 #define SPARSE_SMS_BIN_OP_1(R, F, OP, M, S)     \
   R \
@@ -90,18 +74,6 @@
   SPARSE_SMS_BIN_OP_2 (R2, operator *, *, M, S) \
   SPARSE_SMS_BIN_OP_2 (R2, operator /, /, M, S)
 
-#define SPARSE_SMS_CMP_OP_DECLS(M, S, API) \
-  SPARSE_CMP_OP_DECL (mx_el_lt, M, S, API); \
-  SPARSE_CMP_OP_DECL (mx_el_le, M, S, API); \
-  SPARSE_CMP_OP_DECL (mx_el_ge, M, S, API); \
-  SPARSE_CMP_OP_DECL (mx_el_gt, M, S, API); \
-  SPARSE_CMP_OP_DECL (mx_el_eq, M, S, API); \
-  SPARSE_CMP_OP_DECL (mx_el_ne, M, S, API);
-
-#define SPARSE_SMS_EQNE_OP_DECLS(M, S, API) \
-  SPARSE_CMP_OP_DECL (mx_el_eq, M, S, API); \
-  SPARSE_CMP_OP_DECL (mx_el_ne, M, S, API);
-
 #define SPARSE_SMS_CMP_OP(F, OP, M, MZ, MC, S, SZ, SC)  \
   SparseBoolMatrix \
   F (const M& m, const S& s) \
@@ -151,10 +123,6 @@
   SPARSE_SMS_CMP_OP (mx_el_eq, ==, M, MZ,   , S, SZ,   )        \
   SPARSE_SMS_CMP_OP (mx_el_ne, !=, M, MZ,   , S, SZ,   )
 
-#define SPARSE_SMS_BOOL_OP_DECLS(M, S, API) \
-  SPARSE_BOOL_OP_DECL (mx_el_and, M, S, API); \
-  SPARSE_BOOL_OP_DECL (mx_el_or,  M, S, API);
-
 #define SPARSE_SMS_BOOL_OP(F, OP, M, S, LHS_ZERO, RHS_ZERO) \
   SparseBoolMatrix \
   F (const M& m, const S& s) \
@@ -202,18 +170,7 @@
 #define SPARSE_SMS_BOOL_OPS(M, S, ZERO) \
   SPARSE_SMS_BOOL_OPS2(M, S, ZERO, ZERO)
 
-#define SPARSE_SMS_OP_DECLS(R1, R2, M, S, API) \
-  SPARSE_SMS_BIN_OP_DECLS (R1, R2, M, S, API)    \
-  SPARSE_SMS_CMP_OP_DECLS (M, S, API) \
-  SPARSE_SMS_BOOL_OP_DECLS (M, S, API)
-
-// scalar by matrix operations.
-
-#define SPARSE_SSM_BIN_OP_DECLS(R1, R2, S, M, API)    \
-  SPARSE_BIN_OP_DECL (R1, operator +, S, M, API); \
-  SPARSE_BIN_OP_DECL (R1, operator -, S, M, API); \
-  SPARSE_BIN_OP_DECL (R2, operator *, S, M, API); \
-  SPARSE_BIN_OP_DECL (R2, operator /, S, M, API);
+// scalar by sparse matrix operations.
 
 #define SPARSE_SSM_BIN_OP_1(R, F, OP, S, M) \
   R \
@@ -259,18 +216,6 @@
   SPARSE_SSM_BIN_OP_2 (R2, operator *, *, S, M) \
   SPARSE_SSM_BIN_OP_2 (R2, operator /, /, S, M)
 
-#define SPARSE_SSM_CMP_OP_DECLS(S, M, API) \
-  SPARSE_CMP_OP_DECL (mx_el_lt, S, M, API); \
-  SPARSE_CMP_OP_DECL (mx_el_le, S, M, API); \
-  SPARSE_CMP_OP_DECL (mx_el_ge, S, M, API); \
-  SPARSE_CMP_OP_DECL (mx_el_gt, S, M, API); \
-  SPARSE_CMP_OP_DECL (mx_el_eq, S, M, API); \
-  SPARSE_CMP_OP_DECL (mx_el_ne, S, M, API);
-
-#define SPARSE_SSM_EQNE_OP_DECLS(S, M, API) \
-  SPARSE_CMP_OP_DECL (mx_el_eq, S, M, API); \
-  SPARSE_CMP_OP_DECL (mx_el_ne, S, M, API);
-
 #define SPARSE_SSM_CMP_OP(F, OP, S, SZ, SC, M, MZ, MC)  \
   SparseBoolMatrix \
   F (const S& s, const M& m) \
@@ -320,10 +265,6 @@
   SPARSE_SSM_CMP_OP (mx_el_eq, ==, S, SZ,   , M, MZ,   )        \
   SPARSE_SSM_CMP_OP (mx_el_ne, !=, S, SZ,   , M, MZ,   )
 
-#define SPARSE_SSM_BOOL_OP_DECLS(S, M, API) \
-  SPARSE_BOOL_OP_DECL (mx_el_and, S, M, API); \
-  SPARSE_BOOL_OP_DECL (mx_el_or,  S, M, API); \
-
 #define SPARSE_SSM_BOOL_OP(F, OP, S, M, LHS_ZERO, RHS_ZERO) \
   SparseBoolMatrix \
   F (const S& s, const M& m) \
@@ -371,18 +312,7 @@
 #define SPARSE_SSM_BOOL_OPS(S, M, ZERO) \
   SPARSE_SSM_BOOL_OPS2(S, M, ZERO, ZERO)
 
-#define SPARSE_SSM_OP_DECLS(R1, R2, S, M, API) \
-  SPARSE_SSM_BIN_OP_DECLS (R1, R2, S, M, API)    \
-  SPARSE_SSM_CMP_OP_DECLS (S, M, API) \
-  SPARSE_SSM_BOOL_OP_DECLS (S, M, API) \
-
-// matrix by matrix operations.
-
-#define SPARSE_SMSM_BIN_OP_DECLS(R1, R2, M1, M2, API)   \
-  SPARSE_BIN_OP_DECL (R1, operator +, M1, M2, API); \
-  SPARSE_BIN_OP_DECL (R1, operator -, M1, M2, API); \
-  SPARSE_BIN_OP_DECL (R2, product,    M1, M2, API); \
-  SPARSE_BIN_OP_DECL (R2, quotient,   M1, M2, API);
+// sparse matrix by sparse matrix operations.
 
 #define SPARSE_SMSM_BIN_OP_1(R, F, OP, M1, M2)  \
   R \
@@ -456,7 +386,7 @@
             octave_idx_type  jb_max = m2.cidx (i+1); \
             bool jb_lt_max = jb < jb_max; \
             \
-            while (ja_lt_max || jb_lt_max ) \
+            while (ja_lt_max || jb_lt_max) \
               { \
                 octave_quit (); \
                 if ((! jb_lt_max) || \
@@ -468,8 +398,8 @@
                     ja++; \
                     ja_lt_max= ja < ja_max; \
                   } \
-                else if (( !ja_lt_max ) || \
-                     (jb_lt_max && (m2.ridx (jb) < m1.ridx (ja)) ) ) \
+                else if ((! ja_lt_max) || \
+                     (jb_lt_max && (m2.ridx (jb) < m1.ridx (ja)))) \
                   { \
                     r.ridx (jx) = m2.ridx (jb); \
                     r.data (jx) = 0. OP m2.data (jb); \
@@ -564,7 +494,7 @@
             octave_idx_type  jb_max = m2.cidx (i+1); \
             bool jb_lt_max = jb < jb_max; \
             \
-            while (ja_lt_max || jb_lt_max ) \
+            while (ja_lt_max || jb_lt_max) \
               { \
                 octave_quit (); \
                 if ((! jb_lt_max) || \
@@ -572,8 +502,8 @@
                   { \
                      ja++; ja_lt_max= ja < ja_max; \
                   } \
-                else if (( !ja_lt_max ) || \
-                     (jb_lt_max && (m2.ridx (jb) < m1.ridx (ja)) ) ) \
+                else if ((! ja_lt_max) || \
+                     (jb_lt_max && (m2.ridx (jb) < m1.ridx (ja)))) \
                   { \
                      jb++; jb_lt_max= jb < jb_max; \
                   } \
@@ -680,7 +610,7 @@
             octave_idx_type  jb_max = m2.cidx (i+1); \
             bool jb_lt_max = jb < jb_max; \
             \
-            while (ja_lt_max || jb_lt_max ) \
+            while (ja_lt_max || jb_lt_max) \
               { \
                 octave_quit (); \
                 if ((! jb_lt_max) || \
@@ -691,8 +621,8 @@
                     ja++; \
                     ja_lt_max= ja < ja_max; \
                   } \
-                else if (( !ja_lt_max ) || \
-                     (jb_lt_max && (m2.ridx (jb) < m1.ridx (ja)) ) ) \
+                else if ((! ja_lt_max) || \
+                     (jb_lt_max && (m2.ridx (jb) < m1.ridx (ja)))) \
                   { \
                     /* keep those kludges coming */ \
                     r.elem (m2.ridx (jb),i) = Complex () OP m2.data (jb);  \
@@ -724,18 +654,6 @@
   SPARSE_SMSM_BIN_OP_2 (R2, product,     *, M1, M2) \
   SPARSE_SMSM_BIN_OP_3 (R2, quotient,    /, M1, M2)
 
-#define SPARSE_SMSM_CMP_OP_DECLS(M1, M2, API) \
-  SPARSE_CMP_OP_DECL (mx_el_lt, M1, M2, API); \
-  SPARSE_CMP_OP_DECL (mx_el_le, M1, M2, API); \
-  SPARSE_CMP_OP_DECL (mx_el_ge, M1, M2, API); \
-  SPARSE_CMP_OP_DECL (mx_el_gt, M1, M2, API); \
-  SPARSE_CMP_OP_DECL (mx_el_eq, M1, M2, API); \
-  SPARSE_CMP_OP_DECL (mx_el_ne, M1, M2, API);
-
-#define SPARSE_SMSM_EQNE_OP_DECLS(M1, M2, API) \
-  SPARSE_CMP_OP_DECL (mx_el_eq, M1, M2, API); \
-  SPARSE_CMP_OP_DECL (mx_el_ne, M1, M2, API);
-
 // FIXME: this macro duplicates the bodies of the template functions
 // defined in the SPARSE_SSM_CMP_OP and SPARSE_SMS_CMP_OP macros.
 
@@ -915,10 +833,6 @@
   SPARSE_SMSM_CMP_OP (mx_el_eq, ==, M1, Z1,   , M2, Z2,   ) \
   SPARSE_SMSM_CMP_OP (mx_el_ne, !=, M1, Z1,   , M2, Z2,   )
 
-#define SPARSE_SMSM_BOOL_OP_DECLS(M1, M2, API) \
-  SPARSE_BOOL_OP_DECL (mx_el_and, M1, M2, API); \
-  SPARSE_BOOL_OP_DECL (mx_el_or,  M1, M2, API);
-
 // FIXME: this macro duplicates the bodies of the template functions
 // defined in the SPARSE_SSM_BOOL_OP and SPARSE_SMS_BOOL_OP macros.
 
@@ -1062,18 +976,7 @@
 #define SPARSE_SMSM_BOOL_OPS(M1, M2, ZERO) \
   SPARSE_SMSM_BOOL_OPS2(M1, M2, ZERO, ZERO)
 
-#define SPARSE_SMSM_OP_DECLS(R1, R2, M1, M2, API) \
-  SPARSE_SMSM_BIN_OP_DECLS (R1, R2, M1, M2, API) \
-  SPARSE_SMSM_CMP_OP_DECLS (M1, M2, API) \
-  SPARSE_SMSM_BOOL_OP_DECLS (M1, M2, API)
-
-// matrix by matrix operations.
-
-#define SPARSE_MSM_BIN_OP_DECLS(R1, R2, M1, M2, API)    \
-  SPARSE_BIN_OP_DECL (R1, operator +, M1, M2, API); \
-  SPARSE_BIN_OP_DECL (R1, operator -, M1, M2, API); \
-  SPARSE_BIN_OP_DECL (R2, product,    M1, M2, API); \
-  SPARSE_BIN_OP_DECL (R2, quotient,   M1, M2, API);
+// matrix by sparse matrix operations.
 
 #define SPARSE_MSM_BIN_OP_1(R, F, OP, M1, M2)   \
   R \
@@ -1154,18 +1057,6 @@
   SPARSE_MSM_BIN_OP_2 (R2, product,     *, M1, M2) \
   SPARSE_MSM_BIN_OP_1 (R2, quotient,    /, M1, M2)
 
-#define SPARSE_MSM_CMP_OP_DECLS(M1, M2, API) \
-  SPARSE_CMP_OP_DECL (mx_el_lt, M1, M2, API); \
-  SPARSE_CMP_OP_DECL (mx_el_le, M1, M2, API); \
-  SPARSE_CMP_OP_DECL (mx_el_ge, M1, M2, API); \
-  SPARSE_CMP_OP_DECL (mx_el_gt, M1, M2, API); \
-  SPARSE_CMP_OP_DECL (mx_el_eq, M1, M2, API); \
-  SPARSE_CMP_OP_DECL (mx_el_ne, M1, M2, API);
-
-#define SPARSE_MSM_EQNE_OP_DECLS(M1, M2, API) \
-  SPARSE_CMP_OP_DECL (mx_el_eq, M1, M2, API); \
-  SPARSE_CMP_OP_DECL (mx_el_ne, M1, M2, API);
-
 #define SPARSE_MSM_CMP_OP(F, OP, M1, C1, M2, C2)        \
   SparseBoolMatrix \
   F (const M1& m1, const M2& m2) \
@@ -1184,7 +1075,7 @@
       { \
         if (m1_nr != 0 || m1_nc != 0) \
           { \
-            /* Count num of non-zero elements */ \
+            /* Count num of nonzero elements */ \
             octave_idx_type nel = 0; \
             for (octave_idx_type j = 0; j < m1_nc; j++) \
               for (octave_idx_type i = 0; i < m1_nr; i++) \
@@ -1230,10 +1121,6 @@
   SPARSE_MSM_CMP_OP (mx_el_eq, ==, M1,   , M2,   ) \
   SPARSE_MSM_CMP_OP (mx_el_ne, !=, M1,   , M2,   )
 
-#define SPARSE_MSM_BOOL_OP_DECLS(M1, M2, API) \
-  SPARSE_BOOL_OP_DECL (mx_el_and, M1, M2, API); \
-  SPARSE_BOOL_OP_DECL (mx_el_or,  M1, M2, API);
-
 #define SPARSE_MSM_BOOL_OP(F, OP, M1, M2, LHS_ZERO, RHS_ZERO) \
   SparseBoolMatrix \
   F (const M1& m1, const M2& m2) \
@@ -1252,7 +1139,7 @@
       { \
         if (m1_nr != 0 || m1_nc != 0) \
           { \
-            /* Count num of non-zero elements */ \
+            /* Count num of nonzero elements */ \
             octave_idx_type nel = 0; \
             for (octave_idx_type j = 0; j < m1_nc; j++) \
               for (octave_idx_type i = 0; i < m1_nr; i++) \
@@ -1295,18 +1182,7 @@
 #define SPARSE_MSM_BOOL_OPS(M1, M2, ZERO) \
   SPARSE_MSM_BOOL_OPS2(M1, M2, ZERO, ZERO)
 
-#define SPARSE_MSM_OP_DECLS(R1, R2, M1, M2, API) \
-  SPARSE_MSM_BIN_OP_DECLS (R1, R2, M1, M2, API) \
-  SPARSE_MSM_CMP_OP_DECLS (M1, M2, API) \
-  SPARSE_MSM_BOOL_OP_DECLS (M1, M2, API)
-
-// matrix by matrix operations.
-
-#define SPARSE_SMM_BIN_OP_DECLS(R1, R2, M1, M2, API)    \
-  SPARSE_BIN_OP_DECL (R1, operator +, M1, M2, API); \
-  SPARSE_BIN_OP_DECL (R1, operator -, M1, M2, API); \
-  SPARSE_BIN_OP_DECL (R2, product,    M1, M2, API); \
-  SPARSE_BIN_OP_DECL (R2, quotient,   M1, M2, API);
+// sparse matrix by matrix operations.
 
 #define SPARSE_SMM_BIN_OP_1(R, F, OP, M1, M2)   \
   R \
@@ -1394,18 +1270,6 @@
   SPARSE_SMM_BIN_OP_2 (R2, product,     *, M1, M2) \
   SPARSE_SMM_BIN_OP_2 (R2, quotient,    /, M1, M2)
 
-#define SPARSE_SMM_CMP_OP_DECLS(M1, M2, API) \
-  SPARSE_CMP_OP_DECL (mx_el_lt, M1, M2, API); \
-  SPARSE_CMP_OP_DECL (mx_el_le, M1, M2, API); \
-  SPARSE_CMP_OP_DECL (mx_el_ge, M1, M2, API); \
-  SPARSE_CMP_OP_DECL (mx_el_gt, M1, M2, API); \
-  SPARSE_CMP_OP_DECL (mx_el_eq, M1, M2, API); \
-  SPARSE_CMP_OP_DECL (mx_el_ne, M1, M2, API);
-
-#define SPARSE_SMM_EQNE_OP_DECLS(M1, M2, API) \
-  SPARSE_CMP_OP_DECL (mx_el_eq, M1, M2, API); \
-  SPARSE_CMP_OP_DECL (mx_el_ne, M1, M2, API);
-
 #define SPARSE_SMM_CMP_OP(F, OP, M1, C1, M2, C2)        \
   SparseBoolMatrix \
   F (const M1& m1, const M2& m2) \
@@ -1424,7 +1288,7 @@
       { \
         if (m1_nr != 0 || m1_nc != 0) \
           { \
-            /* Count num of non-zero elements */ \
+            /* Count num of nonzero elements */ \
             octave_idx_type nel = 0; \
             for (octave_idx_type j = 0; j < m1_nc; j++) \
               for (octave_idx_type i = 0; i < m1_nr; i++) \
@@ -1470,10 +1334,6 @@
   SPARSE_SMM_CMP_OP (mx_el_eq, ==, M1,   , M2,   ) \
   SPARSE_SMM_CMP_OP (mx_el_ne, !=, M1,   , M2,   )
 
-#define SPARSE_SMM_BOOL_OP_DECLS(M1, M2, API) \
-  SPARSE_BOOL_OP_DECL (mx_el_and, M1, M2, API); \
-  SPARSE_BOOL_OP_DECL (mx_el_or,  M1, M2, API);
-
 #define SPARSE_SMM_BOOL_OP(F, OP, M1, M2, LHS_ZERO, RHS_ZERO) \
   SparseBoolMatrix \
   F (const M1& m1, const M2& m2) \
@@ -1492,7 +1352,7 @@
       { \
         if (m1_nr != 0 || m1_nc != 0) \
           { \
-            /* Count num of non-zero elements */ \
+            /* Count num of nonzero elements */ \
             octave_idx_type nel = 0; \
             for (octave_idx_type j = 0; j < m1_nc; j++) \
               for (octave_idx_type i = 0; i < m1_nr; i++) \
@@ -1535,11 +1395,6 @@
 #define SPARSE_SMM_BOOL_OPS(M1, M2, ZERO) \
   SPARSE_SMM_BOOL_OPS2(M1, M2, ZERO, ZERO)
 
-#define SPARSE_SMM_OP_DECLS(R1, R2, M1, M2, API) \
-  SPARSE_SMM_BIN_OP_DECLS (R1, R2, M1, M2, API) \
-  SPARSE_SMM_CMP_OP_DECLS (M1, M2, API) \
-  SPARSE_SMM_BOOL_OP_DECLS (M1, M2, API)
-
 // Avoid some code duplication.  Maybe we should use templates.
 
 #define SPARSE_CUMSUM(RET_TYPE, ELT_TYPE, FCN)  \
@@ -1836,7 +1691,7 @@
 
 #define SPARSE_ANY_OP(DIM) SPARSE_ANY_ALL_OP (DIM, false, false, !=, true)
 
-#define SPARSE_SPARSE_MUL( RET_TYPE, RET_EL_TYPE, EL_TYPE ) \
+#define SPARSE_SPARSE_MUL(RET_TYPE, RET_EL_TYPE, EL_TYPE) \
   octave_idx_type nr = m.rows (); \
   octave_idx_type nc = m.cols (); \
   \
@@ -1930,10 +1785,10 @@
           retval.change_capacity (nel); \
           /* The optimal break-point as estimated from simulations */ \
           /* Note that Mergesort is O(nz log(nz)) while searching all */ \
-          /* values is O(nr), where nz here is non-zero per row of */ \
+          /* values is O(nr), where nz here is nonzero per row of */ \
           /* length nr. The test itself was then derived from the */ \
           /* simulation with random square matrices and the observation */ \
-          /* of the number of non-zero elements in the output matrix */ \
+          /* of the number of nonzero elements in the output matrix */ \
           /* it was found that the breakpoints were */ \
           /*   nr: 500  1000  2000  5000 10000 */ \
           /*   nz:   6    25    97   585  2202 */ \
@@ -2005,7 +1860,7 @@
         } \
     }
 
-#define SPARSE_FULL_MUL( RET_TYPE, EL_TYPE, ZERO ) \
+#define SPARSE_FULL_MUL(RET_TYPE, EL_TYPE, ZERO) \
   octave_idx_type nr = m.rows (); \
   octave_idx_type nc = m.cols (); \
   \
@@ -2040,7 +1895,7 @@
       return retval; \
     }
 
-#define SPARSE_FULL_TRANS_MUL( RET_TYPE, EL_TYPE, ZERO, CONJ_OP ) \
+#define SPARSE_FULL_TRANS_MUL(RET_TYPE, EL_TYPE, ZERO, CONJ_OP) \
   octave_idx_type nr = m.rows (); \
   octave_idx_type nc = m.cols (); \
   \
@@ -2076,7 +1931,7 @@
       return retval; \
     }
 
-#define FULL_SPARSE_MUL( RET_TYPE, EL_TYPE, ZERO ) \
+#define FULL_SPARSE_MUL(RET_TYPE, EL_TYPE, ZERO) \
   octave_idx_type nr = m.rows (); \
   octave_idx_type nc = m.cols (); \
   \
@@ -2112,7 +1967,7 @@
       return retval; \
     }
 
-#define FULL_SPARSE_MUL_TRANS( RET_TYPE, EL_TYPE, ZERO, CONJ_OP ) \
+#define FULL_SPARSE_MUL_TRANS(RET_TYPE, EL_TYPE, ZERO, CONJ_OP) \
   octave_idx_type nr = m.rows (); \
   octave_idx_type nc = m.cols (); \
   \
--- a/liboctave/operators/Sparse-perm-op-defs.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/operators/Sparse-perm-op-defs.h	Mon Jan 12 09:17:35 2015 -0800
@@ -67,17 +67,7 @@
       return SM ();
     }
 
-  if (p.is_row_perm ())
-    {
-      // Form the column permutation and then call the colpm_sm routine.
-      const octave_idx_type *prow = p.pvec ().data ();
-      OCTAVE_LOCAL_BUFFER (octave_idx_type, pcol, nr);
-      for (octave_idx_type i = 0; i < nr; ++i)
-        pcol[prow[i]] = i;
-      return octinternal_do_mul_colpm_sm (pcol, a);
-    }
-  else
-    return octinternal_do_mul_colpm_sm (p.pvec ().data (), a);
+  return octinternal_do_mul_colpm_sm (p.col_perm_vec ().data (), a);
 }
 
 template <typename SM>
@@ -163,10 +153,7 @@
       return SM ();
     }
 
-  if (p.is_row_perm ())
-    return octinternal_do_mul_sm_rowpm (a, p.pvec ().data ());
-  else
-    return octinternal_do_mul_sm_colpm (a, p.pvec ().data ());
+  return octinternal_do_mul_sm_colpm (a, p.col_perm_vec ().data ());
 }
 
 #endif // octave_Sparse_perm_op_defs_h
--- a/liboctave/operators/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/operators/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -33,6 +33,7 @@
   operators/mx-op-decl.h \
   operators/mx-op-defs.h \
   operators/Sparse-diag-op-defs.h \
+  operators/Sparse-op-decls.h \
   operators/Sparse-op-defs.h \
   operators/Sparse-perm-op-defs.h
 
@@ -67,3 +68,4 @@
 
 DISTCLEANFILES += $(BUILT_LIBOPERATORS_SOURCES)
 
+liboctave_la_LIBADD += operators/liboperators.la
--- a/liboctave/operators/mx-inlines.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/operators/mx-inlines.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -27,6 +27,7 @@
 
 #include <cstddef>
 #include <cmath>
+#include <cstring>
 #include <memory>
 
 #include "quit.h"
@@ -485,6 +486,14 @@
 #define OP_RED_SUMSQ(ac, el) ac += el*el
 #define OP_RED_SUMSQC(ac, el) ac += cabsq (el)
 
+inline void op_dble_prod (double& ac, float el)
+{ ac *= el; }
+inline void op_dble_prod (Complex& ac, const FloatComplex& el)
+{ ac *= el; } // FIXME: guaranteed?
+template <class T>
+inline void op_dble_prod (double& ac, const octave_int<T>& el)
+{ ac *= el.double_value (); }
+
 inline void op_dble_sum (double& ac, float el)
 { ac += el; }
 inline void op_dble_sum (Complex& ac, const FloatComplex& el)
@@ -514,6 +523,7 @@
 OP_RED_FCN (mx_inline_dsum, T, PROMOTE_DOUBLE(T), op_dble_sum, 0.0)
 OP_RED_FCN (mx_inline_count, bool, T, OP_RED_SUM, 0)
 OP_RED_FCN (mx_inline_prod, T, T, OP_RED_PROD, 1)
+OP_RED_FCN (mx_inline_dprod, T, PROMOTE_DOUBLE(T), op_dble_prod, 1)
 OP_RED_FCN (mx_inline_sumsq, T, T, OP_RED_SUMSQ, 0)
 OP_RED_FCN (mx_inline_sumsq, std::complex<T>, T, OP_RED_SUMSQC, 0)
 OP_RED_FCN (mx_inline_any, T, bool, OP_RED_ANYC, false)
@@ -539,6 +549,7 @@
 OP_RED_FCN2 (mx_inline_dsum, T, PROMOTE_DOUBLE(T), op_dble_sum, 0.0)
 OP_RED_FCN2 (mx_inline_count, bool, T, OP_RED_SUM, 0)
 OP_RED_FCN2 (mx_inline_prod, T, T, OP_RED_PROD, 1)
+OP_RED_FCN2 (mx_inline_dprod, T, PROMOTE_DOUBLE(T), op_dble_prod, 0.0)
 OP_RED_FCN2 (mx_inline_sumsq, T, T, OP_RED_SUMSQ, 0)
 OP_RED_FCN2 (mx_inline_sumsq, std::complex<T>, T, OP_RED_SUMSQC, 0)
 
@@ -612,6 +623,7 @@
 OP_RED_FCNN (mx_inline_dsum, T, PROMOTE_DOUBLE(T))
 OP_RED_FCNN (mx_inline_count, bool, T)
 OP_RED_FCNN (mx_inline_prod, T, T)
+OP_RED_FCNN (mx_inline_dprod, T, PROMOTE_DOUBLE(T))
 OP_RED_FCNN (mx_inline_sumsq, T, T)
 OP_RED_FCNN (mx_inline_sumsq, std::complex<T>, T)
 OP_RED_FCNN (mx_inline_any, T, bool)
@@ -1345,8 +1357,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/operators/mx-op-defs.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/operators/mx-op-defs.h	Mon Jan 12 09:17:35 2015 -0800
@@ -25,6 +25,7 @@
 #if !defined (octave_mx_op_defs_h)
 #define octave_mx_op_defs_h 1
 
+#include "lo-array-gripes.h"
 #include "mx-op-decl.h"
 #include "mx-inlines.cc"
 
@@ -606,13 +607,8 @@
     gripe_nonconformant ("operator *", p.rows (), p.columns (), nr, nc); \
   else \
     { \
-      if (p.is_col_perm ()) \
-        { \
-          result = M (nr, nc); \
-          result.assign (p.pvec (), idx_vector::colon, x); \
-        } \
-      else \
-        result = x.index (p.pvec (), idx_vector::colon); \
+      result = M (nr, nc); \
+      result.assign (p.col_perm_vec (), idx_vector::colon, x); \
     } \
   \
   return result; \
@@ -627,15 +623,7 @@
   if (p.rows () != nc) \
     gripe_nonconformant ("operator *", nr, nc, p.rows (), p.columns ()); \
   else \
-    { \
-      if (p.is_col_perm ()) \
-        result = x.index (idx_vector::colon, p.pvec ()); \
-      else \
-        { \
-          result = M (nr, nc); \
-          result.assign (idx_vector::colon, p.pvec (), x); \
-        } \
-    } \
+    result = x.index (idx_vector::colon, p.col_perm_vec ()); \
   \
   return result; \
 }
--- a/liboctave/operators/sparse-mk-ops.awk	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/operators/sparse-mk-ops.awk	Mon Jan 12 09:17:35 2015 -0800
@@ -170,6 +170,10 @@
                 printf ("#include \"%s\"\n", rhs_header) >> h_file;
             }
 
+          ## FIXME: it might be nice to only include the declarations
+          ## of the operators that are actually needed instead of
+          ## including all of them.
+          printf ("#include \"mx-ops.h\"\n") >> h_file;
           printf ("#include \"Sparse-op-defs.h\"\n") >> h_file;
 
           if (bin_ops)
--- a/liboctave/system/file-ops.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/system/file-ops.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -39,6 +39,10 @@
 #include "pathmax.h"
 #include "canonicalize.h"
 
+extern "C" {
+#include <tempname.h>
+}
+
 #include "dir-ops.h"
 #include "file-ops.h"
 #include "file-stat.h"
@@ -678,21 +682,37 @@
 
   std::string retval;
 
-  const char *pdir = dir.empty () ? 0 : dir.c_str ();
+  // get dir path to use for template
+  std::string templatename;
+  if (dir.empty ())
+    templatename = octave_env::get_temp_directory ();
+  else if (! file_stat (dir, false).is_dir ())
+    templatename = octave_env::get_temp_directory ();
+  else
+    templatename = dir;
 
-  const char *ppfx = pfx.empty () ? 0 : pfx.c_str ();
-
-  char *tmp = tempnam (pdir, ppfx);
+  // add dir sep char if it is not there
+  if (*templatename.rbegin () != file_ops::dir_sep_char ())
+    templatename += file_ops::dir_sep_char ();
 
-  if (tmp)
-    {
-      retval = tmp;
+  if (pfx.empty ())
+    templatename += "file";
+  else
+    templatename += pfx;
+
+  // add the required XXXXXX for the template
+  templatename += "XXXXXX";
 
-      free (tmp);
-    }
+  // create and copy template to char array for call to gen_tempname
+  char tname [templatename.length () + 1];
+
+  strcpy (tname, templatename.c_str ());
+
+  if (gen_tempname (tname, 0, 0, GT_NOCREATE) == -1)
+    msg = gnulib::strerror (errno);
   else
-    msg = gnulib::strerror (errno);
-
+    retval = tname;
+  
   return retval;
 }
 
--- a/liboctave/system/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/system/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -18,10 +18,6 @@
   system/sysdir.h \
   system/syswait.h
 
-SYSTEM_C_SRC = \
-  system/tempnam.c \
-  system/tempname.c
-
 SYSTEM_SRC = \
   system/dir-ops.cc \
   system/file-ops.cc \
@@ -33,11 +29,11 @@
   system/oct-passwd.cc \
   system/oct-syscalls.cc \
   system/oct-time.cc \
-  system/oct-uname.cc \
-  $(SYSTEM_C_SRC)
+  system/oct-uname.cc
 
 noinst_LTLIBRARIES += system/libsystem.la
 
 system_libsystem_la_SOURCES = $(SYSTEM_SRC)
 system_libsystem_la_CPPFLAGS = $(liboctave_la_CPPFLAGS)
 
+liboctave_la_LIBADD += system/libsystem.la
--- a/liboctave/system/oct-env.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/system/oct-env.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -150,6 +150,13 @@
 }
 
 std::string
+octave_env::get_temp_directory ()
+{
+  return (instance_ok ())
+         ? instance->do_get_temp_directory () : std::string ();
+}
+
+std::string
 octave_env::get_program_name (void)
 {
   return (instance_ok ())
@@ -184,6 +191,45 @@
          ? instance->do_get_host_name () : std::string ();
 }
 
+std::string
+octave_env::do_get_temp_directory (void) const
+{
+  std::string tempd;
+
+#if defined (__MINGW32__) || defined (_MSC_VER)
+  
+  tempd = do_getenv ("TEMP");
+
+  if (tempd.empty ())
+    tempd = do_getenv ("TMP");
+
+  #if defined (P_tmpdir)
+  if (tempd.empty ())
+    tempd = P_tmpdir;
+  #endif
+
+  // Some versions of MinGW and MSVC either don't define P_tmpdir, or
+  // define it to a single backslash.  In such cases just use C:\temp.
+  if (tempd.empty () || tempd == "\\")
+    tempd = "c:\\temp";
+
+#else    // Unix-like OS
+
+  tempd = do_getenv ("TMP");
+
+  #if defined (P_tmpdir)
+  if (tempd.empty ())
+    tempd = P_tmpdir;
+  #else
+  if (tempd.empty ())
+    tempd = "/tmp";
+  #endif
+
+#endif
+
+  return tempd;
+}
+
 // FIXME: this leaves no way to distinguish between a
 // variable that is not set and one that is set to the empty string.
 // Is this a problem?
--- a/liboctave/system/oct-env.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/system/oct-env.h	Mon Jan 12 09:17:35 2015 -0800
@@ -51,6 +51,8 @@
 
   static std::string get_home_directory (void);
 
+  static std::string get_temp_directory (void);
+
   static std::string get_program_name (void);
 
   static std::string get_program_invocation_name (void);
@@ -88,6 +90,8 @@
 
   std::string do_get_home_directory (void) const;
 
+  std::string do_get_temp_directory (void) const;
+
   std::string do_get_user_name (void) const;
 
   std::string do_get_host_name (void) const;
--- a/liboctave/system/tempnam.c	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/* Copyright (C) 1991, 1993 Free Software Foundation, Inc.
-This file is part of the GNU C Library.
-
-The GNU C Library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Library General Public License as
-published by the Free Software Foundation; either version 2 of the
-License, or (at your option) any later version.
-
-The GNU C Library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-Library General Public License for more details.
-
-You should have received a copy of the GNU Library General Public
-License along with the GNU C Library; see the file COPYING.LIB.  If
-not, write to the Free Software Foundation, Inc., 51 Franklin Street,
-Fifth Floor, Boston, MA  02110-1301, USA.  */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifndef HAVE_TEMPNAM
-
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-extern char *__stdio_gen_tempname (const char *dir, const char *pfx,
-                                   int dir_search, size_t *lenptr,
-                                   FILE **streamptr);
-
-/* Generate a unique temporary filename using up to five characters of PFX
-   if it is not NULL.  The directory to put this file in is searched for
-   as follows: First the environment variable "TMPDIR" is checked.
-   If it contains the name of a writable directory, that directory is used.
-   If not and if DIR is not NULL, that value is checked.  If that fails,
-   P_tmpdir is tried and finally "/tmp".  The storage for the filename
-   is allocated by `malloc'.  */
-char *
-tempnam (const char *dir, const char *pfx)
-{
-  size_t len;
-  register char *s;
-  register char *t = __stdio_gen_tempname (dir, pfx, 1, &len, (FILE **) NULL);
-
-  if (t == NULL)
-    return NULL;
-
-  s = (char *) malloc (len);
-  if (s == NULL)
-    return NULL;
-
-  (void) memcpy (s, t, len);
-  return s;
-}
-
-#endif
--- a/liboctave/system/tempname.c	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,207 +0,0 @@
-/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
-This file is part of the GNU C Library.
-
-The GNU C Library is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the
-License, or (at your option) any later version.
-
-The GNU C Library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public
-License along with the GNU C Library; see the file COPYING.  If
-not, write to the Free Software Foundation, Inc., 51 Franklin Street,
-Fifth Floor, Boston, MA  02110-1301, USA.  */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifndef HAVE_TEMPNAM
-
-#include <errno.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <fcntl.h>
-
-#include "statdefs.h"
-
-#ifndef FILENAME_MAX
-#ifdef MAXPATHLEN
-#define FILENAME_MAX MAXPATHLEN
-#else
-#define FILENAME_MAX 1024
-#endif
-#endif
-
-#ifndef P_tmpdir
-#define P_tmpdir "/usr/tmp/"
-#endif
-
-/* Return nonzero if DIR is an existent directory.  */
-static int
-diraccess (const char *dir)
-{
-  struct stat buf;
-  return stat (dir, &buf) == 0 && S_ISDIR (buf.st_mode);
-}
-
-/* Return nonzero if FILE exists.  */
-static int
-exists (const char *file)
-{
-  /* We can stat the file even if we can't read its data.  */
-  struct stat st;
-  int save = errno;
-  if (stat (file, &st) == 0)
-    return 1;
-  else
-    {
-      /* We report that the file exists if stat failed for a reason other
-         than nonexistence.  In this case, it may or may not exist, and we
-         don't know; but reporting that it does exist will never cause any
-         trouble, while reporting that it doesn't exist when it does would
-         violate the interface of __stdio_gen_tempname.  */
-      int exists = errno != ENOENT;
-      errno = save;
-      return exists;
-    }
-}
-
-
-/* These are the characters used in temporary filenames.  */
-static const char letters[] =
-  "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
-
-/* Generate a temporary filename and return it (in a static buffer).  If
-   STREAMPTR is not NULL, open a stream "w+b" on the file and set
-   *STREAMPTR to it.  If DIR_SEARCH is nonzero, DIR and PFX are used as
-   described for tempnam.  If not, a temporary filename in P_tmpdir with no
-   special prefix is generated.  If LENPTR is not NULL, *LENPTR is set the
-   to length (including the terminating '\0') of the resultant filename,
-   which is returned.  This goes through a cyclic pattern of all possible
-   filenames consisting of five decimal digits of the current pid and three
-   of the characters in `letters'.  Data for tempnam and tmpnam is kept
-   separate, but when tempnam is using P_tmpdir and no prefix (i.e, it is
-   identical to tmpnam), the same data is used.  Each potential filename is
-   tested for an already-existing file of the same name, and no name of an
-   existing file will be returned.  When the cycle reaches its end
-   (12345ZZZ), NULL is returned.  */
-char *
-__stdio_gen_tempname (const char *dir, const char *pfx,
-                      int dir_search, size_t *lenptr,
-                      FILE **streamptr)
-{
-  int saverrno = errno;
-  static const char tmpdir[] = P_tmpdir;
-  static size_t indices[2];
-  size_t *idx;
-  static char buf[FILENAME_MAX];
-  static pid_t oldpid = (pid_t) 0;
-  pid_t pid = getpid ();
-  register size_t len, plen, dlen;
-
-  if (dir_search)
-    {
-      register const char *d = getenv ("TMPDIR");
-      if (d != NULL && !diraccess (d))
-        d = NULL;
-      if (d == NULL && dir != NULL && diraccess (dir))
-        d = dir;
-      if (d == NULL && diraccess (tmpdir))
-        d = tmpdir;
-      if (d == NULL && diraccess ("/tmp"))
-        d = "/tmp";
-      if (d == NULL)
-        {
-          errno = ENOENT;
-          return NULL;
-        }
-      dir = d;
-    }
-  else
-    dir = tmpdir;
-
-  dlen = strlen (dir);
-
-  /* Remove trailing slashes from the directory name.  */
-  while (dlen > 1 && dir[dlen - 1] == '/')
-    --dlen;
-
-  if (pfx != NULL && *pfx != '\0')
-    {
-      plen = strlen (pfx);
-      if (plen > 5)
-        plen = 5;
-    }
-  else
-    plen = 0;
-
-  if (dir != tmpdir && !strcmp (dir, tmpdir))
-    dir = tmpdir;
-  idx = &indices[(plen == 0 && dir == tmpdir) ? 1 : 0];
-
-  if (pid != oldpid)
-    {
-      oldpid = pid;
-      indices[0] = indices[1] = 0;
-    }
-
-  len = dlen + 1 + plen + 5 + 3;
-  for (; *idx < ((sizeof (letters) - 1) * (sizeof (letters) - 1) *
-                 (sizeof (letters) - 1));
-       ++*idx)
-    {
-      /* Construct a file name and see if it already exists.
-
-         We use a single counter in *IDX to cycle each of three
-         character positions through each of 62 possible letters.  */
-
-      if (sizeof (buf) < len)
-        return NULL;
-
-      sprintf (buf, "%.*s/%.*s%.5d%c%c%c",
-               (int) dlen, dir, (int) plen,
-               pfx, pid % 100000,
-               letters[*idx
-                       % (sizeof (letters) - 1)],
-               letters[(*idx / (sizeof (letters) - 1))
-                       % (sizeof (letters) - 1)],
-               letters[(*idx / ((sizeof (letters) - 1) *
-                                (sizeof (letters) - 1)))
-                       % (sizeof (letters) - 1)]
-              );
-
-      if (! buf || strlen (buf) != (int) len)
-        return NULL;
-
-      if (streamptr != NULL)
-        abort ();
-      else if (exists (buf))
-        continue;
-
-      /* If the file already existed we have continued the loop above,
-         so we only get here when we have a winning name to return.  */
-
-      errno = saverrno;
-
-      if (lenptr != NULL)
-        *lenptr = len + 1;
-      return buf;
-    }
-
-  /* We got out of the loop because we ran out of combinations to try.  */
-  errno = EEXIST;               /* ? */
-  return NULL;
-}
-
-#endif
--- a/liboctave/util/base-list.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/util/base-list.h	Mon Jan 12 09:17:35 2015 -0800
@@ -104,8 +104,6 @@
   // For backward compatibility.
   void append (const elt_type& s) { lst.push_back (s); }
 
-protected:
-
   octave_base_list (void) : lst () { }
 
   octave_base_list (const std::list<elt_type>& l) : lst (l) { }
--- a/liboctave/util/caseless-str.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/util/caseless-str.h	Mon Jan 12 09:17:35 2015 -0800
@@ -57,16 +57,16 @@
         char lp1 = std::tolower (*p1);
         char lp2 = std::tolower (*p2);
 
-        if ( lp1 > lp2 )
+        if (lp1 > lp2)
           return false;
-        if ( lp1 < lp2)
+        if (lp1 < lp2)
           return true;
 
         p1++;
         p2++;
       }
 
-    if ( length () >= s.length ())
+    if (length () >= s.length ())
       return false;
     else
       return true;
--- a/liboctave/util/cmd-hist.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/util/cmd-hist.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -145,8 +145,9 @@
           else if (tmp == "ignorespace")
             history_control |= HC_IGNSPACE;
           else
-            (*current_liboctave_warning_handler)
-              ("unknown histcontrol directive %s", tmp.c_str ());
+            (*current_liboctave_warning_with_id_handler)
+              ("Octave:history-control",
+               "unknown histcontrol directive %s", tmp.c_str ());
 
           if (end != std::string::npos)
             beg = end + 1;
@@ -779,8 +780,9 @@
 void
 command_history::do_process_histcontrol (const std::string&)
 {
-  (*current_liboctave_warning_handler)
-    ("readline is not linked, so history control is not available");
+  (*current_liboctave_warning_with_id_handler)
+    ("Octave:history-control",
+     "readline is not linked, so history control is not available");
 }
 
 void
--- a/liboctave/util/data-conv.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/util/data-conv.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -409,12 +409,11 @@
 
           if (input_is_output)
             {
-              input_is_output = false;
-
               s1 = s.substr (1, pos-1);
 
-              (*current_liboctave_warning_handler)
-                ("warning: ignoring leading * in fread precision");
+              (*current_liboctave_warning_with_id_handler)
+                ("Octave:fread-precision-syntax",
+                 "warning: ignoring leading * in fread precision");
             }
           else
             s1 = s.substr (0, pos);
@@ -587,7 +586,7 @@
       if (len > 0) \
         { \
           OCTAVE_LOCAL_BUFFER (TYPE, ptr, len); \
-          std::streamsize n_bytes = size * len; \
+          std::streamsize n_bytes = size * static_cast<std::streamsize> (len); \
           stream.read (reinterpret_cast<char *> (ptr), n_bytes); \
           if (swap) \
             swap_bytes< size > (ptr, len); \
@@ -610,7 +609,7 @@
           OCTAVE_LOCAL_BUFFER (TYPE, ptr, len); \
           for (octave_idx_type i = 0; i < len; i++) \
             ptr[i] = static_cast <TYPE> (data[i]);         \
-          std::streamsize n_bytes = size * len; \
+          std::streamsize n_bytes = size * static_cast<std::streamsize> (len); \
           stream.write (reinterpret_cast<char *> (ptr), n_bytes); \
         } \
     } \
@@ -809,7 +808,7 @@
     case LS_FLOAT:
       {
         OCTAVE_LOCAL_BUFFER (float, ptr, len);
-        std::streamsize n_bytes = 4 * len;
+        std::streamsize n_bytes = 4 * static_cast<std::streamsize> (len);
         is.read (reinterpret_cast<char *> (ptr), n_bytes);
         do_float_format_conversion (ptr, len, fmt);
         for (octave_idx_type i = 0; i < len; i++)
@@ -867,7 +866,7 @@
 
     case LS_FLOAT: // No conversion necessary.
       {
-        std::streamsize n_bytes = 4 * len;
+        std::streamsize n_bytes = 4 * static_cast<std::streamsize> (len);
         is.read (reinterpret_cast<char *> (data), n_bytes);
         do_float_format_conversion (data, len, fmt);
       }
@@ -876,7 +875,7 @@
     case LS_DOUBLE:
       {
         OCTAVE_LOCAL_BUFFER (double, ptr, len);
-        std::streamsize n_bytes = 8 * len;
+        std::streamsize n_bytes = 8 * static_cast<std::streamsize> (len);
         is.read (reinterpret_cast<char *> (ptr), n_bytes);
         do_double_format_conversion (ptr, len, fmt);
         for (octave_idx_type i = 0; i < len; i++)
@@ -974,7 +973,7 @@
       {
         char tmp_type = static_cast<char> (type);
         os.write (&tmp_type, 1);
-        std::streamsize n_bytes = 4 * len;
+        std::streamsize n_bytes = 4 * static_cast<std::streamsize> (len);
         os.write (reinterpret_cast <const char *> (data), n_bytes);
       }
       break;
--- a/liboctave/util/kpse.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/util/kpse.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -1549,8 +1549,9 @@
       /* What if there isn't a matching close brace? */
       if (! c)
         {
-          (*current_liboctave_warning_handler)
-            ("%s: Unmatched {", text.c_str ());
+          (*current_liboctave_warning_with_id_handler)
+            ("Octave:pathsearch-syntax",
+             "%s: Unmatched {", text.c_str ());
 
           result = string_vector (text);
         }
@@ -2545,8 +2546,9 @@
 {
   if (expanding_p (var))
     {
-      (*current_liboctave_warning_handler)
-        ("kpathsea: variable '%s' references itself (eventually)",
+      (*current_liboctave_warning_with_id_handler)
+        ("Octave:pathsearch-syntax",
+         "kpathsea: variable '%s' references itself (eventually)",
          var.c_str ());
     }
   else
@@ -2623,8 +2625,9 @@
 
               if (var_end == src_len)
                 {
-                  (*current_liboctave_warning_handler)
-                    ("%s: No matching } for ${", src.c_str ());
+                  (*current_liboctave_warning_with_id_handler)
+                    ("Octave:pathsearch-syntax",
+                     "%s: No matching } for ${", src.c_str ());
                   i = var_end - 1; /* will incr to eos at top of loop */
                 }
               else
@@ -2636,8 +2639,9 @@
           else
             {
               /* $<something-else>: error.  */
-              (*current_liboctave_warning_handler)
-                ("%s: Unrecognized variable construct '$%c'",
+              (*current_liboctave_warning_with_id_handler)
+                ("Octave:pathsearch-syntax",
+                 "%s: Unrecognized variable construct '$%c'",
                  src.c_str (), src[i]);
 
               /* Just ignore those chars and keep going.  */
--- a/liboctave/util/lo-array-gripes.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/util/lo-array-gripes.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -34,6 +34,10 @@
 
 const char *error_id_invalid_index = "Octave:invalid-index";
 
+const char *warning_id_nearly_singular_matrix = "Octave:nearly-singular-matrix";
+
+const char *warning_id_singular_matrix = "Octave:singular-matrix";
+
 void
 gripe_nan_to_logical_conversion (void)
 {
@@ -166,3 +170,19 @@
     ("A(I,J,...) = X: dimensions mismatch");
 }
 
+void
+gripe_singular_matrix (double rcond)
+{
+  if (rcond == 0.0)
+    {
+      (*current_liboctave_warning_with_id_handler)
+        (warning_id_singular_matrix,
+         "matrix singular to machine precision");
+    }
+  else
+    {
+      (*current_liboctave_warning_with_id_handler)
+        (warning_id_nearly_singular_matrix,
+         "matrix singular to machine precision, rcond = %g", rcond);
+    }
+}
--- a/liboctave/util/lo-array-gripes.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/util/lo-array-gripes.h	Mon Jan 12 09:17:35 2015 -0800
@@ -31,6 +31,10 @@
 
 extern OCTAVE_API const char *error_id_invalid_index;
 
+extern OCTAVE_API const char *warning_id_nearly_singular_matrix;
+
+extern OCTAVE_API const char *warning_id_singular_matrix;
+
 extern void OCTAVE_API
 gripe_nan_to_logical_conversion (void);
 
@@ -71,4 +75,7 @@
 extern void OCTAVE_API
 gripe_assignment_dimension_mismatch (void);
 
+extern void OCTAVE_API
+gripe_singular_matrix (double rcond = 0.0);
+
 #endif
--- a/liboctave/util/lo-ieee.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/util/lo-ieee.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -106,12 +106,6 @@
     return x;
 }
 
-int
-__lo_ieee_is_NaN_or_NA (double x)
-{
-  return __lo_ieee_isnan (x);
-}
-
 double
 lo_ieee_inf_value (void)
 {
@@ -188,12 +182,6 @@
   return (__lo_ieee_float_isnan (x) && (t.word == LO_IEEE_NA_FLOAT)) ? 1 : 0;
 }
 
-int
-__lo_ieee_float_is_NaN_or_NA (float x)
-{
-  return __lo_ieee_float_isnan (x);
-}
-
 float
 lo_ieee_float_inf_value (void)
 {
--- a/liboctave/util/lo-ieee.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/util/lo-ieee.h	Mon Jan 12 09:17:35 2015 -0800
@@ -74,7 +74,6 @@
 
 extern OCTAVE_API int __lo_ieee_is_NA (double);
 extern OCTAVE_API int __lo_ieee_is_old_NA (double);
-extern OCTAVE_API int __lo_ieee_is_NaN_or_NA (double) GCC_ATTR_DEPRECATED;
 extern OCTAVE_API double __lo_ieee_replace_old_NA (double);
 
 extern OCTAVE_API double lo_ieee_inf_value (void);
@@ -88,7 +87,6 @@
 extern OCTAVE_API int __lo_ieee_float_isinf (float x);
 
 extern OCTAVE_API int __lo_ieee_float_is_NA (float);
-extern OCTAVE_API int __lo_ieee_float_is_NaN_or_NA (float) GCC_ATTR_DEPRECATED;
 
 extern OCTAVE_API float lo_ieee_float_inf_value (void);
 extern OCTAVE_API float lo_ieee_float_na_value (void);
--- a/liboctave/util/lo-regexp.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/util/lo-regexp.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -179,8 +179,9 @@
                   if (!lookbehind_warned)
                     {
                       lookbehind_warned = true;
-                      (*current_liboctave_warning_handler)
-                        ("%s: arbitrary length lookbehind patterns are only supported up to length %d",
+                      (*current_liboctave_warning_with_id_handler)
+                        ("Octave:regexp-lookbehind-limit",
+                         "%s: arbitrary length lookbehind patterns are only supported up to length %d",
                          who.c_str (), MAXLOOKBEHIND);
                     }
 
@@ -282,8 +283,9 @@
         {
           // Try harder; start with default value for MATCH_LIMIT
           // and increase it.
-          (*current_liboctave_warning_handler)
-            ("your pattern caused PCRE to hit its MATCH_LIMIT; trying harder now, but this will be slow");
+          (*current_liboctave_warning_with_id_handler)
+            ("Octave:regexp-match-limit",
+             "your pattern caused PCRE to hit its MATCH_LIMIT; trying harder now, but this will be slow");
 
           pcre_extra pe;
 
--- a/liboctave/util/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/util/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -26,7 +26,6 @@
   util/oct-inttypes.h \
   util/oct-locbuf.h \
   util/oct-md5.h \
-  util/oct-mem.h \
   util/oct-mutex.h \
   util/oct-refcount.h \
   util/oct-rl-edit.h \
@@ -88,6 +87,8 @@
 util_libutil_la_SOURCES = $(UTIL_SRC)
 util_libutil_la_CPPFLAGS = \
   $(liboctave_la_CPPFLAGS) \
+  $(CURL_CPPFLAGS) \
   $(PCRE_CPPFLAGS) \
   $(SPARSE_XCPPFLAGS)
 
+liboctave_la_LIBADD += util/libutil.la
--- a/liboctave/util/oct-binmap.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/util/oct-binmap.h	Mon Jan 12 09:17:35 2015 -0800
@@ -226,8 +226,8 @@
     {
       octave_idx_type nz = ys.nnz ();
       Sparse<U> retval (ys.rows (), ys.cols (), nz);
-      copy_or_memcpy (nz, ys.ridx (), retval.ridx ());
-      copy_or_memcpy (ys.cols () + 1, ys.cidx (), retval.cidx ());
+      std::copy (ys.ridx (), ys.ridx () + nz, retval.ridx ());
+      std::copy (ys.cidx (), ys.cidx () + ys.cols () + 1, retval.cidx ());
 
       for (octave_idx_type i = 0; i < nz; i++)
         {
@@ -257,8 +257,8 @@
     {
       octave_idx_type nz = xs.nnz ();
       Sparse<U> retval (xs.rows (), xs.cols (), nz);
-      copy_or_memcpy (nz, xs.ridx (), retval.ridx ());
-      copy_or_memcpy (xs.cols () + 1, xs.cidx (), retval.cidx ());
+      std::copy (xs.ridx (), xs.ridx () + nz, retval.ridx ());
+      std::copy (xs.cidx (), xs.cidx () + xs.cols () + 1, retval.cidx ());
 
       for (octave_idx_type i = 0; i < nz; i++)
         {
--- a/liboctave/util/oct-locbuf.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/util/oct-locbuf.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -140,8 +140,12 @@
     }
   else
     {
-      (*current_liboctave_warning_handler)
-        ("octave_chunk_buffer::clear: %d active allocations remain!",
+      // FIXME: Doesn't this situation represent a programming error of
+      // some kind?  If so, maybe this should be a fatal error?
+
+      (*current_liboctave_warning_with_id_handler)
+        ("Octave:local-buffer-inconsistency",
+         "octave_chunk_buffer::clear: %d active allocations remain!",
          active);
     }
 }
--- a/liboctave/util/oct-mem.h	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,160 +0,0 @@
-/*
-
-Copyright (C) 2009-2013 VZLU Prague
-
-This file is part of Octave.
-
-Octave is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3 of the License, or (at your
-option) any later version.
-
-Octave is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#if !defined (octave_oct_mem_h)
-#define octave_oct_mem_h 1
-
-#include <cstddef>
-#include <cstring>
-#include <algorithm>
-
-#include "oct-cmplx.h"
-#include "oct-inttypes.h"
-
-// NOTE: These functions are used to optimize stuff where performance is a
-// priority. They assume that the std::complex and octave_int can be
-// manipulated as plain memory, an assumption that is always true in practice
-// but not theoretically guaranteed by the C++ standard. In the future, C++ may
-// provide a better way to accomplish these tasks.
-
-inline size_t safe_size_comp (size_t n, size_t size)
-{
-  if (n > static_cast<size_t> (-1) / size)
-    throw std::bad_alloc ();
-  return n * size;
-}
-
-// Unaliased copy. This boils down to memcpy, even for octave_int and
-// complex types.
-
-template <class T>
-inline void copy_or_memcpy (size_t n, const T *src, T *dest)
-{ std::copy (src, src + n, dest); }
-
-#define DEFINE_POD_UCOPY(T) \
-inline void copy_or_memcpy (size_t n, const T *src, T *dest) \
-{ std::memcpy (dest, src, n * sizeof (T)); }
-
-DEFINE_POD_UCOPY (double)
-DEFINE_POD_UCOPY (float)
-DEFINE_POD_UCOPY (char)
-DEFINE_POD_UCOPY (short)
-DEFINE_POD_UCOPY (int)
-DEFINE_POD_UCOPY (long)
-DEFINE_POD_UCOPY (unsigned char)
-DEFINE_POD_UCOPY (unsigned short)
-DEFINE_POD_UCOPY (unsigned int)
-DEFINE_POD_UCOPY (unsigned long)
-
-DEFINE_POD_UCOPY (Complex)
-DEFINE_POD_UCOPY (FloatComplex)
-
-template <class T>
-DEFINE_POD_UCOPY (octave_int<T>)
-
-// Fill by value, with a check for zero. This boils down to memset if value is
-// a POD zero.
-template <class T>
-inline void fill_or_memset (size_t n, const T& value, T *dest)
-{ std::fill_n (dest, n, value); }
-
-template <class T>
-inline bool helper_is_zero_mem (const T& value)
-{
-  // get integer type of the same size.
-  typedef typename query_integer_type<sizeof (T), false>::type IT;
-  return *(reinterpret_cast<const IT *>(&value)) == 0;
-}
-
-template <class T>
-inline bool helper_is_zero_mem (const std::complex<T>& value)
-{
-  return (helper_is_zero_mem (value.real ())
-          && helper_is_zero_mem (value.imag ()));
-}
-
-template <class T>
-inline bool helper_is_zero_mem (const octave_int<T>& value)
-{ return value.value () == T (); }
-
-#define DEFINE_POD_FILL(T) \
-inline void fill_or_memset (size_t n, const T& value, T *dest) \
-{ \
-  if (helper_is_zero_mem (value)) \
-    std::memset (dest, 0, n * sizeof (T)); \
-  else \
-    std::fill_n (dest, n, value); \
-}
-
-DEFINE_POD_FILL (double)
-DEFINE_POD_FILL (float)
-DEFINE_POD_FILL (char)
-DEFINE_POD_FILL (short)
-DEFINE_POD_FILL (int)
-DEFINE_POD_FILL (long)
-DEFINE_POD_FILL (unsigned char)
-DEFINE_POD_FILL (unsigned short)
-DEFINE_POD_FILL (unsigned int)
-DEFINE_POD_FILL (unsigned long)
-
-DEFINE_POD_FILL (Complex)
-DEFINE_POD_FILL (FloatComplex)
-
-template <class T>
-DEFINE_POD_FILL (octave_int<T>)
-
-// Uninitialized allocation.
-// Will not initialize memory for complex and octave_int.
-// Memory allocated by octave_new should be freed by octave_delete.
-template <class T>
-inline T *no_ctor_new (size_t n)
-{
-  // Some systems let us allocate > 2GB memory even though size_t, which is
-  // either buggy or completely cuckoo, so let's check here to stay safe.
-  safe_size_comp (n, sizeof (T));
-  return new T [n];
-}
-template <class T>
-inline void no_ctor_delete (T *ptr)
-{ delete [] ptr; }
-
-#define DEFINE_POD_NEW_DELETE(T) \
-template <> \
-inline T *no_ctor_new<T > (size_t n) \
-{ return reinterpret_cast<T *> (new char [safe_size_comp (n, sizeof (T))]); } \
-template <> \
-inline void no_ctor_delete<T > (T *ptr) \
-{ delete [] reinterpret_cast<char *> (ptr); }
-
-DEFINE_POD_NEW_DELETE (Complex)
-DEFINE_POD_NEW_DELETE (FloatComplex)
-
-DEFINE_POD_NEW_DELETE (octave_int8)
-DEFINE_POD_NEW_DELETE (octave_int16)
-DEFINE_POD_NEW_DELETE (octave_int32)
-DEFINE_POD_NEW_DELETE (octave_int64)
-DEFINE_POD_NEW_DELETE (octave_uint8)
-DEFINE_POD_NEW_DELETE (octave_uint16)
-DEFINE_POD_NEW_DELETE (octave_uint32)
-DEFINE_POD_NEW_DELETE (octave_uint64)
-
-#endif /* octave_oct_mem_h */
--- a/liboctave/util/oct-shlib.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/util/oct-shlib.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -87,8 +87,9 @@
     {
       tm_loaded = fs.mtime ();
 
-      (*current_liboctave_warning_handler)
-        ("library %s not reloaded due to existing references", file.c_str ());
+      (*current_liboctave_warning_with_id_handler)
+        ("Octave:library-reload",
+         "library %s not reloaded due to existing references", file.c_str ());
     }
 }
 
--- a/liboctave/util/oct-sparse.h	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/util/oct-sparse.h	Mon Jan 12 09:17:35 2015 -0800
@@ -94,4 +94,16 @@
 #endif
 #endif
 
+// Cope with new suitesparse versions
+//
+#if defined (SUITESPARSE_VERSION)
+# if SUITESPARSE_VERSION >= SUITESPARSE_VER_CODE (4, 3)
+#  define SUITESPARSE_ASSIGN_FPTR(f_name, f_var, f_assign) (SuiteSparse_config.f_name = f_assign)
+#  define SUITESPARSE_ASSIGN_FPTR2(f_name, f_var, f_assign) (SuiteSparse_config.f_name = CHOLMOD_NAME (f_assign))
+# else
+#  define SUITESPARSE_ASSIGN_FPTR(f_name, f_var, f_assign) (f_var = f_assign)
+#  define SUITESPARSE_ASSIGN_FPTR2(f_name, f_var, f_assign) (f_var = CHOLMOD_NAME (f_assign))
+# endif
 #endif
+
+#endif
--- a/liboctave/util/sparse-util.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/util/sparse-util.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -48,12 +48,9 @@
   // Ignore CHOLMOD_NOT_POSDEF, since we handle that in Fchol as an
   // error or exit status.
   if (status != CHOLMOD_NOT_POSDEF)
-    {
-      (*current_liboctave_warning_handler)("warning %i, at line %i in file %s",
-                                           status, line, file);
-
-      (*current_liboctave_warning_handler)(message);
-    }
+    (*current_liboctave_warning_with_id_handler)
+      ("Octave:cholmod-message", "warning %i, at line %i in file %s: %s",
+       status, line, file, message);
 }
 
 int
--- a/liboctave/util/str-vec.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/liboctave/util/str-vec.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -250,14 +250,10 @@
     nc = 1;
 
   // Calculate the number of rows that will be in each column except
-  // possibly  for a short column on the right.
+  // possibly for a short column on the right.
 
   octave_idx_type nr = total_names / nc + (total_names % nc != 0);
 
-  // Recalculate columns based on rows.
-
-  nc = total_names / nr + (total_names % nr != 0);
-
   octave_idx_type count;
   for (octave_idx_type row = 0; row < nr; row++)
     {
--- a/m4/acinclude.m4	Mon Jan 12 09:13:19 2015 -0800
+++ b/m4/acinclude.m4	Mon Jan 12 09:17:35 2015 -0800
@@ -598,7 +598,6 @@
     ;;
   esac
 
-  [TEXINFO_]m4_toupper([$1])=
   warn_$1="$3"
   m4_set_add([summary_warning_list], [warn_$1])
 
@@ -623,8 +622,7 @@
         m4_ifblank([$8], [
           warn_$1=
           AC_DEFINE([HAVE_]m4_toupper([$1]), 1,
-            [Define to 1 if $2 is available.])
-          [TEXINFO_]m4_toupper([$1])="@set [HAVE_]m4_toupper([$1])"], [$8])
+            [Define to 1 if $2 is available.])], [$8])
       fi
     fi
     m4_ifnblank([$6], [AC_LANG_POP($6)])
@@ -634,7 +632,6 @@
   fi
 
   AC_SUBST(m4_toupper([$1])_LIBS)
-  AC_SUBST([TEXINFO_]m4_toupper([$1]))
   if test -n "$warn_$1"; then
     AC_MSG_WARN([$warn_$1])
     m4_toupper([$1])_LIBS=
@@ -1810,6 +1807,58 @@
   fi
 ])
 dnl
+dnl Check for raw_fd_ostream API
+dnl
+AC_DEFUN([OCTAVE_LLVM_RAW_FD_OSTREAM_API], [
+  AC_CACHE_CHECK([check LLVM::raw_fd_ostream arg type is llvm::sys:fs],
+    [octave_cv_raw_fd_ostream_arg_is_llvm_sys_fs],
+    [AC_LANG_PUSH(C++)
+      AC_COMPILE_IFELSE(
+        [AC_LANG_PROGRAM([[
+          #include <llvm/Support/raw_os_ostream.h>
+          ]], [[
+          std::string str;
+          llvm::raw_fd_ostream fout ("", str, llvm::sys::fs::F_Binary);
+        ]])],
+        octave_cv_raw_fd_ostream_arg_is_llvm_sys_fs=yes,
+        octave_cv_raw_fd_ostream_arg_is_llvm_sys_fs=no)
+    AC_LANG_POP(C++)
+  ])
+  if test $octave_cv_raw_fd_ostream_arg_is_llvm_sys_fs = yes; then
+    AC_DEFINE(RAW_FD_OSTREAM_ARG_IS_LLVM_SYS_FS, 1,
+      [Define to 1 if LLVM::raw_fd_ostream arg type is llvm::sys:fs.])
+  fi
+])
+dnl
+dnl Check for legacy::PassManager API
+dnl
+AC_DEFUN([OCTAVE_LLVM_LEGACY_PASSMANAGER_API], [
+  AC_CACHE_CHECK([check for LLVM::legacy::PassManager],
+    [octave_cv_legacy_passmanager],
+    [AC_LANG_PUSH(C++)
+      save_LIBS="$LIBS"
+      LIBS="$LLVM_LIBS $LIBS"
+      AC_LINK_IFELSE(
+        [AC_LANG_PROGRAM([[
+          #include <llvm/IR/LegacyPassManager.h>
+          ]], [[
+          llvm::Module *module;
+          llvm::legacy::PassManager *module_pass_manager;
+          llvm::legacy::FunctionPassManager *pass_manager;      
+          module_pass_manager = new llvm::legacy::PassManager ();
+          pass_manager = new llvm::legacy::FunctionPassManager (module);
+        ]])],
+        octave_cv_legacy_passmanager=yes,
+        octave_cv_legacy_passmanager=no)
+      LIBS="$save_LIBS"
+    AC_LANG_POP(C++)
+  ])
+  if test $octave_cv_legacy_passmanager = yes; then
+    AC_DEFINE(LEGACY_PASSMANAGER, 1,
+      [Define to 1 if LLVM::legacy::PassManager exists.])
+  fi
+])
+dnl
 dnl Check for ar.
 dnl
 AC_DEFUN([OCTAVE_PROG_AR], [
--- a/run-octave.in	Mon Jan 12 09:13:19 2015 -0800
+++ b/run-octave.in	Mon Jan 12 09:17:35 2015 -0800
@@ -33,18 +33,21 @@
 d1="$top_srcdir/scripts"
 d2="$builddir/scripts"
 d3="$builddir/libinterp"
+d4="$top_srcdir/examples/data"
 
 d1_list=`$FIND "$d1" -type d -a ! \( \( -name private -o -name '@*' \) -a -prune \) -exec echo '{}' ';' | $SED 's/$/:/'`
 d2_list=`$FIND "$d2" -type d -a ! \( \( -name private -o -name '@*' \) -a -prune \) -exec echo '{}' ';' | $SED 's/$/:/'`
 d3_list=`$FIND "$d3" -type d -a ! \( \( -name private -o -name '@*' \) -a -prune \) -exec echo '{}' ';' | $SED 's/$/:/'`
+d4_list=`$FIND "$d4" -type d -exec echo '{}' ';' | $SED 's/$/:/'`
 
 d1_path=`echo "$d1_list" | $AWK '{ t = (s $0); s = t; } END { sub (/:$/, "", s); print s; }'`
 d2_path=`echo "$d2_list" | $AWK '{ t = (s $0); s = t; } END { sub (/:$/, "", s); print s; }'`
 d3_path=`echo "$d3_list" | $AWK '{ t = (s $0); s = t; } END { sub (/:$/, "", s); print s; }'`
+d4_path=`echo "$d4_list" | $AWK '{ t = (s $0); s = t; } END { sub (/:$/, "", s); print s; }'`
 
 octave_executable="$builddir/src/octave"
 
-LOADPATH="$d1_path:$d2_path:$d3_path"
+LOADPATH="$d1_path:$d2_path:$d3_path:$d4_path"
 IMAGEPATH="$top_srcdir/scripts/image"
 DOCFILE="$builddir/doc/interpreter/doc-cache"
 BUILT_IN_DOCSTRINGS_FILE="$builddir/libinterp/DOCSTRINGS"
@@ -69,6 +72,9 @@
   elif [ "x$1" = "x-valgrind" ]; then
     driver="valgrind --tool=memcheck"
     shift
+  elif [ "x$1" = "x-callgrind" ]; then
+    driver="valgrind --tool=callgrind"
+    shift
   elif [ "x$1" = "x-strace" ]; then
     driver="strace -o octave.trace"
     shift
--- a/scripts/@ftp/ascii.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/@ftp/ascii.m	Mon Jan 12 09:17:35 2015 -0800
@@ -30,3 +30,7 @@
   __ftp_ascii__ (f.curlhandle);
 endfunction
 
+
+## No test possible for interactive function.
+%!assert (1)
+
--- a/scripts/@ftp/binary.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/@ftp/binary.m	Mon Jan 12 09:17:35 2015 -0800
@@ -29,3 +29,7 @@
   __ftp_binary__ (f.curlhandle);
 endfunction
 
+
+## No test possible for interactive function.
+%!assert (1)
+
--- a/scripts/@ftp/cd.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/@ftp/cd.m	Mon Jan 12 09:17:35 2015 -0800
@@ -42,3 +42,7 @@
   path = __ftp_pwd__ (f.curlhandle);
 endfunction
 
+
+## No test possible for interactive function.
+%!assert (1)
+
--- a/scripts/@ftp/close.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/@ftp/close.m	Mon Jan 12 09:17:35 2015 -0800
@@ -27,3 +27,7 @@
   __ftp_close__ (f.curlhandle);
 endfunction
 
+
+## No test possible for interactive function.
+%!assert (1)
+
--- a/scripts/@ftp/delete.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/@ftp/delete.m	Mon Jan 12 09:17:35 2015 -0800
@@ -27,3 +27,7 @@
   __ftp_delete__ (f.curlhandle, file);
 endfunction
 
+
+## No test possible for interactive function.
+%!assert (1)
+
--- a/scripts/@ftp/dir.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/@ftp/dir.m	Mon Jan 12 09:17:35 2015 -0800
@@ -32,3 +32,7 @@
   endif
 endfunction
 
+
+## No test possible for interactive function.
+%!assert (1)
+
--- a/scripts/@ftp/display.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/@ftp/display.m	Mon Jan 12 09:17:35 2015 -0800
@@ -24,3 +24,7 @@
   printf (" mode: %s\n", __ftp_mode__ (obj.curlhandle));
 endfunction
 
+
+## No test possible for interactive function.
+%!assert (1)
+
--- a/scripts/@ftp/ftp.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/@ftp/ftp.m	Mon Jan 12 09:17:35 2015 -0800
@@ -51,7 +51,7 @@
     p.host = host;
     p.username = username;
     p.password = password;
-    p.curlhandle = tmpnam ("ftp-");
+    p.curlhandle = tempname ("ftp-");
     if (nargin > 0)
       p.curlhandle = __ftp__ (host, username, password);
     endif
@@ -59,3 +59,7 @@
   endif
 endfunction
 
+
+## No test possible for interactive function.
+%!assert (1)
+
--- a/scripts/@ftp/loadobj.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/@ftp/loadobj.m	Mon Jan 12 09:17:35 2015 -0800
@@ -34,3 +34,7 @@
   endif
 endfunction
 
+
+## No test possible for interactive function.
+%!assert (1)
+
--- a/scripts/@ftp/mget.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/@ftp/mget.m	Mon Jan 12 09:17:35 2015 -0800
@@ -36,3 +36,7 @@
   __ftp_mget__ (f.curlhandle, file);
 endfunction
 
+
+## No test possible for interactive function.
+%!assert (1)
+
--- a/scripts/@ftp/mkdir.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/@ftp/mkdir.m	Mon Jan 12 09:17:35 2015 -0800
@@ -27,3 +27,7 @@
   __ftp_mkdir__ (f.curlhandle, path);
 endfunction
 
+
+## No test possible for interactive function.
+%!assert (1)
+
--- a/scripts/@ftp/mput.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/@ftp/mput.m	Mon Jan 12 09:17:35 2015 -0800
@@ -34,3 +34,7 @@
   endif
 endfunction
 
+
+## No test possible for interactive function.
+%!assert (1)
+
--- a/scripts/@ftp/rename.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/@ftp/rename.m	Mon Jan 12 09:17:35 2015 -0800
@@ -28,3 +28,7 @@
   __ftp_rename__ (f.curlhandle, oldname, newname);
 endfunction
 
+
+## No test possible for interactive function.
+%!assert (1)
+
--- a/scripts/@ftp/rmdir.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/@ftp/rmdir.m	Mon Jan 12 09:17:35 2015 -0800
@@ -27,3 +27,7 @@
   __ftp_rmdir__ (f.curlhandle, path);
 endfunction
 
+
+## No test possible for interactive function.
+%!assert (1)
+
--- a/scripts/@ftp/saveobj.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/@ftp/saveobj.m	Mon Jan 12 09:17:35 2015 -0800
@@ -22,3 +22,7 @@
   b.dir = __ftp_pwd__ (a.curlhandle);
 endfunction
 
+
+## No test possible for interactive function.
+%!assert (1)
+
--- a/scripts/Makefile.am	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/Makefile.am	Mon Jan 12 09:17:35 2015 -0800
@@ -495,5 +495,5 @@
 
 distclean-local:
 	if [ "x$(srcdir)" != "x." ]; then \
-	  rm $(java_JAVA_IMAGES); \
+	  rm -f $(java_JAVA_IMAGES); \
 	fi
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/audio/@audioplayer/__get_properties__.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,67 @@
+## Copyright (C) 2013 Vytautas Jančauskas
+##
+## 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{properties} =} __get_properties__ (@var{player})
+## Return a struct containing all named properties of the audioplayer
+## object @var{player}.
+## @end deftypefn
+
+function props = __get_properties__ (player)
+
+  if (nargin != 1)
+    print_usage ();
+  endif
+
+  if (__player_isplaying__ (struct (player).player))
+    running = "on";
+  else
+    running = "off";
+  endif
+
+  props = struct ("BitsPerSample",
+                  __player_get_nbits__ (struct (player).player),
+
+                  "CurrentSample",
+                  __player_get_sample_number__ (struct (player).player),
+
+                  "DeviceID",
+                  __player_get_id__ (struct (player).player),
+
+                  "NumberOfChannels",
+                  __player_get_channels__ (struct (player).player),
+
+                  "Running",
+                  running,
+
+                  "SampleRate",
+                  __player_get_fs__ (struct (player).player),
+
+                  "TotalSamples",
+                  __player_get_total_samples__ (struct (player).player),
+
+                  "Tag",
+                  __player_get_tag__ (struct (player).player),
+
+                  "Type",
+                  "audioplayer",
+
+                  "UserData",
+                  __player_get_userdata__ (struct (player).player));
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/audio/@audioplayer/audioplayer.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,202 @@
+## Copyright (C) 2013 Vytautas Jančauskas
+##
+## 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{player} =} audioplayer (@var{y}, @var{fs})
+## @deftypefnx {Function File} {@var{player} =} audioplayer (@var{y}, @var{fs}, @var{nbits})
+## @deftypefnx {Function File} {@var{player} =} audioplayer (@var{y}, @var{fs}, @var{nbits}, @var{id})
+## @deftypefnx {Function File} {@var{player} =} audioplayer (@var{recorder})
+## @deftypefnx {Function File} {@var{player} =} audioplayer (@var{recorder}, @var{id})
+## Create an audioplayer object that will play back data @var{y} at sample
+## rate @var{fs}.  The optional arguments @var{nbits}, and @var{id}
+## specify the bit depth and player device id, respectively.  Device IDs
+## may be found using the audiodevinfo function.
+## Given an audioplayer object, use the data from the object to
+## initialize the player.
+## @end deftypefn
+##
+## The signal @var{y} can be a vector or a two dimensional array.
+##
+## The following example will create an audioplayer object that will play
+## back one second of white noise at 44100 sample rate using 8 bits per
+## sample.
+##
+## @example
+## @group
+## y = randn (2, 44100) - 0.5;
+## player = audioplayer (y, 44100, 8);
+## play (player);
+## @end group
+## @end example
+
+## FIXME: callbacks don't work properly, apparently because portaudio
+## will execute the callbacks in a separate thread, and calling Octave
+## functions in a separate thread which is likely to cause trouble with
+## all of Octave's global data...
+##
+## @deftypefnx {Function File} {@var{player} =} audioplayer (@var{function}, @dots{})
+##
+## Given a function handle, use that function to process the audio.
+#
+## The following example will create and register a callback that generates
+## a sine wave on both channels.
+##
+## @example
+## @group
+## function [ sound, status ] = callback_sine (frames)
+##   global lphase = 0.0;
+##   global rphase = 0.0;
+##   incl = 440.0 / 44100.0;
+##   incr = 443.0 / 44100.0;
+##   nl = incl * frames;
+##   nr = incr * frames;
+##   left = sin (2.0 * pi * [lphase:incl:lphase+nl]);
+##   right = sin (2.0 * pi * [rphase:incr:rphase+nr]);
+##   sound = [left', right'];
+##   status = 0;
+##   lphase = lphase + nl;
+##   rphase = rphase + nr;
+## endfunction
+## player = audioplayer (@@callback_sine, 44100);
+## play (player);
+## # play for as long as you want
+## stop (player);
+## @end group
+
+function player = audioplayer (varargin)
+
+  if (nargin < 1 || nargin > 4
+      || (nargin < 2 && (isa (varargin{1}, "function_handle")
+                         || ischar (varargin{1}))))
+    print_usage ();
+  endif
+
+  if (isa (varargin{1}, "audiorecorder"))
+    if (nargin == 1)
+      player = getplayer (varargin{1});
+    elseif (nargin == 2)
+      recorder = varargin{1};
+      data = getaudiodata (recorder);
+      player = audioplayer (data, get (recorder, "SampleRate"),
+                            get (recorder, "BitsPerSample"), varargin{2});
+    else
+      print_usage ();
+    endif
+  else
+    if (ischar (varargin{1}))
+      varargin{1} = str2func (varargin{1});
+    endif
+    player.player = __player_audioplayer__ (varargin{:});
+    player = class (player, "audioplayer");
+  endif
+
+endfunction
+
+%!testif HAVE_PORTAUDIO
+%! mono = randn (1, 44100) - 0.5;
+%! stereo = randn (2, 44100) - 0.5;
+%! fs = 44100;
+%! player1 = audioplayer (mono, fs);
+%! player2 = audioplayer (stereo, fs);
+%! assert (player1.NumberOfChannels, 1);
+%! assert (player2.NumberOfChannels, 2);
+%! assert (player1.SampleRate, 44100);
+%! assert (player2.SampleRate, 44100);
+%! assert (player1.TotalSamples, 44100);
+%! assert (player2.TotalSamples, 44100);
+%! playblocking (player1);
+%! playblocking (player2);
+
+%!testif HAVE_PORTAUDIO
+%! audio = randn (2, 88200) - 0.5;
+%! fs = 44100;
+%! player = audioplayer (audio, fs);
+%! assert (!isplaying (player));
+%! play (player);
+%! assert (isplaying (player));
+%! sleep (1);
+%! pause (player);
+%! assert (!isplaying (player));
+%! sleep (1);
+%! resume (player);
+%! assert (isplaying (player));
+%! sleep (1);
+
+%!testif HAVE_PORTAUDIO
+%! audio = randn (2, 88200) - 0.5;
+%! fs = 44100;
+%! player = audioplayer (audio, fs);
+%! assert (!isplaying (player));
+%! play (player);
+%! assert (isplaying (player));
+%! sleep (1);
+%! stop (player);
+%! sleep (1);
+%! assert (!isplaying (player));
+%! assert (player.CurrentSample, 0);
+
+%!testif HAVE_PORTAUDIO
+%! audio = randn (2, 44100) - 0.5;
+%! fs = 44100;
+%! player = audioplayer (audio, fs);
+%! set (player, {"SampleRate", "Tag", "UserData"}, {8000, "tag", [1, 2; 3, 4]});
+%! assert (player.SampleRate, 8000);
+%! assert (player.Tag, "tag");
+%! assert (player.UserData, [1, 2; 3, 4]);
+
+%!testif HAVE_PORTAUDIO
+%! audio = randn (2, 44100) - 0.5;
+%! fs = 44100;
+%! player = audioplayer (audio, fs);
+%! settable = set (player);
+%! settable.SampleRate = 8000;
+%! settable.Tag = "tag";
+%! settable.UserData = [1, 2; 3, 4];
+%! set (player, settable);
+%! assert (player.SampleRate, 8000);
+%! assert (player.Tag, "tag");
+%! assert (player.UserData, [1, 2; 3, 4]);
+
+%!testif HAVE_PORTAUDIO
+%! audio = randn (2, 44100) - 0.5;
+%! fs = 44100;
+%! player = audioplayer (audio, fs);
+%! player.SampleRate = 8000;
+%! player.Tag = "tag";
+%! player.UserData = [1, 2; 3, 4];
+%! properties = get (player, {"SampleRate", "Tag", "UserData"});
+%! assert (properties, {8000, "tag", [1, 2; 3, 4]});
+
+#%!function [sound, status] = callback (samples)
+#%!  sound = rand (samples, 2) - 0.5;
+#%!  status = 0;
+#%!endfunction
+
+#%!testif HAVE_PORTAUDIO
+#%! player = audioplayer (@callback, 44100);
+#%! play (player);
+#%! sleep (2);
+#%! stop (player);
+#%! assert (1);
+
+#%!testif HAVE_PORTAUDIO
+#%! player = audioplayer ("callback", 44100, 16);
+#%! play (player);
+#%! sleep (2);
+#%! stop (player);
+#%! assert (1);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/audio/@audioplayer/display.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,32 @@
+## Copyright (C) 2013 Vytautas Jančauskas
+##
+## 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} {} display (@var{player})
+## Display the properties of the audioplayer object @var{player}.
+## @end deftypefn
+
+function display (player)
+
+  if (nargin != 1)
+    print_usage ();
+  endif
+
+  disp (__get_properties__ (player));
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/audio/@audioplayer/get.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,54 @@
+## Copyright (C) 2013 Vytautas Jančauskas
+##
+## 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{value} =} get (@var{player}, @var{name})
+## @deftypefnx {Function File} {@var{values} =} get (@var{player})
+## Return the @var{value} of the property identified by @var{name}.
+## If @var{name} is a cell array return the values of of the properties
+## identified by the elements of the cell array.  Given only the
+## player object, return a scalar structure with values of all
+## properties of @var{player}.  The field names of the structure
+## correspond to property names.
+## @end deftypefn
+
+function retval = get (varargin)
+
+  if (nargin < 1 || nargin > 2)
+    print_usage ();
+  endif
+
+  properties = __get_properties__ (varargin{1});
+
+  if (nargin == 1)
+    retval = properties;
+  elseif (nargin == 2)
+    pnames = varargin{2};
+    if (ischar (pnames))
+      retval = getfield (properties, pnames);
+    elseif (iscellstr (pnames))
+      retval = cell (size (pnames));
+      for i = 1:numel (pnames)
+        retval{i} = getfield (properties, pnames{i});
+      endfor
+    else
+      error ("@audioplayer/get: invalid name argument");
+    endif
+  endif
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/audio/@audioplayer/isplaying.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,33 @@
+## Copyright (C) 2013 Vytautas Jančauskas
+##
+## 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} {} isplaying (@var{player})
+## Return 1 if the audioplayer object @var{player}is currently playing
+## back audio and 0 otherwise.
+## @end deftypefn
+
+function result = isplaying (player)
+
+  if (nargin != 1)
+    print_usage ();
+  endif
+
+  result = __player_isplaying__ (struct (player).player);
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/audio/@audioplayer/pause.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,32 @@
+## Copyright (C) 2013 Vytautas Jančauskas
+##
+## 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} {} pause (@var{player})
+## Pause the audioplayer @var{player}.
+## @end deftypefn
+
+function pause (player)
+
+  if (nargin != 1)
+    print_usage ();
+  endif
+
+  __player_pause__ (struct (player).player);
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/audio/@audioplayer/play.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,38 @@
+## Copyright (C) 2013 Vytautas Jančauskas
+##
+## 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} {} play (@var{player})
+## @deftypefnx {Function File} {} play  (@var{player}, @var{start})
+## @deftypefnx {Function File} {} play (@var{player}, @var{limits})
+## Play audio stored in the audioplayer object @var{player} without blocking.
+## Given optional argument start, begin playing at @var{start} seconds
+## in the recording.  Given a two-element vector @var{limits}, begin and
+## end playing at the number of seconds specified by the elements of the
+## vector.
+## @end deftypefn
+
+function play (varargin)
+
+  if (nargin < 1 || nargin > 2)
+    print_usage ();
+  endif
+
+  __player_play__ (struct (varargin{1}).player, varargin{2:end});
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/audio/@audioplayer/playblocking.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,38 @@
+## Copyright (C) 2013 Vytautas Jančauskas
+##
+## 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} {} playblocking (@var{player})
+## @deftypefnx {Function File} {} playblocking (@var{player}, @var{start})
+## @deftypefnx {Function File} {} playblocking (@var{player}, @var{limits})
+## Play audio stored in the audioplayer object @var{player} with blocking.
+## Given optional argument start, begin playing at @var{start} seconds
+## in the recording.  Given a two-element vector @var{limits}, begin and
+## end playing at the number of seconds specified by the elements of the
+## vector.
+## @end deftypefn
+
+function playblocking (varargin)
+
+  if (nargin < 1 || nargin > 2)
+    print_usage ();
+  endif
+
+  __player_playblocking__ (struct (varargin{1}).player, varargin{2:end});
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/audio/@audioplayer/resume.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,32 @@
+## Copyright (C) 2013 Vytautas Jančauskas
+##
+## 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} {} resume (@var{player})
+## Resume playback for the paused audioplayer object @var{player}.
+## @end deftypefn
+
+function resume (player)
+
+  if (nargin != 1)
+    print_usage ();
+  endif
+
+  __player_resume__ (struct (player).player);
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/audio/@audioplayer/set.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,74 @@
+## Copyright (C) 2013 Vytautas Jančauskas
+##
+## 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} {} set (@var{player}, @var{name}, @var{value})
+## @deftypefnx {Function File} {} set (@var{player}, @var{properties})
+## @deftypefnx {Function File} {@var{properties} =} set (@var{player})
+## Set the value of property specified by @var{name} to a given @var{value}.
+## If @var{name} and @var{value} are cell arrays, set each property to the
+## corresponding value.  Given a structure of @var{properties} with
+## fields corresponding to property names, set the value of those
+## properties to the field values.  Given only the audioplayer object,
+## return a structure of settable properties.
+## @end deftypefn
+
+function settable = set (varargin)
+
+  if (nargin < 1 || nargin > 3)
+    print_usage ();
+  endif
+
+  player = struct (varargin{1}).player;
+
+  if (nargin == 1)
+    settable.SampleRate = {};
+    settable.Tag = {};
+    settable.UserData = {};
+  elseif (nargin == 2)
+    for [value, property] = varargin{2}
+      setproperty (player, property, value);
+    endfor
+  elseif (nargin == 3)
+    if (iscell (varargin{2}))
+      index = 1;
+      for property = varargin{2}
+        setproperty (player, char (property), varargin{3}{index});
+        index = index + 1;
+      endfor
+    else
+      setproperty (player, varargin{2}, varargin{3});
+    endif
+  else
+    error ("@audioplayer/set: wrong number of arguments to the set method");
+  endif
+
+endfunction
+
+function setproperty (player, property, value)
+  switch (property)
+    case "SampleRate"
+      __player_set_fs__ (player, value);
+    case "Tag"
+      __player_set_tag__ (player, value);
+    case "UserData"
+      __player_set_userdata__ (player, value);
+    otherwise
+      error ("audioplayer: no such property or the property specified is read-only");
+  endswitch
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/audio/@audioplayer/stop.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,33 @@
+## Copyright (C) 2013 Vytautas Jančauskas
+##
+## 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} {} stop (@var{player})
+## Stop the playback for the audioplayer @var{player} and reset the
+## relevant variables to their starting values.
+## @end deftypefn
+
+function stop (player)
+
+  if (nargin != 1)
+    print_usage ();
+  endif
+
+  __player_stop__ (struct (player).player);
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/audio/@audioplayer/subsasgn.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,39 @@
+## Copyright (C) 2013 Vytautas Jančauskas
+##
+## 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{value} =} subsasgn (@var{player}, @var{idx}, @var{rhs})
+## Perform subscripted assignment on the audio player object @var{player}.
+## Assign the value of @var{rhs} to the player property named by @var{idx}.
+## @end deftypefn
+
+function value = subsasgn (player, idx, rhs)
+
+  if (isempty (idx))
+    error ("audioplayer: missing index");
+  endif
+
+  if (strcmp (idx(1).type, "."))
+    field = idx.subs;
+    set (player, field, rhs);
+    value = player;
+  else
+    error ("@audioplayer/subsasgn: invalid subscript type");
+  endif
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/audio/@audioplayer/subsref.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,41 @@
+## Copyright (C) 2013 Vytautas Jančauskas
+##
+## 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{value} =} subsref (@var{player}, @var{idx})
+## Perform subscripted selection on the audio player object @var{player}.
+## Return the player property value named by @var{idx}.
+## @end deftypefn
+
+function value = subsref (player, idx)
+  if (nargin != 2)
+    print_usage ();
+  endif
+
+  if (isempty (idx))
+    error ("@audioplayer/subsref: missing index");
+  endif
+
+  if (strcmp (idx(1).type, "."))
+    field = idx.subs;
+    value = get (player, field);
+  else
+    error ("@audioplayer/subsref: invalid subscript type")
+  endif
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/audio/@audiorecorder/__get_properties__.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,67 @@
+## Copyright (C) 2013 Vytautas Jančauskas
+##
+## 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{properties} =} __get_properties__ (@var{recorder})
+## Return a struct containing all named properties of the recorder object
+## @var{recorder}.
+## @end deftypefn
+
+function props = __get_properties__ (recorder)
+
+  if (nargin != 1)
+    print_usage ();
+  endif
+
+  if (__recorder_isrecording__ (struct (recorder).recorder))
+    running = "on";
+  else
+    running = "off";
+  endif
+
+  props = struct ("BitsPerSample",
+                  __recorder_get_nbits__ (struct (recorder).recorder),
+
+                  "CurrentSample",
+                  __recorder_get_sample_number__ (struct (recorder).recorder),
+
+                  "DeviceID",
+                  __recorder_get_id__ (struct (recorder).recorder),
+
+                  "NumberOfChannels",
+                  __recorder_get_channels__ (struct (recorder).recorder),
+
+                  "Running",
+                  running,
+
+                  "SampleRate",
+                  __recorder_get_fs__ (struct (recorder).recorder),
+
+                  "TotalSamples",
+                  __recorder_get_total_samples__ (struct (recorder).recorder),
+
+                  "Tag",
+                  __recorder_get_tag__ (struct (recorder).recorder),
+
+                  "Type",
+                  "audiorecorder",
+
+                  "UserData",
+                  __recorder_get_userdata__ (struct (recorder).recorder));
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/audio/@audiorecorder/audiorecorder.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,140 @@
+## Copyright (C) 2013 Vytautas Jančauskas
+##
+## 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{recorder} =} audiorecorder ()
+## @deftypefnx {Function File} {@var{recorder} =} audiorecorder (@var{fs}, @var{nbits}, @var{channels})
+## @deftypefnx {Function File} {@var{recorder} =} audiorecorder (@var{fs}, @var{nbits}, @var{channels}, @var{id})
+## Create an audiorecorder object recording 8 bit mono audio at 8000 Hz
+## sample rate.  The optional arguments @var{fs}, @var{nbits},
+## @var{channels}, and @var{id} specify the sample rate, bit depth,
+## number of channels and recording device id, respectively.  Device IDs
+## may be found using the audiodevinfo function.
+## @end deftypefn
+
+## FIXME: callbacks don't work properly, apparently because portaudio
+## will execute the callbacks in a separate thread, and calling Octave
+## functions in a separate thread which is likely to cause trouble with
+## all of Octave's global data...
+##
+## @deftypefnx {Function File} {@var{recorder} =} audiorecorder (@var{function}, @dots{})
+##
+## Given a function handle, use that function to process the audio.
+
+function recorder = audiorecorder (varargin)
+
+  if (nargin > 5)
+    print_usage ();
+  endif
+
+  if (nargin > 0 && ischar (varargin{1}))
+    varargin{1} = str2func (varargin{1});
+  endif
+
+  recorder.recorder = __recorder_audiorecorder__ (varargin{:});
+  recorder = class (recorder, "audiorecorder");
+
+endfunction
+
+%!testif HAVE_PORTAUDIO
+%! recorder = audiorecorder (44100, 16, 2);
+%! recordblocking (recorder, 1);
+%! data = getaudiodata (recorder, "int16");
+%! assert (strcmp (class (data), "int16"));
+%! data = getaudiodata (recorder, "int8");
+%! assert (strcmp (class (data), "int8"));
+%! data = getaudiodata (recorder, "uint8");
+%! assert (strcmp (class (data), "uint8"));
+%! assert (size (data)(1), recorder.TotalSamples);
+%! assert (size (data)(2), 2);
+%! assert (size (data)(1) != 0);
+
+%!testif HAVE_PORTAUDIO
+%! recorder = audiorecorder (44100, 16, 2);
+%! record (recorder, 1)
+%! sleep (2);
+%! record (recorder, 1);
+%! sleep (2);
+%! data = getaudiodata (recorder);
+%! assert (size (data)(1) < 44100 * 2);
+
+%!testif HAVE_PORTAUDIO
+%! recorder = audiorecorder (44100, 16, 2);
+%! record (recorder, 1);
+%! sleep (2);
+%! player1 = audioplayer (recorder);
+%! player2 = getplayer (recorder);
+%! play (player1);
+%! sleep (2);
+%! play (player2);
+%! sleep (2);
+%! assert (player1.TotalSamples, recorder.TotalSamples);
+%! assert (player2.TotalSamples, recorder.TotalSamples);
+
+%!testif HAVE_PORTAUDIO
+%! recorder = audiorecorder;
+%! set (recorder, {"SampleRate", "Tag", "UserData"}, {8000, "tag", [1, 2; 3, 4]});
+%! assert (recorder.SampleRate, 8000);
+%! assert (recorder.Tag, "tag");
+%! assert (recorder.UserData, [1, 2; 3, 4]);
+
+%!testif HAVE_PORTAUDIO
+%! recorder = audiorecorder;
+%! settable = set (recorder);
+%! settable.SampleRate = 8000;
+%! settable.Tag = "tag";
+%! settable.UserData = [1, 2; 3, 4];
+%! set (recorder, settable);
+%! assert (recorder.SampleRate, 8000);
+%! assert (recorder.Tag, "tag");
+%! assert (recorder.UserData, [1, 2; 3, 4]);
+
+%!testif HAVE_PORTAUDIO
+%! recorder = audiorecorder;
+%! recorder.SampleRate = 8000;
+%! recorder.Tag = "tag";
+%! recorder.UserData = [1, 2; 3, 4];
+%! properties = get (recorder, {"SampleRate", "Tag", "UserData"});
+%! assert (properties, {8000, "tag", [1, 2; 3, 4]});
+
+#%!function status = callback_record (sound)
+#%!  fid = fopen ("record.txt", "at");
+#%!  for index = 1:rows(sound)
+#%!    fprintf (fid, "%.4f, %.4f\n", sound(index, 1), sound(index, 2));
+#%!  endfor
+#%!  fclose (fid);
+#%!  status = 0;
+#%!endfunction
+
+#%!testif HAVE_PORTAUDIO
+#%! recorder = audiorecorder (@callback_record, 44100);
+#%! unlink ("record.txt")
+#%! record (recorder);
+#%! sleep (2);
+#%! stop (player);
+#%! s = stat ("record.txt");
+#%! assert (s.size > 0);
+
+#%!testif HAVE_PORTAUDIO
+#%! recorder = audiorecorder (@callback_record, 44100);
+#%! unlink ("record.txt")
+#%! record (recorder);
+#%! sleep (2);
+#%! stop (recorder);
+#%! s = stat ("record.txt");
+#%! assert (s.size > 0);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/audio/@audiorecorder/display.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,32 @@
+## Copyright (C) 2013 Vytautas Jančauskas
+##
+## 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} {} display (@var{recorder})
+## Display the properties of the audiorecorder object @var{recorder}.
+## @end deftypefn
+
+function display (recorder)
+
+  if (nargin != 1)
+    print_usage ();
+  endif
+
+  disp (__get_properties__ (recorder));
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/audio/@audiorecorder/get.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,54 @@
+## Copyright (C) 2013 Vytautas Jančauskas
+##
+## 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{value} =} get (@var{recorder}, @var{name})
+## @deftypefnx {Function File} {@var{values} =} get (@var{recorder})
+## Return the @var{value} of the property identified by @var{name}.
+## If @var{name} is a cell array, return the values of the properties
+## corresponding to the elements of the cell array.  Given only the
+## recorder object, return a scalar structure with values of all
+## properties of @var{recorder}.  The field names of the structure
+## correspond to property names.
+## @end deftypefn
+
+function retval = get (varargin)
+
+  if (nargin < 1 || nargin > 2)
+    print_usage ();
+  endif
+
+  properties = __get_properties__ (varargin{1});
+
+  if (nargin == 1)
+    retval = properties;
+  elseif (nargin == 2)
+    pnames = varargin{2};
+    if (ischar (pnames))
+      retval = getfield (properties, pnames);
+    elseif (iscellstr (pnames))
+      retval = cell (size (pnames));
+      for i = 1:numel (pnames)
+        retval{i} = getfield (properties, pnames{i});
+      endfor
+    else
+      error ("@audiorecorder/get: invalid name argument");
+    endif
+  endif
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/audio/@audiorecorder/getaudiodata.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,58 @@
+## Copyright (C) 2013 Vytautas Jančauskas
+##
+## 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{data} =} getaudiodata (@var{recorder})
+## @deftypefnx {Function File} {@var{data} =} getaudiodata (@var{recorder}, @var{datatype})
+## Return recorder audio data as a matrix with values between -1.0 and 1.0
+## and with as many columns as there are channels in the recorder.
+## Given the optional argument @var{datatype}, convert the recorded data
+## to the specified type, which may be one of @qcode{"double"},
+## @qcode{"single"}, @qcode{"int16"}, @qcode{"int8"} or @qcode{"uint8"}.
+## @end deftypefn
+
+function data = getaudiodata (varargin)
+
+  if (nargin < 1 || nargin > 2)
+    print_usage ();
+  endif
+
+  recorder = varargin{1};
+
+  if (nargin == 1)
+    data = __recorder_getaudiodata__ (struct (recorder).recorder);
+  else
+    data = __recorder_getaudiodata__ (struct (recorder).recorder);
+    type = varargin{2};
+    switch (type)
+      case "int16"
+        data = int16 (data * (2.0 ^ 15));
+      case "int8"
+        data = int8 (data * (2.0 ^ 7));
+      case "uint8"
+        data = uint8 ((data + 1.0) * 0.5 * (2.0 ^ 8 - 1));
+    endswitch
+  endif
+
+  if (get (recorder, "NumberOfChannels") == 2)
+    data = data';
+  else
+    data = data(1,:)';
+  endif
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/audio/@audiorecorder/getplayer.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,36 @@
+## Copyright (C) 2013 Vytautas Jančauskas
+##
+## 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{player} =} getplayer (@var{recorder})
+## Return an audioplayer object with data recorded by the audiorecorder
+## object @var{recorder}.
+## @end deftypefn
+
+function player = getplayer (varargin)
+
+  if (nargin < 1 || nargin > 2)
+    print_usage ();
+  endif
+
+  recorder = varargin{1};
+  data = getaudiodata (recorder);
+  player = audioplayer (data, get (recorder, "SampleRate"),
+                        get (recorder, "BitsPerSample"));
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/audio/@audiorecorder/isrecording.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,33 @@
+## Copyright (C) 2013 Vytautas Jančauskas
+##
+## 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} {} isrecording (@var{recorder})
+## Return 1 if the audiorecorder object @var{recorder} is currently
+## recording audio and 0 otherwise.
+## @end deftypefn
+
+function result = isrecording (recorder)
+
+  if (nargin != 1)
+    print_usage ();
+  endif
+
+  result = __recorder_isrecording__ (struct (recorder).recorder);
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/audio/@audiorecorder/pause.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,32 @@
+## Copyright (C) 2013 Vytautas Jančauskas
+##
+## 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} {} pause (@var{recorder})
+## Pause recording with audiorecorder object @var{recorder}.
+## @end deftypefn
+
+function pause (recorder)
+
+  if (nargin != 1)
+    print_usage ();
+  endif
+
+  __recorder_pause__ (struct (recorder).recorder);
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/audio/@audiorecorder/play.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,46 @@
+## Copyright (C) 2013 Vytautas Jančauskas
+##
+## 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{player} =} play (@var{recorder})
+## @deftypefnx {Function File} {@var{player} =} play (@var{recorder}, @var{start})
+## @deftypefnx {Function File} {@var{player} =} play (@var{recorder}, [@var{start}, @var{end}])
+## Play the audio recorded in @var{recorder} and return a corresponding
+## audioplayer object.  If the optional argument @var{start} is
+## provided, begin playing @var{start} seconds in to the recording.
+## If the optional argument @var{end} is provided, stop playing at
+## @var{end} seconds in the recording.
+## @end deftypefn
+
+function player = play (varargin)
+
+  if (nargin < 1 || nargin > 2)
+    print_usage ();
+  endif
+
+  recorder = varargin{1};
+  data = getaudiodata (recorder);
+  player = audioplayer (data, get (recorder, "SampleRate"),
+                        get (recorder, "BitsPerSample"));
+  if (nargin == 1)
+    play (player);
+  else
+    play (player, varargin{2});
+  endif
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/audio/@audiorecorder/record.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,36 @@
+## Copyright (C) 2013 Vytautas Jančauskas
+##
+## 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} {} record (@var{recorder})
+## @deftypefnx {Function File} {} record (@var{recorder}, @var{length})
+## Record audio without blocking using the audiorecorder object
+## @var{recorder} until stopped or paused by the @var{stop} or
+## @var{pause} method.  Given the optional argument @var{length}, record
+## for @var{length} seconds.
+## @end deftypefn
+
+function record (varargin)
+
+  if (nargin < 1 || nargin > 2)
+    print_usage ();
+  endif
+
+  __recorder_record__ (struct (varargin{1}).recorder, varargin{2:end});
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/audio/@audiorecorder/recordblocking.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,33 @@
+## Copyright (C) 2013 Vytautas Jančauskas
+##
+## 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} {} recordblocking (@var{recorder}, @var{length})
+## Record audio with blocking (synchronous I/O).  You must specify the
+## length of the recording in seconds.
+## @end deftypefn
+
+function recordblocking (varargin)
+
+  if (nargin != 2)
+    print_usage ();
+  endif
+
+  __recorder_recordblocking__ (struct (varargin{1}).recorder, varargin{2});
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/audio/@audiorecorder/resume.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,32 @@
+## Copyright (C) 2013 Vytautas Jančauskas
+##
+## 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} {} resume (@var{recorder})
+## Resume recording with the paused audiorecorder object @var{recorder}.
+## @end deftypefn
+
+function resume (recorder)
+
+  if (nargin != 1)
+    print_usage ();
+  endif
+
+  __recorder_resume__ (struct (recorder).recorder);
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/audio/@audiorecorder/set.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,75 @@
+## Copyright (C) 2013 Vytautas Jančauskas
+##
+## 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} {} set (@var{recorder}, @var{name}, @var{value})
+## @deftypefnx {Function File} {} set (@var{recorder}, @var{properties})
+## @deftypefnx {Function File} {@var{properties} =} set (@var{recorder})
+## Set the value of property specified by @var{name} to a given @var{value}.
+## If @var{name} and @var{value} are cell arrays of the same size,
+## set each property to a corresponding value.
+## Given a structure with fields corresponding to property names, set
+## the value of those properties to the corresponding field values.
+## Given a only the recorder object, return a structure of settable
+## properties.
+## @end deftypefn
+
+function settable = set (varargin)
+
+  if (nargin < 1 || nargin > 3)
+    print_usage ();
+  endif
+
+  recorder = struct (varargin{1}).recorder;
+
+  if (nargin == 1)
+    settable.SampleRate = {};
+    settable.Tag = {};
+    settable.UserData = {};
+  elseif (nargin == 2)
+    for [value, property] = varargin{2}
+      setproperty (recorder, property, value);
+    endfor
+  elseif (nargin == 3)
+    if (iscell (varargin{2}))
+      index = 1;
+      for property = varargin{2}
+        setproperty (recorder, char (property), varargin{3}{index});
+        index = index + 1;
+      endfor
+    else
+      setproperty (recorder, varargin{2}, varargin{3});
+    endif
+  endif
+
+endfunction
+
+function setproperty (recorder, property, value)
+
+  switch (property)
+    case "SampleRate"
+      __recorder_set_fs__ (recorder, value);
+    case "Tag"
+      __recorder_set_tag__ (recorder, value);
+    case "UserData"
+      __recorder_set_userdata__ (recorder, value);
+    otherwise
+      error ("@audiorecorder/set: no such property or the property specified is read-only");
+  endswitch
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/audio/@audiorecorder/stop.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,33 @@
+## Copyright (C) 2013 Vytautas Jančauskas
+##
+## 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} {} stop (@var{recorder})
+## Stop the audiorecorder object @var{recorder} and clean up any audio
+## streams.
+## @end deftypefn
+
+function stop (recorder)
+
+  if (nargin != 1)
+    print_usage ();
+  endif
+
+  __recorder_stop__ (struct (recorder).recorder);
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/audio/@audiorecorder/subsasgn.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,42 @@
+## Copyright (C) 2013 Vytautas Jančauskas
+##
+## 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{value} =} subsasgn (@var{recorder}, @var{idx}, @var{rhs})
+## Perform subscripted assignment on the audio recorder object @var{recorder}.
+## Assign the value of @var{rhs} to the recorder property named by @var{idx}.
+## @end deftypefn
+
+function value = subsasgn (recorder, idx, rhs)
+  if (nargin != 3)
+    print_usage ();
+  endif
+
+  if (isempty (idx))
+    error ("@audiorecorder/subsasgn: missing index");
+  endif
+
+  if (strcmp (idx(1).type, "."))
+    field = idx.subs;
+    set (recorder, field, rhs);
+    value = recorder;
+  else
+    error ("@audiorecorder/subsasgn: invalid subscript type");
+  endif
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/audio/@audiorecorder/subsref.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,42 @@
+## Copyright (C) 2013 Vytautas Jančauskas
+##
+## 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{value} =} subsref (@var{recorder}, @var{idx})
+## Perform subscripted selection on the audio recorder object @var{recorder}.
+## Return the recorder property value named by @var{idx}.
+## @end deftypefn
+
+function value = subsref (recorder, idx)
+
+  if (nargin != 2)
+    print_usage ();
+  endif
+
+  if (isempty (idx))
+    error ("@audiorecorder/subsref: missing index");
+  endif
+
+  if (strcmp (idx(1).type, "."))
+    field = idx.subs;
+    value = get (recorder, field);
+  else
+    error ("@audiorecorder/subsref: invalid subscript type")
+  endif
+
+endfunction
--- a/scripts/audio/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/audio/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -9,7 +9,36 @@
   audio/saveaudio.m \
   audio/setaudio.m \
   audio/wavread.m \
-  audio/wavwrite.m
+  audio/wavwrite.m \
+  audio/@audioplayer/__get_properties__.m \
+  audio/@audioplayer/audioplayer.m \
+  audio/@audioplayer/display.m \
+  audio/@audioplayer/get.m \
+  audio/@audioplayer/isplaying.m \
+  audio/@audioplayer/pause.m  \
+  audio/@audioplayer/play.m \
+  audio/@audioplayer/playblocking.m \
+  audio/@audioplayer/resume.m \
+  audio/@audioplayer/set.m \
+  audio/@audioplayer/stop.m \
+  audio/@audioplayer/subsasgn.m \
+  audio/@audioplayer/subsref.m \
+  audio/@audiorecorder/__get_properties__.m \
+  audio/@audiorecorder/audiorecorder.m \
+  audio/@audiorecorder/display.m \
+  audio/@audiorecorder/get.m \
+  audio/@audiorecorder/getaudiodata.m \
+  audio/@audiorecorder/getplayer.m \
+  audio/@audiorecorder/isrecording.m \
+  audio/@audiorecorder/pause.m \
+  audio/@audiorecorder/play.m \
+  audio/@audiorecorder/record.m \
+  audio/@audiorecorder/recordblocking.m \
+  audio/@audiorecorder/resume.m \
+  audio/@audiorecorder/set.m \
+  audio/@audiorecorder/stop.m \
+  audio/@audiorecorder/subsasgn.m \
+  audio/@audiorecorder/subsref.m
 
 FCN_FILES += $(audio_FCN_FILES)
 
--- a/scripts/audio/playaudio.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/audio/playaudio.m	Mon Jan 12 09:17:35 2015 -0800
@@ -41,7 +41,7 @@
     endif
     X = name(:) + 127;
     unwind_protect
-      file = tmpnam ();
+      file = tempname ();
       fid = fopen (file, "wb");
       fwrite (fid, X, "uchar");
       fclose (fid);
--- a/scripts/audio/record.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/audio/record.m	Mon Jan 12 09:17:35 2015 -0800
@@ -39,7 +39,7 @@
 
   unwind_protect
 
-    file = tmpnam ();
+    file = tempname ();
 
     input ("Please hit ENTER and speak afterwards!\n", 1);
 
--- a/scripts/audio/wavwrite.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/audio/wavwrite.m	Mon Jan 12 09:17:35 2015 -0800
@@ -151,7 +151,7 @@
 
 
 %!shared fname
-%! fname = tmpnam ();
+%! fname = tempname ();
 
 %!test
 %! A = [-1:0.1:1; -1:0.1:1]';
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/deprecated/bicubic.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,260 @@
+## Copyright (C) 2005-2013 Hoxide Ma
+##
+## 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{zi} =} bicubic (@var{x}, @var{y}, @var{z}, @var{xi}, @var{yi}, @var{extrapval})
+##
+## @code{bicubic} is deprecated and will be removed in Octave version 4.6.
+## Use @code{interp2 (@dots{}, "spline")} for the equivalent functionality.
+##
+## Return a matrix @var{zi} corresponding to the bicubic
+## interpolations at @var{xi} and @var{yi} of the data supplied
+## as @var{x}, @var{y} and @var{z}.  Points outside the grid are set
+## to @var{extrapval}.
+##
+## See @url{http://wiki.woodpecker.org.cn/moin/Octave/Bicubic}
+## for further information.
+## @seealso{interp2}
+## @end deftypefn
+
+## Bicubic interpolation method.
+## Author: Hoxide Ma <hoxide_dirac@yahoo.com.cn>
+
+## Deprecated in version 4.2
+
+function zi = bicubic (x, y, z, xi, yi, extrapval, spline_alpha)
+
+  persistent warned = false;
+  if (! warned)
+    warned = true;
+    warning ("Octave:deprecated-function",
+             "bicubic is obsolete and will be removed from a future version of Octave, please use interp2 instead");
+  endif
+
+  if (nargin < 1 || nargin > 7)
+    print_usage ();
+  endif
+
+  if (nargin == 7 && isscalar (spline_alpha))
+    a = spline_alpha;
+  else
+    a = 0.5;
+  endif
+
+  if (nargin < 6)
+    extrapval = NaN;
+  endif
+
+  if (isa (x, "single") || isa (y, "single") || isa (z, "single")
+      || isa (xi, "single") || isa (yi, "single"))
+    myeps = eps ("single");
+  else
+    myeps = eps ();
+  endif
+
+  if (nargin <= 2)
+    ## bicubic (z) or bicubic (z, 2)
+    if (nargin == 1)
+      n = 1;
+    else
+      n = y;
+    endif
+    z = x;
+    x = [];
+    [rz, cz] = size (z);
+    s = linspace (1, cz, (cz-1) * pow2 (n) + 1);
+    t = linspace (1, rz, (rz-1) * pow2 (n) + 1);
+  elseif (nargin == 3)
+    if (! isvector (x) || ! isvector (y))
+      error ("bicubic: XI and YI must be vector");
+    endif
+    s = y;
+    t = z;
+    z = x;
+    [rz, cz] = size (z);
+  elseif (nargin == 5 || nargin == 6)
+    [rz, cz] = size (z) ;
+    if (isvector (x) && isvector (y))
+      if (rz != length (y) || cz != length (x))
+        error ("bicubic: length of X and Y must match the size of Z");
+      endif
+    elseif (size_equal (x, y) && size_equal (x, z))
+      x = x(1,:);
+      y = y(:,1);
+    else
+      error ("bicubic: X, Y and Z must be equal size matrices of same size");
+    endif
+
+    if (all (diff (x) < 0))
+      flipx = true;
+      x = fliplr (x);
+    elseif (all (diff (x) > 0))
+      flipx = false;
+    else
+      error ("bicubic:nonmonotonic", "bicubic: X values must be monotonic");
+    endif
+    if (all (diff (y) < 0))
+      flipy = true;
+      y = flipud (y);
+    elseif (all (diff (y) > 0))
+      flipy = false;
+    else
+      error ("bicubic:nonmonotonic", "bicubic: Y values must be monotonic");
+    endif
+
+    ## Mark values outside the lookup table.
+    xfirst_ind = find (xi < x(1));
+    xlast_ind  = find (xi > x(cz));
+    yfirst_ind = find (yi < y(1));
+    ylast_ind  = find (yi > y(rz));
+    ## Set value outside the table preliminary to min max index.
+    xi(xfirst_ind) = x(1);
+    xi(xlast_ind) = x(cz);
+    yi(yfirst_ind) = y(1);
+    yi(ylast_ind) = y(rz);
+
+    x = reshape (x, 1, cz);
+    x(cz) *= 1 + sign (x(cz)) * myeps;
+    if (x(cz) == 0)
+      x(cz) = myeps;
+    endif;
+    xi = reshape (xi, 1, length (xi));
+    [m, i] = sort ([x, xi]);
+    o = cumsum (i <= cz);
+    xidx = o(find (i > cz));
+
+    y = reshape (y, rz, 1);
+    y(rz) *= 1 + sign (y(rz)) * myeps;
+    if (y(rz) == 0)
+      y(rz) = myeps;
+    endif;
+    yi = reshape (yi, length (yi), 1);
+    [m, i] = sort ([y; yi]);
+    o = cumsum (i <= rz);
+    yidx = o([find(i > rz)]);
+
+    ## Set s and t used follow codes.
+    s = xidx + ((xi .- x(xidx)) ./ (x(xidx+1) .- x(xidx)));
+    t = yidx + ((yi  - y(yidx)) ./ (y(yidx+1)  - y(yidx)));
+
+    if (flipx)
+      s = fliplr (s);
+    endif
+    if (flipy)
+      t = flipud (t);
+    endif
+  else
+    print_usage ();
+  endif
+
+  if (rz < 3 || cz < 3)
+    error ("bicubic: Z at least a 3 by 3 matrices");
+  endif
+
+  inds = floor (s);
+  d = find (s == cz);
+  s = s - floor (s);
+  inds(d) = cz-1;
+  s(d) = 1.0;
+
+  d = [];
+  indt = floor (t);
+  d = find (t == rz);
+  t = t - floor (t);
+  indt(d) = rz-1;
+  t(d) = 1.0;
+  d = [];
+
+  p = zeros (size (z) + 2);
+  p(2:rz+1,2:cz+1) = z;
+  p(1,:) =    (6*(1-a))*p(2,:)    - 3*p(3,:)  + (6*a-2)*p(4,:);
+  p(rz+2,:) = (6*(1-a))*p(rz+1,:) - 3*p(rz,:) + (6*a-2)*p(rz-1,:);
+  p(:,1) =    (6*(1-a))*p(:,2)    - 3*p(:,3)  + (6*a-2)*p(:,4);
+  p(:,cz+2) = (6*(1-a))*p(:,cz+1) - 3*p(:,cz) + (6*a-2)*p(:,cz-1);
+
+  ## Calculte the C1(t) C2(t) C3(t) C4(t) and C1(s) C2(s) C3(s) C4(s).
+  t2 = t.*t;
+  t3 = t2.*t;
+
+  ct0 =    -a .* t3 +     (2 * a) .* t2 - a .* t ;      # -a G0
+  ct1 = (2-a) .* t3 +      (-3+a) .* t2          + 1 ;  # F0 - a G1
+  ct2 = (a-2) .* t3 + (-2 *a + 3) .* t2 + a .* t ;      # F1 + a G0
+  ct3 =     a .* t3 -           a .* t2;                # a G1
+  t = []; t2 = []; t3 = [];
+
+  s2 = s.*s;
+  s3 = s2.*s;
+
+  cs0 =    -a .* s3 +     (2 * a) .* s2 - a .*s ;      # -a G0
+  cs1 = (2-a) .* s3 +    (-3 + a) .* s2         + 1 ;  # F0 - a G1
+  cs2 = (a-2) .* s3 + (-2 *a + 3) .* s2 + a .*s ;      # F1 + a G0
+  cs3 =     a .* s3 -           a .* s2;               # a G1
+  s = []; s2 = []; s3 = [];
+
+  cs0 = cs0([1,1,1,1],:);
+  cs1 = cs1([1,1,1,1],:);
+  cs2 = cs2([1,1,1,1],:);
+  cs3 = cs3([1,1,1,1],:);
+
+  lent = length (ct0);
+  lens = columns (cs0);
+  zi = zeros (lent, lens);
+
+  for i = 1:lent
+    it = indt(i);
+    int = [it, it+1, it+2, it+3];
+    zi(i,:) = ([ct0(i),ct1(i),ct2(i),ct3(i)]
+              * (p(int,inds) .* cs0 + p(int,inds+1) .* cs1
+                 + p(int,inds+2) .* cs2 + p(int,inds+3) .* cs3));
+  endfor
+
+  ## Set points outside the table to extrapval.
+  if (! (isempty (xfirst_ind) && isempty (xlast_ind)))
+    zi(:, [xfirst_ind, xlast_ind]) = extrapval;
+  endif
+  if (! (isempty (yfirst_ind) && isempty (ylast_ind)))
+    zi([yfirst_ind; ylast_ind], :) = extrapval;
+  endif
+
+endfunction
+
+
+%!demo
+%! clf;
+%! colormap ("default");
+%! A = [13,-1,12;5,4,3;1,6,2];
+%! x = [0,1,4]+10;
+%! y = [-10,-9,-8];
+%! xi = linspace (min (x), max (x), 17);
+%! yi = linspace (min (y), max (y), 26)';
+%! mesh (xi, yi, bicubic (x,y,A,xi,yi));
+%! [x,y] = meshgrid (x,y);
+%! hold on; plot3 (x(:),y(:),A(:),"b*"); hold off;
+
+%!test
+%! x = linspace (1, -1, 10);
+%! [xx, yy] = meshgrid (x);
+%! z = cos (6 * xx) + sin (6 * yy);
+%! x = linspace (1, -1, 30);
+%! [xx2, yy2] = meshgrid (x);
+%! z1 = interp2 (xx, yy, z, xx2, yy2, "spline");
+%! z2 = interp2 (fliplr (xx), flipud (yy), fliplr (flipud(z)),
+%!               fliplr (xx2), flipud (yy2), "spline");
+%! z2 = fliplr (flipud (z2));
+%! assert (z1, z2, 100 * eps ())
+
--- a/scripts/deprecated/default_save_options.m	Mon Jan 12 09:13:19 2015 -0800
+++ /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/delaunay3.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,88 @@
+## Copyright (C) 1999-2013 Kai Habel
+##
+## 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{tetr} =} delaunay3 (@var{x}, @var{y}, @var{z})
+## @deftypefnx {Function File} {@var{tetr} =} delaunay3 (@var{x}, @var{y}, @var{z}, @var{options})
+##
+## @code{delaunay3} is deprecated and will be removed in Octave version 4.6.
+## Please use @code{delaunay} in all new code.
+##
+## Compute the Delaunay triangulation for a 3-D set of points.
+## The return value @var{tetr} is a set of tetrahedrons which satisfies the
+## Delaunay circum-circle criterion, i.e., only a single data point from
+## [@var{x}, @var{y}, @var{z}] is within the circum-circle of the defining
+## tetrahedron.
+##
+## The set of tetrahedrons @var{tetr} is a matrix of size [n, 4].  Each
+## row defines a tetrahedron and the four columns are the four vertices
+## of the tetrahedron.  The value of @code{@var{tetr}(i,j)} is an index into
+## @var{x}, @var{y}, @var{z} for the location of the j-th vertex of the i-th
+## tetrahedron.
+##
+## An optional fourth argument, which must be a string or cell array of strings,
+## contains options passed to the underlying qhull command.
+## See the documentation for the Qhull library for details
+## @url{http://www.qhull.org/html/qh-quick.htm#options}.
+## The default options are @code{@{"Qt", "Qbb", "Qc", "Qz"@}}.
+##
+## If @var{options} is not present or @code{[]} then the default arguments are
+## used.  Otherwise, @var{options} replaces the default argument list. 
+## To append user options to the defaults it is necessary to repeat the 
+## default arguments in @var{options}.  Use a null string to pass no arguments.
+##
+## @seealso{delaunay, delaunayn, convhull, voronoi, tetramesh}
+## @end deftypefn
+
+## Author: Kai Habel <kai.habel@gmx.de>
+
+function tetr = delaunay3 (x, y, z, options)
+
+  persistent warned = false;
+  if (! warned)
+    warned = true;
+    warning ("Octave:deprecated-function",
+             "delaunay3 is obsolete and will be removed from a future version of Octave, please use delaunay instead");
+  endif
+
+  if (nargin < 3 || nargin > 4)
+    print_usage ();
+  endif
+
+  if (! (isvector (x) && isvector (y) && isvector (z)
+         && length (x) == length (y) && length (x) == length (z)))
+    error ("delaunay: X, Y, and Z must be the same size");
+  elseif (nargin == 4 && ! (ischar (options) || iscellstr (options)))
+    error ("delaunay3: OPTIONS must be a string or cell array of strings");
+  endif
+
+  if (nargin == 3)
+    tetr = delaunayn ([x(:), y(:), z(:)]);
+  else
+    tetr = delaunayn ([x(:), y(:), z(:)], options);
+  endif
+
+endfunction
+
+
+%!testif HAVE_QHULL
+%! x = [-1, -1, 1, 0, -1]; y = [-1, 1, 1, 0, -1]; z = [0, 0, 0, 1, 1];
+%! assert (sortrows (sort (delaunay3 (x, y, z), 2)), [1,2,3,4;1,2,4,5])
+
+%% FIXME: Need input validation tests
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/deprecated/dump_prefs.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,120 @@
+## Copyright (C) 1994-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  {Function File} {} dump_prefs ()
+## @deftypefnx {Function File} {} dump_prefs (@var{fid})
+##
+## @code{dump_prefs} is deprecated and will be removed in Octave version 4.6.
+## Please use individual preference get/set routines in all new code.
+##
+## Dump the current settings of all user preferences to stdout in a format that
+## can be parsed by Octave later.
+##
+## If the optional argument @var{fid} is given then the results are written to
+## the file specified by file descriptor @var{fid}.
+## @seealso{octave_config_info}
+## @end deftypefn
+
+## Author: jwe
+
+function dump_prefs (fid)
+
+  persistent warned = false;
+  if (! warned)
+    warned = true;
+    warning ("Octave:deprecated-function",
+             "dump_prefs is obsolete and will be removed from a future version of Octave, recode using individual preference get/set routines");
+  endif
+
+  if (nargin > 1)
+    print_usage ();
+  endif
+
+  if (nargin == 0)
+    fid = stdout;
+  endif
+
+  ## FIXME: It would be nice to be able to get the list of built-in variables
+  ## directly from Octave so that we wouldn't have to remember to update it
+  ## each time the list of preference variables changes
+
+  ## FIXME: Update this list for 4.2.0 release
+  ##        Example, 'gnuplot_command_end' is no longer valid.
+
+  pref_list = {"EDITOR"
+              "EXEC_PATH"
+              "IMAGE_PATH"
+              "PAGER"
+              "PS1"
+              "PS2"
+              "PS4"
+              "beep_on_error"
+              "completion_append_char"
+              "crash_dumps_octave_core"
+              "echo_executing_commands"
+              "fixed_point_format"
+              "gnuplot_binary"
+              "gnuplot_command_end"
+              "gnuplot_command_plot"
+              "gnuplot_command_replot"
+              "gnuplot_command_splot"
+              "gnuplot_command_title"
+              "gnuplot_command_using"
+              "gnuplot_command_with"
+              "history_file"
+              "history_size"
+              "ignore_function_time_stamp"
+              "info_file"
+              "info_program"
+              "makeinfo_program"
+              "max_recursion_depth"
+              "output_max_field_width"
+              "output_precision"
+              "page_output_immediately"
+              "page_screen_output"
+              "print_answer_id_name"
+              "print_empty_dimensions"
+              "save_precision"
+              "saving_history"
+              "sighup_dumps_octave_core"
+              "sigterm_dumps_octave_core"
+              "silent_functions"
+              "split_long_rows"
+              "string_fill_char"
+              "struct_levels_to_print"
+              "suppress_verbose_help_message"};
+
+  for i = 1:rows (pref_list)
+    pref = pref_list{i};
+    try
+      val = feval (pref);
+      if (isnumeric (val))
+        val = sprintf ("%g", val);
+      endif
+      fprintf (fid, "  %s = %s\n", pref, val);
+    catch
+      fprintf (fid, "# %s = <no value or error in displaying it>\n", pref);
+    end_try_catch
+  endfor
+
+endfunction
+
+
+%!error dump_prefs (1,2)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/deprecated/find_dir_in_path.m	Mon Jan 12 09:17:35 2015 -0800
@@ -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
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/deprecated/finite.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,52 @@
+## Copyright (C) 2014 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 {Mapping Function} {} finite (@var{x})
+##
+## @code{finite} is deprecated and will be removed in Octave version 4.6.
+## Please use @code{isfinite} in all new code.
+##
+## Return a logical array which is true where the elements of @var{x} are
+## finite values and false where they are not.
+## For example:
+## 
+## @example
+## @group
+## finite ([13, Inf, NA, NaN])
+##      @result{} [ 1, 0, 0, 0 ]
+## @end group
+## @end example
+## @seealso{isfinite, isinf, isnan, isna}
+## @end deftypefn
+
+## Deprecated in version 4.2
+
+function retval = finite (varargin)
+
+  persistent warned = false;
+  if (! warned)
+    warned = true;
+    warning ("Octave:deprecated-function",
+             "finite is obsolete and will be removed from a future version of Octave, please use isfinite instead");
+  endif
+
+  retval = isfinite (varargin{:});
+
+endfunction
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/deprecated/fmod.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,51 @@
+## Copyright (C) 2014 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 {Mapping Function} {} fmod (@var{x}, @var{y})
+##
+## @code{fmod} is deprecated and will be removed in Octave version 4.6.
+## Please use @code{rem} in all new code.
+##
+## Return the remainder of the division @code{@var{x} / @var{y}}, computed
+## using the expression
+## 
+## @example
+## x - y .* fix (x ./ y)
+## @end example
+## 
+## An error message is printed if the dimensions of the arguments do not
+## agree, or if either of the arguments is complex.
+## @seealso{rem, mod}
+## @end deftypefn
+
+## Deprecated in version 4.2
+
+function retval = fmod (varargin)
+
+  persistent warned = false;
+  if (! warned)
+    warned = true;
+    warning ("Octave:deprecated-function",
+             "fmod is obsolete and will be removed from a future version of Octave, please use rem instead");
+  endif
+
+  retval = rem (varargin{:});
+
+endfunction
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/deprecated/fnmatch.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,52 @@
+## Copyright (C) 2014 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} {} fnmatch (@var{pattern}, @var{string})
+##
+## @code{fnmatch} is deprecated and will be removed in Octave version 4.6.
+## Please use @code{glob} or @code{regexp} in all new code.
+##
+## Return true or false for each element of @var{string} that matches any of
+## the elements of the string array @var{pattern}, using the rules of
+## filename pattern matching.  For example:
+## 
+## @example
+## @group
+## fnmatch (\"a*b\", @{\"ab\"; \"axyzb\"; \"xyzab\"@})
+##      @result{} [ 1; 1; 0 ]
+## @end group
+## @end example
+## @seealso{glob, regexp}
+## @end deftypefn
+
+## Deprecated in version 4.2
+
+function retval = fnmatch (varargin)
+
+  persistent warned = false;
+  if (! warned)
+    warned = true;
+    warning ("Octave:deprecated-function",
+             "fnmatch is obsolete and will be removed from a future version of Octave, please use glob or regexp instead");
+  endif
+
+  retval = __fnmatch__ (varargin{:});
+
+endfunction
+
--- a/scripts/deprecated/gen_doc_cache.m	Mon Jan 12 09:13:19 2015 -0800
+++ /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 12 09:13:19 2015 -0800
+++ /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 12 09:13:19 2015 -0800
+++ /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 12 09:13:19 2015 -0800
+++ /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 12 09:13:19 2015 -0800
+++ /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_invoke.m	Mon Jan 12 09:13:19 2015 -0800
+++ /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_new.m	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +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_new (@var{name})
-## @deftypefnx {Loadable Function} {@var{obj} =} java_new (@var{name}, @var{arg1}, @dots{})
-## Create a Java object of class @var{name}, by calling the class constructor
-## with the arguments @var{arg1}, @dots{}
-## 
-## @example
-## @group
-##   x = java_new ("java.lang.StringBuffer")
-##   x = java_new ("java.lang.StringBuffer", "Initial string")
-## @end group
-## @end example
-## 
-## @seealso{javaObject, javaMethod}
-## @end deftypefn
-
-function retval = java_new (varargin)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "java_new is obsolete and will be removed from a future version of Octave; please use javaObject instead");
-  endif
-
-  if (nargin < 1)
-    print_usage ();
-  endif
-
-  retval = javaObject (varargin{:});
-
-endfunction
-
--- a/scripts/deprecated/java_unsigned_conversion.m	Mon Jan 12 09:13:19 2015 -0800
+++ /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 12 09:13:19 2015 -0800
+++ /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 12 09:13:19 2015 -0800
+++ /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
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/deprecated/luinc.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,93 @@
+## Copyright (C) 2014 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/>.
+
+## @deftypefn  {Built-in Function} {[@var{L}, @var{U}, @var{P}, @var{Q}] =} luinc (@var{A}, '0')
+## @deftypefnx {Built-in Function} {[@var{L}, @var{U}, @var{P}, @var{Q}] =} luinc (@var{A}, @var{droptol})
+## @deftypefnx {Built-in Function} {[@var{L}, @var{U}, @var{P}, @var{Q}] =} luinc (@var{A}, @var{opts})
+##
+## @code{luinc} is deprecated and will be removed in Octave version 4.6.
+## Please use @code{ilu} or @code{ichol} in all new code.
+##
+## Produce the incomplete LU@tie{}factorization of the sparse matrix @var{A}.
+## Two types of incomplete factorization are possible, and the type
+## is determined by the second argument to @code{luinc}.
+## 
+## Called with a second argument of @qcode{'0'}, the zero-level incomplete
+## LU@tie{}factorization is produced.  This creates a factorization of @var{A}
+## where the position of the nonzero arguments correspond to the same
+## positions as in the matrix @var{A}.
+## 
+## Alternatively, the fill-in of the incomplete LU@tie{}factorization can
+## be controlled through the variable @var{droptol} or the structure
+## @var{opts}.  The @sc{umfpack} multifrontal factorization code by Tim A.
+## Davis is used for the incomplete LU@tie{}factorization, (availability
+## @url{http://www.cise.ufl.edu/research/sparse/umfpack/})
+## 
+## @var{droptol} determines the values below which the values in the
+## LU@tie{} factorization are dropped and replaced by zero.  It must be a
+## positive scalar, and any values in the factorization whose absolute value
+## are less than this value are dropped, expect if leaving them increase the
+## sparsity of the matrix.  Setting @var{droptol} to zero results in a complete
+## LU@tie{}factorization which is the default.
+## 
+## @var{opts} is a structure containing one or more of the fields
+## 
+## @table @code
+## @item droptol
+## The drop tolerance as above.  If @var{opts} only contains @code{droptol}
+## then this is equivalent to using the variable @var{droptol}.
+## 
+## @item milu
+## A logical variable flagging whether to use the modified incomplete
+## LU@tie{} factorization.  In the case that @code{milu} is true, the dropped
+## values are subtracted from the diagonal of the matrix @var{U} of the
+## factorization.  The default is @code{false}.
+## 
+## @item udiag
+## A logical variable that flags whether zero elements on the diagonal of
+## @var{U} should be replaced with @var{droptol} to attempt to avoid singular
+## factors.  The default is @code{false}.
+## 
+## @item thresh
+## Defines the pivot threshold in the interval [0,1].  Values outside that
+## range are ignored.
+## @end table
+## 
+## All other fields in @var{opts} are ignored.  The outputs from @code{luinc}
+## are the same as for @code{lu}.
+## 
+## Given the string argument @qcode{\"vector\"}, @code{luinc} returns the
+## values of @var{p} @var{q} as vector values.
+## @seealso{ilu, ichol, lu, sparse}
+## @end deftypefn
+
+## Deprecated in version 4.2
+
+function [L, U, P, Q] = luinc (varargin)
+
+  persistent warned = false;
+  if (! warned)
+    warned = true;
+    warning ("Octave:deprecated-function",
+             "luinc is obsolete and will be removed from a future version of Octave, please use ilu or ichol instead");
+  endif
+
+  [L, U, P, Q] = __luinc__ (varargin{:});
+
+endfunction
+
--- a/scripts/deprecated/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/deprecated/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -1,21 +1,20 @@
 FCN_FILE_DIRS += deprecated
 
 deprecated_FCN_FILES = \
-  deprecated/default_save_options.m \
-  deprecated/gen_doc_cache.m \
-  deprecated/interp1q.m \
-  deprecated/isequalwithequalnans.m \
+  deprecated/bicubic.m \
+  deprecated/delaunay3.m \
+  deprecated/dump_prefs.m \
+  deprecated/find_dir_in_path.m \
+  deprecated/finite.m \
+  deprecated/fmod.m \
+  deprecated/fnmatch.m \
   deprecated/isstr.m \
-  deprecated/java_convert_matrix.m \
-  deprecated/java_debug.m \
-  deprecated/java_invoke.m \
-  deprecated/java_new.m \
-  deprecated/java_unsigned_conversion.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/luinc.m \
+  deprecated/octave_tmp_file_name.m \
+  deprecated/nfields.m \
+  deprecated/strmatch.m \
+  deprecated/syl.m \
+  deprecated/usage.m
 
 FCN_FILES += $(deprecated_FCN_FILES)
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/deprecated/nfields.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,44 @@
+## Copyright (C) 2014 Rik Wehbring
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {} nfields (@var{s})
+## Return the number of fields of the structure @var{s}.
+##
+## @strong{Warning:} @code{nfields} is scheduled for removal in version 4.6.
+## Use @code{numfields} instead.
+## @seealso{numfields, fieldnames}
+## @end deftypefn
+
+function retval = nfields (varargin)
+
+  persistent warned = false;
+  if (! warned)
+    warned = true;
+    warning ("Octave:deprecated-function",
+             "nfields is obsolete and will be removed from a future version of Octave; please use numfields instead");
+  endif
+
+  if (nargin < 1)
+    print_usage ();
+  endif
+
+  retval = numfields (varargin{:});
+
+endfunction
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/deprecated/octave_tmp_file_name.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,54 @@
+## Copyright (C) 2014 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} {@var{fname} =} octave_tmp_file_name ()
+## @deftypefnx {Built-in Function} {@var{fname} =} octave_tmp_file_name (@var{dir})
+## @deftypefnx {Built-in Function} {@var{fname} =} octave_tmp_file_name (@var{dir}, @var{prefix})
+##
+## @code{octave_tmp_file_name} is deprecated and will be removed in Octave
+## version 4.6.  Use @code{tempname} for equivalent functionality.
+##
+## Return a unique temporary file name as a string.
+## 
+## If @var{prefix} is omitted, a value of @qcode{"oct-"} is used.
+## If @var{dir} is also omitted, the default directory for temporary files
+## (@code{P_tmpdir} is used.  If @var{dir} is provided, it must exist,
+## otherwise the default directory for temporary files is used.
+## @seealso{tempname, tmpnam, mkstemp, tempdir, P_tmpdir, tmpfile}
+## @end deftypefn
+
+## Deprecated in version 4.2
+
+
+function filename = octave_tmp_file_name (varargin)
+
+  persistent warned = false;
+  if (! warned)
+    warned = true;
+    warning ("Octave:deprecated-function",
+             "octave_tmp_file_name is obsolete and will be removed from a future version of Octave, please use tempname instead");
+  endif
+
+  filename = tmpnam (varargin{:});
+
+endfunction
+
+
+%!assert (1)
+
--- a/scripts/deprecated/re_read_readline_init_file.m	Mon Jan 12 09:13:19 2015 -0800
+++ /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 12 09:13:19 2015 -0800
+++ /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 12 09:13:19 2015 -0800
+++ /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
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/deprecated/strmatch.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,130 @@
+## Copyright (C) 2000-2013 Paul Kienzle
+## Copyright (C) 2003 Alois Schloegl
+## Copyright (C) 2010 VZLU Prague
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {Function File} {} strmatch (@var{s}, @var{A})
+## @deftypefnx {Function File} {} strmatch (@var{s}, @var{A}, "exact")
+##
+## @code{strmatch} is deprecated and will be removed in Octave version 4.6.
+## Use @code{strncmp} (normal case), or @code{strcmp} (@qcode{"exact"} case),
+## or @code{regexp} in all new code.
+##
+## Return indices of entries of @var{A} which begin with the string @var{s}.
+## The second argument @var{A} must be a string, character matrix, or a cell
+## array of strings.  If the third argument @qcode{"exact"} is not given, then
+## @var{s} only needs to match @var{A} up to the length of @var{s}.
+## Trailing spaces and nulls in @var{s} and @var{A} are ignored when matching.
+##
+## For example:
+##
+## @example
+## @group
+## strmatch ("apple", "apple juice")
+##      @result{} 1
+##
+## strmatch ("apple", ["apple  "; "apple juice"; "an apple"])
+##      @result{} [1; 2]
+##
+## strmatch ("apple", ["apple  "; "apple juice"; "an apple"], "exact")
+##      @result{} [1]
+## @end group
+## @end example
+##
+## @seealso{strfind, findstr, strcmp, strncmp, strcmpi, strncmpi, find}
+## @end deftypefn
+
+## Author: Paul Kienzle, Alois Schloegl
+## Adapted-by: jwe
+
+## Deprecated in version 4.2
+
+function idx = strmatch (s, A, exact)
+
+  persistent warned = false;
+  if (! warned)
+    warned = true;
+    warning ("Octave:deprecated-function",
+             "strmatch is obsolete and will be removed from a future version of Octave, please use strncmp, strcmp, or regexp instead");
+  endif
+
+  if (nargin < 2 || nargin > 3)
+    print_usage ();
+  endif
+
+  if (! ischar (s) || (! isempty (s) && ! isvector (s)))
+    error ("strmatch: S must be a string");
+  elseif (! (ischar (A) || iscellstr (A)))
+    error ("strmatch: A must be a string or cell array of strings");
+  endif
+
+  ## Trim blanks and nulls from search string
+  s = regexprep (s, "[ \\0]+$", '');
+  len = length (s);
+
+  exact = nargin == 3 && ischar (exact) && strcmp (exact, "exact");
+
+  if (ischar (A))
+    [nr, nc] = size (A);
+    if (len > nc)
+      idx = [];
+    else
+      match = all (bsxfun (@eq, A(:,1:len), s), 2);
+      if (exact)
+        AA = A(:,len+1:nc);
+        match &= all (AA == " " | AA == "\0", 2);
+      endif
+      idx = find (match);
+    endif
+  else
+    if (len > 0)
+      idx = find (strncmp (s, A, len));
+    else
+      idx = find (strcmp (s, A));
+    endif
+    if (exact)
+      ## We can't just use strcmp, because we need to ignore spaces at end.
+      B = regexprep (A(idx), "[ \\0]+$", '');
+      idx = idx(strcmp (s, B));
+    endif
+  endif
+
+endfunction
+
+
+%!assert (strmatch ("a", {"aaa", "bab", "bbb"}), 1)
+%!assert (strmatch ("apple", "apple juice"), 1)
+%!assert (strmatch ("apple", ["apple pie"; "apple juice"; "an apple"]), [1; 2])
+%!assert (strmatch ("apple", {"apple pie"; "apple juice"; "tomato"}), [1; 2])
+%!assert (strmatch ("apple pie", "apple"), [])
+%!assert (strmatch ("a ", "a"), 1)
+%!assert (strmatch ("a", "a \0", "exact"), 1)
+%!assert (strmatch ("a b", {"a b", "a c", "c d"}), 1)
+%!assert (strmatch ("", {"", "foo", "bar", ""}), [1, 4])
+%!assert (strmatch ('', { '', '% comment', 'var a = 5', ''}, 'exact'), [1,4])
+
+%% Test input validation
+%!error <Invalid call to strmatch> strmatch ()
+%!error <Invalid call to strmatch> strmatch ("a")
+%!error <Invalid call to strmatch> strmatch ("a", "aaa", "exact", 1)
+%!error <S must be a string> strmatch (1, "aaa")
+%!error <S must be a string> strmatch (char ("a", "bb"), "aaa")
+%!error <A must be a string> strmatch ("a", 1)
+%!error <A must be a string> strmatch ("a", {"hello", [1]})
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/deprecated/syl.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,66 @@
+## Copyright (C) 2014 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} {@var{x} =} syl (@var{A}, @var{B}, @var{C})
+##
+## @code{syl} is deprecated and will be removed in Octave version 4.6.
+## Use @code{sylvester} for the equivalent functionality.
+##
+## Solve the Sylvester equation
+## @tex
+## $$
+##  A X + X B + C = 0
+## $$
+## @end tex
+## @ifnottex
+## 
+## @example
+## A X + X B + C = 0
+## @end example
+## 
+## @end ifnottex
+## using standard @sc{lapack} subroutines.  For example:
+## 
+## @example
+## @group
+## syl ([1, 2; 3, 4], [5, 6; 7, 8], [9, 10; 11, 12])
+##    @result{} [ -0.50000, -0.66667; -0.66667, -0.50000 ]
+## @end group
+## @end example
+## @end deftypefn
+
+## Deprecated in version 4.2
+
+function x = syl (A, B, C)
+
+  persistent warned = false;
+  if (! warned)
+    warned = true;
+    warning ("Octave:deprecated-function",
+             "syl is obsolete and will be removed from a future version of Octave, please use sylvester instead");
+  endif
+
+  if (nargin != 3 || nargout > 1)
+    print_usage ();
+  endif
+
+  x = -sylvester (A, B, C);
+
+endfunction
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/deprecated/usage.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,66 @@
+## Copyright (C) 2014 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} {} usage (@var{msg})
+##
+## @code{usage} is deprecated and will be removed in Octave version 4.6.
+## Please use @code{print_usage} in all new code.
+##
+## Print the message @var{msg}, prefixed by the string @samp{usage: }, and
+## set Octave's internal error state such that control will return to the
+## top level without evaluating any more commands.  This is useful for
+## aborting from functions.
+## 
+## After @code{usage} is evaluated, Octave will print a traceback of all
+## the function calls leading to the usage message.
+## 
+## You should use this function for reporting problems errors that result
+## from an improper call to a function, such as calling a function with an
+## incorrect number of arguments, or with arguments of the wrong type.  For
+## example, most functions distributed with Octave begin with code like
+## this
+## 
+## @example
+## @group
+## if (nargin != 2)
+##   usage (\"foo (a, b)\");
+## endif
+## @end group
+## @end example
+## 
+## @noindent
+## to check for the proper number of arguments.
+## @seealso{print_usage}
+## @end deftypefn
+
+## Deprecated in version 4.2
+
+function retval = usage (varargin)
+
+  persistent warned = false;
+  if (! warned)
+    warned = true;
+    warning ("Octave:deprecated-function",
+             "usage is obsolete and will be removed from a future version of Octave, please use print_usage instead");
+  endif
+
+  retval = __usage__ (varargin{:});
+
+endfunction
+
--- a/scripts/elfun/cosd.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/elfun/cosd.m	Mon Jan 12 09:17:35 2015 -0800
@@ -34,7 +34,7 @@
   I = x / 180;
   y = cos (I .* pi);
   I = I + 0.5;
-  y(I == fix (I) & finite (I)) = 0;
+  y(I == fix (I) & isfinite (I)) = 0;
 
 endfunction
 
--- a/scripts/elfun/sind.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/elfun/sind.m	Mon Jan 12 09:17:35 2015 -0800
@@ -33,7 +33,7 @@
 
   I = x / 180;
   y = sin (I .* pi);
-  y(I == fix (I) & finite (I)) = 0;
+  y(I == fix (I) & isfinite (I)) = 0;
 
 endfunction
 
--- a/scripts/elfun/tand.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/elfun/tand.m	Mon Jan 12 09:17:35 2015 -0800
@@ -35,8 +35,8 @@
   I0 = x / 180;
   I90 = (x-90) / 180;
   y = tan (I0 .* pi);
-  y(I0 == fix (I0) & finite (I0)) = 0;
-  y(I90 == fix (I90) & finite (I90)) = Inf;
+  y(I0 == fix (I0) & isfinite (I0)) = 0;
+  y(I90 == fix (I90) & isfinite (I90)) = Inf;
 
 endfunction
 
--- a/scripts/general/bicubic.m	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,248 +0,0 @@
-## Copyright (C) 2005-2013 Hoxide Ma
-##
-## 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{zi} =} bicubic (@var{x}, @var{y}, @var{z}, @var{xi}, @var{yi}, @var{extrapval})
-##
-## Return a matrix @var{zi} corresponding to the bicubic
-## interpolations at @var{xi} and @var{yi} of the data supplied
-## as @var{x}, @var{y} and @var{z}.  Points outside the grid are set
-## to @var{extrapval}.
-##
-## See @url{http://wiki.woodpecker.org.cn/moin/Octave/Bicubic}
-## for further information.
-## @seealso{interp2}
-## @end deftypefn
-
-## Bicubic interpolation method.
-## Author: Hoxide Ma <hoxide_dirac@yahoo.com.cn>
-
-function zi = bicubic (x, y, z, xi, yi, extrapval, spline_alpha)
-
-  if (nargin < 1 || nargin > 7)
-    print_usage ();
-  endif
-
-  if (nargin == 7 && isscalar (spline_alpha))
-    a = spline_alpha;
-  else
-    a = 0.5;
-  endif
-
-  if (nargin < 6)
-    extrapval = NaN;
-  endif
-
-  if (isa (x, "single") || isa (y, "single") || isa (z, "single")
-      || isa (xi, "single") || isa (yi, "single"))
-    myeps = eps ("single");
-  else
-    myeps = eps ();
-  endif
-
-  if (nargin <= 2)
-    ## bicubic (z) or bicubic (z, 2)
-    if (nargin == 1)
-      n = 1;
-    else
-      n = y;
-    endif
-    z = x;
-    x = [];
-    [rz, cz] = size (z);
-    s = linspace (1, cz, (cz-1) * pow2 (n) + 1);
-    t = linspace (1, rz, (rz-1) * pow2 (n) + 1);
-  elseif (nargin == 3)
-    if (! isvector (x) || ! isvector (y))
-      error ("bicubic: XI and YI must be vector");
-    endif
-    s = y;
-    t = z;
-    z = x;
-    [rz, cz] = size (z);
-  elseif (nargin == 5 || nargin == 6)
-    [rz, cz] = size (z) ;
-    if (isvector (x) && isvector (y))
-      if (rz != length (y) || cz != length (x))
-        error ("bicubic: length of X and Y must match the size of Z");
-      endif
-    elseif (size_equal (x, y) && size_equal (x, z))
-      x = x(1,:);
-      y = y(:,1);
-    else
-      error ("bicubic: X, Y and Z must be equal size matrices of same size");
-    endif
-
-    if (all (diff (x) < 0))
-      flipx = true;
-      x = fliplr (x);
-    elseif (all (diff (x) > 0))
-      flipx = false;
-    else
-      error ("bicubic:nonmonotonic", "bicubic: X values must be monotonic");
-    endif
-    if (all (diff (y) < 0))
-      flipy = true;
-      y = flipud (y);
-    elseif (all (diff (y) > 0))
-      flipy = false;
-    else
-      error ("bicubic:nonmonotonic", "bicubic: Y values must be monotonic");
-    endif
-
-    ## Mark values outside the lookup table.
-    xfirst_ind = find (xi < x(1));
-    xlast_ind  = find (xi > x(cz));
-    yfirst_ind = find (yi < y(1));
-    ylast_ind  = find (yi > y(rz));
-    ## Set value outside the table preliminary to min max index.
-    xi(xfirst_ind) = x(1);
-    xi(xlast_ind) = x(cz);
-    yi(yfirst_ind) = y(1);
-    yi(ylast_ind) = y(rz);
-
-    x = reshape (x, 1, cz);
-    x(cz) *= 1 + sign (x(cz)) * myeps;
-    if (x(cz) == 0)
-      x(cz) = myeps;
-    endif;
-    xi = reshape (xi, 1, length (xi));
-    [m, i] = sort ([x, xi]);
-    o = cumsum (i <= cz);
-    xidx = o(find (i > cz));
-
-    y = reshape (y, rz, 1);
-    y(rz) *= 1 + sign (y(rz)) * myeps;
-    if (y(rz) == 0)
-      y(rz) = myeps;
-    endif;
-    yi = reshape (yi, length (yi), 1);
-    [m, i] = sort ([y; yi]);
-    o = cumsum (i <= rz);
-    yidx = o([find(i > rz)]);
-
-    ## Set s and t used follow codes.
-    s = xidx + ((xi .- x(xidx)) ./ (x(xidx+1) .- x(xidx)));
-    t = yidx + ((yi  - y(yidx)) ./ (y(yidx+1)  - y(yidx)));
-
-    if (flipx)
-      s = fliplr (s);
-    endif
-    if (flipy)
-      t = flipud (t);
-    endif
-  else
-    print_usage ();
-  endif
-
-  if (rz < 3 || cz < 3)
-    error ("bicubic: Z at least a 3 by 3 matrices");
-  endif
-
-  inds = floor (s);
-  d = find (s == cz);
-  s = s - floor (s);
-  inds(d) = cz-1;
-  s(d) = 1.0;
-
-  d = [];
-  indt = floor (t);
-  d = find (t == rz);
-  t = t - floor (t);
-  indt(d) = rz-1;
-  t(d) = 1.0;
-  d = [];
-
-  p = zeros (size (z) + 2);
-  p(2:rz+1,2:cz+1) = z;
-  p(1,:) =    (6*(1-a))*p(2,:)    - 3*p(3,:)  + (6*a-2)*p(4,:);
-  p(rz+2,:) = (6*(1-a))*p(rz+1,:) - 3*p(rz,:) + (6*a-2)*p(rz-1,:);
-  p(:,1) =    (6*(1-a))*p(:,2)    - 3*p(:,3)  + (6*a-2)*p(:,4);
-  p(:,cz+2) = (6*(1-a))*p(:,cz+1) - 3*p(:,cz) + (6*a-2)*p(:,cz-1);
-
-  ## Calculte the C1(t) C2(t) C3(t) C4(t) and C1(s) C2(s) C3(s) C4(s).
-  t2 = t.*t;
-  t3 = t2.*t;
-
-  ct0 =    -a .* t3 +     (2 * a) .* t2 - a .* t ;      # -a G0
-  ct1 = (2-a) .* t3 +      (-3+a) .* t2          + 1 ;  # F0 - a G1
-  ct2 = (a-2) .* t3 + (-2 *a + 3) .* t2 + a .* t ;      # F1 + a G0
-  ct3 =     a .* t3 -           a .* t2;                # a G1
-  t = []; t2 = []; t3 = [];
-
-  s2 = s.*s;
-  s3 = s2.*s;
-
-  cs0 =    -a .* s3 +     (2 * a) .* s2 - a .*s ;      # -a G0
-  cs1 = (2-a) .* s3 +    (-3 + a) .* s2         + 1 ;  # F0 - a G1
-  cs2 = (a-2) .* s3 + (-2 *a + 3) .* s2 + a .*s ;      # F1 + a G0
-  cs3 =     a .* s3 -           a .* s2;               # a G1
-  s = []; s2 = []; s3 = [];
-
-  cs0 = cs0([1,1,1,1],:);
-  cs1 = cs1([1,1,1,1],:);
-  cs2 = cs2([1,1,1,1],:);
-  cs3 = cs3([1,1,1,1],:);
-
-  lent = length (ct0);
-  lens = columns (cs0);
-  zi = zeros (lent, lens);
-
-  for i = 1:lent
-    it = indt(i);
-    int = [it, it+1, it+2, it+3];
-    zi(i,:) = ([ct0(i),ct1(i),ct2(i),ct3(i)]
-              * (p(int,inds) .* cs0 + p(int,inds+1) .* cs1
-                 + p(int,inds+2) .* cs2 + p(int,inds+3) .* cs3));
-  endfor
-
-  ## Set points outside the table to extrapval.
-  if (! (isempty (xfirst_ind) && isempty (xlast_ind)))
-    zi(:, [xfirst_ind, xlast_ind]) = extrapval;
-  endif
-  if (! (isempty (yfirst_ind) && isempty (ylast_ind)))
-    zi([yfirst_ind; ylast_ind], :) = extrapval;
-  endif
-
-endfunction
-
-
-%!demo
-%! clf;
-%! colormap ("default");
-%! A = [13,-1,12;5,4,3;1,6,2];
-%! x = [0,1,4]+10;
-%! y = [-10,-9,-8];
-%! xi = linspace (min (x), max (x), 17);
-%! yi = linspace (min (y), max (y), 26)';
-%! mesh (xi, yi, bicubic (x,y,A,xi,yi));
-%! [x,y] = meshgrid (x,y);
-%! hold on; plot3 (x(:),y(:),A(:),"b*"); hold off;
-
-%!test
-%! x = linspace (1, -1, 10);
-%! [xx, yy] = meshgrid (x);
-%! z = cos (6 * xx) + sin (6 * yy);
-%! x = linspace (1, -1, 30);
-%! [xx2, yy2] = meshgrid (x);
-%! z1 = interp2 (xx, yy, z, xx2, yy2, "cubic");
-%! z2 = interp2 (fliplr (xx), flipud (yy), fliplr (flipud(z)),
-%!               fliplr (xx2), flipud (yy2), "cubic");
-%! z2 = fliplr (flipud (z2));
-%! assert (z1, z2, 100 * eps ())
-
--- a/scripts/general/bitcmp.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/general/bitcmp.m	Mon Jan 12 09:17:35 2015 -0800
@@ -31,6 +31,7 @@
 ##   @result{} 110100
 ## @end group
 ## @end example
+##
 ## @seealso{bitand, bitor, bitxor, bitset, bitget, bitcmp, bitshift, bitmax}
 ## @end deftypefn
 
@@ -52,27 +53,11 @@
   elseif (isa (A, "single"))
     bmax = bitmax ("single");
     amax = ceil (log2 (bmax));
+  elseif (isinteger (A))
+    amax = sizeof (ones (1, class (A))) * 8;
+    bmax = bitpack (true (amax, 1), class (A));
   else
-    if (isa (A, "uint8"))
-      amax = 8;
-    elseif (isa (A, "uint16"))
-      amax = 16;
-    elseif (isa (A, "uint32"))
-      amax = 32;
-    elseif (isa (A, "uint64"))
-      amax = 64;
-    elseif (isa (A, "int8"))
-      amax = 8;
-    elseif (isa (A, "int16"))
-      amax = 16;
-    elseif (isa (A, "int32"))
-      amax = 32;
-    elseif (isa (A, "int64"))
-      amax = 64;
-    else
-      error ("bitcmp: invalid class %s", class (A));
-    endif
-    bmax = intmax (class (A));
+    error ("bitcmp: invalid class %s", class (A));
   endif
 
   if (nargin == 1 || k == amax)
@@ -131,3 +116,9 @@
 %! assert (bitcmp (A,Amax-1), bitshift (uint64 (1),Amax-2));
 %! assert (bitcmp (A,Amax-2), uint64 (0));
 
+## Do not forget signed integers
+%!assert (bitcmp (int8 (127)), int8 (-128)) # [1 1 1 1 1 1 1 0]
+%!assert (bitcmp (int8 (1)), int8 (-2))     # [1 0 0 0 0 0 0 0]
+%!assert (bitcmp (int8 (0)), int8 (-1))     # [0 0 0 0 0 0 0 0]
+%!assert (bitcmp (int8 (8)), int8 (-9))     # [0 0 0 1 0 0 0 0]
+
--- a/scripts/general/cell2mat.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/general/cell2mat.m	Mon Jan 12 09:17:35 2015 -0800
@@ -32,15 +32,14 @@
     print_usage ();
   endif
 
-  if (! iscell (c))
-    error ("cell2mat: C is not a cell array");
-  endif
-
   nb = numel (c);
 
   if (nb == 0)
     m = [];
   else
+    if (! iscell (c))
+      error ("cell2mat: C must be a cell array");
+    endif
 
     ## Check first for valid matrix types
     valid = cellfun ("isnumeric", c);
@@ -94,6 +93,7 @@
 %! cell2mat (C)
 
 %!assert (cell2mat ({}), []);
+%!assert (cell2mat ([]), []);
 %!test
 %! C = {[1], [2 3 4]; [5; 9], [6 7 8; 10 11 12]};
 %! D = C; D(:,:,2) = C;
@@ -115,7 +115,7 @@
 
 %!error cell2mat ()
 %!error cell2mat (1,2)
-%!error <C is not a cell array> cell2mat ([1,2])
+%!error <C must be a cell array> cell2mat ([1,2])
 %!error <mixed cells, structs, and matrices> cell2mat ({[1], struct()})
 %!error <mixed cells, structs, and matrices> cell2mat ({[1], {1}})
 %!error <mixed cells, structs, and matrices> cell2mat ({struct(), {1}})
--- a/scripts/general/cplxpair.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/general/cplxpair.m	Mon Jan 12 09:17:35 2015 -0800
@@ -23,7 +23,7 @@
 ## Sort the numbers @var{z} into complex conjugate pairs ordered by
 ## increasing real part.  Place the negative imaginary complex number
 ## first within each pair.  Place all the real numbers (those with
-## @code{abs (imag (@var{z}) / @var{z}) < @var{tol})}) after the
+## @code{abs (imag (@var{z}) / @var{z}) < @var{tol}}) after the
 ## complex pairs.
 ##
 ## If @var{tol} is unspecified the default value is 100*@code{eps}.
--- a/scripts/general/deal.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/general/deal.m	Mon Jan 12 09:17:35 2015 -0800
@@ -54,6 +54,26 @@
 ## @example
 ## a = b = c = x;
 ## @end example
+##
+## Programming Note: @code{deal} is often used with comma separated lists
+## derived from cell arrays or structures.  This is unnecessary as the
+## interpreter can perform the same action without the overhead of a function
+## call.  For example:
+##
+## @example
+## @group
+## c = @{[1 2], "Three", 4@};
+## [x, y, z ] = c@{:@}
+## @result{}
+##    x =
+##
+##       1   2
+##
+##    y = Three
+##    z =  4
+## @end group
+## @end example
+## @seealso{cell2struct, struct2cell, repmat}
 ## @end deftypefn
 
 ## Author: Ariel Tankus
@@ -83,3 +103,6 @@
 %! assert (a, 1);
 %! assert (b, 1);
 
+%!error deal ()
+%!error <nargin . 1 and nargin != nargout> y = deal (1, 2)
+
--- a/scripts/general/del2.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/general/del2.m	Mon Jan 12 09:17:35 2015 -0800
@@ -158,3 +158,164 @@
   D = D ./ nd;
 endfunction
 
+
+## 3x3 constant test
+%!test
+%! a = ones (3,3);
+%! b = del2 (a);
+%! assert (b(:,1), [0.00;0.00;0.00]);
+%! assert (b(:,2), [0.00;0.00;0.00]);
+%! assert (b(:,3), [0.00;0.00;0.00]);
+
+## 3x3 planar test
+%!test
+%! a = [1,2,3;2,3,4;3,4,5];
+%! b = del2 (a);
+%! assert (b(:,1), [0.00;0.00;0.00]);
+%! assert (b(:,2), [0.00;0.00;0.00]);
+%! assert (b(:,3), [0.00;0.00;0.00]);
+
+## 3x3 corner test
+%!test
+%! a = zeros (3,3);
+%! a(1,1) = 1.0;
+%! b = 2*del2 (a);
+%! assert (b(:,1), [1.00;0.50;0.50]);
+%! assert (b(:,2), [0.50;0.00;0.00]);
+%! assert (b(:,3), [0.50;0.00;0.00]);
+%! assert (b, flipud (2*del2 (flipud (a))));
+%! assert (b, fliplr (2*del2 (fliplr (a))));
+%! assert (b, flipud (fliplr (2*del2 (fliplr (flipud (a))))));
+
+## 3x3 boundary test
+%!test
+%! a = zeros (3,3);
+%! a(2,1)=1.0;
+%! b = 2*del2 (a);
+%! assert (b(:,1), [-1.00;-0.50;-1.00]);
+%! assert (b(:,2), [0.00;0.50;0.00]);
+%! assert (b(:,3), [0.00;0.50;0.00]);
+%! assert (b, flipud (2*del2 (flipud (a))));
+%! assert (b, fliplr (2*del2 (fliplr (a))));
+%! assert (b, flipud (fliplr (2*del2 (fliplr (flipud (a))))));
+
+## 3x3 center test
+%!test
+%! a = zeros (3,3);
+%! a(2,2) = 1.0;
+%! b = del2 (a);
+%! assert (b(:,1), [0.00;-0.50;0.00]);
+%! assert (b(:,2), [-0.50;-1.00;-0.50]);
+%! assert (b(:,3), [0.00;-0.50;0.00]);
+
+## 4x4 constant test
+%!test
+%! a = ones (4,4);
+%! b = del2 (a);
+%! assert (b(:,1), [0.00;0.00;0.00;0.00]);
+%! assert (b(:,2), [0.00;0.00;0.00;0.00]);
+%! assert (b(:,3), [0.00;0.00;0.00;0.00]);
+%! assert (b(:,4), [0.00;0.00;0.00;0.00]);
+
+## 4x4 planar test
+%!test
+%! a = [1,2,3,4;2,3,4,5;3,4,5,6;4,5,6,7];
+%! b = del2 (a);
+%! assert (b(:,1), [0.00;0.00;0.00;0.00]);
+%! assert (b(:,2), [0.00;0.00;0.00;0.00]);
+%! assert (b(:,3), [0.00;0.00;0.00;0.00]);
+%! assert (b(:,4), [0.00;0.00;0.00;0.00]);
+
+## 4x4 corner test
+%!test
+%! a = zeros (4,4);
+%! a(1,1) = 1.0;
+%! b = 2*del2 (a);
+%! assert (b(:,1), [2.00;0.50;0.00;-0.50]);
+%! assert (b(:,2), [0.50;0.00;0.00;0.00]);
+%! assert (b(:,3), [0.00;0.00;0.00;0.00]);
+%! assert (b(:,4), [-0.50;0.00;0.00;0.00]);
+%! assert (b, flipud (2*del2 (flipud (a))));
+%! assert (b, fliplr (2*del2 (fliplr (a))));
+%! assert (b, flipud (fliplr (2*del2 (fliplr (flipud (a))))));
+
+## 9x9 center test
+%!test
+%! a = zeros (9,9);
+%! a(5,5) = 1.0;
+%! b = 2*del2 (a);
+%! assert (b(:,1), [0.00;0.00;0.00;0.00;0.00;0.00;0.00;0.00;0.00]);
+%! assert (b(:,2), [0.00;0.00;0.00;0.00;0.00;0.00;0.00;0.00;0.00]);
+%! assert (b(:,3), [0.00;0.00;0.00;0.00;0.00;0.00;0.00;0.00;0.00]);
+%! assert (b(:,4), [0.00;0.00;0.00;0.00;0.50;0.00;0.00;0.00;0.00]);
+%! assert (b(:,5), [0.00;0.00;0.00;0.50;-2.00;0.50;0.00;0.00;0.00]);
+%! assert (b(:,6), b(:,4));
+%! assert (b(:,7), b(:,3));
+%! assert (b(:,8), b(:,2));
+%! assert (b(:,9), b(:,1));
+
+## 9x9 boundary test
+%!test
+%! a = zeros (9,9);
+%! a(1,5) = 1.0;
+%! b = 2*del2 (a);
+%! assert (b(1,:), [0.00,0.00,0.00,0.50,0.00,0.50,0.00,0.00,0.00]);
+%! assert (b(2,:), [0.00,0.00,0.00,0.00,0.50,0.00,0.00,0.00,0.00]);
+%! assert (b(3:9,:), zeros (7,9));
+%! a(1,5) = 0.0;
+%! a(5,1) = 1.0;
+%! b = 2*del2 (a);
+%! assert (b(:,1), [0.00;0.00;0.00;0.50;0.00;0.50;0.00;0.00;0.00]);
+%! assert (b(:,2), [0.00;0.00;0.00;0.00;0.50;0.00;0.00;0.00;0.00]);
+%! assert (b(:,3:9), zeros (9,7));
+
+## 9x9 dh center test
+%!test
+%! a = zeros (9,9);
+%! a(5,5) = 1.0;
+%! b = 8*del2 (a,2);
+%! assert (b(:,1:3), zeros (9,3));
+%! assert (b(:,4), [0.00;0.00;0.00;0.00;0.50;0.00;0.00;0.00;0.00]);
+%! assert (b(:,5), [0.00;0.00;0.00;0.50;-2.00;0.50;0.00;0.00;0.00]);
+%! assert (b(:,6), b(:,4));
+%! assert (b(:,7:9), zeros (9,3));
+
+## 9x9 dx test
+%!test
+%! a = zeros (9,9);
+%! a(5,5) = 1.0;
+%! b = 4*del2 (a,2,1);
+%! assert (b(1:3,:), zeros (3,9));
+%! assert (b(4,:), [0.00;0.00;0.00;0.00;1.00;0.00;0.00;0.00;0.00]');
+%! assert (b(5,:), [0.00;0.00;0.00;0.25;-2.5;0.25;0.00;0.00;0.00]');
+%! assert (b(6,:), b(4,:));
+%! assert (b(7:9,:), zeros (3,9));
+
+## 9x9 dy test
+%!test
+%! a = zeros (9,9);
+%! a(5,5) = 1.0;
+%! b = 4*del2 (a,1,2);
+%! assert (b(:,1:3), zeros (9,3));
+%! assert (b(:,4), [0.00;0.00;0.00;0.00;1.00;0.00;0.00;0.00;0.00]);
+%! assert (b(:,5), [0.00;0.00;0.00;0.25;-2.5;0.25;0.00;0.00;0.00]);
+%! assert (b(:,6), b(:,4));
+%! assert (b(:,7:9), zeros (9,3));
+
+## 3D test
+%!test
+%! a = zeros (9,9,9);
+%! a(5,5,5) = 1.0;
+%! b = 8*3*del2 (a,2);
+%! assert (b(:,:,1:3), zeros (9,9,3));
+%! assert (b(:,1:3,:), zeros (9,3,9));
+%! assert (b(1:3,:,:), zeros (3,9,9));
+%! assert (b(4:5,4,4), [0.0,0.0]');
+%! assert (b(5,5,4), 1.00);
+%! assert (b(4,4,5), 0.00);
+%! assert (b(5,4,5), 1.00);
+%! assert (b(5,5,5),-6.00);
+%! assert (b, flip (b,1));
+%! assert (b, flip (b,2));
+%! assert (b, flip (b,3));
+
--- a/scripts/general/fieldnames.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/general/fieldnames.m	Mon Jan 12 09:17:35 2015 -0800
@@ -33,7 +33,7 @@
 ## When the input is a Java object @var{javaobj} or Java classname
 ## @var{jclassname} the name are the public data elements of the object or
 ## class.
-## @seealso{nfields, isfield, orderfields, struct, methods}
+## @seealso{numfields, isfield, orderfields, struct, methods}
 ## @end deftypefn
 
 function names = fieldnames (obj)
@@ -70,9 +70,13 @@
 %! s = struct ();
 %! assert (fieldnames (s), cell (0, 1));
 
-## test Java classname
-%!testif HAVE_JAVA 
+## test Java classname by passing classname
+%!testif HAVE_JAVA
 %! names = fieldnames ("java.lang.Double");
-%! search = strfind (names, "java.lang.Double.MAX_VALUE");
-%! assert (! isempty ([search{:}]));
+%! assert (any (strcmp (names, "MAX_VALUE")));
 
+## test Java classname by passing java object
+%!testif HAVE_JAVA
+%! names = fieldnames (javaObject ("java.lang.Double", 10));
+%! assert (any (strcmp (names, "MAX_VALUE")));
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/general/flip.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,106 @@
+## Copyright (C) 2004-2013 David Bateman
+## Copyright (C) 2009 VZLU Prague
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {Function File} {} flip (@var{x})
+## @deftypefnx {Function File} {} flip (@var{x}, @var{dim})
+## Flip array across specific dimension.
+##
+## Return a copy of @var{x} flipped about the dimension @var{dim}.
+## @var{dim} defaults to the first non-singleton dimension.
+## For example:
+##
+## @example
+## @group
+## flip ([1  2  3  4])
+##       @result{}  4  3  2  1
+##
+## flip ([1; 2; 3; 4])
+##       @result{}  4
+##           3
+##           2
+##           1
+##
+## flip ([1 2; 3 4])
+##       @result{}  3  4
+##           1  2
+##
+## flip ([1 2; 3 4], 2)
+##       @result{}  2  1
+##           4  3
+## @end group
+## @end example
+##
+## @seealso{fliplr, flipud, rot90, rotdim, permute, transpose}
+## @end deftypefn
+
+## Author: David Bateman, Jaroslav Hajek
+
+function y = flip (x, dim)
+
+  if (nargin < 1 || nargin > 2)
+    print_usage ();
+  endif
+
+  nd = ndims (x);
+  sz = size (x);
+  if (nargin == 1)
+    ## Find the first non-singleton dimension.
+    (dim = find (sz > 1, 1)) || (dim = 1);
+  elseif (! (isscalar (dim) && isindex (dim)))
+    error ("flip: DIM must be a positive integer");
+  endif
+
+  idx(1:max(nd, dim)) = {':'};
+  idx{dim} = size (x, dim):-1:1;
+  y = x(idx{:});
+
+endfunction
+
+
+%!assert (flip ([1 2; 3 4], 2), [2 1; 4 3])
+%!assert (flip ([1 2; 3 4], 3), [1 2; 3 4])
+
+## Test defaults
+%!assert (flip ([1 2 3 4]), [4 3 2 1])
+%!assert (flip ([1 2 3 4].'), [4 3 2 1].')
+%!assert (flip ([1 2; 3 4]), flip ([1 2 ; 3 4], 1))
+
+## Test NDArrays
+%!test
+%! a(1:2,1:2,1) = [1 2; 3 4];
+%! a(1:2,1:2,2) = [5 6; 7 8];
+%! b(1:2,1:2,1) = [5 6; 7 8];
+%! b(1:2,1:2,2) = [1 2; 3 4];
+%! assert (flip (a, 3), b)
+
+%!test
+%! a = b = zeros (2, 2, 1, 2);
+%! a(1:2,1:2,:,1) = [1 2; 3 4];
+%! a(1:2,1:2,:,2) = [5 6; 7 8];
+%! b(1:2,1:2,:,1) = [5 6; 7 8];
+%! b(1:2,1:2,:,2) = [1 2; 3 4];
+%! assert (flip (a, 3), a)
+%! assert (flip (a, 4), b)
+%! assert (flip (a, 5), a)
+
+%!error flip ()
+%!error flip (1, 2, 3)
+%!error <DIM must be a positive integer> flip (magic (3), -1)
+
--- a/scripts/general/flipdim.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/general/flipdim.m	Mon Jan 12 09:17:35 2015 -0800
@@ -20,50 +20,22 @@
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {} flipdim (@var{x})
 ## @deftypefnx {Function File} {} flipdim (@var{x}, @var{dim})
-## Return a copy of @var{x} flipped about the dimension @var{dim}.
-## @var{dim} defaults to the first non-singleton dimension.
-## For example:
+## Flip array across specific dimension.
 ##
-## @example
-## @group
-## flipdim ([1, 2; 3, 4], 2)
-##       @result{}  2  1
-##           4  3
-## @end group
-## @end example
-## @seealso{fliplr, flipud, rot90, rotdim}
+## This function is an alias for @code{flip} and exists for backwards
+## and @sc{matlab} compatibility.  See further details about its usage
+## on @code{flip} help text.
+##
+## @seealso{flip, fliplr, flipud, rot90, rotdim}
 ## @end deftypefn
 
 ## Author: David Bateman, Jaroslav Hajek
 
-function y = flipdim (x, dim)
-
-  if (nargin != 1 && nargin != 2)
-    print_usage ();
-  endif
-
-  nd = ndims (x);
-  sz = size (x);
-  if (nargin == 1)
-    ## Find the first non-singleton dimension.
-    (dim = find (sz > 1, 1)) || (dim = 1);
-  elseif (! (isscalar (dim) && isindex (dim)))
-    error ("flipdim: DIM must be a positive integer");
-  endif
-
-  idx(1:max(nd, dim)) = {':'};
-  idx{dim} = size (x, dim):-1:1;
-  y = x(idx{:});
-
+function y = flipdim (varargin)
+  y = flip (varargin{:});
 endfunction
 
 
-%!assert (flipdim ([1,2;3,4]), flipdim ([1,2 ; 3,4], 1))
-%!assert (flipdim ([1,2;3,4], 2), [2,1;4,3])
-%!assert (flipdim ([1,2;3,4], 3), [1,2;3,4])
+## No tests needed for alias.  All tests for functionality are in flip.m
+%!assert (1)
 
-## FIXME -- we need tests for multidimensional arrays.
-
-%!error flipdim ()
-%!error flipdim (1, 2, 3)
-
--- a/scripts/general/fliplr.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/general/fliplr.m	Mon Jan 12 09:17:35 2015 -0800
@@ -18,6 +18,8 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} fliplr (@var{x})
+## Flip array left to right.
+##
 ## Return a copy of @var{x} with the order of the columns reversed.  In
 ## other words, @var{x} is flipped left-to-right about a vertical axis.  For
 ## example:
@@ -30,9 +32,7 @@
 ## @end group
 ## @end example
 ##
-## Note that @code{fliplr} only works with 2-D arrays.  To flip N-D arrays
-## use @code{flipdim} instead.
-## @seealso{flipud, flipdim, rot90, rotdim}
+## @seealso{flipud, flip, rot90, rotdim}
 ## @end deftypefn
 
 ## Author: jwe
@@ -42,13 +42,7 @@
   if (nargin != 1)
     print_usage ();
   endif
-
-  if (ndims (x) > 2)
-    error ("fliplr: Only works with 2-D arrays");
-  endif
-
-  nc = columns (x);
-  y = x (:, nc:-1:1);
+  y = flip (x, 2);
 
 endfunction
 
@@ -56,6 +50,29 @@
 %!assert (fliplr ([1, 2; 3, 4]), [2, 1; 4, 3])
 %!assert (fliplr ([1, 2; 3, 4; 5, 6]), [2, 1; 4, 3; 6, 5])
 %!assert (fliplr ([1, 2, 3; 4, 5, 6]), [3, 2, 1; 6, 5, 4])
+%!assert (fliplr ([1 2 3].'), [1 2 3].')
+
+## Test NDArrays
+%!test
+%! a(:,:,1) = [ 1  2;  3  4;  5  6];
+%! a(:,:,2) = [ 7  8;  9 10; 11 12];
+%! b(:,:,1) = [ 2  1;  4  3;  6  5];
+%! b(:,:,2) = [ 8  7; 10  9; 12 11];
+%! assert (fliplr (a), b)
+
+## Test NDArray with singleton dimensions
+%!test
+%! a(:,:,:,1) = [ 1  2;  3  4;  5  6];
+%! a(:,:,:,2) = [ 7  8;  9 10; 11 12];
+%! b(:,:,:,1) = [ 2  1;  4  3;  6  5];
+%! b(:,:,:,2) = [ 8  7; 10  9; 12 11];
+%! assert (fliplr (a), b)
+
+## Test for 1 row, i.e., returns the same
+%!test
+%! a(:,1,:,1) = [ 1  2  3  4];
+%! a(:,1,:,2) = [ 5  6  7  8];
+%! assert (fliplr (a), a)
 
 %!error fliplr()
 %!error fliplr (1, 2)
--- a/scripts/general/flipud.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/general/flipud.m	Mon Jan 12 09:17:35 2015 -0800
@@ -18,6 +18,8 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} flipud (@var{x})
+## Flip array upside down.
+##
 ## Return a copy of @var{x} with the order of the rows reversed.  In
 ## other words, @var{x} is flipped upside-down about a horizontal axis.  For
 ## example:
@@ -30,9 +32,7 @@
 ## @end group
 ## @end example
 ##
-## Note that @code{flipud} only works with 2-D arrays.  To flip N-D arrays
-## use @code{flipdim} instead.
-## @seealso{fliplr, flipdim, rot90, rotdim}
+## @seealso{fliplr, flip, rot90, rotdim}
 ## @end deftypefn
 
 ## Author: jwe
@@ -42,13 +42,7 @@
   if (nargin != 1)
     print_usage ();
   endif
-
-  if (ndims (x) > 2)
-    error ("flipud: Only works with 2-d arrays");
-  endif
-
-  nr = rows (x);
-  y = x (nr:-1:1, :);
+  y = flip (x, 1);
 
 endfunction
 
@@ -56,6 +50,29 @@
 %!assert (flipud ([1, 2; 3, 4]), [3, 4; 1, 2])
 %!assert (flipud ([1, 2; 3, 4; 5, 6]), [5, 6; 3, 4; 1, 2])
 %!assert (flipud ([1, 2, 3; 4, 5, 6]), [4, 5, 6; 1, 2, 3])
+%!assert (flipud ([1 2 3]), [1 2 3])
+
+## Test NDArrays
+%!test
+%! a(:,:,1) = [ 1  2  3;  4  5  6];
+%! a(:,:,2) = [ 7  8  9; 10 11 12];
+%! b(:,:,1) = [ 4  5  6;  1  2  3];
+%! b(:,:,2) = [10 11 12;  7  8  9];
+%! assert (flipud (a), b)
+
+## Test NDArray with singleton dimensions
+%!test
+%! a(:,:,:,1) = [ 1  2  3;  4  5  6];
+%! a(:,:,:,2) = [ 7  8  9; 10 11 12];
+%! b(:,:,:,1) = [ 4  5  6;  1  2  3];
+%! b(:,:,:,2) = [10 11 12;  7  8  9];
+%! assert (flipud (a), b)
+
+## Test for 1 row, i.e., returns the same
+%!test
+%! a(1,:,:,1) = [ 1  2  3  4];
+%! a(1,:,:,2) = [ 5  6  7  8];
+%! assert (flipud (a), a)
 
 %!error flipud ()
 %!error flipud (1, 2)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/general/inputParser.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,590 @@
+## Copyright (C) 2011-2014 Carnë Draug
+##
+## 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{p} =} inputParser ()
+## Create object @var{p} of the inputParser class.
+##
+## This class is designed to allow easy parsing of function arguments.  The
+## class supports four types of arguments:
+##
+## @enumerate
+## @item mandatory (see @command{addRequired});
+##
+## @item optional (see @command{addOptional});
+##
+## @item named (see @command{addParamValue});
+##
+## @item switch (see @command{addSwitch}).
+## @end enumerate
+##
+## After defining the function API with these methods, the supplied arguments
+## can be parsed with the @command{parse} method and the parsing results
+## accessed with the @command{Results} accessor.
+##
+## @end deftypefn
+## @deftypefn {Accessor method} {} inputParser.Parameters
+## Return list of parameter names already defined.
+##
+## @end deftypefn
+## @deftypefn {Accessor method} {} inputParser.Results
+## Return structure with argument names as fieldnames and corresponding values.
+##
+## @end deftypefn
+## @deftypefn {Accessor method} {} inputParser.Unmatched
+## Return structure similar to @command{Results}, but for unmatched parameters.
+## See the @command{KeepUnmatched} property.
+##
+## @end deftypefn
+## @deftypefn {Accessor method} {} inputParser.UsingDefaults
+## Return cell array with the names of arguments that are using default values.
+##
+## @end deftypefn
+## @deftypefn {Class property} {} inputParser.CaseSensitive = @var{boolean}
+## Set whether matching of argument names should be case sensitive.  Defaults
+## to false.
+##
+## @end deftypefn
+## @deftypefn {Class property} {} inputParser.FunctionName = @var{name}
+## Set function name to be used in error messages; Defaults to empty string.
+##
+## @end deftypefn
+## @deftypefn {Class property} {} inputParser.KeepUnmatched = @var{boolean}
+## Set whether an error should be given for non-defined arguments.  Defaults to
+## false.  If set to true, the extra arguments can be accessed through
+## @code{Unmatched} after the @code{parse} method.  Note that since
+## @command{Switch} and @command{ParamValue} arguments can be mixed, it is
+## not possible to know the unmatched type.  If argument is found unmatched
+## it is assumed to be of the @command{ParamValue} type and it is expected to
+## be followed by a value.
+##
+## @end deftypefn
+## @deftypefn {Class property} {} inputParser.StructExpand = @var{boolean}
+## Set whether a structure can be passed to the function instead of
+## parameter/value pairs.  Defaults to true.  Not implemented yet.
+##
+## The following example shows how to use this class:
+##
+## @example
+## @group
+## function check (varargin)
+## @c The next two comments need to be indented by one for alignment
+##   p = inputParser ();                      # create object
+##   p.FunctionName = "check";                # set function name
+##   p.addRequired ("pack", @@ischar);         # mandatory argument
+##   p.addOptional ("path", pwd(), @@ischar);  # optional argument
+##
+##   ## create a function handle to anonymous functions for validators
+##   val_mat = @@(x) isvector (x) && all (x <= 1) && all (x >= 0);
+##   p.addOptional ("mat", [0 0], val_mat);
+##
+##   ## create two arguments of type "ParamValue"
+##   val_type = @@(x) any (strcmp (x, @{"linear", "quadratic"@}));
+##   p.addParamValue ("type", "linear", val_type);
+##   val_verb = @@(x) any (strcmp (x, @{"low", "medium", "high"@}));
+##   p.addParamValue ("tolerance", "low", val_verb);
+##
+##   ## create a switch type of argument
+##   p.addSwitch ("verbose");
+##
+##   p.parse (varargin@{:@});  # Run created parser on inputs
+##
+##   ## the rest of the function can access inputs by using p.Results.
+##   ## for example, get the tolerance input with p.Results.tolerance
+## endfunction
+## @end group
+##
+## check ("mech");           # valid, use defaults for other arguments
+## check ();                 # error, one argument is mandatory
+## check (1);                # error, since !ischar
+## check ("mech", "~/dev");  # valid, use defaults for other arguments
+##
+## check ("mech", "~/dev", [0 1 0 0], "type", "linear");  # valid
+##
+## ## following is also valid.  Note how the Switch argument type can
+## ## be mixed into or before the ParamValue argument type (but it
+## ## must still appear after any Optional argument).
+## check ("mech", "~/dev", [0 1 0 0], "verbose", "tolerance", "high");
+##
+## ## following returns an error since not all optional arguments,
+## ## `path' and `mat', were given before the named argument `type'.
+## check ("mech", "~/dev", "type", "linear");
+## @end example
+##
+## @emph{Note 1}: A function can have any mixture of the four API types but
+## they must appear in a specific order.  @command{Required} arguments must be
+## first and can be followed by any @command{Optional} arguments.  Only
+## the @command{ParamValue} and @command{Switch} arguments may be mixed
+## together and they must appear at the end.
+##
+## @emph{Note 2}: If both @command{Optional} and @command{ParamValue} arguments
+## are mixed in a function API then once a string Optional argument fails to
+## validate it will be considered the end of the @command{Optional}
+## arguments.  The remaining arguments will be compared against any
+## @command{ParamValue} or @command{Switch} arguments.
+##
+## @seealso{nargin, validateattributes, validatestring, varargin}
+## @end deftypefn
+
+## -*- texinfo -*-
+## @deftypefn  {Function File} {} addOptional (@var{argname}, @var{default})
+## @deftypefnx {Function File} {} addOptional (@var{argname}, @var{default}, @var{validator})
+## Add new optional argument to the object @var{parser} of the class inputParser
+## to implement an ordered arguments type of API 
+##
+## @var{argname} must be a string with the name of the new argument.  The order
+## in which new arguments are added with @command{addOptional}, represents the
+## expected order of arguments.
+##
+## @var{default} will be the value used when the argument is not specified.
+##
+## @var{validator} is an optional anonymous function to validate the given
+## values for the argument with name @var{argname}.  Alternatively, a
+## function name can be used.
+##
+## See @command{help inputParser} for examples.
+##
+## @emph{Note}: if a string argument does not validate, it will be considered a
+## ParamValue key.  If an optional argument is not given a validator, anything
+## will be valid, and so any string will be considered will be the value of the
+## optional argument (in @sc{matlab}, if no validator is given and argument is
+## a string it will also be considered a ParamValue key).
+##
+## @end deftypefn
+
+## -*- texinfo -*-
+## @deftypefn  {Function File} {} addParamValue (@var{argname}, @var{default})
+## @deftypefnx {Function File} {} addParamValue (@var{argname}, @var{default}, @var{validator})
+## Add new parameter to the object @var{parser} of the class inputParser to
+## implement a name/value pair type of API.
+##
+## @var{argname} must be a string with the name of the new parameter.
+##
+## @var{default} will be the value used when the parameter is not specified.
+##
+## @var{validator} is an optional function handle to validate the given values
+## for the parameter with name @var{argname}.  Alternatively, a function name
+## can be used.
+##
+## See @command{help inputParser} for examples.
+##
+## @end deftypefn
+
+## -*- texinfo -*-
+## @deftypefn  {Function File} {} addRequired (@var{argname})
+## @deftypefnx {Function File} {} addRequired (@var{argname}, @var{validator})
+## Add new mandatory argument to the object @var{parser} of inputParser class.
+##
+## This method belongs to the inputParser class and implements an ordered
+## arguments type of API.
+##
+## @var{argname} must be a string with the name of the new argument.  The order
+## in which new arguments are added with @command{addrequired}, represents the
+## expected order of arguments.
+##
+## @var{validator} is an optional function handle to validate the given values
+## for the argument with name @var{argname}.  Alternatively, a function name
+## can be used.
+##
+## See @command{help inputParser} for examples.
+##
+## @emph{Note}: this can be used together with the other type of arguments but
+## it must be the first (see @command{@@inputParser}).
+##
+## @end deftypefn
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {} addSwitch (@var{argname})
+## Add new switch type of argument to the object @var{parser} of inputParser
+## class.
+##
+## This method belongs to the inputParser class and implements a switch
+## arguments type of API.
+##
+## @var{argname} must be a string with the name of the new argument.  Arguments
+## of this type can be specified at the end, after @code{Required} and
+## @code{Optional}, and mixed between the @code{ParamValue}.  They default to
+## false.  If one of the arguments supplied is a string like @var{argname},
+## then after parsing the value of @var{parse}.Results.@var{argname} will be
+## true.
+##
+## See @command{help inputParser} for examples.
+##
+## @end deftypefn
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {} parse (@var{varargin})
+## Parses and validates list of arguments according to object @var{parser} of
+## the class inputParser.
+##
+## After parsing, the results can be accessed with the @command{Results}
+## accessor.  See @command{help inputParser} for a more complete description.
+##
+## @end deftypefn
+
+## Author: Carnë Draug <carandraug@octave.org>
+
+classdef inputParser < handle
+  properties
+    ## TODO set input checking for this properties
+    CaseSensitive   = false;
+    FunctionName    = "";
+    KeepUnmatched   = false;
+#    PartialMatching = true;   # TODO unimplemented
+#    StructExpand    = true;   # TODO unimplemented
+  endproperties
+
+  properties (SetAccess = protected)
+    Parameters      = cell ();
+    Results         = struct ();
+    Unmatched       = struct ();
+    UsingDefaults   = cell ();
+  endproperties
+
+  properties (Access = protected)
+    ## Since Required and Optional are ordered, they get a cell array of
+    ## structs with the fields "name", "def" (default), and "val" (validator).
+    Required    = cell ();
+    Optional    = cell ();
+    ## ParamValue and Swicth are unordered so we have a struct whose fieldnames
+    ## are the argname, and values are a struct with fields "def" and "val"
+    ParamValue  = struct ();
+    Switch      = struct ();
+
+    ## List of ParamValues and Switch names to ease searches
+    ParamValueNames = cell ();
+    SwitchNames     = cell ();
+
+    ## When checking for fieldnames in a Case Insensitive way, this variable
+    ## holds the correct identifier for the last searched named using the
+    ## is_argname method.
+    last_name = "";
+  endproperties
+
+  properties (Access = protected, Constant = true)
+    ## Default validator, always returns scalar true.
+    def_val = @() true;
+  endproperties
+
+  methods
+    function addRequired (this, name, val = inputParser.def_val)
+      if (nargin < 2 || nargin > 3)
+        print_usage ();
+      elseif (numel (this.Optional) || numel (fieldnames (this.ParamValue))
+              || numel (fieldnames (this.Switch)))
+        error (["inputParser.addRequired: can't have a Required argument " ...
+                "after Optional, ParamValue, or Switch"]);
+      endif
+      this.validate_name ("Required", name);
+      this.Required{end+1} = struct ("name", name, "val", val);
+    endfunction
+
+    function addOptional (this, name, def, val = inputParser.def_val)
+      if (nargin < 3 || nargin > 4)
+        print_usage ();
+      elseif (numel (fieldnames (this.ParamValue))
+              || numel (fieldnames (this.Switch)))
+        error (["inputParser.Optional: can't have Optional arguments " ...
+                "after ParamValue or Switch"]);
+      endif
+      this.validate_name ("Optional", name);
+      this.validate_default ("Optional", name, def, val);
+      this.Optional{end+1} = struct ("name", name, "def", def, "val", val);
+    endfunction
+
+    function addParamValue (this, name, def, val = inputParser.def_val)
+      if (nargin < 3 || nargin > 4)
+        print_usage ();
+      endif
+      this.validate_name ("ParamValue", name);
+      this.validate_default ("ParamValue", name, def, val);
+      this.ParamValue.(name).def = def;
+      this.ParamValue.(name).val = val;
+    endfunction
+
+    function addSwitch (this, name)
+      if (nargin != 2)
+        print_usage ();
+      endif
+      this.validate_name ("Switch", name);
+      this.Switch.(name).def = false;
+    endfunction
+
+    function parse (this, varargin)
+      if (numel (varargin) < numel (this.Required))
+        if (this.FunctionName)
+          print_usage (this.FunctionName);
+        else
+          this.error ("not enough input arguments");
+        endif
+      endif
+      pnargin = numel (varargin);
+
+      this.ParamValueNames = fieldnames (this.ParamValue);
+      this.SwitchNames     = fieldnames (this.Switch);
+
+      ## Evaluate the Required arguments first
+      nReq = numel (this.Required);
+      for idx = 1:nReq
+        req = this.Required{idx};
+        this.validate_arg (req.name, req.val, varargin{idx});
+      endfor
+
+      vidx = nReq;  # current index in varargin
+
+      ## Search for a list of Optional arguments
+      idx  = 0;     # current index on the array of Optional
+      nOpt = numel (this.Optional);
+      while (vidx < pnargin && idx < nOpt)
+        opt = this.Optional{++idx};
+        in  = varargin{++vidx};
+        if (! opt.val (in))
+          ## If it does not match there's two options:
+          ##    1) input is actually wrong and we should error;
+          ##    2) it's a ParamValue or Switch name and we should use the
+          ##       the default for the rest.
+          if (ischar (in))
+            idx--;
+            vidx--;
+            break
+          else
+            this.error (sprintf ("failed validation of %s",
+                                 toupper (opt.name)));
+          endif
+        endif
+        this.Results.(opt.name) = in;
+      endwhile
+
+      ## Fill in with defaults of missing Optional
+      while (idx++ < nOpt)
+        opt = this.Optional{idx};
+        this.UsingDefaults{end+1} = opt.name;
+        this.Results.(opt.name) = opt.def;
+      endwhile
+
+      ## Search unordered Options (Switch and ParamValue)
+      while (vidx++ < pnargin)
+        name = varargin{vidx};
+        if (this.is_argname ("ParamValue", name))
+          if (vidx++ > pnargin)
+            this.error (sprintf ("no matching value for option '%s'",
+                                 toupper (name)));
+          endif
+          this.validate_arg (this.last_name, this.ParamValue.(this.last_name).val,
+                             varargin{vidx});
+        elseif (this.is_argname ("Switch", name))
+          this.Results.(this.last_name) = true;
+        else
+          if (vidx++ < pnargin && this.KeepUnmatched)
+            this.Unmatched.(name) = varargin{vidx};
+          else
+            this.error (sprintf ("argument '%s' is not a valid parameter",
+                                  toupper (name)));
+          endif
+        endif
+      endwhile
+      ## Add them to the UsingDeafults list
+      this.add_missing ("ParamValue");
+      this.add_missing ("Switch");
+
+    endfunction
+
+    function display (this)
+      if (nargin > 1)
+        print_usage ();
+      endif
+      printf ("inputParser object with properties:\n\n");
+      b2s = @(x) ifelse (any (x), "true", "false");
+      printf (["   CaseSensitive   : %s\n   FunctionName    : %s\n" ...
+               "   KeepUnmatched   : %s\n   PartialMatching : %s\n" ...
+               "   StructExpand    : %s\n\n"],
+               b2s (this.CaseSensitive), b2s (this.FunctionName),
+               b2s (this.KeepUnmatched), b2s (this.PartialMatching),
+               b2s (this.StructExpand));
+      printf ("Defined parameters:\n\n   {%s}\n",
+              strjoin (this.Parameters, ", "));
+    endfunction
+  endmethods
+
+  methods (Access = private)
+    function validate_name (this, type, name)
+      if (! isvarname (name))
+        error ("inputParser.add%s: NAME is an invalid identifier", method);
+      elseif (any (strcmpi (this.Parameters, name)))
+        ## Even if CaseSensitive is "on", we still shouldn't allow
+        ## two args with the same name.
+        error ("inputParser.add%s: argname '%s' has already been specified",
+               type, name);
+      endif
+      this.Parameters{end+1} = name;
+    endfunction
+
+    function validate_default (this, type, name, def, val)
+      if (! feval (val, def))
+        error ("inputParser.add%s: failed validation for '%s' default value",
+               type, name);
+      endif
+    endfunction
+
+    function validate_arg (this, name, val, in)
+        if (! val (in))
+          this.error (sprintf ("failed validation of %s", toupper (name)));
+        endif
+        this.Results.(name) = in;
+    endfunction
+
+    function r = is_argname (this, type, name)
+      if (this.CaseSensitive)
+        r = isfield (this.(type), name);
+        this.last_name = name;
+      else
+        fnames = this.([type "Names"]);
+        l = strcmpi (name, fnames);
+        r = any (l(:));
+        if (r)
+          this.last_name = fnames{l};
+        endif
+      endif
+    endfunction
+
+    function add_missing (this, type)
+      unmatched = setdiff (fieldnames (this.(type)), fieldnames (this.Results));
+      for namec = unmatched(:)'
+        name = namec{1};
+        this.UsingDefaults{end+1} = name;
+        this.Results.(name) = this.(type).(name).def;
+      endfor
+    endfunction
+
+    function error (this, msg)
+      where = "";
+      if (this.FunctionName)
+        where = [this.FunctionName ": "];
+      endif
+      error ("%s%s", where, msg);
+    endfunction
+  endmethods
+
+endclassdef
+
+%!function p = create_p ()
+%!  p = inputParser ();
+%!  p.CaseSensitive = true;
+%!  p.addRequired ("req1", @(x) ischar (x));
+%!  p.addOptional ("op1", "val", @(x) any (strcmp (x, {"val", "foo"})));
+%!  p.addOptional ("op2", 78, @(x) x > 50);
+%!  p.addSwitch ("verbose");
+%!  p.addParamValue ("line", "tree", @(x) any (strcmp (x, {"tree", "circle"})));
+%!endfunction
+
+## check normal use, only required are given
+%!test
+%! p = create_p ();
+%! p.parse ("file");
+%! r = p.Results;
+%! assert (r.req1, "file");
+%! assert (sort (p.UsingDefaults), sort ({"op1", "op2", "verbose", "line"}));
+%! assert ({r.req1, r.op1, r.op2, r.verbose, r.line},
+%!        {"file", "val", 78,    false,     "tree"});
+
+## check normal use, but give values different than defaults
+%!test
+%! p = create_p ();
+%! p.parse ("file", "foo", 80, "line", "circle", "verbose");
+%! r = p.Results;
+%! assert ({r.req1, r.op1, r.op2, r.verbose, r.line},
+%!         {"file", "foo", 80,    true,      "circle"});
+
+## check optional is skipped and considered ParamValue if unvalidated string
+%!test
+%! p = create_p ();
+%! p.parse ("file", "line", "circle");
+%! r = p.Results;
+%! assert ({r.req1, r.op1, r.op2, r.verbose, r.line}, 
+%!         {"file", "val", 78,    false,     "circle"});
+
+## check case insensitivity
+%!test
+%! p = create_p ();
+%!  p.CaseSensitive = false;
+%! p.parse ("file", "foo", 80, "LiNE", "circle", "vERbOSe");
+%! r = p.Results;
+%! assert ({r.req1, r.op1, r.op2, r.verbose, r.line},
+%!         {"file", "foo", 80,    true,      "circle"});
+
+## check KeepUnmatched
+%!test
+%! p = create_p ();
+%! p.KeepUnmatched = true;
+%! p.parse ("file", "foo", 80, "line", "circle", "verbose", "extra", 50);
+%! assert (p.Unmatched.extra, 50)
+
+## check error when missing required
+%!error <not enough input arguments>
+%! p = create_p ();
+%! p.parse ();
+
+## check error when given required does not validate
+%!error <failed validation of >
+%! p = create_p ();
+%! p.parse (50);
+
+## check error when given optional does not validate
+%!error <is not a valid parameter>
+%! p = create_p ();
+%! p.parse ("file", "no-val");
+
+## check error when given ParamValue does not validate
+%!error <failed validation of >
+%! p = create_p ();
+%! p.parse ("file", "foo", 51, "line", "round");
+
+## check alternative method (obj, ...) API
+%!function p2 = create_p2 ();
+%!  p2 = inputParser;
+%!  addRequired (p2, "req1", @(x) ischar (x));
+%!  addOptional (p2, "op1", "val", @(x) any (strcmp (x, {"val", "foo"})));
+%!  addOptional (p2, "op2", 78, @(x) x > 50);
+%!  addSwitch (p2, "verbose");
+%!  addParamValue (p2, "line", "tree", @(x) any (strcmp (x, {"tree", "circle"})));
+%!endfunction
+
+## check normal use, only required are given
+%!test
+%! p2 = create_p2 ();
+%! parse (p2, "file");
+%! r = p2.Results;
+%! assert ({r.req1, r.op1, r.op2, r.verbose, r.line},
+%!         {"file", "val", 78,    false,     "tree"});
+%! assert (sort (p2.UsingDefaults), sort ({"op1", "op2", "verbose", "line"}));
+
+## check normal use, but give values different than defaults
+%!test
+%! p2 = create_p2 ();
+%! parse (p2, "file", "foo", 80, "line", "circle", "verbose");
+%! r = p2.Results;
+%! assert ({r.req1, r.op1, r.op2, r.verbose, r.line},
+%!         {"file", "foo", 80,    true,      "circle"});
+
+## FIXME: This somehow works in Matlab
+#%!test
+#%! p = inputParser;
+#%! p.addOptional ("op1", "val");
+#%! p.addParamValue ("line", "tree");
+#%! p.parse ("line", "circle");
+#%! assert (p.Results, struct ("op1", "val", "line", "circle"));
--- a/scripts/general/interp1.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/general/interp1.m	Mon Jan 12 09:17:35 2015 -0800
@@ -1,3 +1,4 @@
+## Copyright (C) 2014 Nir Krakauer
 ## Copyright (C) 2000-2013 Paul Kienzle
 ## Copyright (C) 2009 VZLU Prague
 ##
@@ -29,28 +30,35 @@
 ## One-dimensional interpolation.
 ##
 ## Interpolate input data to determine the value of @var{yi} at the points
-## @var{xi}.  If not specified, @var{x} is taken to be the indices of @var{y}.
-## If @var{y} is a matrix or an N-dimensional array, the interpolation is
-## performed on each column of @var{y}.
+## @var{xi}.  If not specified, @var{x} is taken to be the indices of @var{y}
+## (@code{1:length (@var{y})}).  If @var{y} is a matrix or an N-dimensional
+## array, the interpolation is performed on each column of @var{y}.
 ##
-## Method is one of:
+## The interpolation @var{method} is one of:
 ##
 ## @table @asis
 ## @item @qcode{"nearest"}
-## Return the nearest neighbor
+## Return the nearest neighbor.
+##
+## @item @qcode{"previous"}
+## Return the previous neighbor.
 ##
-## @item @qcode{"linear"}
-## Linear interpolation from nearest neighbors
+## @item @qcode{"next"}
+## Return the next neighbor.
+##
+## @item @qcode{"linear"} (default)
+## Linear interpolation from nearest neighbors.
 ##
 ## @item @qcode{"pchip"}
-## Piecewise cubic Hermite interpolating polynomial
+## Piecewise cubic Hermite interpolating polynomial---shape-preserving
+## interpolation with smooth first derivative.
 ##
 ## @item @qcode{"cubic"}
-## Cubic interpolation (same as @code{pchip})
+## Cubic interpolation (same as @qcode{"pchip"}).
 ##
 ## @item @qcode{"spline"}
 ## Cubic spline interpolation---smooth first and second derivatives
-## throughout the curve
+## throughout the curve.
 ## @end table
 ##
 ## Adding '*' to the start of any method above forces @code{interp1}
@@ -61,7 +69,7 @@
 ## If @var{extrap} is the string @qcode{"extrap"}, then extrapolate values
 ## beyond the endpoints using the current @var{method}.  If @var{extrap} is a
 ## number, then replace values beyond the endpoints with that number.  When
-## unspecified, @var{extrap} defaults to NA.
+## unspecified, @var{extrap} defaults to @code{NA}.
 ##
 ## If the string argument @qcode{"pp"} is specified, then @var{xi} should not
 ## be supplied and @code{interp1} returns a piecewise polynomial object.  This 
@@ -76,7 +84,7 @@
 ## right-continuous.  If @var{x} is decreasing, the default discontinuous
 ## interpolant is left-continuous.
 ## The continuity condition of the interpolant may be specified by using
-## the options, @qcode{"left"} or @qcode{"right"}, to select a left-continuous
+## the options @qcode{"left"} or @qcode{"right"} to select a left-continuous
 ## or right-continuous interpolant, respectively.
 ## Discontinuous interpolation is only allowed for @qcode{"nearest"} and
 ## @qcode{"linear"} methods; in all other cases, the @var{x}-values must be
@@ -91,16 +99,16 @@
 ## xp = [0:10];
 ## yp = sin (2*pi*xp/5);
 ## lin = interp1 (xp, yp, xf);
+## near = interp1 (xp, yp, xf, "nearest");
+## pch = interp1 (xp, yp, xf, "pchip");
 ## spl = interp1 (xp, yp, xf, "spline");
-## cub = interp1 (xp, yp, xf, "cubic");
-## near = interp1 (xp, yp, xf, "nearest");
-## plot (xf, yf, "r", xf, lin, "g", xf, spl, "b",
-##       xf, cub, "c", xf, near, "m", xp, yp, "r*");
-## legend ("original", "linear", "spline", "cubic", "nearest");
+## plot (xf,yf,"r", xf,near,"g", xf,lin,"b", xf,pch,"c", xf,spl,"m", 
+##       xp,yp,"r*");
+## legend ("original", "nearest", "linear", "pchip", "spline");
 ## @end group
 ## @end example
 ##
-## @seealso{interpft, interp2, interp3, interpn}
+## @seealso{pchip, spline, interpft, interp2, interp3, interpn}
 ## @end deftypefn
 
 ## Author: Paul Kienzle
@@ -130,17 +138,18 @@
       arg = varargin{i};
       if (ischar (arg))
         arg = tolower (arg);
-        if (strcmp ("extrap", arg))
-          extrap = "extrap";
-        elseif (strcmp ("pp", arg))
-          ispp = true;
-        elseif (strcmp (arg, "right") || strcmp (arg, "-right"))
-          rightcontinuous = true;
-        elseif (strcmp (arg, "left") || strcmp (arg, "-left"))
-          rightcontinuous = false;
-        else
-          method = arg;
-        endif
+        switch (arg)
+          case "extrap"
+            extrap = "extrap";
+          case "pp"
+            ispp = true;
+          case {"right", "-right"}
+            rightcontinuous = true;
+          case {"left", "-left"}
+            rightcontinuous = false;
+          otherwise
+            method = arg;
+        endswitch
       else
         if (firstnumeric)
           xi = arg;
@@ -177,7 +186,7 @@
 
   ## determine sizes
   if (nx < 2 || ny < 2)
-    error ("interp1: table too short");
+    error ("interp1: minimum of 2 points required in each dimension");
   endif
 
   ## check whether x is sorted; sort if not.
@@ -186,6 +195,10 @@
     y = y(p,:);
   endif
 
+  if (any (strcmp (method, {"previous", "*previous", "next", "*next"})))
+    rightcontinuous = NaN; # needed for these methods to work
+  endif 
+
   if (isnan (rightcontinuous))
     ## If not specified, set the continuity condition
     if (x(end) < x(1))
@@ -193,15 +206,25 @@
     else
       rightcontinuous = true;
     endif
-  endif
-
-  if ((rightcontinuous && (x(end) < x(1)))
-      || (! rightcontinuous && (x(end) > x(1))))
+  elseif ((rightcontinuous && (x(end) < x(1)))
+          || (! rightcontinuous && (x(end) > x(1))))
     ## Switch between left-continuous and right-continuous
     x = flipud (x);
     y = flipud (y);
   endif
 
+  ## Because of the way mkpp works, it's easiest to implement "next"
+  ## by running "previous" with vectors flipped.
+  if (strcmp (method, "next"))
+    x = flipud (x);
+    y = flipud (y);
+    method = "previous";
+  elseif (strcmp (method, "*next"))
+    x = flipud (x);
+    y = flipud (y);
+    method = "*previous";  
+  endif
+
   starmethod = method(1) == "*";
 
   if (starmethod)
@@ -215,7 +238,8 @@
           warning ("interp1: multiple discontinuities at the same X value");
         endif
       else
-        error ("interp1: discontinuities not supported for method '%s'", method);
+        error ("interp1: discontinuities not supported for method '%s'",
+                                                                   method);
       endif
     endif
   endif
@@ -238,6 +262,29 @@
       pp = mkpp ([x(1), x(1)+[0.5:(nx-1)]*dx, x(nx)],
                  shiftdim (y, 1), szy(2:end));
       pp.orient = "first";
+
+      if (ispp)
+        yi = pp;
+      else
+        yi = ppval (pp, reshape (xi, szx));
+      endif
+
+    case "previous"
+      pp = mkpp ([x(1:nx); 2*x(nx)-x(nx-1)],
+                 shiftdim (y, 1), szy(2:end));
+      pp.orient = "first";
+
+      if (ispp)
+        yi = pp;
+      else
+        yi = ppval (pp, reshape (xi, szx));
+      endif
+
+    case "*previous"
+      pp = mkpp (x(1)+[0:nx]*dx,
+                 shiftdim (y, 1), szy(2:end));
+      pp.orient = "first";
+
       if (ispp)
         yi = pp;
       else
@@ -323,7 +370,7 @@
 
   endswitch
 
-  if (! ispp && ! ischar (extrap))
+  if (! ispp && isnumeric (extrap))
     ## determine which values are out of range and set them to extrap,
     ## unless extrap == "extrap".
     minx = min (x(1), x(nx));
@@ -349,12 +396,13 @@
 %! clf;
 %! xf = 0:0.05:10;  yf = sin (2*pi*xf/5);
 %! xp = 0:10;       yp = sin (2*pi*xp/5);
-%! lin = interp1 (xp,yp,xf, "linear");
-%! spl = interp1 (xp,yp,xf, "spline");
-%! cub = interp1 (xp,yp,xf, "pchip");
-%! near= interp1 (xp,yp,xf, "nearest");
-%! plot (xf,yf,"r",xf,near,"g",xf,lin,"b",xf,cub,"c",xf,spl,"m",xp,yp,"r*");
-%! legend ("original", "nearest", "linear", "pchip", "spline");
+%! lin = interp1 (xp,yp,xf, 'linear');
+%! spl = interp1 (xp,yp,xf, 'spline');
+%! pch = interp1 (xp,yp,xf, 'pchip');
+%! near= interp1 (xp,yp,xf, 'nearest');
+%! plot (xf,yf,'r',xf,near,'g',xf,lin,'b',xf,pch,'c',xf,spl,'m',xp,yp,'r*');
+%! legend ('original', 'nearest', 'linear', 'pchip', 'spline');
+%! title ('Interpolation of continuous function sin (x) w/various methods');
 %! %--------------------------------------------------------
 %! % confirm that interpolated function matches the original
 
@@ -362,36 +410,50 @@
 %! clf;
 %! xf = 0:0.05:10;  yf = sin (2*pi*xf/5);
 %! xp = 0:10;       yp = sin (2*pi*xp/5);
-%! lin = interp1 (xp,yp,xf, "*linear");
-%! spl = interp1 (xp,yp,xf, "*spline");
-%! cub = interp1 (xp,yp,xf, "*cubic");
-%! near= interp1 (xp,yp,xf, "*nearest");
-%! plot (xf,yf,"r",xf,near,"g",xf,lin,"b",xf,cub,"c",xf,spl,"m",xp,yp,"r*");
-%! legend ("*original", "*nearest", "*linear", "*cubic", "*spline");
+%! lin = interp1 (xp,yp,xf, '*linear');
+%! spl = interp1 (xp,yp,xf, '*spline');
+%! pch = interp1 (xp,yp,xf, '*pchip');
+%! near= interp1 (xp,yp,xf, '*nearest');
+%! plot (xf,yf,'r',xf,near,'g',xf,lin,'b',xf,pch,'c',xf,spl,'m',xp,yp,'r*');
+%! legend ('*original', '*nearest', '*linear', '*pchip', '*spline');
+%! title ('Interpolation of continuous function sin (x) w/various *methods');
 %! %--------------------------------------------------------
 %! % confirm that interpolated function matches the original
 
 %!demo
 %! clf;
+%! fstep = @(x) x > 1;
+%! xf = 0:0.05:2;  yf = fstep (xf);
+%! xp = linspace (0,2,10);  yp = fstep (xp);
+%! pch = interp1 (xp,yp,xf, 'pchip');
+%! spl = interp1 (xp,yp,xf, 'spline');
+%! plot (xf,yf,'r',xf,pch,'b',xf,spl,'m',xp,yp,'r*');
+%! title ({'Interpolation of step function with discontinuity at x==1', ...
+%!         'Note: "pchip" is shape-preserving, "spline" (continuous 1st, 2nd derivatives) is not'});
+%! legend ('original', 'pchip', 'spline');
+
+%!demo
+%! clf;
 %! t = 0 : 0.3 : pi; dt = t(2)-t(1);
 %! n = length (t); k = 100; dti = dt*n/k;
 %! ti = t(1) + [0 : k-1]*dti;
 %! y = sin (4*t + 0.3) .* cos (3*t - 0.1);
-%! ddyc = diff (diff (interp1 (t,y,ti, "cubic")) ./dti)./dti;
-%! ddys = diff (diff (interp1 (t,y,ti, "spline"))./dti)./dti;
-%! ddyp = diff (diff (interp1 (t,y,ti, "pchip")) ./dti)./dti;
-%! plot (ti(2:end-1),ddyc,'g+', ti(2:end-1),ddys,'b*', ti(2:end-1),ddyp,'c^');
-%! legend ("cubic", "spline", "pchip");
-%! title ("Second derivative of interpolated 'sin (4*t + 0.3) .* cos (3*t - 0.1)'");
+%! ddys = diff (diff (interp1 (t,y,ti, 'spline'))./dti)./dti;
+%! ddyp = diff (diff (interp1 (t,y,ti, 'pchip')) ./dti)./dti;
+%! ddyc = diff (diff (interp1 (t,y,ti, 'cubic')) ./dti)./dti;
+%! plot (ti(2:end-1),ddys,'b*', ti(2:end-1),ddyp,'c^', ti(2:end-1),ddyc,'g+');
+%! title ({'Second derivative of interpolated "sin (4*t + 0.3) .* cos (3*t - 0.1)"', ...
+%!         'Note: "spline" has continous 2nd derivative, others do not'});
+%! legend ('spline', 'pchip', 'cubic');
 
 %!demo
 %! clf;
 %! xf = 0:0.05:10;                yf = sin (2*pi*xf/5) - (xf >= 5);
 %! xp = [0:.5:4.5,4.99,5:.5:10];  yp = sin (2*pi*xp/5) - (xp >= 5);
-%! lin = interp1 (xp,yp,xf, "linear");
-%! near= interp1 (xp,yp,xf, "nearest");
-%! plot (xf,yf,"r", xf,near,"g", xf,lin,"b", xp,yp,"r*");
-%! legend ("original", "nearest", "linear");
+%! lin = interp1 (xp,yp,xf, 'linear');
+%! near= interp1 (xp,yp,xf, 'nearest');
+%! plot (xf,yf,'r', xf,near,'g', xf,lin,'b', xp,yp,'r*');
+%! legend ('original', 'nearest', 'linear');
 %! %--------------------------------------------------------
 %! % confirm that interpolated function matches the original
 
@@ -412,7 +474,7 @@
 %! %--------------------------------------------------------
 %! % red curve is left-continuous and blue is right-continuous at x = 2
 
-##FIXME: add test for n-d arguments here
+##FIXME: add test for N-d arguments here
 
 ## For each type of interpolated test, confirm that the interpolated
 ## value at the knots match the values at the knots.  Points away
@@ -425,7 +487,7 @@
 %! xi = [-1, 0, 2.2, 4, 6.6, 10, 11];
 
 ## The following BLOCK/ENDBLOCK section is repeated for each style
-##    nearest, linear, cubic, spline, pchip
+##    nearest, previous, next, linear, cubic, spline, pchip
 ## The test for ppval of cubic has looser tolerance, but otherwise
 ## the tests are identical.
 ## Note that the block checks style and *style; if you add more tests
@@ -468,6 +530,78 @@
 %!error interp1 (1,1,1, style)
 ## ENDBLOCK
 
+%!test style = "previous";
+## BLOCK
+%!assert (interp1 (xp, yp, [min(xp)-1, max(xp)+1],style), [NA, NA])
+%!assert (interp1 (xp,yp,xp,style), yp, 100*eps)
+%!assert (interp1 (xp,yp,xp',style), yp', 100*eps)
+%!assert (interp1 (xp',yp',xp',style), yp', 100*eps)
+%!assert (interp1 (xp',yp',xp,style), yp, 100*eps)
+%!assert (isempty (interp1 (xp',yp',[],style)))
+%!assert (isempty (interp1 (xp,yp,[],style)))
+%!assert (interp1 (xp,[yp',yp'],xi(:),style),...
+%!        [interp1(xp,yp,xi(:),style),interp1(xp,yp,xi(:),style)])
+## This test is expected to fail, so commented out.
+## "previous" and "next" options are not symmetric w.r.t to flipping xp,yp
+#%!assert (interp1 (xp,yp,xi,style),... 
+#%!        interp1 (fliplr (xp),fliplr (yp),xi,style),100*eps)
+%!assert (ppval (interp1 (xp,yp,style,"pp"),xi),
+%!        interp1 (xp,yp,xi,style,"extrap"),10*eps)
+%!error interp1 (1,1,1, style)
+%!assert (interp1 (xp,[yp',yp'],xi,style),
+%!        interp1 (xp,[yp',yp'],xi,["*",style]),100*eps)
+%!test style = ["*",style];
+%!assert (interp1 (xp, yp, [min(xp)-1, max(xp)+1],style), [NA, NA])
+%!assert (interp1 (xp,yp,xp,style), yp, 100*eps)
+%!assert (interp1 (xp,yp,xp',style), yp', 100*eps)
+%!assert (interp1 (xp',yp',xp',style), yp', 100*eps)
+%!assert (interp1 (xp',yp',xp,style), yp, 100*eps)
+%!assert (isempty (interp1 (xp',yp',[],style)))
+%!assert (isempty (interp1 (xp,yp,[],style)))
+%!assert (interp1 (xp,[yp',yp'],xi(:),style),...
+%!        [interp1(xp,yp,xi(:),style),interp1(xp,yp,xi(:),style)])
+# %!assert (interp1 (xp,yp,xi,style),... 
+# %!        interp1 (fliplr (xp),fliplr (yp),xi,style),100*eps)
+%!assert (ppval (interp1 (xp,yp,style,"pp"),xi),
+%!        interp1 (xp,yp,xi,style,"extrap"),10*eps)
+%!error interp1 (1,1,1, style)
+## ENDBLOCK
+
+%!test style = "next";
+## BLOCK
+%!assert (interp1 (xp, yp, [min(xp)-1, max(xp)+1],style), [NA, NA])
+%!assert (interp1 (xp,yp,xp,style), yp, 100*eps)
+%!assert (interp1 (xp,yp,xp',style), yp', 100*eps)
+%!assert (interp1 (xp',yp',xp',style), yp', 100*eps)
+%!assert (interp1 (xp',yp',xp,style), yp, 100*eps)
+%!assert (isempty (interp1 (xp',yp',[],style)))
+%!assert (isempty (interp1 (xp,yp,[],style)))
+%!assert (interp1 (xp,[yp',yp'],xi(:),style),...
+%!        [interp1(xp,yp,xi(:),style),interp1(xp,yp,xi(:),style)])
+# %!assert (interp1 (xp,yp,xi,style),... 
+# %!        interp1 (fliplr (xp),fliplr (yp),xi,style),100*eps)
+%!assert (ppval (interp1 (xp,yp,style,"pp"),xi),
+%!        interp1 (xp,yp,xi,style,"extrap"),10*eps)
+%!error interp1 (1,1,1, style)
+%!assert (interp1 (xp,[yp',yp'],xi,style),
+%!        interp1 (xp,[yp',yp'],xi,["*",style]),100*eps)
+%!test style = ["*",style];
+%!assert (interp1 (xp, yp, [min(xp)-1, max(xp)+1],style), [NA, NA])
+%!assert (interp1 (xp,yp,xp,style), yp, 100*eps)
+%!assert (interp1 (xp,yp,xp',style), yp', 100*eps)
+%!assert (interp1 (xp',yp',xp',style), yp', 100*eps)
+%!assert (interp1 (xp',yp',xp,style), yp, 100*eps)
+%!assert (isempty (interp1 (xp',yp',[],style)))
+%!assert (isempty (interp1 (xp,yp,[],style)))
+%!assert (interp1 (xp,[yp',yp'],xi(:),style),...
+%!        [interp1(xp,yp,xi(:),style),interp1(xp,yp,xi(:),style)])
+# %!assert (interp1 (xp,yp,xi,style),... 
+# %!        interp1 (fliplr (xp),fliplr (yp),xi,style),100*eps)
+%!assert (ppval (interp1 (xp,yp,style,"pp"),xi),
+%!        interp1 (xp,yp,xi,style,"extrap"),10*eps)
+%!error interp1 (1,1,1, style)
+## ENDBLOCK
+
 %!test style = "linear";
 ## BLOCK
 %!assert (interp1 (xp, yp, [min(xp)-1, max(xp)+1],style), [NA, NA])
@@ -611,20 +745,27 @@
 ## ENDBLOCK
 ## ENDBLOCKTEST
 
-## test extrapolation (linear)
+## test extrapolation
 %!assert (interp1 ([1:5],[3:2:11],[0,6],"linear","extrap"), [1, 13], eps)
+%!assert (interp1 ([1:5],[3:2:11],[0,6],"nearest","extrap"), [3, 11], eps)
+%!assert (interp1 ([1:5],[3:2:11],[0,6],"previous","extrap"), [3, 11], eps)
+%!assert (interp1 ([1:5],[3:2:11],[0,6],"next","extrap"), [3, 11], eps)
 %!assert (interp1 (xp, yp, [-1, max(xp)+1],"linear",5), [5, 5])
 %!assert (interp1 ([0,1],[1,0],[0.1,0.9;0.2,1.1]), [0.9 0.1; 0.8 NA], eps)
 %!assert (interp1 ([0,1],[1,0],[0.1,0.9;0.2,1]), [0.9 0.1; 0.8 0], eps)
 
 ## Basic sanity checks
 %!assert (interp1 (1:2,1:2,1.4,"nearest"), 1)
+%!assert (interp1 (1:2,1:2,1.6,"previous"), 1)
+%!assert (interp1 (1:2,1:2,1.4,"next"), 2)
 %!assert (interp1 (1:2,1:2,1.4,"linear"), 1.4)
 %!assert (interp1 (1:4,1:4,1.4,"cubic"), 1.4)
 %!assert (interp1 (1:2,1:2,1.1,"spline"), 1.1)
 %!assert (interp1 (1:3,1:3,1.4,"spline"), 1.4)
 
 %!assert (interp1 (1:2:4,1:2:4,1.4,"*nearest"), 1)
+%!assert (interp1 (1:2:4,1:2:4,2.2,"*previous"), 1)
+%!assert (interp1 (1:2:4,1:2:4,1.4,"*next"), 3)
 %!assert (interp1 (1:2:4,1:2:4,[0,1,1.4,3,4],"*linear"), [NA,1,1.4,3,NA])
 %!assert (interp1 (1:2:8,1:2:8,1.4,"*cubic"), 1.4)
 %!assert (interp1 (1:2,1:2,1.3, "*spline"), 1.3)
@@ -642,12 +783,15 @@
 %% Test input validation
 %!error interp1 ()
 %!error interp1 (1,2,3,4,5,6,7)
-%!error <table too short> interp1 (1,1,1, "linear")
-%!error <table too short> interp1 (1,1,1, "*nearest")
-%!error <table too short> interp1 (1,1,1, "*linear")
+%!error <minimum of 2 points required> interp1 (1,1,1, "linear")
+%!error <minimum of 2 points required> interp1 (1,1,1, "*nearest")
+%!error <minimum of 2 points required> interp1 (1,1,1, "*linear")
+%!error <minimum of 2 points required> interp1 (1,1,1, "previous")
+%!error <minimum of 2 points required> interp1 (1,1,1, "*previous")
 %!warning <multiple discontinuities> interp1 ([1 1 1 2], [1 2 3 4], 1);
+%!error <discontinuities not supported> interp1 ([1 1],[1 2],1, "next")
 %!error <discontinuities not supported> interp1 ([1 1],[1 2],1, "pchip")
 %!error <discontinuities not supported> interp1 ([1 1],[1 2],1, "cubic")
 %!error <discontinuities not supported> interp1 ([1 1],[1 2],1, "spline")
-%!error <invalid method> interp1 (1:2,1:2,1, "bogus")
+%!error <invalid method 'bogus'> interp1 (1:2,1:2,1, "bogus")
 
--- a/scripts/general/interp2.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/general/interp2.m	Mon Jan 12 09:17:35 2015 -0800
@@ -19,63 +19,63 @@
 
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {@var{zi} =} interp2 (@var{x}, @var{y}, @var{z}, @var{xi}, @var{yi})
-## @deftypefnx {Function File} {@var{zi} =} interp2 (@var{Z}, @var{xi}, @var{yi})
-## @deftypefnx {Function File} {@var{zi} =} interp2 (@var{Z}, @var{n})
+## @deftypefnx {Function File} {@var{zi} =} interp2 (@var{z}, @var{xi}, @var{yi})
+## @deftypefnx {Function File} {@var{zi} =} interp2 (@var{z}, @var{n})
+## @deftypefnx {Function File} {@var{zi} =} interp2 (@var{z})
 ## @deftypefnx {Function File} {@var{zi} =} interp2 (@dots{}, @var{method})
-## @deftypefnx {Function File} {@var{zi} =} interp2 (@dots{}, @var{method}, @var{extrapval})
+## @deftypefnx {Function File} {@var{zi} =} interp2 (@dots{}, @var{method}, @var{extrap})
+##
+## Two-dimensional interpolation.
 ##
-## Two-dimensional interpolation.  @var{x}, @var{y} and @var{z} describe a
-## surface function.  If @var{x} and @var{y} are vectors their length
-## must correspondent to the size of @var{z}.  @var{x} and @var{y} must be
-## monotonic.  If they are matrices they must have the @code{meshgrid}
-## format.
-##
-## @table @code
-## @item interp2 (@var{x}, @var{y}, @var{Z}, @var{xi}, @var{yi}, @dots{})
-## Returns a matrix corresponding to the points described by the
-## matrices @var{xi}, @var{yi}.
+## Interpolate reference data @var{x}, @var{y}, @var{z} to determine @var{zi}
+## at the coordinates @var{xi}, @var{yi}.  The reference data @var{x}, @var{y}
+## can be matrices, as returned by @code{meshgrid}, in which case the sizes of
+## @var{x}, @var{y}, and @var{z} must be equal.  If @var{x}, @var{y} are
+## vectors describing a grid then @code{length (@var{x}) == columns (@var{z})}
+## and @code{length (@var{y}) == rows (@var{z})}.  In either case the input
+## data must be strictly monotonic.
 ##
-## If the last argument is a string, the interpolation method can
-## be specified.  The method can be @qcode{"linear"}, @qcode{"nearest"} or
-## @qcode{"cubic"}.  If it is omitted @qcode{"linear"} interpolation is
-## assumed.
+## If called without @var{x}, @var{y}, and just a single reference data matrix
+## @var{z}, the 2-D region
+## @code{@var{x} = 1:columns (@var{z}), @var{y} = 1:rows (@var{z})} is assumed.
+## This saves memory if the grid is regular and the distance between points is
+## not important.
 ##
-## @item interp2 (@var{z}, @var{xi}, @var{yi})
-## Assumes @code{@var{x} = 1:rows (@var{z})} and @code{@var{y} =
-## 1:columns (@var{z})}
+## If called with a single reference data matrix @var{z} and a refinement
+## value @var{n}, then perform interpolation over a grid where each original
+## interval has been recursively subdivided @var{n} times.  This results in
+## @code{2^@var{n}-1} additional points for every interval in the original
+## grid.  If @var{n} is omitted a value of 1 is used.  As an example, the
+## interval [0,1] with @code{@var{n}==2} results in a refined interval with
+## points at [0, 1/4, 1/2, 3/4, 1].
 ##
-## @item interp2 (@var{z}, @var{n})
-## Interleaves the matrix @var{z} n-times.  If @var{n} is omitted a value
-## of @code{@var{n} = 1} is assumed.
-## @end table
-##
-## The variable @var{method} defines the method to use for the
-## interpolation.  It can take one of the following values
+## The interpolation @var{method} is one of:
 ##
 ## @table @asis
 ## @item @qcode{"nearest"}
 ## Return the nearest neighbor.
 ##
-## @item @qcode{"linear"}
+## @item @qcode{"linear"} (default)
 ## Linear interpolation from nearest neighbors.
 ##
 ## @item @qcode{"pchip"}
-## Piecewise cubic Hermite interpolating polynomial.
+## Piecewise cubic Hermite interpolating polynomial---shape-preserving
+## interpolation with smooth first derivative.
 ##
 ## @item @qcode{"cubic"}
-## Cubic interpolation from four nearest neighbors.
+## Cubic interpolation (same as @qcode{"pchip"}).
 ##
 ## @item @qcode{"spline"}
 ## Cubic spline interpolation---smooth first and second derivatives
 ## throughout the curve.
 ## @end table
 ##
-## If a scalar value @var{extrapval} is defined as the final value, then
-## values outside the mesh as set to this value.  Note that in this case
-## @var{method} must be defined as well.  If @var{extrapval} is not
-## defined then NA is assumed.
-##
-## @seealso{interp1}
+## If @var{extrap} is the string @qcode{"extrap"}, then extrapolate values
+## beyond the endpoints using the current @var{method}.  If @var{extrap} is a
+## number, then replace values beyond the endpoints with that number.  When
+## unspecified, @var{extrap} defaults to @code{NA}.  Note that if @var{extrap}
+## is used, @var{method} must be specified as well.
+## @seealso{interp1, interp3, interpn, meshgrid}
 ## @end deftypefn
 
 ## Author:      Kai Habel <kai.habel@gmx.de>
@@ -94,10 +94,14 @@
 ##       "meshgridded") to be consistent with the help message
 ##       above and for compatibility.
 
+## FIXME: Need better input validation.
+##        E.g, interp2 (1,1,1) => A(I): index out of bounds
+
 function ZI = interp2 (varargin)
+
   Z = X = Y = XI = YI = n = [];
   method = "linear";
-  extrapval = NA;
+  extrap = NA;
 
   switch (nargin)
     case 1
@@ -120,36 +124,41 @@
       if (ischar (varargin{4}))
         [Z, XI, YI, method] = deal (varargin{:});
       else
-        [Z, n, method, extrapval] = deal (varargin{:});
+        [Z, n, method, extrap] = deal (varargin{:});
       endif
     case 5
       if (ischar (varargin{4}))
-        [Z, XI, YI, method, extrapval] = deal (varargin{:});
+        [Z, XI, YI, method, extrap] = deal (varargin{:});
       else
         [X, Y, Z, XI, YI] = deal (varargin{:});
       endif
     case 6
         [X, Y, Z, XI, YI, method] = deal (varargin{:});
     case 7
-        [X, Y, Z, XI, YI, method, extrapval] = deal (varargin{:});
+        [X, Y, Z, XI, YI, method, extrap] = deal (varargin{:});
     otherwise
       print_usage ();
   endswitch
 
-  ## Type checking.
-  if (!ismatrix (Z))
-    error ("interp2: Z must be a matrix");
+  ## Type checking
+  if (! (ismatrix (Z) && ndims (Z) == 2))
+    error ("interp2: Z must be a 2-D matrix");
   endif
-  if (!isempty (n) && !isscalar (n))
-    error ("interp2: N must be a scalar");
+  if (! isempty (n) && ! (isscalar (n) && n >= 0 && n == fix (n)))
+    error ("interp2: N must be an integer >= 0");
   endif
-  if (!ischar (method))
+  if (! ischar (method))
     error ("interp2: METHOD must be a string");
+  elseif (method(1) == "*")
+    warning ("interp2: ignoring unsupported '*' flag to METHOD");
+    method(1) = [];
   endif
-  if (ischar (extrapval) || strcmp (extrapval, "extrap"))
-    extrapval = [];
-  elseif (!isscalar (extrapval))
-    error ("interp2: EXTRAPVAL must be a scalar");
+  if (isnumeric (extrap) && isscalar (extrap))
+    ## Typical case
+  elseif (strcmp (extrap, "extrap"))
+    extrap = [];
+  else
+    error ('interp2: EXTRAP must be a numeric scalar or "extrap"');
   endif
 
   ## Define X, Y, XI, YI if needed
@@ -171,21 +180,32 @@
     error ("interp2: XI, YI must be numeric");
   endif
 
-
-  if (strcmp (method, "linear") || strcmp (method, "nearest") ...
-      || strcmp (method, "pchip"))
+  if (isvector (X) && isvector (Y))
+    X = X(:);  Y = Y(:);
+  elseif (size_equal (X, Y))
+    X = X(1,:).';  Y = Y(:,1);
+  else
+    error ("interp2: X and Y must be matrices of equal size");
+  endif
+  if (columns (Z) != length (X) || rows (Z) != length (Y))
+    error ("interp2: X and Y size must match the dimensions of Z");
+  endif
+  dx = diff (X);
+  if (all (dx < 0))
+    X = flipud (X);
+    Z = fliplr (Z); 
+  elseif (any (dx <= 0))
+    error ("interp2: X must be strictly monotonic");
+  endif
+  dy = diff (Y);
+  if (all (dy < 0))
+    Y = flipud (Y);
+    Z = flipud (Z); 
+  elseif (any (dy <= 0))
+    error ("interp2: Y must be strictly monotonic");
+  endif
 
-    ## If X and Y vectors produce a grid from them
-    if (isvector (X) && isvector (Y))
-      X = X(:); Y = Y(:);
-    elseif (size_equal (X, Y))
-      X = X(1,:)'; Y = Y(:,1);
-    else
-      error ("interp2: X and Y must be matrices of same size");
-    endif
-    if (columns (Z) != length (X) || rows (Z) != length (Y))
-      error ("interp2: X and Y size must match the dimensions of Z");
-    endif
+  if (any (strcmp (method, {"nearest", "linear", "pchip", "cubic"})))
 
     ## If Xi and Yi are vectors of different orientation build a grid
     if ((rows (XI) == 1 && columns (YI) == 1)
@@ -244,10 +264,11 @@
       idx = sub2ind (size (Z), yidx+jj, xidx+ii);
       ZI = Z(idx);
 
-    elseif (strcmp (method, "pchip"))
+    elseif (strcmp (method, "pchip") || strcmp (method, "cubic"))
 
       if (length (X) < 2 || length (Y) < 2)
-        error ("interp2: pchip2 requires at least 2 points in each dimension");
+        error ("interp2: %s requires at least 2 points in each dimension",
+               method);
       endif
 
       ## first order derivatives
@@ -303,121 +324,114 @@
 
     endif
 
-    if (! isempty (extrapval))
-      ## set points outside the table to 'extrapval'
-      if (X (1) < X (end))
-        if (Y (1) < Y (end))
-          ZI (XI < X(1,1) | XI > X(end) | YI < Y(1,1) | YI > Y(end)) = ...
-                  extrapval;
+    if (! isempty (extrap))
+      ## set points outside the table to 'extrap'
+      if (X(1) < X(end))
+        if (Y(1) < Y(end))
+          ZI(XI < X(1,1) | XI > X(end) | YI < Y(1,1) | YI > Y(end)) = ...
+                  extrap;
         else
-          ZI (XI < X(1) | XI > X(end) | YI < Y(end) | YI > Y(1)) = ...
-                  extrapval;
+          ZI(XI < X(1) | XI > X(end) | YI < Y(end) | YI > Y(1)) = ...
+                  extrap;
         endif
       else
-        if (Y (1) < Y (end))
-          ZI (XI < X(end) | XI > X(1) | YI < Y(1) | YI > Y(end)) = ...
-                  extrapval;
+        if (Y(1) < Y(end))
+          ZI(XI < X(end) | XI > X(1) | YI < Y(1) | YI > Y(end)) = ...
+                  extrap;
         else
-          ZI (XI < X(1,end) | XI > X(1) | YI < Y(end) | YI > Y(1)) = ...
-                  extrapval;
+          ZI(XI < X(1,end) | XI > X(1) | YI < Y(end) | YI > Y(1)) = ...
+                  extrap;
         endif
       endif
     endif
 
   else
 
-    ## Check dimensions of X and Y
-    if (isvector (X) && isvector (Y))
-      X = X(:).';
-      Y = Y(:);
-      if (!isequal ([length(Y), length(X)], size(Z)))
-        error ("interp2: X and Y size must match the dimensions of Z");
-      endif
-    elseif (!size_equal (X, Y))
-      error ("interp2: X and Y must be matrices of equal size");
-      if (! size_equal (X, Z))
-        error ("interp2: X and Y size must match the dimensions of Z");
-      endif
-    endif
-
     ## Check dimensions of XI and YI
     if (isvector (XI) && isvector (YI) && ! size_equal (XI, YI))
-      XI = XI(:).';
-      YI = YI(:);
-      [XI, YI] = meshgrid (XI, YI);
+      XI = XI(:).';  YI = YI(:);
     elseif (! size_equal (XI, YI))
       error ("interp2: XI and YI must be matrices of equal size");
     endif
 
+    ## FIXME: Previously used algorithm for cubic.
+    ##        This produced results within a few eps of "spline".
+    ##        Matlab compatibility requires "cubic" to be a C1 algorithm
+    ##        equivalent to "pchip" so this was commented out 2014/03/30.
+    ##        This can be removed completely in the future if no problems are
+    ##        encountered.
+    #{
     if (strcmp (method, "cubic"))
       if (isgriddata (XI) && isgriddata (YI'))
-        ZI = bicubic (X, Y, Z, XI (1, :), YI (:, 1), extrapval);
+        ZI = bicubic (X, Y, Z, XI (1, :), YI (:, 1), extrap);
       elseif (isgriddata (X) && isgriddata (Y'))
         ## Allocate output
         ZI = zeros (size (X));
 
         ## Find inliers
-        inside = !(XI < X (1) | XI > X (end) | YI < Y (1) | YI > Y (end));
+        inside = !(XI < X(1) | XI > X(end) | YI < Y(1) | YI > Y(end));
 
         ## Scale XI and YI to match indices of Z
-        XI = (columns (Z) - 1) * (XI - X (1)) / (X (end) - X (1)) + 1;
-        YI = (rows (Z) - 1) * (YI - Y (1)) / (Y (end) - Y (1)) + 1;
+        XI = (columns (Z) - 1) * (XI - X(1)) / (X(end) - X(1)) + 1;
+        YI = (rows (Z) - 1) * (YI - Y(1)) / (Y(end) - Y(1)) + 1;
 
         ## Start the real work
         K = floor (XI);
         L = floor (YI);
 
         ## Coefficients
-        AY1  = bc ((YI - L + 1));
-        AX1  = bc ((XI - K + 1));
-        AY0  = bc ((YI - L + 0));
-        AX0  = bc ((XI - K + 0));
-        AY_1 = bc ((YI - L - 1));
-        AX_1 = bc ((XI - K - 1));
-        AY_2 = bc ((YI - L - 2));
-        AX_2 = bc ((XI - K - 2));
+        AY1  = bc (YI - L + 1);
+        AX1  = bc (XI - K + 1);
+        AY0  = bc (YI - L + 0);
+        AX0  = bc (XI - K + 0);
+        AY_1 = bc (YI - L - 1);
+        AX_1 = bc (XI - K - 1);
+        AY_2 = bc (YI - L - 2);
+        AX_2 = bc (XI - K - 2);
 
         ## Perform interpolation
         sz = size (Z);
-        ZI = AY_2 .* AX_2 .* Z (sym_sub2ind (sz, L+2, K+2)) ...
-           + AY_2 .* AX_1 .* Z (sym_sub2ind (sz, L+2, K+1)) ...
-           + AY_2 .* AX0  .* Z (sym_sub2ind (sz, L+2, K))   ...
-           + AY_2 .* AX1  .* Z (sym_sub2ind (sz, L+2, K-1)) ...
-           + AY_1 .* AX_2 .* Z (sym_sub2ind (sz, L+1, K+2)) ...
-           + AY_1 .* AX_1 .* Z (sym_sub2ind (sz, L+1, K+1)) ...
-           + AY_1 .* AX0  .* Z (sym_sub2ind (sz, L+1, K))   ...
-           + AY_1 .* AX1  .* Z (sym_sub2ind (sz, L+1, K-1)) ...
-           + AY0  .* AX_2 .* Z (sym_sub2ind (sz, L,   K+2)) ...
-           + AY0  .* AX_1 .* Z (sym_sub2ind (sz, L,   K+1)) ...
-           + AY0  .* AX0  .* Z (sym_sub2ind (sz, L,   K))   ...
-           + AY0  .* AX1  .* Z (sym_sub2ind (sz, L,   K-1)) ...
-           + AY1  .* AX_2 .* Z (sym_sub2ind (sz, L-1, K+2)) ...
-           + AY1  .* AX_1 .* Z (sym_sub2ind (sz, L-1, K+1)) ...
-           + AY1  .* AX0  .* Z (sym_sub2ind (sz, L-1, K))   ...
-           + AY1  .* AX1  .* Z (sym_sub2ind (sz, L-1, K-1));
-        ZI (!inside) = extrapval;
+        ZI = AY_2 .* AX_2 .* Z(sym_sub2ind (sz, L+2, K+2)) ...
+           + AY_2 .* AX_1 .* Z(sym_sub2ind (sz, L+2, K+1)) ...
+           + AY_2 .* AX0  .* Z(sym_sub2ind (sz, L+2, K))   ...
+           + AY_2 .* AX1  .* Z(sym_sub2ind (sz, L+2, K-1)) ...
+           + AY_1 .* AX_2 .* Z(sym_sub2ind (sz, L+1, K+2)) ...
+           + AY_1 .* AX_1 .* Z(sym_sub2ind (sz, L+1, K+1)) ...
+           + AY_1 .* AX0  .* Z(sym_sub2ind (sz, L+1, K))   ...
+           + AY_1 .* AX1  .* Z(sym_sub2ind (sz, L+1, K-1)) ...
+           + AY0  .* AX_2 .* Z(sym_sub2ind (sz, L,   K+2)) ...
+           + AY0  .* AX_1 .* Z(sym_sub2ind (sz, L,   K+1)) ...
+           + AY0  .* AX0  .* Z(sym_sub2ind (sz, L,   K))   ...
+           + AY0  .* AX1  .* Z(sym_sub2ind (sz, L,   K-1)) ...
+           + AY1  .* AX_2 .* Z(sym_sub2ind (sz, L-1, K+2)) ...
+           + AY1  .* AX_1 .* Z(sym_sub2ind (sz, L-1, K+1)) ...
+           + AY1  .* AX0  .* Z(sym_sub2ind (sz, L-1, K))   ...
+           + AY1  .* AX1  .* Z(sym_sub2ind (sz, L-1, K-1));
+        ZI (!inside) = extrap;
 
       else
         error ("interp2: input data must have 'meshgrid' format");
       endif
+    #}
 
-    elseif (strcmp (method, "spline"))
+    if (strcmp (method, "spline"))
       if (isgriddata (XI) && isgriddata (YI'))
-        ZI = __splinen__ ({Y(:,1).', X(1,:)}, Z, {YI(:,1), XI(1,:)}, extrapval,
-                        "spline");
+        ZI = __splinen__ ({Y, X}, Z, {YI(:,1), XI(1,:)}, extrap,
+                          "spline");
       else
-        error ("interp2: input data must have 'meshgrid' format");
+        error ("interp2: XI, YI must have uniform spacing ('meshgrid' format)");
       endif
     else
-      error ("interp2: interpolation METHOD not recognized");
+      error ("interp2: unrecognized interpolation method '%s'", method);
     endif
 
   endif
+
 endfunction
 
 function b = isgriddata (X)
   d1 = diff (X, 1, 1);
-  b = all (d1 (:) == 0);
+  b = all (d1(:) == 0);
 endfunction
 
 ## Compute the bicubic interpolation coefficients
@@ -432,16 +446,16 @@
 
 ## This version of sub2ind behaves as if the data was symmetrically padded
 function ind = sym_sub2ind (sz, Y, X)
-  Y (Y < 1) = 1 - Y (Y < 1);
-  while (any (Y (:) > 2 * sz (1)))
-    Y (Y > 2 * sz (1)) = round (Y (Y > 2 * sz (1)) / 2);
+  Y(Y < 1) = 1 - Y(Y < 1);
+  while (any (Y(:) > 2*sz(1)))
+    Y(Y > 2*sz(1)) = round (Y(Y > 2*sz(1)) / 2);
   endwhile
-  Y (Y > sz (1)) = 1 + 2 * sz (1) - Y (Y > sz (1));
-  X (X < 1) = 1 - X (X < 1);
-  while (any (X (:) > 2 * sz (2)))
-    X (X > 2 * sz (2)) = round (X (X > 2 * sz (2)) / 2);
+  Y(Y > sz(1)) = 1 + 2*sz(1) - Y(Y > sz(1));
+  X(X < 1) = 1 - X(X < 1);
+  while (any (X(:) > 2*sz(2)))
+    X(X > 2 * sz(2)) = round (X(X > 2*sz(2)) / 2);
   endwhile
-  X (X > sz (2)) = 1 + 2 * sz (2) - X (X > sz (2));
+  X(X > sz(2)) = 1 + 2*sz(2) - X(X > sz(2));
   ind = sub2ind (sz, Y, X);
 endfunction
 
@@ -455,7 +469,7 @@
 %! yi = linspace (min (y), max (y), 26)';
 %! mesh (xi,yi,interp2 (x,y,A,xi,yi, "linear"));
 %! [x,y] = meshgrid (x,y);
-%! hold on; plot3 (x(:),y(:),A(:),"b*"); hold off;
+%! hold on; plot3 (x,y,A,"b*"); hold off;
 
 %!demo
 %! clf;
@@ -466,7 +480,7 @@
 %! yi = linspace (min (y), max (y), 41)';
 %! mesh (xi,yi,interp2 (x,y,A,xi,yi, "linear"));
 %! [x,y] = meshgrid (x,y);
-%! hold on; plot3 (x(:),y(:),A(:),"b*"); hold off;
+%! hold on; plot3 (x,y,A,"b*"); hold off;
 
 %!demo
 %! clf;
@@ -477,7 +491,7 @@
 %! yi = linspace (min (y), max (y), 26)';
 %! mesh (xi,yi,interp2 (x,y,A,xi,yi, "nearest"));
 %! [x,y] = meshgrid (x,y);
-%! hold on; plot3 (x(:),y(:),A(:),"b*"); hold off;
+%! hold on; plot3 (x,y,A,"b*"); hold off;
 
 %!demo
 %! clf;
@@ -488,9 +502,10 @@
 %! yi = linspace (min (y), max (y), 41)';
 %! mesh (xi,yi,interp2 (x,y,A,xi,yi, "nearest"));
 %! [x,y] = meshgrid (x,y);
-%! hold on; plot3 (x(:),y(:),A(:),"b*"); hold off;
+%! hold on; plot3 (x,y,A,"b*"); hold off;
 
-%!demo
+## 'pchip' commented out since it is the same as 'cubic'
+%!#demo
 %! clf;
 %! colormap ("default");
 %! A = [13,-1,12;5,4,3;1,6,2];
@@ -499,9 +514,10 @@
 %! yi = linspace (min (y), max (y), 26)';
 %! mesh (xi,yi,interp2 (x,y,A,xi,yi, "pchip"));
 %! [x,y] = meshgrid (x,y);
-%! hold on; plot3 (x(:),y(:),A(:),"b*"); hold off;
+%! hold on; plot3 (x,y,A,"b*"); hold off;
 
-%!demo
+## 'pchip' commented out since it is the same as 'cubic'
+%!#demo
 %! clf;
 %! colormap ("default");
 %! [x,y,A] = peaks (10);
@@ -510,7 +526,7 @@
 %! yi = linspace (min (y), max (y), 41)';
 %! mesh (xi,yi,interp2 (x,y,A,xi,yi, "pchip"));
 %! [x,y] = meshgrid (x,y);
-%! hold on; plot3 (x(:),y(:),A(:),"b*"); hold off;
+%! hold on; plot3 (x,y,A,"b*"); hold off;
 
 %!demo
 %! clf;
@@ -521,7 +537,7 @@
 %! yi = linspace (min (y), max (y), 26)';
 %! mesh (xi,yi,interp2 (x,y,A,xi,yi, "cubic"));
 %! [x,y] = meshgrid (x,y);
-%! hold on; plot3 (x(:),y(:),A(:),"b*"); hold off;
+%! hold on; plot3 (x,y,A,"b*"); hold off;
 
 %!demo
 %! clf;
@@ -532,7 +548,7 @@
 %! yi = linspace (min (y), max (y), 41)';
 %! mesh (xi,yi,interp2 (x,y,A,xi,yi, "cubic"));
 %! [x,y] = meshgrid (x,y);
-%! hold on; plot3 (x(:),y(:),A(:),"b*"); hold off;
+%! hold on; plot3 (x,y,A,"b*"); hold off;
 
 %!demo
 %! clf;
@@ -543,7 +559,7 @@
 %! yi = linspace (min (y), max (y), 26)';
 %! mesh (xi,yi,interp2 (x,y,A,xi,yi, "spline"));
 %! [x,y] = meshgrid (x,y);
-%! hold on; plot3 (x(:),y(:),A(:),"b*"); hold off;
+%! hold on; plot3 (x,y,A,"b*"); hold off;
 
 %!demo
 %! clf;
@@ -554,68 +570,75 @@
 %! yi = linspace (min (y), max (y), 41)';
 %! mesh (xi,yi,interp2 (x,y,A,xi,yi, "spline"));
 %! [x,y] = meshgrid (x,y);
-%! hold on; plot3 (x(:),y(:),A(:),"b*"); hold off;
+%! hold on; plot3 (x,y,A,"b*"); hold off;
 
-%!test % simple test
+%!test  # simple test
 %! x = [1,2,3];
 %! y = [4,5,6,7];
 %! [X, Y] = meshgrid (x, y);
-%! Orig = X.^2 + Y.^3;
+%! orig = X.^2 + Y.^3;
 %! xi = [1.2,2, 1.5];
 %! yi = [6.2, 4.0, 5.0]';
 %!
-%! Expected = ...
+%! expected = ...
 %!   [243,   245.4,  243.9;
 %!     65.6,  68,     66.5;
 %!    126.6, 129,    127.5];
-%! Result = interp2 (x,y,Orig, xi, yi);
+%! result = interp2 (x,y,orig, xi, yi);
 %!
-%! assert (Result, Expected, 1000*eps);
+%! assert (result, expected, 1000*eps);
 
-%!test % 2^n form
+%!test  # 2^n refinement form
 %! x = [1,2,3];
 %! y = [4,5,6,7];
 %! [X, Y] = meshgrid (x, y);
-%! Orig = X.^2 + Y.^3;
+%! orig = X.^2 + Y.^3;
 %! xi = [1:0.25:3];  yi = [4:0.25:7]';
-%! Expected = interp2 (x,y,Orig, xi, yi);
-%! Result = interp2 (Orig, 2);
+%! expected = interp2 (x,y,orig, xi, yi);
+%! result = interp2 (orig, 2);
 %!
-%! assert (Result, Expected, 10*eps);
+%! assert (result, expected, 10*eps);
 
-%!test % matrix slice
+%!test  # matrix slice
 %! A = eye (4);
 %! assert (interp2 (A,[1:4],[1:4]), [1,1,1,1]);
 
-%!test % non-gridded XI,YI
+%!test  # non-gridded XI,YI
 %! A = eye (4);
 %! assert (interp2 (A,[1,2;3,4],[1,3;2,4]), [1,0;0,1]);
 
-%!test % for values outside of boundaries
+%!test  # for values outside of boundaries
 %! x = [1,2,3];
 %! y = [4,5,6,7];
 %! [X, Y] = meshgrid (x,y);
-%! Orig = X.^2 + Y.^3;
+%! orig = X.^2 + Y.^3;
 %! xi = [0,4];
 %! yi = [3,8]';
-%! assert (interp2 (x,y,Orig, xi, yi), [NA,NA;NA,NA]);
-%! assert (interp2 (x,y,Orig, xi, yi,"linear", 0), [0,0;0,0]);
+%! assert (interp2 (x,y,orig, xi, yi), [NA,NA;NA,NA]);
+%! assert (interp2 (x,y,orig, xi, yi,"linear", 0), [0,0;0,0]);
+%! assert (interp2 (x,y,orig, xi, yi,"linear", "extrap"), [1,17;468,484]);
+%! assert (interp2 (x,y,orig, xi, yi,"nearest", "extrap"), orig([1,end],[1,end]));
 
-%!test % for values at boundaries
-%! A=[1,2;3,4];
-%! x=[0,1];
-%! y=[2,3]';
+%!test  # for values at boundaries
+%! A = [1,2;3,4];
+%! x = [0,1];
+%! y = [2,3]';
 %! assert (interp2 (x,y,A,x,y,"linear"), A);
 %! assert (interp2 (x,y,A,x,y,"nearest"), A);
 
-%!test % for Matlab-compatible rounding for 'nearest'
+%!test  # for Matlab-compatible rounding for 'nearest'
 %! X = meshgrid (1:4);
 %! assert (interp2 (X, 2.5, 2.5, "nearest"), 3);
 
+## re-order monotonically decreasing (bug #41838).
+%!assert (interp2 ([1 2 3], [3 2 1], magic (3), 2.5, 3), 3.5);
+%!assert (interp2 ([3 2 1], [1 2 3], magic (3), 1.5, 1), 3.5);
+
 %!shared z, zout, tol
 %! z = [1 3 5; 3 5 7; 5 7 9];
 %! zout = [1 2 3 4 5; 2 3 4 5 6; 3 4 5 6 7; 4 5 6 7 8; 5 6 7 8 9];
 %! tol = 2 * eps;
+%!
 %!assert (interp2 (z), zout, tol)
 %!assert (interp2 (z, "linear"), zout, tol)
 %!assert (interp2 (z, "pchip"), zout, tol)
@@ -630,3 +653,32 @@
 %!assert (interp2 (z, [2 3 1], [2 2 2], "cubic"), [5 7 3], 10 * tol)
 %!assert (interp2 (z, [2 3 1], [2 2 2], "spline"), [5 7 3], tol)
 
+%% Test input validation
+%!error <Z must be a 2-D matrix> interp2 ({1})
+%!error <Z must be a 2-D matrix> interp2 (ones (2,2,2))
+%!error <N must be an integer .= 0> interp2 (1, ones (2))
+%!error <N must be an integer .= 0> interp2 (1, -1)
+%!error <N must be an integer .= 0> interp2 (1, 1.5)
+%!error <METHOD must be a string> interp2 (1, 1, 1, 1, 1, 2)
+%!warning <ignoring unsupported '\*' flag> interp2 (rand (3,3), 1, "*linear");
+%!error <EXTRAP must be a numeric scalar or "extrap"> interp2 (1, 1, 1, 1, 1, 'linear', {1})
+%!error <EXTRAP must be a numeric scalar or "extrap"> interp2 (1, 1, 1, 1, 1, 'linear', ones (2,2))
+%!error <EXTRAP must be a numeric scalar or "extrap"> interp2 (1, 1, 1, 1, 1, 'linear', "abc")
+%!error <X, Y must be numeric matrices> interp2 ({1}, 1, 1, 1, 1)
+%!error <X, Y must be numeric matrices> interp2 (1, {1}, 1, 1, 1)
+%!error <XI, YI must be numeric> interp2 (1, 1, 1, {1}, 1)
+%!error <XI, YI must be numeric> interp2 (1, 1, 1, 1, {1})
+%!error <X and Y must be matrices of equal size> interp2 (ones(2,2), 1, 1, 1, 1)
+%!error <X and Y must be matrices of equal size> interp2 (ones(2,2), ones(2,3), 1, 1, 1)
+%!error <X and Y size must match the dimensions of Z> interp2 (1:3, 1:3, ones (3,2), 1, 1)
+%!error <X and Y size must match the dimensions of Z> interp2 (1:2, 1:2, ones (3,2), 1, 1)
+%!error <X must be strictly monotonic> interp2 ([1 0 2], 1:3, ones (3,3), 1, 1)
+%!error <Y must be strictly monotonic> interp2 (1:3, [1 0 2], ones (3,3), 1, 1)
+%!error <XI and YI must be matrices of equal size> interp2 (1, 1, 1, ones(2,2), 1)
+%!error <XI and YI must be matrices of equal size> interp2 (1, 1, 1, 1, ones(2,2))
+%!error <pchip requires at least 2 points> interp2 (1, 1, 1, 1, 1, "pchip")
+%!error <cubic requires at least 2 points> interp2 (1, 1, 1, 1, 1, "cubic")
+%!error <XI, YI must have uniform spacing> interp2 (1, 1, 1, [1 2 4], [1 2 3], "spline")
+%!error <XI, YI must have uniform spacing> interp2 (1, 1, 1, [1 2 3], [1 2 4], "spline")
+%!error <unrecognized interpolation method 'foobar'> interp2 (1, 1, 1, 1, 1, "foobar")
+
--- a/scripts/general/interp3.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/general/interp3.m	Mon Jan 12 09:17:35 2015 -0800
@@ -19,52 +19,72 @@
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {@var{vi} =} interp3 (@var{x}, @var{y}, @var{z}, @var{v}, @var{xi}, @var{yi}, @var{zi})
 ## @deftypefnx {Function File} {@var{vi} =} interp3 (@var{v}, @var{xi}, @var{yi}, @var{zi})
-## @deftypefnx {Function File} {@var{vi} =} interp3 (@var{v}, @var{m})
+## @deftypefnx {Function File} {@var{vi} =} interp3 (@var{v}, @var{n})
 ## @deftypefnx {Function File} {@var{vi} =} interp3 (@var{v})
 ## @deftypefnx {Function File} {@var{vi} =} interp3 (@dots{}, @var{method})
 ## @deftypefnx {Function File} {@var{vi} =} interp3 (@dots{}, @var{method}, @var{extrapval})
 ##
-## Perform 3-dimensional interpolation.  Each element of the 3-dimensional
-## array @var{v} represents a value at a location given by the parameters
-## @var{x}, @var{y}, and @var{z}.  The parameters @var{x}, @var{x}, and
-## @var{z} are either 3-dimensional arrays of the same size as the array
-## @var{v} in the @qcode{"meshgrid"} format or vectors.  The parameters
-## @var{xi}, etc. respect a similar format to @var{x}, etc., and they
-## represent the points at which the array @var{vi} is interpolated.
+## Three-dimensional interpolation.
+##
+## Interpolate reference data @var{x}, @var{y}, @var{z}, @var{v} to determine
+## @var{vi} at the coordinates @var{xi}, @var{yi}, @var{zi}.  The reference
+## data @var{x}, @var{y}, @var{z} can be matrices, as returned by
+## @code{meshgrid}, in which case the sizes of
+## @var{x}, @var{y}, @var{z}, and @var{v} must be equal.  If @var{x}, @var{y},
+## @var{z} are vectors describing a cubic grid then
+## @code{length (@var{x}) == columns (@var{v})},
+## @code{length (@var{y}) == rows (@var{v})},
+## and @code{length (@var{z}) == size (@var{v}, 3)}.  In either case the input
+## data must be strictly monotonic.
 ##
-## If @var{x}, @var{y}, @var{z} are omitted, they are assumed to be
-## @code{x = 1 : size (@var{v}, 2)}, @code{y = 1 : size (@var{v}, 1)} and
-## @code{z = 1 : size (@var{v}, 3)}.  If @var{m} is specified, then
-## the interpolation adds a point half way between each of the interpolation
-## points.  This process is performed @var{m} times.  If only @var{v} is
-## specified, then @var{m} is assumed to be @code{1}.
+## If called without @var{x}, @var{y}, @var{z}, and just a single reference
+## data matrix @var{v}, the 3-D region
+## @code{@var{x} = 1:columns (@var{v}), @var{y} = 1:rows (@var{v}),
+## @var{z} = 1:size (@var{v}, 3)} is assumed.
+## This saves memory if the grid is regular and the distance between points is
+## not important.
 ##
-## Method is one of:
+## If called with a single reference data matrix @var{v} and a refinement
+## value @var{n}, then perform interpolation over a 3-D grid where each original
+## interval has been recursively subdivided @var{n} times.  This results in
+## @code{2^@var{n}-1} additional points for every interval in the original
+## grid.  If @var{n} is omitted a value of 1 is used.  As an example, the
+## interval [0,1] with @code{@var{n}==2} results in a refined interval with
+## points at [0, 1/4, 1/2, 3/4, 1].
+##
+## The interpolation @var{method} is one of:
 ##
 ## @table @asis
 ## @item @qcode{"nearest"}
 ## Return the nearest neighbor.
 ##
-## @item @qcode{"linear"}
+## @item @qcode{"linear"} (default)
 ## Linear interpolation from nearest neighbors.
 ##
+## @item @qcode{"pchip"}
+## Piecewise cubic Hermite interpolating polynomial---shape-preserving
+## interpolation with smooth first derivative (not implemented yet).
+##
 ## @item @qcode{"cubic"}
-## Cubic interpolation from four nearest neighbors (not implemented yet).
+## Cubic interpolation (same as @qcode{"pchip"} [not implemented yet]).
 ##
 ## @item @qcode{"spline"}
 ## Cubic spline interpolation---smooth first and second derivatives
 ## throughout the curve.
 ## @end table
 ##
-## The default method is @qcode{"linear"}.
-##
-## If @var{extrap} is the string @qcode{"extrap"}, then extrapolate values
-## beyond the endpoints.  If @var{extrap} is a number, replace values beyond
-## the endpoints with that number.  If @var{extrap} is missing, assume NA.
-## @seealso{interp1, interp2, spline, meshgrid}
+## If @var{extrapval} is a number, then replace values beyond the endpoints
+## with that number.  When unspecified, @var{extrapval} defaults to @code{NA}.
+## Note that if @var{extrapval} is used, @var{method} must be specified as well.
+## @seealso{interp1, interp2, interpn, meshgrid}
 ## @end deftypefn
 
+## FIXME: Need to validate N argument (maybe change interpn).
+## FIXME: Need to add support for 'pchip' method (maybe change interpn).
+## FIXME: Need to add support for "extrap" string value (maybe change interpn).
+
 function vi = interp3 (varargin)
+
   method = "linear";
   extrapval = NA;
   nargs = nargin;
@@ -75,112 +95,143 @@
 
   if (ischar (varargin{end}))
     method = varargin{end};
-    nargs = nargs - 1;
-  elseif (nargs > 1 && ischar (varargin{end - 1}))
+    nargs--;
+  elseif (nargs > 1 && ischar (varargin{end-1}))
+    ## FIXME: No support for "extrap" string
     if (! isnumeric (varargin{end}) || ! isscalar (varargin{end}))
-      error ("interp3: extrapal is expected to be a numeric scalar");
+      error ("interp3: EXTRAPVAL must be a numeric scalar");
     endif
     extrapval = varargin{end};
     method = varargin{end-1};
-    nargs = nargs - 2;
+    nargs -= 2;
   endif
 
-  if (nargs < 3 || (nargs == 4 && ! isvector (varargin{1})
-                    && nargs == (ndims (varargin{1}) + 1)))
+  if (method(1) == "*")
+    warning ("interp3: ignoring unsupported '*' flag to METHOD");
+    method(1) = [];
+  endif
+
+  if (nargs < 3)
+    ## Calling form interp3 (v) OR interp3 (v, n)
     v = varargin{1};
     if (ndims (v) != 3)
-      error ("interp3: expect 3-dimensional array of values");
+      error ("interp3: V must be a 3-D array of values");
     endif
-    x = varargin (2:nargs);
-    if (any (! cellfun (@isvector, x)))
-      for i = 2 : 3
-        if (! size_equal (x{1}, x{i}))
-          error ("interp3: dimensional mismatch");
-        endif
-        x{i} = permute (x{i}, [2, 1, 3]);
+    n = varargin(2:nargs);
+    v = permute (v, [2, 1, 3]);
+    vi = ipermute (interpn (v, n{:}, method, extrapval), [2, 1, 3]);
+
+  elseif (nargs == 4 && ! isvector (varargin{1}))
+    ## Calling form interp3 (v, xi, yi, zi)
+    v = varargin{1};
+    if (ndims (v) != 3)
+      error ("interp3: V must be a 3-D array of values");
+    endif
+    xi = varargin(2:4);
+    if (any (! cellfun (@isvector, xi)))
+      ## Meshgridded values rather than vectors
+      if (! size_equal (xi{:}))
+        error ("interp3: XI, YI, and ZI dimensions must be equal");
+      endif
+      for i = 1 : 3
+        xi{i} = permute (xi{i}, [2, 1, 3]);
       endfor
-      x{1} = permute (x{1}, [2, 1, 3]);
     endif
     v = permute (v, [2, 1, 3]);
-    vi = ipermute (interpn (v, x{:}, method, extrapval), [2, 1, 3]);
-  elseif (nargs == 7 && nargs == (2 * ndims (varargin{ceil (nargs / 2)})) + 1)
+    vi = ipermute (interpn (v, xi{:}, method, extrapval), [2, 1, 3]);
+
+  elseif (nargs == 7)
+    ## Calling form interp3 (x, y, z, v, xi, yi, zi)
     v = varargin{4};
     if (ndims (v) != 3)
-      error ("interp3: expect 3-dimensional array of values");
+      error ("interp3: V must be a 3-D array of values");
     endif
-    x = varargin (1:3);
+    x = varargin(1:3);
     if (any (! cellfun (@isvector, x)))
-      for i = 2 : 3
-        if (! size_equal (x{1}, x{i}) || ! size_equal (x{i}, v))
-          error ("interp3: dimensional mismatch");
-        endif
+      ## Meshgridded values rather than vectors
+      if (! size_equal (x{:}, v))
+        error ("interp3: X, Y, Z, and V dimensions must be equal");
+      endif
+      for i = 1 : 3
         x{i} = permute (x{i}, [2, 1, 3]);
       endfor
-      x{1} = permute (x{1}, [2, 1, 3]);
     endif
-    y = varargin (5:7);
-    if (any (! cellfun (@isvector, y)))
-      for i = 2 : 3
-        if (! size_equal (y{1}, y{i}))
-          error ("interp3: dimensional mismatch");
-        endif
-        y{i} = permute (y{i}, [2, 1, 3]);
+    xi = varargin(5:7);
+    if (any (! cellfun (@isvector, xi)))
+      ## Meshgridded values rather than vectors
+      if (! size_equal (xi{:}))
+        error ("interp3: XI, YI, and ZI dimensions must be equal");
+      endif
+      for i = 1 : 3
+        xi{i} = permute (xi{i}, [2, 1, 3]);
       endfor
-      y{1} = permute (y{1}, [2, 1, 3]);
     endif
     v = permute (v, [2, 1, 3]);
-    vi = ipermute (interpn (x{:}, v, y{:}, method, extrapval), [2, 1, 3]);
+    vi = ipermute (interpn (x{:}, v, xi{:}, method, extrapval), [2, 1, 3]);
+
   else
     error ("interp3: wrong number or incorrectly formatted input arguments");
   endif
+
 endfunction
 
 
-%!test
-%! x = y = z = -1:1; y = y + 2;
+%% FIXME: Need some demo blocks here to show off the function like interp2.m.
+
+%!test  # basic test
+%! x = y = z = -1:1;  y = y + 2;
 %! f = @(x,y,z) x.^2 - y - z.^2;
 %! [xx, yy, zz] = meshgrid (x, y, z);
 %! v = f (xx,yy,zz);
-%! xi = yi = zi = -1:0.5:1; yi = yi + 2.1;
+%! xi = yi = zi = -1:0.5:1;  yi = yi + 2.1;
 %! [xxi, yyi, zzi] = meshgrid (xi, yi, zi);
 %! vi = interp3 (x, y, z, v, xxi, yyi, zzi);
 %! [xxi, yyi, zzi] = ndgrid (yi, xi, zi);
 %! vi2 = interpn (y, x, z, v, xxi, yyi, zzi);
-%! tol = 10 * eps;
-%! assert (vi, vi2, tol);
+%! assert (vi, vi2, 10*eps);
 
-%!test
-%! x=z=1:2; y=1:3;xi=zi=.6:1.6; yi=1; v=ones([3,2,2]);  v(:,2,1)=[7 ;5;4];  v(:,1,2)=[2 ;3;5];
+%!test  # meshgridded xi, yi, zi
+%! x = z = 1:2;  y = 1:3;
+%! v = ones ([3,2,2]);  v(:,2,1) = [7;5;4];  v(:,1,2) = [2;3;5];
+%! xi = zi = .6:1.6;  yi = 1; 
 %! [xxi3, yyi3, zzi3] = meshgrid (xi, yi, zi);
 %! [xxi, yyi, zzi] = ndgrid (yi, xi, zi);
 %! vi = interp3 (x, y, z, v, xxi3, yyi3, zzi3, "nearest");
-%! vi2 = interpn (y, x, z, v, xxi, yyi, zzi,"nearest");
+%! vi2 = interpn (y, x, z, v, xxi, yyi, zzi, "nearest");
 %! assert (vi, vi2);
 
-%!test
-%! x=z=1:2; y=1:3;xi=zi=.6:1.6; yi=1; v=ones([3,2,2]);  v(:,2,1)=[7 ;5;4];  v(:,1,2)=[2 ;3;5];
-%! vi = interp3 (x, y, z, v, xi+1, yi, zi, "nearest",3);
-%! vi2 = interpn (y, x, z, v, yi, xi+1, zi,"nearest", 3);
-%! assert (vi, vi2);
-
-%!test
-%! x=z=1:2; y=1:3;xi=zi=.6:1.6; yi=1; v=ones([3,2,2]);  v(:,2,1)=[7 ;5;4];  v(:,1,2)=[2 ;3;5];
+%!test  # vector xi, yi, zi
+%! x = z = 1:2;  y = 1:3;
+%! v = ones ([3,2,2]);  v(:,2,1) = [7;5;4];  v(:,1,2) = [2;3;5];
+%! xi = zi = .6:1.6;  yi = 1; 
 %! vi = interp3 (x, y, z, v, xi, yi, zi, "nearest");
 %! vi2 = interpn (y, x, z, v, yi, xi, zi,"nearest");
 %! assert (vi, vi2);
 
-%!test
-%! x=z=1:2; y=1:3;xi=zi=.6:1.6; yi=1; v=ones([3,2,2]);  v(:,2,1)=[7 ;5;4];  v(:,1,2)=[2 ;3;5];
-%! vi = interp3 (v, xi, yi, zi, "nearest",3);
-%! vi2 = interpn (v, yi, xi, zi,"nearest", 3);
+%!test  # vector xi+1 with extrap value
+%! x = z = 1:2;  y = 1:3;
+%! v = ones ([3,2,2]);  v(:,2,1) = [7;5;4];  v(:,1,2) = [2;3;5];
+%! xi = zi = .6:1.6;  yi = 1; 
+%! vi = interp3 (x, y, z, v, xi+1, yi, zi, "nearest", 3);
+%! vi2 = interpn (y, x, z, v, yi, xi+1, zi, "nearest", 3);
 %! assert (vi, vi2);
 
-%!test
-%! xi=zi=.6:1.6; yi=1; v=ones([3,2,2]);  v(:,2,1)=[7 ;5;4];  v(:,1,2)=[2 ;3;5];
+%!test  # input value matrix--no x,y,z
+%! x = z = 1:2;  y = 1:3;
+%! v = ones ([3,2,2]);  v(:,2,1) = [7;5;4];  v(:,1,2) = [2;3;5];
+%! xi = zi = .6:1.6;  yi = 1; 
 %! vi = interp3 (v, xi, yi, zi, "nearest");
 %! vi2 = interpn (v, yi, xi, zi,"nearest");
 %! assert (vi, vi2);
 
+%!test  # input value matrix--no x,y,z, with extrap value
+%! x = z = 1:2;  y = 1:3;
+%! v = ones ([3,2,2]);  v(:,2,1) = [7;5;4];  v(:,1,2) = [2;3;5];
+%! xi = zi = .6:1.6;  yi = 1; 
+%! vi = interp3 (v, xi, yi, zi, "nearest", 3);
+%! vi2 = interpn (v, yi, xi, zi, "nearest", 3);
+%! assert (vi, vi2);
+
 %!shared z, zout, tol
 %! z = zeros (3, 3, 3);
 %! zout = zeros (5, 5, 5);
@@ -195,7 +246,21 @@
 %!                  5 6 7 8 9] + (n-1);
 %! end
 %! tol = 10 * eps;
+%!
 %!assert (interp3 (z), zout, tol)
 %!assert (interp3 (z, "linear"), zout, tol)
 %!assert (interp3 (z, "spline"), zout, tol)
 
+%% Test input validation
+%!error interp3 ()
+%!error interp3 ({1})
+%!error <EXTRAPVAL must be a numeric scalar> interp3 (1,2,3,4,1,2,3,"linear", {1})
+%!error <EXTRAPVAL must be a numeric scalar> interp3 (1,2,3,4,1,2,3,"linear", ones (2,2))
+%!warning <ignoring unsupported '\*' flag> interp3 (rand (3,3,3), 1, "*linear");
+%!error <V must be a 3-D array> interp3 (rand (2,2))
+%!error <V must be a 3-D array> interp3 (rand (2,2), 1,1,1)
+%!error <XI, YI, and ZI dimensions must be equal> interp3 (rand (2,2,2), 1,1, ones (2,2))
+%!error <V must be a 3-D array> interp3 (1:2, 1:2, 1:2, rand (2,2), 1,1,1)
+%!error <X, Y, Z, and V dimensions must be equal> interp3 (ones(1,2,2), ones(2,2,2), ones(2,2,2), rand (2,2,2), 1,1,1)
+%!error <XI, YI, and ZI dimensions must be equal> interp3 (1:2, 1:2, 1:2, rand (2,2,2), 1,1, ones (2,2))
+
--- a/scripts/general/interpn.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/general/interpn.m	Mon Jan 12 09:17:35 2015 -0800
@@ -86,6 +86,11 @@
     nargs -= 2;
   endif
 
+  if (method(1) == "*")
+    warning ("interpn: ignoring unsupported '*' flag to METHOD");
+    method(1) = [];
+  endif
+
   if (nargs < 3)
     v = varargin{1};
     m = 1;
@@ -318,3 +323,6 @@
 %! assert (interpn (z, "linear"), zout, tol);
 %! assert (interpn (z, "spline"), zout, tol);
 
+%% Test input validation
+%!warning <ignoring unsupported '\*' flag> interpn (rand (3,3), 1, "*linear");
+
--- a/scripts/general/iscolumn.m	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-## 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/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} {} iscolumn (@var{x})
-## Return true if @var{x} is a column vector.
-## @seealso{isrow, isscalar, isvector, ismatrix}
-## @end deftypefn
-
-## Author: Rik Wehbring
-
-function retval = iscolumn (x)
-
-  if (nargin != 1)
-    print_usage ();
-  endif
-
-  sz = size (x);
-  retval = (ndims (x) == 2 && (sz(2) == 1));
-
-endfunction
-
-
-%!assert (iscolumn ([1, 2, 3]), false)
-%!assert (iscolumn ([1; 2; 3]))
-%!assert (iscolumn (1))
-%!assert (iscolumn ([]), false)
-%!assert (iscolumn ([1, 2; 3, 4]), false)
-
-%!assert (iscolumn ("t"))
-%!assert (iscolumn ("test"), false)
-%!assert (iscolumn (["test"; "ing"]), false)
-
-%!test
-%! s.a = 1;
-%! assert (iscolumn (s));
-
-%% Test input validation
-%!error iscolumn ()
-%!error iscolumn ([1, 2], 2)
-
--- a/scripts/general/isequal.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/general/isequal.m	Mon Jan 12 09:17:35 2015 -0800
@@ -33,53 +33,133 @@
 endfunction
 
 
+## test empty input
+%!assert (isequal ([], []), true)
+%!assert (isequal ([], [], 1), false)
+%!assert (isequal ([], 1, []), false)
+%!assert (isequal (1, [], []), false)
+%!assert (isequal (1, [], []), false)
+
 ## test size and shape
-%!assert (isequal ([1,2,3,4],[1,2,3,4]), true)
-%!assert (isequal ([1;2;3;4],[1;2;3;4]), true)
-%!assert (isequal ([1,2,3,4],[1;2;3;4]), false)
-%!assert (isequal ([1,2,3,4],[1,2;3,4]), false)
-%!assert (isequal ([1,2,3,4],[1,3;2,4]), false)
+%!assert (isequal ([1,2,3,4], [1,2,3,4]), true)
+%!assert (isequal ([1;2;3;4], [1;2;3;4]), true)
+%!assert (isequal ([1,2,3,4], [1;2;3;4]), false)
+%!assert (isequal ([1,2,3,4], [1,2;3,4]), false)
+%!assert (isequal ([1,2,3,4], [1,3;2,4]), false)
 
 %!test
 %! A = 1:8;
 %! B = reshape (A, 2, 2, 2);
 %! assert (isequal (A, B), false);
-
 %!test
 %! A = reshape (1:8, 2, 2, 2);
 %! B = A;
 %! assert (isequal (A, B), true);
-
 %!test
 %! A = reshape (1:8, 2, 4);
 %! B = reshape (A, 2, 2, 2);
 %! assert (isequal (A, B), false);
 
-## test for equality
-%!assert (isequal ([1,2,3,4],[1,2,3,4]), true)
-%!assert (isequal (['a','b','c','d'],['a','b','c','d']), true)
-## Test multi-line strings
-%!assert (isequal (["test";"strings"],["test";"strings"],["test";"strings"]), true)
-## test for inequality
-%!assert (isequal ([1,2,3,4],[1;2;3;4]), false)
-%!assert (isequal ({1,2,3,4},[1,2,3,4]), false)
-%!assert (isequal ([1,2,3,4],{1,2,3,4}), false)
-%!assert (isequal ([1,2,NaN,4],[1,2,NaN,4]), false)
-%!assert (isequal (['a','b','c','d'],['a';'b';'c';'d']), false)
-%!assert (isequal ({'a','b','c','d'},{'a';'b';'c';'d'}), false)
-## test for equality (struct)
-%!assert (isequal (struct ('a',1,'b',2),struct ('a',1,'b',2)), true)
-%!assert (isequal (struct ('a',1,'b',2),struct ('a',1,'b',2),struct ('a',1,'b',2)), true)
-%!assert (isequal (struct ('a',"abc",'b',2),struct ('a',"abc",'b',2)), true)
-## test for inequality (struct)
-%!assert (isequal (struct ('a',NaN,'b',2),struct ('a',NaN,'b',2),struct ('a',NaN,'b',2)), false)
+## test all numeric built-in primitives
+%!assert (isequal (false, logical (0), char (0),
+%!                 int8 (0), int16 (0), int32 (0), int64 (0),
+%!                 uint8 (0), uint16 (0), uint32 (0), uint64 (0),
+%!                 double (0), single (0),
+%!                 double (complex (0,0)), single (complex (0,0))),
+%!        true)
+%!assert (isequal (true, logical (1), char (1), 
+%!                 int8 (1), int16 (1), int32 (1), int64 (1), 
+%!                 uint8 (1), uint16 (1), uint32 (1), uint64 (1), 
+%!                 double (1), single (1),
+%!                 double (complex (1,0)), single (complex (1,0))),
+%!        true)
+
+## test characters and strings
+%!assert (isequal ('a', "a"), true)
+%!assert (isequal ("abab", ["a", "b", "a", "b"]), true)
+%!assert (isequal (["a","b","c","d"], ["a","b","c","d"]), true)
+%!assert (isequal (["test   ";"strings"], ["test   ";"strings"],
+%!                 ["test   ";"strings"]), true)
+%!assert (isequal (["a","b","c","d"], ["a";"b";"c";"d"]), false)
+
+## test function_handle
+%!test
+%! fcn = @(x) x.^2;
+%! assert (isequal (fcn, fcn), true);
+%! assert (isequal (fcn, @(x) x.^2), false);
+%! assert (isequal (@(x) x.^2, fcn), false);
+
+## test structures
+%!assert (isequal (struct ([]),struct ([])), true)
+%!assert (isequal (struct ("a",1), struct ("a",1)), true)
+%!assert (isequal (struct ("a",1), struct ("a",2)), false)
+%!assert (isequal (struct ("a",1), struct ("b",1)), false)
+%!assert (isequal (struct ("a",1,"b",2), struct ("a",1,"b",2)), true)
+%!assert (isequal (struct ("a",1,"b",2), struct ("b",2,"a",1)), true)
+%!assert (isequal (struct ("a",1,"b",2), struct ("a",1,"b",2),
+%!                 struct ("a",1,"b",2)), true)
+%!assert (isequal (struct ("a","abc","b",2), struct ("a","abc","b",2)), true)
+
+## recursive structure
+%!test  
+%! x.a = "a1";
+%! x.b.a = "ba1";
+%! x.b.b = "bb1";
+%! assert (isequal (x, x, x), true);
+%! y = x;
+%! y.b.b = "bb2";
+%! assert (isequal (x, y), false);
+%! y = x;
+%! y.b = rmfield (y.b, "b");
+%! y.b.b.a = "bba1";
+%! assert (isequal (x, y), false);
+
+## test cells
+%!assert (isequal (cell (1,1), cell (1,1)), true)
+%!assert (isequal (cell (1,1), cell (1,2)), false)
+%!assert (isequal ({"a",1}, {"a",1}), true)
+%!assert (isequal ({"a",1}, {"a",2}), false)
+%!assert (isequal ({"a",1}, {"b",1}), false)
+%!assert (isequal ({"a",1,"b",2}, {"a",1,"b",2}), true)
+%!assert (isequal ({"a",1,"b",2}, {"b",2,"a",1}), false)
+%!assert (isequal ({"a",1,"b",2}, {"a",1,"b",2}, {"a",1,"b",2}), true)
+%!assert (isequal ({"a","abc","b",2}, {"a","abc","b",2}), true)
+%!assert (isequal ({"a","b","c","d"}, {"a","b","c","d"}), true)
+%!assert (isequal ({"a","b","c","d"}, {"a";"b";"c";"d"}), false)
+%!assert (isequal (["a","b","c","d"], {"a","b","c","d"}), false)
+
+## recursive cell
+%!test
+%! x = cell (1,3);
+%! x{1} = {[1], [1 2]};
+%! x{2} = true;
+%! x{3} = {{"hello"}, {"world"}};
+%! assert (isequal (x, x));
+%! y = x;
+%! y{3}{1}{1} = "goodbye";
+%! assert (isequal (x, y), false);
 
 ## test for sparse matrices
+%!assert (isequal (sparse ([]), []), true)
+%!assert (isequal ([], sparse ([])), true)
 %!assert (isequal (sparse (0,1), sparse (0,1)), true)
+%!assert (isequal (sparse (0,1), zeros (0,1)), true)
+%!assert (isequal (sparse (2,2), sparse (2,2)), true)
+%!assert (isequal (zeros (2,2), sparse (2,2)), true)
+%!assert (isequal (speye (1), eye (1)), true)
+%!assert (isequal (eye (300), speye (300)), true)
 %!assert (isequal (sparse (0,1), sparse (1,0)), false)
-%!assert (isequal (sparse (2, 2), sparse (2, 2)), true)
 
-## Input validation
+## test NaN
+%!assert (isequal (NaN, NaN), false)
+%!assert (isequal (NaN, Inf), false)
+%!assert (isequal (NaN, 1.0), false)
+%!assert (isequal ([1,2,NaN,4], [1,2,NaN,4]), false)
+%!assert (isequal (struct ("a",NaN,"b",2), struct ("a",NaN,"b",2), 
+%!                 struct ("a",NaN,"b",2)), false)
+
+## test input validation
 %!error isequal ()
 %!error isequal (1)
+%!error isequal ([1,1])
 
--- a/scripts/general/isequaln.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/general/isequaln.m	Mon Jan 12 09:17:35 2015 -0800
@@ -36,13 +36,14 @@
 
 
 ## test for equality
-%!assert (isequaln ({1,2,NaN,4},{1,2,NaN,4}), true)
-%!assert (isequaln ([1,2,NaN,4],[1,2,NaN,4]), true)
+%!assert (isequaln ({1,2,NaN,4}, {1,2,NaN,4}), true)
+%!assert (isequaln ([1,2,NaN,4], [1,2,NaN,4]), true)
 ## test for inequality
-%!assert (isequaln ([1,2,NaN,4],[1,NaN,3,4]), false)
-%!assert (isequaln ([1,2,NaN,4],[1,2,3,4]), false)
+%!assert (isequaln ([1,2,NaN,4], [1,NaN,3,4]), false)
+%!assert (isequaln ([1,2,NaN,4], [1,2,3,4]), false)
 ## test for equality (struct)
-%!assert (isequaln (struct ('a',NaN,'b',2),struct ('a',NaN,'b',2),struct ('a',NaN,'b',2)), true)
+%!assert (isequaln (struct ("a",NaN,"b",2), struct ("a",NaN,"b",2),
+%!                  struct ("a",NaN,"b",2)), true)
 %!assert (isequaln (1,2,1), false)
 
 ## Input validation
--- a/scripts/general/isrow.m	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-## 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/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} {} isrow (@var{x})
-## Return true if @var{x} is a row vector.
-## @seealso{iscolumn, isscalar, isvector, ismatrix}
-## @end deftypefn
-
-## Author: Rik Wehbring
-
-function retval = isrow (x)
-
-  if (nargin != 1)
-    print_usage ();
-  endif
-
-  sz = size (x);
-  retval = (ndims (x) == 2 && (sz(1) == 1));
-
-endfunction
-
-
-%!assert (isrow ([1, 2, 3]))
-%!assert (isrow ([1; 2; 3]), false)
-%!assert (isrow (1))
-%!assert (isrow ([]), false)
-%!assert (isrow ([1, 2; 3, 4]), false)
-
-%!assert (isrow ("t"))
-%!assert (isrow ("test"))
-%!assert (isrow (["test"; "ing"]), false)
-
-%!test
-%! s.a = 1;
-%! assert (isrow (s));
-
-%% Test input validation
-%!error isrow ()
-%!error isrow ([1, 2], 2)
-
--- a/scripts/general/isscalar.m	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-## Copyright (C) 1996-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 {Function File} {} isscalar (@var{x})
-## Return true if @var{x} is a scalar.
-## @seealso{isvector, ismatrix}
-## @end deftypefn
-
-## Author: jwe
-
-function retval = isscalar (x)
-
-  if (nargin != 1)
-    print_usage ();
-  endif
-
-  retval = numel (x) == 1;
-
-endfunction
-
-
-%!assert (isscalar (1))
-%!assert (isscalar ([1, 2]), false)
-%!assert (isscalar ([]), false)
-%!assert (isscalar ([1, 2; 3, 4]), false)
-
-%!assert (isscalar ("t"))
-%!assert (isscalar ("test"), false)
-%!assert (isscalar (["test"; "ing"]), false)
-
-%!test
-%! s.a = 1;
-%! assert (isscalar (s));
-
-%% Test input validation
-%!error isscalar ()
-%!error isscalar (1, 2)
-
--- a/scripts/general/issquare.m	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-## Copyright (C) 1996-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 {Function File} {} issquare (@var{x})
-## Return true if @var{x} is a square matrix.
-## @seealso{isscalar, isvector, ismatrix, size}
-## @end deftypefn
-
-## Author: A. S. Hodel <scotte@eng.auburn.edu>
-## Created: August 1993
-## Adapted-By: jwe
-
-function retval = issquare (x)
-
-  if (nargin != 1)
-    print_usage ();
-  endif
-
-  if (ndims (x) == 2)
-    [r, c] = size (x);
-    retval = r == c;
-  else
-    retval = false;
-  endif
-
-endfunction
-
-
-%!assert (issquare ([]))
-%!assert (issquare (1))
-%!assert (! issquare ([1, 2]))
-%!assert (issquare ([1, 2; 3, 4]))
-%!assert (! issquare ([1, 2; 3, 4; 5, 6]))
-%!assert (! issquare (ones (3,3,3)))
-%!assert (issquare ("t"))
-%!assert (! issquare ("test"))
-%!assert (issquare (["test"; "ing"; "1"; "2"]))
-%!test
-%! s.a = 1;
-%! assert (issquare (s));
-%!assert (issquare ({1, 2; 3, 4}))
-%!assert (sparse (([1, 2; 3, 4])))
-
-%% Test input validation
-%!error issquare ()
-%!error issquare ([1, 2; 3, 4], 2)
-
--- a/scripts/general/isvector.m	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-## Copyright (C) 1996-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 {Function File} {} isvector (@var{x})
-## Return true if @var{x} is a vector.  A vector is a 2-D array
-## where one of the dimensions is equal to 1.  As a consequence a
-## 1x1 array, or scalar, is also a vector.
-## @seealso{isscalar, ismatrix, size, rows, columns, length}
-## @end deftypefn
-
-## Author: jwe
-
-function retval = isvector (x)
-
-  if (nargin != 1)
-    print_usage ();
-  endif
-
-  sz = size (x);
-  retval = (ndims (x) == 2 && (sz(1) == 1 || sz(2) == 1));
-
-endfunction
-
-
-%!assert (isvector (1))
-%!assert (isvector ([1; 2; 3]))
-%!assert (isvector ([]), false)
-%!assert (isvector ([1, 2; 3, 4]), false)
-
-%!assert (isvector ("t"))
-%!assert (isvector ("test"))
-%!assert (isvector (["test"; "ing"]), false)
-
-%!test
-%! s.a = 1;
-%! assert (isvector (s));
-
-%% Test input validation
-%!error isvector ()
-%!error isvector ([1, 2], 2)
-
--- a/scripts/general/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/general/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -7,7 +7,6 @@
 general_FCN_FILES = \
   general/accumarray.m \
   general/accumdim.m \
-  general/bicubic.m \
   general/bincoeff.m \
   general/bitcmp.m \
   general/bitget.m \
@@ -29,33 +28,30 @@
   general/display.m \
   general/divergence.m \
   general/fieldnames.m \
+  general/flip.m \
   general/flipdim.m \
   general/fliplr.m \
   general/flipud.m \
   general/gradient.m \
   general/idivide.m \
+  general/inputParser.m \
   general/int2str.m \
   general/interp1.m \
   general/interp2.m \
   general/interp3.m \
+  general/interpft.m \
   general/interpn.m \
-  general/interpft.m \
-  general/iscolumn.m \
   general/isdir.m \
   general/isequal.m \
   general/isequaln.m \
-  general/isrow.m \
-  general/isscalar.m \
-  general/issquare.m \
-  general/isvector.m \
   general/loadobj.m \
   general/logspace.m \
   general/methods.m \
   general/nargchk.m \
   general/narginchk.m \
   general/nargoutchk.m \
+  general/nextpow2.m \
   general/nthargout.m \
-  general/nextpow2.m \
   general/num2str.m \
   general/pol2cart.m \
   general/polyarea.m \
@@ -79,8 +75,8 @@
   general/sph2cart.m \
   general/structfun.m \
   general/subsindex.m \
+  general/trapz.m \
   general/triplequad.m \
-  general/trapz.m \
   general/validateattributes.m \
   $(general_PRIVATE_FCN_FILES)
 
--- a/scripts/general/nargchk.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/general/nargchk.m	Mon Jan 12 09:17:35 2015 -0800
@@ -25,6 +25,9 @@
 ##
 ## This is useful for checking to see that the number of input arguments
 ## supplied to a function is within an acceptable range.
+##
+## @strong{Caution}: @code{nargchk} is scheduled for deprecation.  Use
+## @code{narginchk} in all new code.
 ## @seealso{nargoutchk, narginchk, error, nargin, nargout}
 ## @end deftypefn
 
--- a/scripts/general/narginchk.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/general/narginchk.m	Mon Jan 12 09:17:35 2015 -0800
@@ -28,7 +28,7 @@
 ##
 ## Note that this function evaluates @code{nargin} on the caller.
 ##
-## @seealso{nargchk, nargoutchk, error, nargout, nargin}
+## @seealso{nargoutchk, error, nargout, nargin}
 ## @end deftypefn
 
 ## Author: Carnë Draug <carandraug+dev@gmail.com>
--- a/scripts/general/nargoutchk.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/general/nargoutchk.m	Mon Jan 12 09:17:35 2015 -0800
@@ -38,7 +38,7 @@
 ##
 ## This is useful for checking to see that the number of output
 ## arguments supplied to a function is within an acceptable range.
-## @seealso{nargchk, narginchk, error, nargout, nargin}
+## @seealso{narginchk, error, nargout, nargin}
 ## @end deftypefn
 
 ## Author: Bill Denney <bill@denney.ws>
@@ -76,7 +76,7 @@
     if (strcmpi (outtype, "string"))
       msg = msg.message;
     elseif (isempty (msg.message))
-      ## Compatability: Matlab returns a 0x1 empty struct when nargchk passes
+      ## Compatibility: Matlab returns a 0x1 empty struct when nargoutchk passes
       msg = resize (msg, 0, 1);
     endif
 
--- a/scripts/general/prepad.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/general/prepad.m	Mon Jan 12 09:17:35 2015 -0800
@@ -97,7 +97,7 @@
 %!assert (prepad ([1,2], 2, 2, 3), reshape ([2,2,1,2], 1, 2, 2))
 %!assert (prepad ([1;2], 2, 2, 3), reshape ([2;2;1;2], 2, 1, 2))
 
-## FIXME -- we need tests for multidimensional arrays.
+## FIXME: We need tests for multidimensional arrays.
 
 %!error prepad ()
 %!error prepad (1)
--- a/scripts/general/private/__isequal__.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/general/private/__isequal__.m	Mon Jan 12 09:17:35 2015 -0800
@@ -33,17 +33,19 @@
 ## Algorithm:
 ##
 ## 1. Determine the class of x
-## 2. If x is of the struct, cell, list or char class, for each
-##    argument after x, determine whether it has the same class
-##    and size as x.
-##    Otherwise, for each argument after x, verify that it is not
-##    of the struct, cell, list or char class, and that it has
-##    the same size as x.
+## 2. If x and all other arguments have the same class, then check that the
+##    number of dimensions and then the size of each dimension match.
+##    If not all arguments share the same class, then verify that all of the
+##    arguments belong to a comparable "numeric" class which includes
+##    numeric, logical, and character arrays.  Check that number of dimensions
+##    and size of each dimension match.
 ## 3. For each argument after x, compare it for equality with x:
 ##    a. struct     compare each member by name, not by order (recursive)
-##    b. cell/list  compare each member by order (recursive)
-##    c. char       compare each member with strcmp
-##    d. <other>    compare each nonzero member, and assume NaN == NaN
+##    b. object     converted to struct, and then compared as stated above
+##    c. cell       compare each member by order (recursive)
+##    d. char       compare each member with strcmp
+##    e  fcn_handle compare using overloade 'eq' operator
+##    f. <other>    compare each nonzero member, and assume NaN == NaN
 ##                  if nans_compare_equal is nonzero.
 
 function t = __isequal__ (nans_compare_equal, x, varargin)
@@ -53,39 +55,31 @@
   ## Generic tests.
 
   ## All arguments must either be of the same class or they must be
-  ## numeric values.
+  ## "numeric" values.
   t = (all (strcmp (class (x),
                     cellfun ("class", varargin, "uniformoutput", false)))
-       || ((isnumeric (x) || islogical (x))
-           && all (cellfun ("isnumeric", varargin)
-                   | cellfun ("islogical", varargin))));
+       || ((isreal (x) || isnumeric (x))
+           && all (cellfun ("isreal", varargin)
+                   | cellfun ("isnumeric", varargin))));
 
   if (t)
     ## Test that everything has the same number of dimensions.
-    s_x = size (x);
-    s_v = cellfun (@size, varargin, "uniformoutput", false);
-    t = all (length (s_x) == cellfun ("length", s_v));
+    t = all (ndims (x) == cellfun ("ndims", varargin));
   endif
 
   if (t)
-    ## Test that everything is the same size since it has the same
-    ## dimensionality.
-    l_x = length (s_x);
-    s_v = reshape ([s_v{:}], length (s_x), []);
-    idx = 0;
-    while (t && idx < l_x)
-      idx++;
-      t = all (s_x(idx) == s_v(idx,:));
-    endwhile
+    ## Test that everything is the same size since the dimensionality matches.
+    nd = ndims (x);
+    k = 1;
+    do
+      t = all (size (x,k) == cellfun ("size", varargin, k));
+    until (!t || k++ == nd);
   endif
 
   ## From here on, compare objects as if they were structures.
-  if (isobject (x))
+  if (t && isobject (x))
     x = builtin ("struct", x);
     for i = 1:numel (varargin)
-      if (! isobject (varargin{i}))
-        break;
-      endif
       varargin{i} = builtin ("struct", varargin{i});
     endfor
   endif
@@ -95,9 +89,9 @@
     if (isstruct (x))
       ## Test the number of fields.
       fn_x = fieldnames (x);
-      l_fn_x = length (fn_x);
+      l_fn_x = numfields (x);
       fn_v = cellfun ("fieldnames", varargin, "uniformoutput", false);
-      t = all (l_fn_x == cellfun ("length", fn_v));
+      t = all (l_fn_x == cellfun ("numel", fn_v));
 
       ## Test that all the names are equal.
       idx = 0;
@@ -112,12 +106,12 @@
       while (t && idx < l_fn_x)
         ## Test that all field values are equal.
         idx++;
-        args = {nans_compare_equal, {x.(fn_x{idx})}};
+        args = cell (1, 2+l_v);
+        args(1:2) = {nans_compare_equal, {x.(fn_x{idx})}};
         for argn = 1:l_v
           args{argn+2} = {varargin{argn}.(fn_x{idx})};
         endfor
-        ## Minimize function calls by calling for all the arguments at
-        ## once.
+        ## Minimize function calls by calling for all the arguments at once.
         t = __isequal__ (args{:});
       endwhile
 
@@ -127,24 +121,24 @@
       idx = 0;
       while (t && idx < l_x)
         idx++;
-        args = {nans_compare_equal, x{idx}};
-        for p = 1:l_v
-          args{p+2} = varargin{p}{idx};
-        endfor
+        args = cell (1, 2+l_v);
+        args(1:2) = {nans_compare_equal, x{idx}}; 
+        args(3:end) = [cellindexmat(varargin, idx){:}];
+
         t = __isequal__ (args{:});
       endwhile
 
-    elseif (ischar (x))
-
+    elseif (ischar (x) && all (cellfun ("isclass", varargin, "char")))
       ## Sizes are equal already, so we can just make everything into a
       ## row and test the rows.
+      n_x = numel (x);
+      strings = cell (1, l_v);
       for i = 1:l_v
-        strings{i} = reshape (varargin{i}, 1, []);
+        strings{i} = reshape (varargin{i}, 1, n_x);
       endfor
-      t = all (strcmp (reshape (x, 1, []), strings));
+      t = all (strcmp (reshape (x, 1, n_x), strings));
 
     elseif (isa (x, "function_handle"))
-
       ## The == operator is overloaded for handles.
       t = all (cellfun ("eq", {x}, varargin));
 
@@ -179,11 +173,5 @@
     endif
   endif
 
-  if (!t)
-    t = false;
-  else
-    t = true;
-  endif
-
 endfunction
 
--- a/scripts/general/profshow.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/general/profshow.m	Mon Jan 12 09:17:35 2015 -0800
@@ -1,4 +1,4 @@
-## Copyright (C) 2012-2013 Daniel Kraft
+## Copyright (C) 2012-2014 Daniel Kraft
 ##
 ## This file is part of Octave.
 ##
@@ -19,17 +19,20 @@
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {} profshow (@var{data})
 ## @deftypefnx {Function File} {} profshow (@var{data}, @var{n})
-## Show flat profiler results.
+## @deftypefnx {Function File} {} profshow ()
+## @deftypefnx {Function File} {} profshow (@var{n})
+## Display flat per-function profiler results.
 ##
-## This command prints out profiler data as a flat profile.  @var{data} is the
-## structure returned by @code{profile ("info")}.  If @var{n} is given, it
-## specifies the number of functions to show in the profile; functions are
-## sorted in descending order by total time spent in them.  If there are more
-## than @var{n} included in the profile, those will not be shown.  @var{n}
+## Print out profiler data (execution time, number of calls) for the most
+## critical @var{n} functions.  The results are sorted in descending order by
+## the total time spent in each function.  If @var{n} is unspecified it
 ## defaults to 20.
 ##
-## The attribute column shows @samp{R} for recursive functions and nothing
-## otherwise.
+## The input @var{data} is the structure returned by @code{profile ("info")}.
+## If unspecified, @code{profshow} will use the current profile dataset.
+##
+## The attribute column displays @samp{R} for recursive functions, and is blank
+## for all other function types.
 ## @seealso{profexplore, profile}
 ## @end deftypefn
 
@@ -38,10 +41,17 @@
 
 function profshow (data, n = 20)
 
-  if (nargin < 1 || nargin > 2)
+  if (nargin > 2)
     print_usage ();
   endif
 
+  if (nargin == 0)
+    data = profile ("info");
+  elseif (nargin == 1 && ! isstruct (data))
+    n = data;
+    data = profile ("info");
+  endif
+
   n = fix (n);
   if (! isscalar (n) || ! isreal (n) || ! (n > 0))
     error ("profile: N must be a positive integer");
@@ -53,30 +63,32 @@
   ## We want to sort by times in descending order.  For this, extract the
   ## times to an array, then sort this, and use the resulting index permutation
   ## to print out our table.
-  times = -[ data.FunctionTable.TotalTime ];
+  times = [ data.FunctionTable.TotalTime ];
+  totalTime = sum (times);
 
-  [~, p] = sort (times);
+  [~, p] = sort (times, "descend");
 
   ## For printing the table, find out the maximum length of a function name
   ## so that we can proportion the table accordingly.  Based on this,
   ## we can build the format used for printing table rows.
-  nameLen = length ("Function");
-  for i = 1 : n
-    nameLen = max (nameLen, length (data.FunctionTable(p(i)).FunctionName));
-  endfor
-  headerFormat = sprintf ("%%4s %%%ds %%4s %%12s %%12s\n", nameLen);
-  rowFormat = sprintf ("%%4d %%%ds %%4s %%12.3f %%12d\n", nameLen);
+  nameLen = max (length ("Function"),
+                 columns (char (data.FunctionTable(p(1:n)).FunctionName)));
+  headerFormat = sprintf ("%%4s %%%ds %%4s %%12s %%10s %%12s\n", nameLen);
+  rowFormat = sprintf ("%%4d %%%ds %%4s %%12.3f %%10.2f %%12d\n", nameLen);
 
-  printf (headerFormat, "#", "Function", "Attr", "Time (s)", "Calls");
-  printf ("%s\n", repmat ("-", 1, nameLen + 2 * 5 + 2 * 13));
+  printf (headerFormat, ...
+          "#", "Function", "Attr", "Time (s)", "Time (%)", "Calls");
+  printf ("%s\n", repmat ("-", 1, nameLen + 2 * 5 + 11 + 2 * 13));
+
   for i = 1 : n
     row = data.FunctionTable(p(i));
+    timePercent = 100 * row.TotalTime / totalTime;
     attr = "";
     if (row.IsRecursive)
       attr = "R";
     endif
-    printf (rowFormat, p(i), row.FunctionName, attr, ...
-            row.TotalTime, row.NumCalls);
+    printf (rowFormat, p(i), row.FunctionName, attr,
+            row.TotalTime, timePercent, row.NumCalls);
   endfor
 
 endfunction
@@ -96,7 +108,6 @@
 %! profile off;
 %! profshow (profile ("info"), 5);
 
-%!error profshow ()
 %!error profshow (1, 2, 3)
 %!error <N must be a positive integer> profshow (struct (), ones (2))
 %!error <N must be a positive integer> profshow (struct (), 1+i)
--- a/scripts/general/quadgk.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/general/quadgk.m	Mon Jan 12 09:17:35 2015 -0800
@@ -27,7 +27,7 @@
 ## using adaptive Gauss-Konrod quadrature.
 ## @var{f} is a function handle, inline function, or string
 ## containing the name of the function to evaluate.
-## The formulation is based on a proposal by L.F. Shampine,
+## The formulation is based on a proposal by @nospell{L.F. Shampine},
 ## @cite{"Vectorized adaptive quadrature in @sc{matlab}", Journal of
 ## Computational and Applied Mathematics, pp131-140, Vol 211, Issue 2,
 ## Feb 2008} where all function evaluations at an iteration are
--- a/scripts/general/quadl.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/general/quadl.m	Mon Jan 12 09:17:35 2015 -0800
@@ -45,7 +45,7 @@
 ## @var{f}.  To use default values for @var{tol} and @var{trace}, one may pass
 ## empty matrices ([]).
 ##
-## Reference: W. Gander and W. Gautschi, @cite{Adaptive Quadrature -
+## Reference: @nospell{W. Gander and W. Gautschi}, @cite{Adaptive Quadrature -
 ## Revisited}, BIT Vol. 40, No. 1, March 2000, pp. 84--101.
 ## @url{http://www.inf.ethz.ch/personal/gander/}
 ## @seealso{quad, quadv, quadgk, quadcc, trapz, dblquad, triplequad}
--- a/scripts/general/rat.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/general/rat.m	Mon Jan 12 09:17:35 2015 -0800
@@ -142,7 +142,7 @@
       s_nc = columns (s);
       if (n_nc > s_nc)
         s(:,s_nc+1:n_nc) = " ";
-      elseif (s_nc > n_nc)
+      elseif (s_nc > n_nc && n_nc != 0)
         n(:,n_nc+1:s_nc) = " ";
       endif
       n = cat (1, n, s);
@@ -157,6 +157,9 @@
 %! assert (n, [1, 3, 1]);
 %! assert (d, [2, 10, 3]);
 
+## bug #43374
+%!assert (eval (rat (0.75)), [0.75])
+
 %!error rat ();
 %!error rat (1, 2, 3);
 
--- a/scripts/general/repmat.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/general/repmat.m	Mon Jan 12 09:17:35 2015 -0800
@@ -1,3 +1,4 @@
+## Copyright (C) 2014 Markus Bergholz
 ## Copyright (C) 2000-2013 Paul Kienzle
 ## Copyright (C) 2008 Jaroslav Hajek
 ##
@@ -20,6 +21,7 @@
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {} repmat (@var{A}, @var{m})
 ## @deftypefnx {Function File} {} repmat (@var{A}, @var{m}, @var{n})
+## @deftypefnx {Function File} {} repmat (@var{A}, @var{m}, @var{n}, @var{p} @dots{})
 ## @deftypefnx {Function File} {} repmat (@var{A}, [@var{m} @var{n}])
 ## @deftypefnx {Function File} {} repmat (@var{A}, [@var{m} @var{n} @var{p} @dots{}])
 ## Form a block matrix of size @var{m} by @var{n}, with a copy of matrix
@@ -33,13 +35,14 @@
 ## Author: Paul Kienzle <pkienzle@kienzle.powernet.co.uk>
 ## Created: July 2000
 
-function x = repmat (A, m, n)
+function x = repmat (A, m, varargin)
 
-  if (nargin < 2 || nargin > 3)
+  if (nargin < 2)
     print_usage ();
   endif
 
   if (nargin == 3)
+    n = varargin{1};
     if (! isempty (m) && isempty (n))
       m = m(:).';
       n = 1;
@@ -64,12 +67,20 @@
       n = n(:).';
     endif
   else
-    if (isempty (m))
+    if (nargin > 3)
+      # input check for m and varargin
+      if (isscalar (m) && all (cellfun ("numel", varargin) == 1))
+        m = [m varargin{:}];
+        n = [];
+      else
+        error ("repmat: all input arguments must be scalar");
+      end
+    elseif (isempty (m))
       m = n = 1;
     elseif (isscalar (m))
       n = m;
     elseif (ndims (m) > 2)
-      error ("repmat: M has more than 2 dimensions")
+      error ("repmat: M has more than 2 dimensions");
     elseif (all (size (m) > 1))
       m = m(:,1).';
       n = [];
@@ -81,7 +92,7 @@
   idx = [m, n];
 
   if (all (idx < 0))
-    error ("repmat: invalid dimensions")
+    error ("repmat: invalid dimensions");
   else
     idx = max (idx, 0);
   endif
@@ -150,6 +161,7 @@
 %!assert (repmat (x, [1 3]), repmat (x, 1, 3))
 %!assert (repmat (x, [3 1]), repmat (x, 3, 1))
 %!assert (repmat (x, [3 3]), repmat (x, 3, 3))
+%!assert (repmat (pi, [1,2,3,4]), repmat (pi, 1,2,3,4))
 
 # Tests for numel==1 case:
 %!shared x, r
--- a/scripts/general/rot90.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/general/rot90.m	Mon Jan 12 09:17:35 2015 -0800
@@ -19,6 +19,8 @@
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {} rot90 (@var{A})
 ## @deftypefnx {Function File} {} rot90 (@var{A}, @var{k})
+## Rotate array by 90 degree increments.
+##
 ## Return a copy of @var{A} with the elements rotated counterclockwise in
 ## 90-degree increments.  The second argument is optional, and specifies
 ## how many 90-degree rotations are to be applied (the default value is 1).
@@ -45,9 +47,11 @@
 ## @end group
 ## @end example
 ##
-## Note that @code{rot90} only works with 2-D arrays.  To rotate N-D arrays
-## use @code{rotdim} instead.
-## @seealso{rotdim, flipud, fliplr, flipdim}
+## The rotation is always performed on the plane of the first two dimensions,
+## i.e., rows and columns.  To perform a rotation on any other plane, use
+## @code{rotdim}.
+##
+## @seealso{rotdim, fliplr, flipud, flip}
 ## @end deftypefn
 
 ## Author: jwe
@@ -58,22 +62,24 @@
     print_usage ();
   endif
 
-  if (ndims (A) > 2)
-    error ("rot90: A must be a 2-D array");
-  elseif (! (isscalar (k) && isreal (k) && k == fix (k)))
+  if (! (isscalar (k) && isreal (k) && k == fix (k)))
     error ("rot90: K must be a single real integer");
   endif
 
   k = mod (k, 4);
+  nd = ndims (A);
 
   if (k == 0)
     B = A;
   elseif (k == 1)
-    B = flipud (A.');
+    B = flipud (permute (A, [2 1 3:1:nd]));
   elseif (k == 2)
-    B = flipud (fliplr (A));
+    idx(1:nd) = {':'};
+    idx{1} = rows (A):-1:1;
+    idx{2} = columns (A):-1:1;
+    B = A(idx{:});
   elseif (k == 3)
-    B = (flipud (A)).';
+    B = permute (flipud (A), [2 1 3:1:nd]);
   else
     error ("rot90: internal error!");
   endif
@@ -94,6 +100,38 @@
 %! assert (rot90 (x1, 5), x2);
 %! assert (rot90 (x1, -1), x4);
 
+## Test NDArrays
+%!test
+%! a(1:2,1:2,1) = [1 2; 3 4];
+%! a(1:2,1:2,2) = [5 6; 7 8];
+%! b(1:2,1:2,1) = [2 4; 1 3];
+%! b(1:2,1:2,2) = [6 8; 5 7];
+%! assert (rot90 (a, 1), b)
+%! assert (rot90 (a, 2), rot90 (b, 1))
+%! assert (rot90 (a, 3), rot90 (b, 2))
+
+%!test
+%! a = b = zeros (2, 2, 1, 2);
+%! a(1:2,1:2,:,1) = [1 2; 3 4];
+%! a(1:2,1:2,:,2) = [5 6; 7 8];
+%! b(1:2,1:2,:,1) = [2 4; 1 3];
+%! b(1:2,1:2,:,2) = [6 8; 5 7];
+%! assert (rot90 (a, 1), b)
+%! assert (rot90 (a, 2), rot90 (b, 1))
+%! assert (rot90 (a, 3), rot90 (b, 2))
+
+## With non-square matrices
+%!test
+%! a = zeros (3, 2, 1, 2);
+%! b = zeros (2, 3, 1, 2);
+%! a(1:2,1:3,:,1) = [ 1  2  3;  4  5  6];
+%! a(1:2,1:3,:,2) = [ 7  8  9; 10 11 12];
+%! b(1:3,1:2,:,1) = [ 3  6;  2  5;  1  4];
+%! b(1:3,1:2,:,2) = [ 9 12;  8 11;  7 10];
+%! assert (rot90 (a, 1), b)
+%! assert (rot90 (a, 2), rot90 (b, 1))
+%! assert (rot90 (a, 3), rot90 (b, 2))
+
 %% Test input validation
 %!error rot90 ()
 %!error rot90 (1, 2, 3)
--- a/scripts/general/rotdim.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/general/rotdim.m	Mon Jan 12 09:17:35 2015 -0800
@@ -51,7 +51,7 @@
 ## rotdim ([1, 2; 3, 4], 7, [1, 2])
 ## @end group
 ## @end example
-## @seealso{rot90, flipud, fliplr, flipdim}
+## @seealso{rot90, fliplr, flipud, flip}
 ## @end deftypefn
 
 function y = rotdim (x, n, plane)
@@ -107,16 +107,16 @@
   if (n == 0)
     y = x;
   elseif (n == 2)
-    y = flipdim (flipdim (x, plane(1)), plane(2));
+    y = flip (flip (x, plane(1)), plane(2));
   elseif (n == 1 || n == 3)
     perm = 1:nd;
     perm(plane(1)) = plane(2);
     perm(plane(2)) = plane(1);
     y = permute (x, perm);
     if (n == 1)
-      y = flipdim (y, min (plane));
+      y = flip (y, min (plane));
     else
-      y = flipdim (y, max (plane));
+      y = flip (y, max (plane));
     endif
   else
     error ("rotdim: internal error!");
@@ -152,8 +152,8 @@
 %!assert (rotdim (m, 3), rotdim (m, -1))
 %!assert (rotdim (m, 1), rotdim (m))
 
-## FIXME -- we need tests for multidimensional arrays and different
-## values of PLANE.
+## FIXME: We need tests for multidimensional arrays
+##        and different values of PLANE.
 
 %!error rotdim ()
 %!error rotdim (1, 2, 3, 4)
--- a/scripts/general/validateattributes.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/general/validateattributes.m	Mon Jan 12 09:17:35 2015 -0800
@@ -161,7 +161,7 @@
 ##
 ## @end table
 ##
-## @seealso{nargin, varargin, isa, validatestring}
+## @seealso{isa, validatestring, inputParser}
 ## @end deftypefn
 
 function validateattributes (A, cls, attr, varargin)
--- a/scripts/geometry/delaunay.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/geometry/delaunay.m	Mon Jan 12 09:17:35 2015 -0800
@@ -17,22 +17,32 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} delaunay (@var{x}, @var{y})
-## @deftypefnx {Function File} {} delaunay (@var{x})
-## @deftypefnx {Function File} {} delaunay (@dots{}, @var{options})
-## @deftypefnx {Function File} {@var{tri} =} delaunay (@dots{})
-## Compute the Delaunay triangulation for a 2-D set of points.
-## The return value @var{tri} is a set of triangles which satisfies the
-## Delaunay circum-circle criterion, i.e., only a single data point from
-## [@var{x}, @var{y}] is within the circum-circle of the defining triangle.
-## The input @var{x} may also be a matrix with two columns where the first
-## column contains x-data and the second y-data.
+## @deftypefn  {Function File} {@var{tri} =} delaunay (@var{x}, @var{y})
+## @deftypefnx {Function File} {@var{tetr} =} delaunay (@var{x}, @var{y}, @var{z})
+## @deftypefnx {Function File} {@var{tri} =} delaunay (@var{x})
+## @deftypefnx {Function File} {@var{tri} =} delaunay (@dots{}, @var{options})
+## Compute the Delaunay triangulation for a 2-D or 3-D set of points.
 ##
-## The set of triangles @var{tri} is a matrix of size [n, 3].  Each
-## row defines a triangle and the three columns are the three vertices
-## of the triangle.  The value of @code{@var{tri}(i,j)} is an index into
-## @var{x} and @var{y} for the location of the j-th vertex of the i-th
-## triangle.
+## For 2-D sets, the return value @var{tri} is a set of triangles which
+## satisfies the Delaunay circum-circle criterion, i.e., only a single data
+## point from [@var{x}, @var{y}] is within the circum-circle of the defining
+## triangle.  The set of triangles @var{tri} is a matrix of size [n, 3].  Each
+## row defines a triangle and the three columns are the three vertices of the
+## triangle.  The value of @code{@var{tri}(i,j)} is an index into @var{x} and
+## @var{y} for the location of the j-th vertex of the i-th triangle.
+##
+## For 3-D sets, the return value @var{tetr} is a set of tetrahedrons which
+## satisfies the Delaunay circum-circle criterion, i.e., only a single data
+## point from [@var{x}, @var{y}, @var{z}] is within the circum-circle of the
+## defining tetrahedron.  The set of tetrahedrons is a matrix of size [n, 4].
+## Each row defines a tetrahedron and the four columns are the four vertices of
+## the tetrahedron.  The value of @code{@var{tetr}(i,j)} is an index into
+## @var{x}, @var{y}, @var{z} for the location of the j-th vertex of the i-th
+## tetrahedron.
+##
+## The input @var{x} may also be a matrix with two or three columns where the
+## first column contains x-data, the second y-data, and the optional third
+## column contains z-data.
 ##
 ## The optional last argument, which must be a string or cell array of strings,
 ## contains options passed to the underlying qhull command.
@@ -45,63 +55,84 @@
 ## To append user options to the defaults it is necessary to repeat the 
 ## default arguments in @var{options}.  Use a null string to pass no arguments.
 ##
-## If no output argument is specified the resulting Delaunay triangulation 
-## is plotted along with the original set of points.
-##
 ## @example
 ## @group
 ## x = rand (1, 10);
 ## y = rand (1, 10);
-## T = delaunay (x, y);
-## VX = [ x(T(:,1)); x(T(:,2)); x(T(:,3)); x(T(:,1)) ];
-## VY = [ y(T(:,1)); y(T(:,2)); y(T(:,3)); y(T(:,1)) ];
+## tri = delaunay (x, y);
+## triplot (tri, x, y);
+## hold on;
+## plot (x, y, "r*");
 ## axis ([0,1,0,1]);
-## plot (VX, VY, "b", x, y, "r*");
 ## @end group
 ## @end example
-## @seealso{delaunay3, delaunayn, convhull, voronoi, triplot, trimesh, trisurf}
+## @seealso{delaunayn, convhull, voronoi, triplot, trimesh, tetramesh, trisurf}
 ## @end deftypefn
 
 ## Author: Kai Habel <kai.habel@gmx.de>
 
 function tri = delaunay (varargin)
 
-  if (nargin < 1 || nargin > 3)
+  if (nargin < 1 || nargin > 4)
     print_usage ();
   endif
 
+  z = [];
   options = [];
 
   switch (nargin)
 
     case 1
-      if (! ismatrix (varargin{1}) || columns (varargin{1}) != 2)
-          error ("delaunay: X must be a matrix with 2 columns");
+      if (! ismatrix (varargin{1})
+          || (columns (varargin{1}) != 2 && columns (varargin{1}) != 3))
+          error ("delaunay: X must be a matrix with 2 or 3 columns");
       else
         x = varargin{1}(:,1);
         y = varargin{1}(:,2);
+        if (columns (varargin{1}) == 3)
+          z = varargin{1}(:,3);
+        endif
       endif
     
     case 2
       if (isnumeric (varargin{2}))
         x = varargin{1};
         y = varargin{2};
-      elseif (ischar (varargin{2}) || iscellstr (varargin{2}))
+      elseif (! (ischar (varargin{2}) || iscellstr (varargin{2})))
+        error ("delaunay: OPTIONS must be a string or cell array of strings");
+      else
         options = varargin{2};
-        if (! ismatrix (varargin{1}) && columns (varargin{1}) != 2)
-            error ("delaunay: X must be a matrix with 2 columns");
+        ncols = columns (varargin{1});
+
+        if (! ismatrix (varargin{1}) || (ncols != 2 && ncols != 3))
+          error ("delaunay: X must be a matrix with 2 or 3 columns");
         else
           x = varargin{1}(:,1);
           y = varargin{1}(:,2);
+          if (ncols == 3)
+            z = varargin{1}(:,3);
+          endif
         endif
-      else
-        error ("delaunay: OPTIONS must be a string or cell array of strings");
       endif
 
     case 3
+      if (isnumeric (varargin{3}))
+        x = varargin{1};
+        y = varargin{2};
+        z = varargin{3};
+      elseif (! (ischar (varargin{3}) || iscellstr (varargin{3})))
+        error ("delaunay: OPTIONS must be a string or cell array of strings");
+      else
+        x = varargin{1};
+        y = varargin{2};
+        options = varargin{3};
+      endif
+
+    case 4
       x = varargin{1};
       y = varargin{2};
-      options = varargin{3};
+      z = varargin{3};
+      options = varargin{4};
 
       if (! (ischar (options) || iscellstr (options)))
         error ("delaunay: OPTIONS must be a string or cell array of strings");
@@ -109,20 +140,16 @@
 
   endswitch
 
-  if (! (isequal(size(x),size(y))))
-    error ("delaunay: X and Y must be the same size");
-  endif
-
-  T = delaunayn ([x(:), y(:)], options);
-
-  if (nargout == 0)
-    x = x(:).';
-    y = y(:).';
-    VX = [ x(T(:,1)); x(T(:,2)); x(T(:,3)); x(T(:,1)) ];
-    VY = [ y(T(:,1)); y(T(:,2)); y(T(:,3)); y(T(:,1)) ];
-    plot (VX, VY, "b", x, y, "r*");
+  if (isempty (z))
+    if (! size_equal (x, y))
+      error ("delaunay: X and Y must be the same size");
+    endif
+    tri = delaunayn ([x(:), y(:)], options);
   else
-    tri = T;
+    if (! size_equal (x, y, z))
+      error ("delaunay: X, Y, and Z must be the same size");
+    endif
+    tri = delaunayn ([x(:), y(:), z(:)], options);
   endif
 
 endfunction
@@ -134,11 +161,11 @@
 %! rand ("state", 1);
 %! x = rand (1,10);
 %! y = rand (1,10);
-%! T = delaunay (x,y);
-%! VX = [ x(T(:,1)); x(T(:,2)); x(T(:,3)); x(T(:,1)) ];
-%! VY = [ y(T(:,1)); y(T(:,2)); y(T(:,3)); y(T(:,1)) ];
+%! tri = delaunay (x,y);
 %! clf;
-%! plot (VX,VY,"b", x,y,"r*");
+%! triplot (tri, x, y);
+%! hold on;
+%! plot (x, y, "r*");
 %! axis ([0,1,0,1]);
 
 %!testif HAVE_QHULL
@@ -165,5 +192,19 @@
 %! y = [5 7 8; 1 2 3];
 %! assert (sortrows (sort (delaunay (x, y), 2)), [1,2,4;1,3,4;1,3,5;3,4,6]);
 
-%% FIXME: Need input validation tests
+## Test 3-D input
+%!testif HAVE_QHULL
+%! x = [-1, -1, 1, 0, -1]; y = [-1, 1, 1, 0, -1]; z = [0, 0, 0, 1, 1];
+%! assert (sortrows (sort (delaunay (x, y, z), 2)), [1,2,3,4;1,2,4,5])
 
+%% Input validation tests
+%!error delaunay ()
+%!error delaunay (1,2,3,4,5)
+%!error <X must be a matrix with 2 or 3 columns> delaunay (ones (2,4))
+%!error <OPTIONS must be a string or cell array> delaunay (ones (2,2), struct())
+%!error <X must be a matrix with 2 or 3 columns> delaunay (ones (2,4), "")
+%!error <OPTIONS must be a string or cell array> delaunay (ones (2,2), ones (2,2), struct())
+%!error <OPTIONS must be a string or cell array> delaunay (ones (2,2), ones (2,2), ones (2,2), struct())
+%!error <X and Y must be the same size> delaunay (1, [1 2])
+%!error <X, Y, and Z must be the same size> delaunay (1, [1 2], [1 2])
+
--- a/scripts/geometry/delaunay3.m	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-## Copyright (C) 1999-2013 Kai Habel
-##
-## 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{tetr} =} delaunay3 (@var{x}, @var{y}, @var{z})
-## @deftypefnx {Function File} {@var{tetr} =} delaunay3 (@var{x}, @var{y}, @var{z}, @var{options})
-## Compute the Delaunay triangulation for a 3-D set of points.
-## The return value @var{tetr} is a set of tetrahedrons which satisfies the
-## Delaunay circum-circle criterion, i.e., only a single data point from
-## [@var{x}, @var{y}, @var{z}] is within the circum-circle of the defining
-## tetrahedron.
-##
-## The set of tetrahedrons @var{tetr} is a matrix of size [n, 4].  Each
-## row defines a tetrahedron and the four columns are the four vertices
-## of the tetrahedron.  The value of @code{@var{tetr}(i,j)} is an index into
-## @var{x}, @var{y}, @var{z} for the location of the j-th vertex of the i-th
-## tetrahedron.
-##
-## An optional fourth argument, which must be a string or cell array of strings,
-## contains options passed to the underlying qhull command.
-## See the documentation for the Qhull library for details
-## @url{http://www.qhull.org/html/qh-quick.htm#options}.
-## The default options are @code{@{"Qt", "Qbb", "Qc", "Qz"@}}.
-##
-## If @var{options} is not present or @code{[]} then the default arguments are
-## used.  Otherwise, @var{options} replaces the default argument list. 
-## To append user options to the defaults it is necessary to repeat the 
-## default arguments in @var{options}.  Use a null string to pass no arguments.
-##
-## @seealso{delaunay, delaunayn, convhull, voronoi, tetramesh}
-## @end deftypefn
-
-## Author: Kai Habel <kai.habel@gmx.de>
-
-function tetr = delaunay3 (x, y, z, options)
-
-  if (nargin < 3 || nargin > 4)
-    print_usage ();
-  endif
-
-  if (! (isvector (x) && isvector (y) && isvector (z)
-         && length (x) == length (y) && length (x) == length (z)))
-    error ("delaunay: X, Y, and Z must be the same size");
-  elseif (nargin == 4 && ! (ischar (options) || iscellstr (options)))
-    error ("delaunay3: OPTIONS must be a string or cell array of strings");
-  endif
-
-  if (nargin == 3)
-    tetr = delaunayn ([x(:), y(:), z(:)]);
-  else
-    tetr = delaunayn ([x(:), y(:), z(:)], options);
-  endif
-
-endfunction
-
-
-%!testif HAVE_QHULL
-%! x = [-1, -1, 1, 0, -1]; y = [-1, 1, 1, 0, -1]; z = [0, 0, 0, 1, 1];
-%! assert (sortrows (sort (delaunay3 (x, y, z), 2)), [1,2,3,4;1,2,4,5])
-
-%% FIXME: Need input validation tests
-
--- a/scripts/geometry/delaunayn.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/geometry/delaunayn.m	Mon Jan 12 09:17:35 2015 -0800
@@ -47,7 +47,7 @@
 ## To append user options to the defaults it is necessary to repeat the 
 ## default arguments in @var{options}.  Use a null string to pass no arguments.
 ##
-## @seealso{delaunay, delaunay3, convhulln, voronoin, trimesh, tetramesh}
+## @seealso{delaunay, convhulln, voronoin, trimesh, tetramesh}
 ## @end deftypefn
 
 function T = delaunayn (pts, varargin)
@@ -59,9 +59,9 @@
   T = __delaunayn__ (pts, varargin{:});
 
   if (isa (pts, "single"))
-    myeps = eps ("single");
+    tol = 1e3 * eps ("single");
   else
-    myeps = eps;
+    tol = 1e3 * eps;
   endif
 
   ## Try to remove the zero volume simplices.  The volume of the i-th simplex is
@@ -75,10 +75,10 @@
   ## prod(1:n) is dropped.
   idx = [];
   [nt, n] = size (T);
-  ## FIXME: Vectorize this for loop or convert to delaunayn to .oct function
+  ## FIXME: Vectorize this for loop or convert delaunayn to .oct function
   for i = 1:nt
     X = pts(T(i,1:end-1),:) - pts(T(i,2:end),:);
-    if (abs (det (X)) / sqrt (sum (X .^ 2, 2)) < 1e3 * myeps)
+    if (abs (det (X)) / sqrt (sumsq (X, 2)) < tol)
       idx(end+1) = i;
     endif
   endfor
@@ -87,7 +87,17 @@
 endfunction
 
 
+%!testif HAVE_QHULL
+%! x = [-1, 0; 0, 1; 1, 0; 0, -1; 0, 0];
+%! assert (sortrows (sort (delaunayn (x), 2)), [1,2,5;1,4,5;2,3,5;3,4,5]);
+
+## Test 3-D input
+%!testif HAVE_QHULL
+%! x = [-1, -1, 1, 0, -1]; y = [-1, 1, 1, 0, -1]; z = [0, 0, 0, 1, 1];
+%! assert (sortrows (sort (delaunayn ([x(:) y(:) z(:)]), 2)), [1,2,3,4;1,2,4,5])
+
 %% FIXME: Need tests for delaunayn
 
-%% FIXME: Need input validation tests
+%% Input validation tests
+%!error delaunayn ()
 
--- a/scripts/geometry/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/geometry/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -2,7 +2,6 @@
 
 geometry_FCN_FILES = \
   geometry/convhull.m \
-  geometry/delaunay3.m \
   geometry/delaunayn.m \
   geometry/delaunay.m \
   geometry/dsearch.m \
--- a/scripts/geometry/voronoi.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/geometry/voronoi.m	Mon Jan 12 09:17:35 2015 -0800
@@ -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/gui/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/gui/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -3,6 +3,7 @@
 gui_PRIVATE_FCN_FILES = \
   gui/private/__file_filter__.m \
   gui/private/__fltk_file_filter__.m \
+  gui/private/__get_funcname__.m \
   gui/private/__is_function__.m \
   gui/private/__uigetdir_fltk__.m \
   gui/private/__uigetfile_fltk__.m \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/gui/private/__get_funcname__.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,42 @@
+## Copyright (C) 2014 Andreas Weber
+##
+## 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{funcname} =} __get_funcname__ (@var{basename})
+## Internal function.
+##
+## Build function name for the current graphics toolkit according to schema
+## __[basename]_[graphics_toolkit]__, use fltk as default.
+## @end deftypefn
+
+## Author: Andreas Weber
+
+function funcname = __get_funcname__ (basename)
+
+  if (! __octave_link_enabled__ ())
+    tk = graphics_toolkit ();
+    funcname = strcat ("__", basename, "_", tk, "__");
+    if ((numel (tk) > 0) && (! strcmp(tk, "fltk")) && (! __is_function__ (funcname)))
+      warning ("%s: no implementation for toolkit '%s', using 'fltk' instead",basename, tk);
+    endif
+    funcname = strcat ("__", basename, "_fltk__");
+  else
+    funcname = "";
+  endif
+
+endfunction
--- a/scripts/gui/private/__is_function__.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/gui/private/__is_function__.m	Mon Jan 12 09:17:35 2015 -0800
@@ -26,7 +26,7 @@
 function result = __is_function__ (func)
 
   existval = exist (func);
-  result = (existval == 2 || existval == 3 || existval == 5 || existval == 6);
+  result = (existval == 2 || existval == 3 || existval == 5);
 
 endfunction
 
--- a/scripts/gui/uigetdir.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/gui/uigetdir.m	Mon Jan 12 09:17:35 2015 -0800
@@ -30,20 +30,7 @@
 
 function dirname = uigetdir (init_path = pwd, dialog_name = "Select Directory to Open")
 
-  if (! __octave_link_enabled__ ())
-    defaulttoolkit = get (0, "defaultfigure__graphics_toolkit__");
-    funcname = ["__uigetdir_", defaulttoolkit, "__"];
-    functype = exist (funcname);
-    if (! __is_function__ (funcname))
-      funcname = "__uigetdir_fltk__";
-      if (! __is_function__ (funcname))
-        error ("uigetdir: fltk graphics toolkit required");
-      elseif (! strcmp (defaulttoolkit, "gnuplot"))
-        warning ("uigetdir: no implementation for toolkit '%s', using 'fltk' instead",
-                 defaulttoolkit);
-      endif
-    endif
-  endif
+  funcname = __get_funcname__ (mfilename ());
 
   if (nargin > 2)
     print_usage ();
--- a/scripts/gui/uigetfile.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/gui/uigetfile.m	Mon Jan 12 09:17:35 2015 -0800
@@ -66,21 +66,8 @@
 
 function [retfile, retpath, retindex] = uigetfile (varargin)
 
-  if (! __octave_link_enabled__ ())
-    defaulttoolkit = get (0, "defaultfigure__graphics_toolkit__");
-    funcname = ["__uigetfile_", defaulttoolkit, "__"];
-    functype = exist (funcname);
-    if (! __is_function__ (funcname))
-      funcname = "__uigetfile_fltk__";
-      if (! __is_function__ (funcname))
-        error ("uigetfile: fltk graphics toolkit required");
-      elseif (! strcmp (defaulttoolkit, "gnuplot"))
-        warning ("uigetfile: no implementation for toolkit '%s', using 'fltk' instead",
-               defaulttoolkit);
-      endif
-    endif
-  endif
-  
+  funcname = __get_funcname__ (mfilename ());
+
   if (nargin > 7)
     error ("uigetfile: number of input arguments must be less than eight");
   endif
--- a/scripts/gui/uiputfile.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/gui/uiputfile.m	Mon Jan 12 09:17:35 2015 -0800
@@ -56,20 +56,7 @@
 
 function [retfile, retpath, retindex] = uiputfile (varargin)
 
-  if (! __octave_link_enabled__ ())
-    defaulttoolkit = get (0, "defaultfigure__graphics_toolkit__");
-    funcname = ["__uiputfile_", defaulttoolkit, "__"];
-    functype = exist (funcname);
-    if (! __is_function__ (funcname))
-      funcname = "__uiputfile_fltk__";
-      if (! __is_function__ (funcname))
-        error ("uiputfile: fltk graphics toolkit required");
-      elseif (! strcmp (defaulttoolkit, "gnuplot"))
-        warning ("uiputfile: no implementation for toolkit '%s', using 'fltk' instead",
-               defaulttoolkit);
-      endif
-    endif
-  endif
+  funcname = __get_funcname__ (mfilename ());
 
   if (nargin > 3)
     print_usage ();
--- a/scripts/help/__gripe_missing_component__.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/help/__gripe_missing_component__.m	Mon Jan 12 09:17:35 2015 -0800
@@ -17,7 +17,7 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} __gripe_missing_component__ (@var{caller}, @var{component})
+## @deftypefn {Function File} {} __gripe_missing_component__ (@var{caller}, @var{component})
 ## Undocumented internal function.
 ## @end deftypefn
 
@@ -46,7 +46,7 @@
       case "octave-config"
         msg = "unable to find the octave-config command, Octave installation is incomplete";
       otherwise
-        msg = ["unable to find required Octave component \"" component "\""];
+        msg = ['unable to find required Octave component "' component '"'];
     endswitch
   endif
 
@@ -54,3 +54,14 @@
 
 endfunction
 
+
+## Some trivial testing
+%!error <abc: unable to find the Octave info manual> __gripe_missing_component__ ("abc", "info-file")
+%!error <abc: unable to find the octave executable> __gripe_missing_component__ ("abc", "octave")
+%!error <abc: unable to find the octave-config command> __gripe_missing_component__ ("abc", "octave-config")
+%!error <abc: unable to find required Octave component "xyz"> __gripe_missing_component__ ("abc", "xyz")
+
+%!error __gripe_missing_component__ ()
+%!error __gripe_missing_component__ ("fcn")
+%!error __gripe_missing_component__ ("fcn", 1 , 2)
+
--- a/scripts/help/__unimplemented__.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/help/__unimplemented__.m	Mon Jan 12 09:17:35 2015 -0800
@@ -103,7 +103,7 @@
 
     ## control system
     case {"absorbDelay", "allmargin", "append", "augstate", "balreal", ...
-          "balred", "balredOptions", "bandwidth", "bdschur", "bode", ...
+          "balred", "balredOptions", "bdschur", "bode", ...
           "bodemag", "bodeoptions", "bodeplot", "c2d", "c2dOptions", ...
           "canon", "care", "chgFreqUnit", "chgTimeUnit", "connect", ...
           "connectOptions", "covar", "ctrb", "ctrbf", "ctrlpref", "d2c", ...
@@ -534,17 +534,14 @@
   "Tiff",
   "VideoReader",
   "VideoWriter",
+  "addCause",
+  "addcats",
   "align",
   "alim",
   "alpha",
   "alphamap",
   "annotation",
-  "audiodevinfo",
-  "audioinfo",
-  "audioplayer",
-  "audioread",
-  "audiorecorder",
-  "audiowrite",
+  "array2table",
   "bar3",
   "bar3h",
   "bench",
@@ -572,16 +569,19 @@
   "camup",
   "camva",
   "camzoom",
+  "categorical",
+  "categories",
   "cdf2rdf",
   "cdfepoch",
   "cdfinfo",
+  "cdflib",
   "cdfread",
   "cdfwrite",
+  "cell2table",
   "cellplot",
-  "checkin",
   "checkcode",
+  "checkin",
   "checkout",
-  "cholinc",
   "clearvars",
   "clipboard",
   "cmopts",
@@ -593,6 +593,8 @@
   "coneplot",
   "containers.Map",
   "contourslice",
+  "corrcoef",
+  "countcats",
   "createClassFromWsdl",
   "createSoapMessage",
   "customverctrl",
@@ -607,6 +609,7 @@
   "delaunayTriangulation",
   "depdir",
   "depfun",
+  "details",
   "deval",
   "dialog",
   "dither",
@@ -614,20 +617,24 @@
   "dragrect",
   "dynamicprops",
   "echodemo",
+  "empty",
+  "enumeration",
   "evalc",
+  "events",
   "export2wsdlg",
   "figurepalette",
   "filebrowser",
   "fill3",
+  "findprop",
   "fitsdisp",
   "fitsinfo",
   "fitsread",
   "fitswrite",
   "flow",
-  "frame2im",
   "freqspace",
   "funm",
   "gammaincinv",
+  "getReport",
   "getframe",
   "getpixelposition",
   "gobjects",
@@ -635,10 +642,7 @@
   "graymon",
   "griddedInterpolant",
   "gsvd",
-  "guidata",
   "guide",
-  "guihandles",
-  "handle",
   "h5create",
   "h5disp",
   "h5info",
@@ -646,35 +650,39 @@
   "h5readatt",
   "h5write",
   "h5writeatt",
+  "handle",
   "hdfinfo",
   "hdfread",
+  "height",
   "hgexport",
-  "hgload",
-  "hgsave",
   "hgsetget",
   "hgtransform",
-  "ichol",
-  "ilu",
-  "im2frame",
   "im2java",
   "imapprox",
   "import",
   "inmem",
-  "inputParser",
+  "innerjoin",
   "inspect",
-  "instrcallback",
-  "instrfind",
-  "instrfindall",
   "integral",
   "integral2",
   "integral3",
   "interpstreamspeed",
-  "iscom",
-  "isinterface",
-  "isjava",
+  "isKey",
+  "iscategorical",
+  "iscategory",
+  "ismissing",
   "isocaps",
+  "isordinal",
+  "isprotected",
   "isstudent",
-  "javachk",
+  "istable",
+  "isundefined",
+  "isvalid",
+  "javaMethodEDT",
+  "javaObjectEDT",
+  "join",
+  "keys",
+  "last",
   "ldl",
   "libfunctions",
   "libfunctionsview",
@@ -684,11 +692,10 @@
   "light",
   "lightangle",
   "lighting",
-  "linkaxes",
   "linkdata",
   "listfonts",
   "loadlibrary",
-  "lscov",
+  "localfunctions",
   "lsqr",
   "makehgtform",
   "material",
@@ -696,7 +703,7 @@
   "matlabrc",
   "memmapfile",
   "memory",
-  "metaclass",
+  "mergecats",
   "methodsview",
   "minres",
   "mlintrpt",
@@ -715,8 +722,10 @@
   "ncwrite",
   "ncwriteatt",
   "ncwriteschema",
+  "netcdf",
   "noanimate",
   "notebook",
+  "notify",
   "ode113",
   "ode15i",
   "ode15s",
@@ -728,15 +737,14 @@
   "odeget",
   "odeset",
   "odextend",
-  "open",
   "openfig",
   "opengl",
   "openvar",
   "ordeig",
   "ordqz",
   "ordschur",
+  "outerjoin",
   "padecoef",
-  "pan",
   "parseSoapResponse",
   "pathtool",
   "pcode",
@@ -750,23 +758,26 @@
   "printpreview",
   "profsave",
   "propedit",
+  "properties",
   "propertyeditor",
   "psi",
   "publish",
-  "qmr",
   "quad2d",
   "rbbox",
+  "readtable",
   "reducepatch",
   "reducevolume",
-  "readasync",
+  "remove",
+  "removecats",
+  "renamecats",
+  "reordercats",
   "rng",
-  "rotate",
-  "rotate3d",
+  "rowfun",
+  "savefig",
   "scatteredInterpolant",
   "selectmoveresize",
   "sendmail",
   "serial",
-  "serialbreak",
   "setpixelposition",
   "showplottool",
   "smooth3",
@@ -774,8 +785,9 @@
   "sound",
   "soundsc",
   "ss2tf",
+  "stack",
+  "standardizeMissing",
   "startup",
-  "stopasync",
   "stream2",
   "stream3",
   "streamline",
@@ -783,30 +795,32 @@
   "streamribbon",
   "streamslice",
   "streamtube",
-  "strings",
+  "struct2table",
   "subvolume",
+  "summary",
   "superclasses",
   "surf2patch",
+  "sylvester",
   "symmlq",
-  "syntax",
+  "table2array",
+  "table2cell",
+  "table2struct",
   "texlabel",
   "textwrap",
   "tfqmr",
+  "throw",
+  "throwAsCaller",
+  "timeit",
   "timer",
   "timeseries",
   "todatenum",
   "toolboxdir",
   "triangulation",
   "tscollection",
-  "tstool",
   "uibuttongroup",
-  "uicontextmenu",
-  "uicontrol",
   "uigetpref",
   "uiimport",
   "uiopen",
-  "uipanel",
-  "uipushtool",
   "uiresume",
   "uisave",
   "uisetcolor",
@@ -821,21 +835,27 @@
   "unicode2native",
   "unloadlibrary",
   "unmesh",
+  "unstack",
   "userpath",
+  "values",
+  "varfun",
+  "verLessThan",
   "verctrl",
-  "verLessThan",
   "viewmtx",
   "visdiff",
   "volumebounds",
   "web",
-  "whatsnew",
+  "width",
   "winopen",
   "winqueryreg",
   "workspace",
+  "writetable",
+  "xlsfinfo",
+  "xlsread",
+  "xlswrite",
   "xmlread",
   "xmlwrite",
   "xslt",
-  "zoom",
   };
 endfunction
 
--- a/scripts/help/doc.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/help/doc.m	Mon Jan 12 09:17:35 2015 -0800
@@ -42,7 +42,7 @@
 
     if (nargin == 1)
       ## Get the directory where the function lives.
-      ## FIXME -- maybe we should have a better way of doing this.
+      ## FIXME: Maybe we should have a better way of doing this?
 
       if (ischar (fname))
         ftype = exist (fname);
@@ -81,12 +81,13 @@
         info_file_name = info_file ();
 
         if (! exist (info_file_name, "file")
-            && ! exist ([info_file_name ".gz"], "file"))
+            && ! exist ([info_file_name ".gz"], "file")
+            && ! exist ([info_file_name ".bz2"], "file"))
           __gripe_missing_component__ ("doc", "info-file");
         endif
       endif
 
-      ## FIXME -- don't change the order of the arguments below because
+      ## FIXME: Don't change the order of the arguments below because
       ## the info-emacs-info script currently expects --directory DIR as
       ## the third and fourth arguments.  Someone should fix that.
 
--- a/scripts/help/doc_cache_create.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/help/doc_cache_create.m	Mon Jan 12 09:17:35 2015 -0800
@@ -55,6 +55,7 @@
 
   ## Save cache
   if (! isempty (cache))
+     save_header_format_string (["# doc-cache created by Octave " OCTAVE_VERSION], "local");
      save ("-text", out_file, "cache");
   endif
 
--- a/scripts/help/get_first_help_sentence.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/help/get_first_help_sentence.m	Mon Jan 12 09:17:35 2015 -0800
@@ -28,7 +28,7 @@
 ##
 ## The optional output argument @var{status} returns the status reported by
 ## @code{makeinfo}.  If only one output argument is requested, and @var{status}
-## is non-zero, a warning is displayed.
+## is nonzero, a warning is displayed.
 ##
 ## As an example, the first sentence of this help text is
 ##
--- a/scripts/help/help.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/help/help.m	Mon Jan 12 09:17:35 2015 -0800
@@ -20,9 +20,11 @@
 ## @deftypefn  {Command} {} help @var{name}
 ## @deftypefnx {Command} {} help @code{--list}
 ## @deftypefnx {Command} {} help @code{.}
-## Display the help text for @var{name}.  For example, the command
-## @kbd{help help} prints a short message describing the @code{help}
-## command.
+## @deftypefnx {Command} {} help
+## Display the help text for @var{name}.
+##
+## For example, the command @kbd{help help} prints a short message describing
+## the @code{help} command.
 ##
 ## Given the single argument @code{--list}, list all operators,
 ## keywords, built-in functions, and loadable functions available
@@ -34,10 +36,11 @@
 ## If invoked without any arguments, @code{help} display instructions
 ## on how to access help from the command line.
 ##
-## The help command can give you information about operators, but not the
-## comma and semicolons that are used as command separators.  To get help
-## for those, you must type @kbd{help comma} or @kbd{help semicolon}.
-## @seealso{doc, lookfor, which}
+## The help command can provide information about most operators, for example
+## @code{help +}, but not the comma and semicolon characters which are used
+## by the Octave interpreter as command separators.  For help on either of
+## these type @kbd{help comma} or @kbd{help semicolon}.
+## @seealso{doc, lookfor, which, info}
 ## @end deftypefn
 
 function retval = help (name)
@@ -69,21 +72,21 @@
   elseif (nargin == 1 && ischar (name))
 
     if (strcmp (name, "--list"))
-      tmp = do_list_functions ();
+      list = do_list_functions ();
       if (nargout == 0)
-        printf ("%s", tmp);
+        printf ("%s", list);
       else
-        retval = tmp;
+        retval = list;
       endif
       return;
     endif
 
     if (strcmp (name, "."))
-      tmp = do_list_operators ();
+      list = do_list_operators ();
       if (nargout == 0)
-        printf ("%s", tmp);
+        printf ("%s", list);
       else
-        retval = tmp;
+        retval = list;
       endif
       return;
     endif
@@ -129,7 +132,7 @@
 function retval = do_list_operators ()
   
   retval = sprintf ("*** operators:\n\n%s\n\n",
-                       list_in_columns (__operators__ ()));
+                    list_in_columns (__operators__ ()));
 endfunction
 
 function retval = do_list_functions ()
@@ -163,7 +166,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"));
@@ -207,5 +210,10 @@
 
 
 %!assert (! isempty (strfind (help ("ls"), "List directory contents")))
+%!assert (! isempty (strfind (help ("."), "||")))
+
+## Test input validation
 %!error <invalid input> help (42)
+%!error <invalid input> help ("abc", "def")
+%!error <'_!UNLIKELY_FCN!_' not found> help ("_!UNLIKELY_FCN!_")
 
--- a/scripts/help/which.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/help/which.m	Mon Jan 12 09:17:35 2015 -0800
@@ -28,9 +28,21 @@
   if (nargin > 0 && iscellstr (varargin))
     m = __which__ (varargin{:});
 
+    ## Check whether each name is a variable, variables take precedence over
+    ## functions in name resolution.
+    for i = 1:nargin
+      m(i).is_variable = evalin ("caller",
+                                 ["exist (\"" m(i).name "\", \"var\")"], false);
+      if (m(i).is_variable)
+        m(i).file = "variable";
+      endif
+    endfor
+
     if (nargout == 0)
       for i = 1:nargin
-        if (isempty (m(i).file))
+        if (m(i).is_variable)
+          printf ("'%s' is a variable\n", m(i).name);
+        elseif (isempty (m(i).file))
           if (! isempty (m(i).type))
             printf ("'%s' is a %s\n",
                     m(i).name, m(i).type);
@@ -64,3 +76,17 @@
 
 %!assert (which ("_NO_SUCH_NAME_"), "")
 
+%!test
+%! x = 3;
+%! str = which ("x");
+%! assert (str, "variable");
+
+%!test
+%! str = which ("amd");
+%! assert (str(end-6:end), "amd.oct");
+%! amd = 12;
+%! str = which ("amd");
+%! assert (str, "variable");
+%! clear amd;
+%! str = which ("amd");
+%! assert (str(end-6:end), "amd.oct");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/image/cubehelix.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,81 @@
+## Copyright (C) 2014 Carnë Draug
+##
+## 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{map} =} cubehelix ()
+## @deftypefnx {Function File} {@var{map} =} cubehelix (@var{n})
+## Create cubehelix colormap.
+##
+## This colormap varies from black to white going though blue, green, and red
+## tones while maintaining a monotonically increasing perception of intensity.
+## This is achieved by transversing a color cube from black to white through
+## a helix, hence the name cubehelix, while taking into account the perceived
+## brightness of each channel according to the NTSC specifications from 1953.
+##
+## @example
+## rgbplot (cubehelix (256))
+## @end example
+##
+## The argument @var{n} must be a scalar and corresponds to the lenght of the
+## colormap.  Defaults to the length of the current colormap.
+##
+## Development of this colormap is described in @cite{Green, D. A., 2011,
+## "A colour scheme for the display of astronomical intensity images",
+## Bulletin of the Astronomical Society of India, 39, 289.}.
+##
+## @seealso{colormap}
+## @end deftypefn
+
+## Author: Carnë Draug <carandraug@octave.org>
+
+## PKG_ADD: colormap ("register", "cubehelix");
+## PKG_DEL: colormap ("unregister", "cubehelix");
+
+function map = cubehelix (n = rows (colormap ()), start = 0.5,
+                          rots = -1.5, hue = 1, gamma = 1)
+
+  if (nargin > 5)
+    print_usage ()
+  endif
+
+  if (! isscalar (n) || n < 1)
+    error ("cubehelix: N must be a positive scalar");
+  endif
+
+  coeff = [ -0.14861  -0.29227   1.97294
+             1.78277  -0.90649   0.00000];
+
+  fract = ((0:n-1) / (n-1))';
+  angle = 2 * pi * (start/3 + 1 + rots*fract);
+  fract = fract .^ gamma;
+  amp   = hue * fract .* (1-fract) /2;
+  warning ("off", "Octave:broadcast", "local");
+  map   = fract + amp .* ([cos(angle) sin(angle)] * coeff);
+
+  ## Clip values (only in case users have changed values of hue or gamma)
+  map(map < 0) = 0;
+  map(map > 1) = 1;
+
+endfunction
+
+%!demo
+%! subplot (1, 2, 1)
+%! rgbplot (cubehelix (256), "composite")
+%! subplot (1, 2, 2)
+%! rgbplot (cubehelix (256))
+
--- a/scripts/image/image.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/image/image.m	Mon Jan 12 09:17:35 2015 -0800
@@ -69,7 +69,7 @@
   
   do_new = true;
   if (nargin == 0)
-    img = imread ("default.img");
+    img = get (0, "defaultimagecdata");
     x = y = [];
   elseif (chararg == 1) 
     ## Low-Level syntax
@@ -111,6 +111,8 @@
       hax = newplot (hax);
     elseif (isempty (hax))
       hax = gca ();
+    else
+      hax = hax(1);
     endif
 
     htmp = __img__ (hax, do_new, x, y, img, varargin{chararg:end});
@@ -139,26 +141,20 @@
 
 function h = __img__ (hax, do_new, x, y, img, varargin)
 
-  ## FIXME: Hack for integer formats which use zero-based indexing
-  ##        Hack favors correctness of display over size of image in memory.
-  ##        True fix must be done in C++ code for renderer. 
-  if (ndims (img) == 2 && (isinteger (img) || islogical (img)))
-    img = single (img) + 1;
-  endif
-
   if (! isempty (img))
 
     if (isempty (x))
-      x = [1, columns(img)];
+      xdata = [];
+    else
+      xdata = x([1, end])(:).';  # (:).' is a hack to guarantee row vector
     endif
 
     if (isempty (y))
-      y = [1, rows(img)];
+      ydata = [];
+    else
+      ydata = y([1, end])(:).';
     endif
 
-    xdata = x([1, end])(:).';  # (:).' is a hack to guarantee row vector
-    ydata = y([1, end])(:).';
-
     if (numel (x) > 2 && numel (y) > 2)
       ## Test data for non-linear spacing which is unsupported
       tol = .01;  # 1% tolerance.  FIXME: this value was chosen without thought.
@@ -198,7 +194,7 @@
 
     endif  # ! isempty (img)
 
-    set (hax, "view", [0, 90], "ydir", "reverse", "layer", "bottom");
+    set (hax, "view", [0, 90], "ydir", "reverse", "layer", "top");
 
   endif  # do_new
 
@@ -225,4 +221,31 @@
 %!  h = image (-x, -y, img);
 %!  title ("image (-x, -y, img)");
 
+%!test
+%! ## test hidden properties x/ydatamode (bug #42121)
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   nx = 64; ny = 64;
+%!   cdata = rand (ny, nx)*127;
+%!   hi = image (cdata);             # x/ydatamode is auto
+%!   assert (get (hi, "xdata"), [1 nx])
+%!   assert (get (hi, "ydata"), [1 ny])
+%!   set (hi, "cdata", cdata(1:2:end, 1:2:end))
+%!   assert (get (hi, "xdata"), [1 nx/2])
+%!   assert (get (hi, "ydata"), [1 ny/2])
+%! 
+%!   set (hi, "xdata", [10 100])     # xdatamode is now manual
+%!   set (hi, "ydata", [10 1000])    # ydatamode is now manual
+%!   set (hi, "cdata", cdata)
+%!   assert (get (hi, "xdata"), [10 100])
+%!   assert (get (hi, "ydata"), [10 1000])
+%! 
+%!   set (hi, "ydata", [])           # ydatamode is now auto
+%!   set (hi, "cdata", cdata(1:2:end, 1:2:end))
+%!   assert (get (hi, "xdata"), [10 100])
+%!   assert (get (hi, "ydata"), [1 ny/2])
+%! unwind_protect_cleanup
+%!   close (hf)
+%! end_unwind_protect
+
 ## FIXME: Need %!tests for linear
--- a/scripts/image/imfinfo.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/image/imfinfo.m	Mon Jan 12 09:17:35 2015 -0800
@@ -18,8 +18,8 @@
 
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {@var{info} =} imfinfo (@var{filename})
-## @deftypefnx {Function File} {@var{info} =} imfinfo (@var{filename}, @var{ext})
 ## @deftypefnx {Function File} {@var{info} =} imfinfo (@var{url})
+## @deftypefnx {Function File} {@var{info} =} imfinfo (@dots{}, @var{ext})
 ## Read image information from a file.
 ##
 ## @code{imfinfo} returns a structure containing information about the image
@@ -148,14 +148,32 @@
 
 ## Author: Soren Hauberg <hauberg@gmail.com>
 
-function info = imfinfo (varargin)
+function info = imfinfo (filename, varargin)
   if (nargin < 1 || nargin > 2)
     print_usage ();
-  elseif (! ischar (varargin{1}))
+  elseif (! ischar (filename))
     error ("imfinfo: FILENAME must be a string");
-  elseif (nargin > 1 && ! ischar (varargin{2}))
+  elseif (nargin > 1 && ! ischar (ext))
     error ("imfinfo: EXT must be a string");
   endif
-  info = imageIO (@__imfinfo__, "info", varargin, varargin{:});
+  info = imageIO ("imfinfo", @__imfinfo__, "info", filename, varargin{:});
 endfunction
 
+## This test is the same as the similar one in imread. imfinfo must check
+## if file exists before calling __imfinfo_. This test confirm this.
+%!testif HAVE_MAGICK
+%! fmt = fmt_ori = imformats ("jpg");
+%! fmt.info = @true;
+%! error_thrown = false;
+%! imformats ("update", "jpg", fmt);
+%! unwind_protect
+%!   try
+%!     imread ("I sure hope this file does not exist.jpg");
+%!   catch
+%!     error_thrown = true;
+%!   end_try_catch
+%! unwind_protect_cleanup
+%!   imformats ("update", "jpg", fmt_ori);
+%! end_unwind_protect
+%! assert (error_thrown, true);
+
--- a/scripts/image/imformats.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/image/imformats.m	Mon Jan 12 09:17:35 2015 -0800
@@ -266,11 +266,10 @@
 endfunction
 
 function match = find_ext_idx (formats, ext)
-  ## FIXME: is matlab sensitive to file extensions?
   ## XXX: what should we do if there's more than one hit?
   ##      Should this function prevent the addition of
   ##      duplicated extensions?
-  match = cellfun (@(x) any (strcmp (x, ext)), {formats.ext});
+  match = cellfun (@(x) any (strcmpi (x, ext)), {formats.ext});
 endfunction
 
 function bool = isa_magick (coder, filename)
@@ -281,34 +280,68 @@
   end_try_catch
 endfunction
 
+## When imread or imfinfo are called, the file must exist or the
+## function defined by imformats will never be called.  Because
+## of this, we must create a file for the tests to work.
 
-## changing the function to read
+## changing the function that does the reading
 %!testif HAVE_MAGICK
-%! fmt = imformats ("jpg");
-%! fmt.read = @(x) size (x, 2);
-%! imformats ("update", "jpg", fmt);
-%! assert (imread ("this is 30 characters long.jpg"), 30);
+%! fname = [tempname() ".jpg"];
+%! def_fmt = imformats ();
+%! fid = fopen (fname, "w");
+%! unwind_protect
+%!   fmt = imformats ("jpg");
+%!   fmt.read = @numel;
+%!   imformats ("update", "jpg", fmt);
+%!   assert (imread (fname), numel (fname));
+%! unwind_protect_cleanup
+%!   fclose (fid);
+%!   unlink (fname);
+%!   imformats (def_fmt);
+%! end_unwind_protect
 
 ## adding a new format
 %!testif HAVE_MAGICK
-%! fmt = imformats ("jpg");
-%! fmt.ext = "junk";
-%! fmt.read = @(x) true();
-%! imformats ("add", fmt);
-%! assert (imread ("some file.junk"), true);
+%! fname = [tempname() ".new_fmt"];
+%! def_fmt = imformats ();
+%! fid = fopen (fname, "w");
+%! unwind_protect
+%!   fmt = imformats ("jpg"); # take jpg as template
+%!   fmt.ext = "new_fmt";
+%!   fmt.read = @() true ();
+%!   imformats ("add", fmt);
+%!   assert (imread (fname), true);
+%! unwind_protect_cleanup
+%!   fclose (fid);
+%!   unlink (fname);
+%!   imformats (def_fmt);
+%! end_unwind_protect
 
-## adding multiple formats in one way
+## adding multiple formats at the same time
 %!testif HAVE_MAGICK
-%! fmt = imformats ("jpg");
-%! fmt.ext = "junk1";
-%! fmt.read = @(x) true();
-%! fmt(2) = fmt(1);
-%! fmt(2).ext = "junk2";
-%! imformats ("add", fmt);
-%! assert (imread ("some file.junk1"), true);
-%! assert (imread ("some file.junk2"), true);
+%! fname1 = [tempname() ".new_fmt1"];
+%! fid1 = fopen (fname1, "w");
+%! fname2 = [tempname() ".new_fmt2"];
+%! fid2 = fopen (fname2, "w");
+%! def_fmt = imformats ();
+%! unwind_protect
+%!   fmt = imformats ("jpg"); # take jpg as template
+%!   fmt.ext = "new_fmt1";
+%!   fmt.read = @() true();
+%!   fmt(2) = fmt(1);
+%!   fmt(2).ext = "new_fmt2";
+%!   imformats ("add", fmt);
+%!   assert (imread (fname1), true);
+%!   assert (imread (fname2), true);
+%! unwind_protect_cleanup
+%!   fclose (fid1);
+%!   fclose (fid2);
+%!   unlink (fname1);
+%!   unlink (fname2);
+%!   imformats (def_fmt);
+%! end_unwind_protect
 
-## changing format
+## changing format and resetting back to default
 %!testif HAVE_MAGICK
 %! ori_fmt = mod_fmt = imformats ("jpg");
 %! mod_fmt.description = "Another description";
@@ -319,10 +352,15 @@
 %! new_fmt = imformats ("jpg");
 %! assert (new_fmt.description, ori_fmt.description);
 
-## FIXME: how to test for error together with testif?
-## update to an invalid format
-#%!testif HAVE_MAGICK
-#%! fmt = imformats ("jpg");
-#%! fmt = rmfield (fmt, "read");
-#%! error imformats ("update", "jpg", fmt);
+## updating to an invalid format should cause an error
+%!testif HAVE_MAGICK
+%! fmt = imformats ("jpg");
+%! fmt = rmfield (fmt, "read");
+%! error_thrown = false;
+%! try
+%!   imformats ("update", "jpg", fmt);
+%! catch
+%!   error_thrown = true;
+%! end_try_catch
+%! assert (error_thrown, true);
 
--- a/scripts/image/imread.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/image/imread.m	Mon Jan 12 09:17:35 2015 -0800
@@ -23,16 +23,16 @@
 
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {[@var{img}, @var{map}, @var{alpha}] =} imread (@var{filename})
-## @deftypefnx {Function File} {[@dots{}] =} imread (@var{filename}, @var{ext})
 ## @deftypefnx {Function File} {[@dots{}] =} imread (@var{url})
+## @deftypefnx {Function File} {[@dots{}] =} imread (@dots{}, @var{ext})
 ## @deftypefnx {Function File} {[@dots{}] =} imread (@dots{}, @var{idx})
 ## @deftypefnx {Function File} {[@dots{}] =} imread (@dots{}, @var{param1}, @var{val1}, @dots{})
 ## Read images from various file formats.
 ##
 ## Reads an image as a matrix from the file @var{filename}.  If there is
 ## no file @var{filename}, and @var{ext} was specified, it will look for
-## a file named @var{filename} and extension @var{ext}, i.e., a file named
-## @var{filename}.@var{ext}.
+## a file with the extension @var{ext}.  Finally, it will attempt to download
+## and read an image from @var{url}.
 ##
 ## The size and class of the output depends on the
 ## format of the image.  A color image is returned as an
@@ -75,7 +75,17 @@
 ## Controls the image region that is read.  Takes as value a cell array
 ## with two arrays of 3 elements @code{@{@var{rows} @var{cols}@}}.  The
 ## elements in the array are the start, increment and end pixel to be
-## read.  If the increment value is omitted, defaults to 1.
+## read.  If the increment value is omitted, defaults to 1.  For example,
+## the following are all equivalent:
+##
+## @example
+## @group
+## imread (filename, "PixelRegion", @{[200 600] [300 700]@});
+## imread (filename, "PixelRegion", @{[200 1 600] [300 1 700]@});
+## imread (filename)(200:600, 300:700);
+## @end group
+## @end example
+##
 ## @end table
 ##
 ## @seealso{imwrite, imfinfo, imformats}
@@ -88,23 +98,14 @@
 ## Author: Stefan van der Walt <stefan@sun.ac.za>
 ## Author: Andy Adler
 
-function [img, varargout] = imread (varargin)
+function [img, varargout] = imread (filename, varargin)
   if (nargin < 1)
     print_usage ();
-  elseif (! ischar (varargin{1}))
+  elseif (! ischar (filename))
     error ("imread: FILENAME must be a string");
   endif
-  ## In case the file format was specified as a separate argument we
-  ## do this. imageIO() will ignore the second part if filename on its
-  ## own is enough. And if the second argument was a parameter name instead
-  ## of an extension, it is still going to be passed to the next function
-  ## since we are passing the whole function input as well.
-  filename = {varargin{1}};
-  if (nargin > 1 && ischar (varargin {2}))
-    filename{2} = varargin{2};
-  endif
 
-  [img, varargout{1:nargout-1}] = imageIO (@__imread__, "read", filename, varargin{:});
+  [img, varargout{1:nargout-1}] = imageIO ("imread", @__imread__, "read", filename, varargin{:});
 endfunction
 
 
@@ -126,7 +127,7 @@
 %!   16,  28, 160,  16,   0, 197, 214,  13,  34,  74, ...
 %!  117, 213,  17,   0,   0,   0,   0,  73,  69,  78, ...
 %!   68, 174,  66,  96, 130];
-%! filename = [tmpnam() ".png"];
+%! filename = [tempname() ".png"];
 %! unwind_protect
 %!   fid = fopen (filename, "wb");
 %!   fwrite (fid, vpng);
@@ -139,3 +140,66 @@
 %! assert (A(:,:,2), uint8 ([0, 255, 0; 255,  28, 255; 0, 255, 0]));
 %! assert (A(:,:,3), uint8 ([0, 255, 0; 255,  36, 255; 0, 255, 0]));
 
+%!function [r, cmap, a] = write_and_read (w, varargin)
+%!  filename = [tempname() ".tif"];
+%!  unwind_protect
+%!    imwrite (w, filename);
+%!    [r, cmap, a] = imread (filename, varargin{:});
+%!  unwind_protect_cleanup
+%!    unlink (filename);
+%!  end_unwind_protect
+%!endfunction
+
+## test PixelRegion option
+%!testif HAVE_MAGICK
+%! w = randi (255, 100, 100, "uint8");
+%! [r, cmap, a] = write_and_read (w, "PixelRegion", {[50 70] [20 40]});
+%! assert (r, w(50:70, 20:40))
+%! [r, cmap, a] = write_and_read (w, "PixelRegion", {[50 2 70] [20 3 40]});
+%! assert (r, w(50:2:70, 20:3:40))
+
+## If a file does not exist, it's the job of imread to check the file
+## exists before sending it over to __imread__ or whatever function
+## is defined in imformats to handle that specific format.  This is the
+## same in imfinfo.  So in this test we replace one format in imformats
+## with something that will not give an error if the file is missing
+## and make sure we do get an error.
+%!testif HAVE_MAGICK
+%! fmt = fmt_ori = imformats ("jpg");
+%! fmt.read = @true;
+%! error_thrown = false;
+%! imformats ("update", "jpg", fmt);
+%! unwind_protect
+%!   try
+%!     imread ("I sure hope this file does not exist.jpg");
+%!   catch
+%!     error_thrown = true;
+%!   end_try_catch
+%! unwind_protect_cleanup
+%!   imformats ("update", "jpg", fmt_ori);
+%! end_unwind_protect
+%! assert (error_thrown, true);
+
+## make one of the formats read, return what it received as input to
+## confirm that the input parsing is working correcly
+%!testif HAVE_MAGICK
+%! fname = [tempname() ".jpg"];
+%! def_fmt = imformats ();
+%! fid = fopen (fname, "w");
+%! unwind_protect
+%!   fmt = imformats ("jpg");
+%!   fmt.read = @(varargin) varargin;
+%!   imformats ("update", "jpg", fmt);
+%!   assert (imread (fname), {fname});
+%!   assert (imread (fname, "jpg"), {fname});
+%!   assert (imread (fname(1:end-4), "jpg"), {fname});
+%!   extra_inputs = {"some", 89, i, {6 7 8}};
+%!   assert (imread (fname, extra_inputs{:}), {fname, extra_inputs{:}});
+%!   assert (imread (fname, "jpg", extra_inputs{:}), {fname, extra_inputs{:}});
+%!   assert (imread (fname(1:end-4), "jpg", extra_inputs{:}), {fname, extra_inputs{:}});
+%! unwind_protect_cleanup
+%!   fclose (fid);
+%!   unlink (fname);
+%!   imformats (def_fmt);
+%! end_unwind_protect
+
--- a/scripts/image/imshow.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/image/imshow.m	Mon Jan 12 09:17:35 2015 -0800
@@ -45,6 +45,9 @@
 ## @table @asis
 ## @item @qcode{"displayrange"}
 ## @var{value1} is the display range as described above.
+##
+## @item @qcode{"colormap"}
+## @var{value1} is the colormap to use when displaying an indexed image.
 ## 
 ## @item @qcode{"xdata"}
 ## If @var{value1} is a two element vector, it must contain horizontal axis
@@ -75,7 +78,7 @@
   endif
 
   display_range = NA;
-  true_color = false;
+  truecolor = false;
   indexed = false;
   xdata = ydata = [];
 
@@ -98,9 +101,9 @@
     endif
   elseif (size (im, 3) == 3)
     if (ismember (class (im), {"uint8", "uint16", "double", "single"}))
-      true_color = true;
+      truecolor = true;
     else
-      error ("imshow: color image must be uint8, uint16, double, or single");
+      error ("imshow: TrueColor image must be uint8, uint16, double, or single");
     endif
   else
     error ("imshow: expecting MxN or MxNx3 matrix for image");
@@ -114,34 +117,47 @@
         display_range = arg;
       elseif (columns (arg) == 3)
         indexed = true;
-        colormap (arg);
+        if (iscolormap (arg))
+          colormap (arg);
+        else
+          error ("imshow: invalid colormap MAP");
+        endif
       elseif (! isempty (arg))
-        error ("imshow: argument number %d is invalid", narg+1);
+        error ("imshow: argument number %d is invalid", narg);
       endif
     elseif (ischar (arg))
       switch (tolower (arg))
-        case "displayrange";
+        case "colormap"
+          map = varargin{narg++};
+          if (iscolormap (map))
+            colormap (map);
+          else
+            error ("imshow: invalid colormap");
+          endif
+        case "displayrange"
           display_range = varargin{narg++};
-        case "xdata";
+        case "parent"
+          warning ("imshow: parent argument is not implemented");
+        case {"truesize", "initialmagnification"}
+          warning ("image: zoom argument ignored -- use GUI features");
+        case "xdata"
           xdata = varargin{narg++};
           if (! isvector (xdata))
             error ("imshow: xdata must be a vector")
           endif
           xdata = [xdata(1) xdata(end)];
-        case "ydata";
+        case "ydata"
           ydata = varargin{narg++};
           if (! isvector (ydata))
-            error ("imshow: expect a vector for ydata")
+            error ("imshow: ydata must be a vector")
           endif
           ydata = [ydata(1) ydata(end)];
-        case {"truesize", "initialmagnification"}
-          warning ("image: zoom argument ignored -- use GUI features");
         otherwise
           warning ("imshow: unrecognized property %s", arg);
           narg++;
       endswitch
     else
-      error ("imshow: argument number %d is invalid", narg+1);
+      error ("imshow: argument number %d is invalid", narg);
     endif
   endwhile
 
@@ -159,46 +175,44 @@
     switch (t)
       case {"double", "single", "logical"}
         display_range = [0, 1];
-      case {"int8", "int16", "int32", "uint8", "uint16", "uint32"}
+      case {"uint8", "uint16", "int16"}
         display_range = [intmin(t), intmax(t)];
       otherwise
         error ("imshow: invalid data type for image");
     endswitch
   endif
 
-  nans = isnan (im(:));
-  if (any (nans))
-    warning ("Octave:imshow-NaN",
-             "imshow: pixels with NaN or NA values are set to minimum pixel value");
-    im(nans) = display_range(1);
-  endif
-
-  ## This is for compatibility.
-  if (! (indexed || (true_color && isinteger (im))) || islogical (im))
-    im = double (im);
+  if (isfloat (im))
+    nans = isnan (im(:));
+    if (any (nans))
+      warning ("Octave:imshow-NaN",
+               "imshow: pixels with NaN or NA values are set to minimum pixel value");
+      im(nans) = display_range(1);
+    endif
   endif
 
+  ## FIXME: Commented out 2014/05/01.  imagesc and 'clim' will automatically
+  ## take care of displaying out-of-range data clamped to the limits.
+  ## Eventually, this can be deleted if no problems arise.
   ## Clamp the image to the range boundaries
-  if (! (true_color || indexed || islogical (im)))
-    low = display_range(1);
-    high = display_range(2);
-    im(im < low) = low;
-    im(im > high) = high;
-  endif
+  ##if (! (truecolor || indexed || islogical (im)))
+  ##  low = display_range(1);
+  ##  high = display_range(2);
+  ##  im(im < low) = low;
+  ##  im(im > high) = high;
+  ##endif
 
-  if (true_color || indexed)
-    tmp = image (xdata, ydata, im);
+  if (truecolor || indexed)
+    htmp = image (xdata, ydata, im);
   else
-    tmp = image (xdata, ydata, im);
-    set (tmp, "cdatamapping", "scaled");
-    ## The backend is responsible for scaling to clim if necessary.
+    htmp = imagesc (xdata, ydata, im, display_range);
     set (gca (), "clim", display_range);
   endif
-  set (gca (), "visible", "off", "ydir", "reverse");
+  set (gca (), "visible", "off", "view", [0, 90], "ydir", "reverse", "layer", "top");
   axis ("image");
 
   if (nargout > 0)
-    h = tmp;
+    h = htmp;
   endif
 
 endfunction
@@ -244,5 +258,22 @@
 %% Test input validation
 %!error imshow ()
 %!error <IM must be an image> imshow ({"cell"})
+%!error <TrueColor image must be uint8> imshow (ones (3,3,3, "uint32"))
+%!error <TrueColor image must be uint8> imshow (ones (3,3,3, "int16"))
 %!error <expecting MxN or MxNx3 matrix> imshow (ones (4,4,4))
 
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   fail ("imshow ([1,1], [2 0 0])", "invalid colormap MAP");
+%!   fail ("imshow ([1,1], [1 0 0 0])", "argument number 2 is invalid"); 
+%!   fail ('imshow ([1,1], "colormap", [2 0 0])', "invalid colormap"); 
+%!   fail ('imshow ([1,1], "xdata", ones (2,2))', "xdata must be a vector"); 
+%!   fail ('imshow ([1,1], "ydata", ones (2,2))', "ydata must be a vector"); 
+%!   fail ('imshow ([1,1], "foobar")', "warning", "unrecognized property foobar")
+%!   fail ("imshow ([1,1], {1})", "argument number 2 is invalid"); 
+%!   fail ("imshow ([1+i,1-i])", "warning", "only showing real part of complex image");
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
--- a/scripts/image/imwrite.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/image/imwrite.m	Mon Jan 12 09:17:35 2015 -0800
@@ -49,7 +49,7 @@
 ##
 ## @item DelayTime
 ## For formats that accept animations (such as GIF), controls for how long a
-## frame is displayed until it moves to the next one. The value must be scalar
+## frame is displayed until it moves to the next one.  The value must be scalar
 ## (which will applied to all frames in @var{img}), or a vector of length
 ## equal to the number of frames in @var{im}.  The value is in seconds, must
 ## be between 0 and 655.35, and defaults to 0.5.
@@ -100,7 +100,7 @@
   fmt = imformats (ext);
   ## When there is no match, fmt will be a 1x1 structure with
   ## no fields, so we can't just use `isempty (fmt)'.
-  if (isempty (fieldnames (fmt)))
+  if (numfields (fmt) == 0)
     if (isempty (ext))
       error ("imwrite: no extension found for %s to identify the image format",
              filename);
@@ -126,7 +126,7 @@
 %!error imwrite (spones (2), "filename.jpg")  # Invalid sparse img
 
 %!function [r, cmap, a] = write_and_read (varargin)
-%!  filename = [tmpnam() ".tif"];
+%!  filename = [tempname() ".tif"];
 %!  unwind_protect
 %!    imwrite (varargin{1}, filename, varargin{2:end});
 %!    [r, cmap, a] = imread (filename, "Index", "all");
--- a/scripts/image/ind2gray.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/image/ind2gray.m	Mon Jan 12 09:17:35 2015 -0800
@@ -69,18 +69,19 @@
 
 %!shared i2g
 %! i2g = ind2gray (1:100, gray (100));
-%!assert (i2g, 0:1/99:1, eps);
-%!assert (gray2ind (i2g, 100), uint8 (0:99));
+%!
+%!assert (i2g, 0:1/99:1, eps)
+%!assert (gray2ind (i2g, 100), uint8 (0:99))
 
 %% Test input validation
 %!error ind2gray ()
 %!error ind2gray (1)
 %!error ind2gray (1,2,3)
-%!error <X must be an indexed image> ind2gray ({1}, jet (64))
+%!error <X must be an indexed image> ind2gray (ones (3,3,3), jet (64))
 %!error <X must be an indexed image> ind2gray (1+i, jet (64))
 %!error <X must be an indexed image> ind2gray (sparse (1), jet (64))
-%!error <X must be an indexed image> ind2gray (0, jet (64))
 %!error <X must be an indexed image> ind2gray (1.1, jet (64))
+%!error <X must be an indexed image> ind2gray ({1}, jet (64))
 %!error <MAP must be a valid colormap> ind2gray (1, {1})
 %!error <MAP must be a valid colormap> ind2gray (1, 1+i)
 %!error <MAP must be a valid colormap> ind2gray (1, ones (2,2,2))
@@ -88,3 +89,7 @@
 %!error <MAP must be a valid colormap> ind2gray (1, [-1])
 %!error <MAP must be a valid colormap> ind2gray (1, [2])
 
+%!warning <contains colors outside of colormap> ind2gray ([0 1 2], gray (5));
+%!warning <contains colors outside of colormap> ind2gray ([1 2 6], gray (5));
+%!warning <contains colors outside of colormap> ind2gray (uint8 ([1 2 5]), gray (5));
+
--- a/scripts/image/ind2rgb.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/image/ind2rgb.m	Mon Jan 12 09:17:35 2015 -0800
@@ -82,23 +82,28 @@
 %! ## test basic usage with 1 and 3 outputs
 %! [rgb] = ind2rgb (img, map);
 %! [r, g, b] = ind2rgb (img, map);
-%!assert (ergb, rgb);
-%!assert (ergb, reshape ([r(:) g(:) b(:)], [size(img) 3]));
+%!
+%!assert (ergb, rgb)
+%!assert (ergb, reshape ([r(:) g(:) b(:)], [size(img) 3]))
+%!test
 %! ## test correction for integers
-%! img = uint8 (img -1);
+%! img = uint8 (img - 1);
 %! [rgb] = ind2rgb (img, map);
-%!assert (ergb, rgb);
-%! ## check it fails when image is a float with an index value of 0
-%!fail ("[rgb] = ind2rgb (double(img), map)")
+%! assert (ergb, rgb);
+%!test
+%! ## Check that values below lower bound are mapped to first color value 
+%! rgb = ind2rgb ([-1 0 2], gray (64));
+%! assert (rgb(:,1:2,:), zeros (1,2,3));
+%! assert (rgb(:,3,:), 1/63 * ones (1,1,3));
 
 %% Test input validation
 %!error ind2rgb ()
 %!error ind2rgb (1,2,3)
-%!error <X must be an indexed image> ind2rgb ({1}, jet (64))
+%!error <X must be an indexed image> ind2rgb (ones (3,3,3), jet (64))
 %!error <X must be an indexed image> ind2rgb (1+i, jet (64))
 %!error <X must be an indexed image> ind2rgb (sparse (1), jet (64))
-%!error <X must be an indexed image> ind2rgb (0, jet (64))
 %!error <X must be an indexed image> ind2rgb (1.1, jet (64))
+%!error <X must be an indexed image> ind2rgb ({1}, jet (64))
 %!error <MAP must be a valid colormap> ind2rgb (1, {1})
 %!error <MAP must be a valid colormap> ind2rgb (1, 1+i)
 %!error <MAP must be a valid colormap> ind2rgb (1, ones (2,2,2))
@@ -106,3 +111,8 @@
 %!error <MAP must be a valid colormap> ind2rgb (1, [-1])
 %!error <MAP must be a valid colormap> ind2rgb (1, [2])
 
+%!warning <contains colors outside of colormap> ind2rgb ([-1 1], jet (64));
+%!warning <contains colors outside of colormap> ind2rgb ([0 1 2], gray (5));
+%!warning <contains colors outside of colormap> ind2rgb ([1 2 6], gray (5));
+%!warning <contains colors outside of colormap> ind2rgb (uint8 ([1 2 5]), gray (5));
+
--- a/scripts/image/private/__imfinfo__.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/image/private/__imfinfo__.m	Mon Jan 12 09:17:35 2015 -0800
@@ -17,56 +17,22 @@
 ## along with Octave; see the file COPYING.  If not, see
 ## <http://www.gnu.org/licenses/>.
 
-## This function does al the work of imfinfo. It exists here as private
+## This function does all the work of imfinfo. It exists here as private
 ## function so that imfinfo can use other functions if imformats is
 ## configured to. It is also needed so that imformats can create a
 ## function handle for it.
 
 ## Author: Soren Hauberg <hauberg@gmail.com>
 
-function info = __imfinfo__ (filename, ext)
+function info = __imfinfo__ (filename)
 
-  if (nargin < 1 || nargin > 2)
+  if (nargin != 1)
     print_usage ("imfinfo");
+  elseif (! ischar (filename))
+    error ("imfinfo: FILENAME must be a string");
   endif
 
-  if (! ischar (filename))
-    error ("imfinfo: FILENAME must be a string");
-  elseif (nargin >= 2 && ! ischar (ext))
-    error ("imfinfo: EXT must be a string");
-  endif
-  filename = tilde_expand (filename);
-
-  delete_file = false;
-  unwind_protect
-
-    fn = file_in_path (IMAGE_PATH, filename);
-    if (isempty (fn))
-      ## We couldn't find the file so...
-      if (nargin >= 2)
-        ## try adding a possible file extesion
-        filename  = [filename "." ext];
-        fn        = file_in_path (IMAGE_PATH, filename);
-        if (isempty (fn))
-          error ("imfinfo: cannot find file %s", filename);
-        endif
-      else
-        ## try filename as an URL
-        [fn, status, msg] = urlwrite (filename, tmpnam ());
-        if (! status)
-          error ("imfinfo: cannot find or download %s: %s", filename, msg);
-        endif
-        delete_file = true;
-      endif
-    endif
-
-    info = __magick_finfo__ (fn);
-
-  unwind_protect_cleanup
-    if (delete_file)
-      unlink (fn);
-    endif
-  end_unwind_protect
+  info = __magick_finfo__ (filename);
 
 endfunction
 
--- a/scripts/image/private/__imread__.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/image/private/__imread__.m	Mon Jan 12 09:17:35 2015 -0800
@@ -44,18 +44,6 @@
   ## keep track of the varargin offset we're looking at each moment
   offset    = 1;
 
-  filename  = tilde_expand (filename);
-  fn        = file_in_path (IMAGE_PATH, filename);
-  if (isempty (fn) && nargin >= offset + 1 && ischar (varargin{offset}))
-    ## if we can't find the file, check if the next input is the file extension
-    filename  = [filename "." varargin{offset}];
-    fn        = file_in_path (IMAGE_PATH, filename);
-    offset++;
-  endif
-  if (isempty (fn))
-    error ("imread: cannot find %s", filename);
-  endif
-
   ## It is possible for an file with multiple pages to have very different
   ## images on each page. Specifically, they may have different sizes. Because
   ## of this, we need to first find out the index of the images to read so
@@ -90,114 +78,62 @@
     endif
   endif
 
-  try
-    ## Use information from the first image to be read to set defaults.
-    if (ischar (options.index) && strcmpi (options.index, "all"))
-      info = __magick_ping__ (fn, 1);
-    else
-      info = __magick_ping__ (fn, options.index(1));
-    endif
+  ## Use information from the first image to be read to set defaults.
+  if (ischar (options.index) && strcmpi (options.index, "all"))
+    info = __magick_ping__ (filename, 1);
+  else
+    info = __magick_ping__ (filename, options.index(1));
+  endif
 
-    ## Set default for options.
-    options.region = {1:1:info.rows 1:1:info.columns};
+  ## Set default for options.
+  options.region = {1:1:info.rows 1:1:info.columns};
+
+  for idx = offset:2:(numel (varargin) - offset + 1)
+    switch (tolower (varargin{idx}))
 
-    for idx = offset:2:(numel (varargin) - offset + 1)
-      switch (tolower (varargin{idx}))
+      case {"frames", "index"}
+        ## Do nothing. This options were already processed before the loop.
 
-        case {"frames", "index"}
-          ## Do nothing. This options were already processed before the loop.
-
-        case "pixelregion",
-          options.region = varargin{idx+1};
-          if (! iscell (options.region) || numel (options.region) != 2)
-            error ("imread: value for %s must be a 2 element cell array",
+      case "pixelregion",
+        options.region = varargin{idx+1};
+        if (! iscell (options.region) || numel (options.region) != 2)
+          error ("imread: value for %s must be a 2 element cell array",
+                 varargin{idx});
+        endif
+        for reg_idx = 1:2
+          if (numel (options.region{reg_idx}) == 3)
+            ## do nothing
+          elseif (numel (options.region{reg_idx}) == 2)
+            options.region{reg_idx}(3) = options.region{reg_idx}(2);
+            options.region{reg_idx}(2) = 1;
+          else
+            error ("imread: range for %s must be a 2 or 3 element vector",
                    varargin{idx});
           endif
-          for reg_idx = 1:2
-            if (numel (options.region{reg_idx}) == 3)
-              ## do nothing
-            elseif (numel (options.region{reg_idx}) == 2)
-              options.region{reg_idx}(3) = options.region{reg_idx}(2);
-              options.region{reg_idx}(2) = 1;
-            else
-              error ("imread: range for %s must be a 2 or 3 element vector",
-                     varargin{idx});
-            endif
-            options.region{reg_idx} = floor (options.region{reg_idx}(1)): ...
-                                      floor (options.region{reg_idx}(2)): ...
-                                      floor (options.region{reg_idx}(3));
-          endfor
-          if (options.region{1}(end) > info.rows)
-            error ("imread: end ROWS for PixelRegions option is larger than image height");
-          elseif (options.region{2}(end) > info.columns)
-            error ("imread: end COLS for PixelRegions option is larger than image width");
-          endif
-
-        case "info",
-          ## We ignore this option. This parameter exists in Matlab to
-          ## speed up the reading of multipage TIFF by passing a structure
-          ## that contains information about the start on the file of each
-          ## page.  We can't control it through GraphicsMagic but at least
-          ## we allow to load multiple pages with one command.
-
-        otherwise
-          error ("imread: invalid PARAMETER `%s'", varargin{idx});
-
-      endswitch
-    endfor
-
-    [varargout{1:nargout}] = __magick_read__ (fn, options);
+          options.region{reg_idx} = floor (options.region{reg_idx}(1)): ...
+                                    floor (options.region{reg_idx}(2)): ...
+                                    floor (options.region{reg_idx}(3));
+        endfor
+        if (options.region{1}(end) > info.rows)
+          error ("imread: end ROWS for PixelRegions option is larger than image height");
+        elseif (options.region{2}(end) > info.columns)
+          error ("imread: end COLS for PixelRegions option is larger than image width");
+        endif
 
-  catch
-    ## If we can't read it with Magick, maybe the image is in Octave's
-    ## native image format.  This is from back before Octave had 'imread'
-    ## and 'imwrite'. Then we had the functions 'loadimage' and 'saveimage'.
-    ##
-    ## This "image format" seems to be any file that can be read with
-    ## load() and contains 2 variables.  The variable named "map" is a
-    ## colormap and must exist whether the image is indexed or not. The
-    ## other variable must be named "img" or "X" for a "normal" or
-    ## indexed image.
-    ##
-    ## FIXME: this has been deprecated for the next major release (3.8 or 4.0).
-    ##        If someone wants to revive this as yet another image format, a
-    ##        separate Octave package can be written for it, that register the
-    ##        format through imformats.
-
-    magick_error = lasterr ();
-
-    img_field = false;
-    x_field   = false;
-    map_field = false;
+      case "info",
+        ## We ignore this option. This parameter exists in Matlab to
+        ## speed up the reading of multipage TIFF by passing a structure
+        ## that contains information about the start on the file of each
+        ## page.  We can't control it through GraphicsMagic but at least
+        ## we allow to load multiple pages with one command.
 
-    try
-      vars = load (fn);
-      if (isstruct (vars))
-        img_field = isfield (vars, "img");
-        x_field   = isfield (vars, "X");
-        map_field = isfield (vars, "map");
-      endif
-    catch
-      error ("imread: invalid image file: %s", magick_error);
-    end_try_catch
+      otherwise
+        error ("imread: invalid PARAMETER `%s'", varargin{idx});
 
-    if (map_field && (img_field || x_field))
-      varargout{2} = vars.map;
-      if (img_field)
-        varargout{1} = vars.img;
-      else
-        varargout{1} = vars.X;
-      endif
-      persistent warned = false;
-      if (! warned)
-        warning ("Octave's native image format has been deprecated.");
-        warned = true;
-      endif
-    else
-      error ("imread: invalid Octave image file format");
-    endif
+    endswitch
+  endfor
 
-  end_try_catch
+  [varargout{1:nargout}] = __magick_read__ (filename, options);
 
 endfunction
 
@@ -205,10 +141,6 @@
 ## can be defined in two places, but only in one place can it also be the
 ## string "all"
 function bool = is_valid_index_option (arg)
-  ## is the index option
-  bool = false;
-  if (isvector (arg) && isnumeric (arg) && isreal (arg))
-    bool = true;
-  endif
+  bool = isvector (arg) && isnumeric (arg) && isreal (arg);
 endfunction
 
--- a/scripts/image/private/imageIO.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/image/private/imageIO.m	Mon Jan 12 09:17:35 2015 -0800
@@ -16,54 +16,111 @@
 ## along with Octave; see the file COPYING.  If not, see
 ## <http://www.gnu.org/licenses/>.
 
-## This function simply connects imread and imfinfo() to the function
-## to be used based on their format. It does it by checking the file extension
-## of the file and redirecting to the appropriate function after checking
-## with imformats.
+## This function the image input functions imread() and imfinfo() to the
+## functions that will actually be used, based on their format.  See below
+## on the details on how it identifies the format, and to what it defaults.
+##
+## It will change the input arguments that were passed to imread() and
+## imfinfo().  It will change the filename to provide the absolute filepath
+## for the file, it will extract the possible format name from the rest of
+## the input arguments (in case there was one), and will give an error if
+## the file can't be found.
 ##
-## First argument is a function handle for the default imageIO function (what
-## to use if the file extension for the image file is not listed by imformats).
-## Second argument is the fieldname in the struct returned by imformats with a
-## function handle for the function to use. Third argument is a cell array, its
-## first element the filename, and the second, an optional file extension to
-## add to filename, if filename alone does not exist. All the others are the
-## original input arguments passed to the original imageIO function which will
-## be passed on to the destination function.
+## Usage:
 ##
-## No input checking whatsoever is performed. That should be performed by the
-## function calling it.
-
-function varargout = imageIO (core_func, fieldname, filename, varargin)
+## func      - Function name to use on error message.
+## core_func - Function handle for the default function to use if we can't
+##             find the format in imformats.
+## fieldname - Name of the field in the struct returned by imformats that
+##             has the function to use.
+## filename  - Most likely the first input argument from the function that
+##             called this. May be missing the file extension which can be
+##             on varargin.
+## varargin  - Followed by all the OTHER arguments passed to imread and
+##             imfinfo.
 
-  ## It should not be this function job to check if the file exists or not.
-  ## However, we need to know the file extension to use with imformats and
-  ## that means we need to know the actual filename that will be used which
-  ## is dependent on whether a file exists.
-  ##
-  ## If a file named filename{1} exists, then that's it, we will use that
-  ## wether it has an extension or not. If it does not exist and we have
-  ## something in filename{2}, then we will consider it the file extension.
-  ## Note the detail that if we find a file using filename{1} only, then we
-  ## should completely ignore filename{2}. It won't even be used by
-  ## imformats() at all, even if filename{1} has no extension to use with
-  ## imformats().
-  if (isscalar (filename) || ! isempty (file_in_path (IMAGE_PATH, filename{1})))
-    [~, ~, ext] = fileparts (filename{1});
-    if (! isempty (ext))
-      ## remove dot from extension
-      ext = ext(2:end);
-    endif
-  else
-    ext = filename{2};
+function varargout = imageIO (func, core_func, fieldname, filename, varargin)
+
+  ## First thing: figure out the filename and possibly download it.
+  ## The first attempt is to try the filename and see if it exists.  If it
+  ## does not, we try to add the next argument since the file extension can
+  ## be given as a separate argument.  If we still can't find the file, it
+  ## can be a URL.  Lastly, if we still didn't found a file, try adding the
+  ## extension to the URL
+
+  file_2_delete = false;  # will we have to remove the file in the end?
+  persistent abs_path = @(x) file_in_path (IMAGE_PATH, tilde_expand (x));
+
+  ## Filename was given with file extension
+  fn = abs_path (filename);
+  if (isempty (fn) && ! isempty (varargin))
+    ## Maybe if we add a file extension
+    fn = abs_path ([filename "." varargin{1}]);
   endif
 
-  fmt = imformats (ext);
-  ## When there is no match, fmt will be a 1x1 structure with no fields,
-  ## so we can't just use `isempty (fmt)'.
-  if (isempty (fieldnames (fmt)))
-    [varargout{1:nargout}] = core_func (varargin{:});
-  else
-    [varargout{1:nargout}] = fmt.(fieldname) (varargin{:});
+  ## Maybe we have an URL
+  if (isempty (fn))
+    file_2_delete = true; # mark file for deletion
+    [fn, ~] = urlwrite (filename, tempname ());
+    ## Maybe the URL is missing the file extension
+    if (isempty (fn) && ! isempty (varargin))
+      [fn, ~] = urlwrite ([filename "." varargin{1}], tempname ());
+    endif
+
+    if (isempty (fn))
+      error ("%s: unable to find file %s", func, filename);
+    endif
   endif
+
+  ## unwind_protect block because we may have a file to remove in the end
+  unwind_protect
+
+    ## When guessing the format to use, we first check if the second
+    ## argument is a format defined in imformats.  If so, we remove it
+    ## from the rest of arguments before passing them on.  If not, we
+    ## try to guess the format from the file extension.  Finally, if
+    ## we still don't know the format, we use the Octave core functions
+    ## which is the same for all formats.
+    foo = []; # the function we will use
+
+    ## We check if the call to imformats (ext) worked using
+    ## "numfields (fmt) > 0 because when it fails, the returned
+    ## struct is not considered empty.
+
+    ## try the second input argument
+    if (! isempty (varargin) && ischar (varargin{1}))
+      fmt = imformats (varargin{1});
+      if (numfields (fmt) > 0)
+        foo = fmt.(fieldname);
+        varargin(1) = []; # remove format name from arguments
+      endif
+    endif
+
+    ## try extension from file name
+    if (isempty (foo))
+      [~, ~, ext] = fileparts (fn);
+      if (! isempty (ext))
+        ## remove dot from extension
+        ext = ext(2:end);
+      endif
+      fmt = imformats (ext);
+      if (numfields (fmt) > 0)
+        foo = fmt.(fieldname);
+      endif
+    endif
+
+    ## use the core function
+    if (isempty (foo))
+      foo = core_func;
+    endif
+
+    [varargout{1:nargout}] = foo (fn, varargin{:});
+
+  unwind_protect_cleanup
+    if (file_2_delete)
+      unlink (fn);
+    endif
+  end_unwind_protect
+
 endfunction
 
--- a/scripts/image/private/ind2x.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/image/private/ind2x.m	Mon Jan 12 09:17:35 2015 -0800
@@ -22,12 +22,13 @@
 function [x, map] = ind2x (caller, x, map)
 
   ## Check if X is an indexed image.
-  ## an indexed image is defined has having only 2D, and that's how Matlab
+  ## An indexed image is defined has having only 2D, and that's how Matlab
   ## behaves.  But we want to support ND images, so we will allow up to 4D
-  ## and check that the 3rd is a singleton
-  if (all (ndims (x) != [2 4]) || size (x, 3) != 1 || issparse (x) ||
-      (isfloat (x) && ! isindex (x)) ||
-      ! any (strcmp (class (x), {"uint8", "uint16", "single", "double"})))
+  ## and check that the 3rd dimension is a singleton.
+  if (all (ndims (x) != [2 4]) || size (x, 3) != 1
+      || iscomplex (x) || issparse (x)
+      || (isfloat (x) && x != fix (x))
+      || ! any (strcmp (class (x), {"uint8", "uint16", "single", "double"})))
     error ("%s: X must be an indexed image", caller);
   endif
 
@@ -36,10 +37,20 @@
     error ("%s: MAP must be a valid colormap", caller);
   endif
 
-  ## Do we have enough colors in the color map?
-  ## there's an offset of 1 when the indexed image is an integer class so we fix
-  ## it now and convert it to float only if really necessary and even then only
-  ## to single precision since that is enough for both uint8 and uint16.
+  ## Any color indices below the lower bound of the color map are modified
+  ## to point to the first color in the map (see bug #41851).
+  if (isfloat (x))
+    invalid_idx = x < 1;
+    if (any (invalid_idx(:)))
+      warning (["Octave:" caller ":invalid-idx-img"],
+               [caller ": indexed image contains colors outside of colormap"]);
+      x(invalid_idx) = 1;
+    endif
+  endif
+
+  ## Switch to using 1-based indexing.
+  ## It is possible that an integer storage class may not have enough room
+  ## to make the switch, in which case we convert the data to single.
   maxidx = max (x(:));
   if (isinteger (x))
     if (maxidx == intmax (class (x)))
@@ -49,9 +60,12 @@
     maxidx += 1;
   endif
 
+  ## When there are more colors in the image, than there are in the map,
+  ## pad the colormap with the last color in the map for Matlab compatibility.
   num_colors = rows (map);
   if (num_colors < maxidx)
-    ## Pad with the last color in the map for Matlab compatibility
+    warning (["Octave:" caller ":invalid-idx-img"],
+             [caller ": indexed image contains colors outside of colormap"]);
     pad = repmat (map(end,:), maxidx - num_colors, 1);
     map(end+1:maxidx, :) = pad;
   endif
--- a/scripts/io/csvwrite.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/io/csvwrite.m	Mon Jan 12 09:17:35 2015 -0800
@@ -37,7 +37,7 @@
 
 
 %!shared fname
-%! fname = tmpnam ();
+%! fname = tempname ();
 
 %!test
 %! csvwrite (fname, magic (3));
--- a/scripts/io/dlmwrite.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/io/dlmwrite.m	Mon Jan 12 09:17:35 2015 -0800
@@ -201,7 +201,7 @@
 
 
 %!test
-%! f = tmpnam ();
+%! f = tempname ();
 %! dlmwrite (f,[1,2;3,4],"precision","%5.2f","newline","unix","roffset",1,"coffset",1);
 %! fid = fopen (f,"rt");
 %! f1 = char (fread (fid,Inf,"char")');
--- a/scripts/io/fileread.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/io/fileread.m	Mon Jan 12 09:17:35 2015 -0800
@@ -48,7 +48,7 @@
 
 %!test
 %! cstr = {"Hello World", "The answer is 42", "Goodbye World"};
-%! fname = tmpnam ();
+%! fname = tempname ();
 %! fid = fopen (fname, "w");
 %! fprintf (fid, "%s\n", cstr{:});
 %! fclose (fid);
--- a/scripts/io/importdata.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/io/importdata.m	Mon Jan 12 09:17:35 2015 -0800
@@ -146,8 +146,7 @@
     ## i.e., output = output.onlyFieldLeft
 
     ## Update the list of fields
-    fields = fieldnames (output);
-    if (numel (fields) == 1)
+    if (numfields (output) == 1)
       output = output.(fields{1});
     endif
   endif
@@ -210,11 +209,33 @@
 
   endwhile
 
-  fclose (fid);
+  if (row == -1)
+    ## No numeric data found => return file as cellstr array
+    ## 1. Read as char string
+    fseek (fid, 0, "bof");
+    output = fread (fid, Inf, "*char")';
+    fclose (fid);
+    ## 2. Find EOL type
+    idx = find (output(1:min (4096, length (output))) == "\n", 1) - 1;
+    if (isindex (idx) && output(idx) == "\r")
+      dlm = "\r\n";
+    else
+      dlm = "\n";
+    endif
+    ## 3. Split each line into a cell (column vector)
+    output = strsplit (output, dlm)';
+    ## 4. Remove last cell (for files with -proper- EOL before EOF)
+    if (isempty (output{end}))
+      output(end) = [];
+    endif
+    ## 5. Return after setting some output data
+    delimiter = "";
+    header_rows = numel (output);
+    return;
+  else
+    fclose (fid);
+  endif
 
-  if (row == -1)
-    error ("importdata: Unable to determine delimiter");
-  endif
   if (num_header_rows >= 0)
     header_rows = num_header_rows;
   endif
@@ -271,7 +292,7 @@
 %!test
 %! ## Comma separated values
 %! A = [3.1 -7.2 0; 0.012 6.5 128];
-%! fn  = tmpnam ();
+%! fn  = tempname ();
 %! fid = fopen (fn, "w");
 %! fputs (fid, "3.1,-7.2,0\n0.012,6.5,128");
 %! fclose (fid);
@@ -288,7 +309,7 @@
 %!test
 %! ## Tab separated values
 %! A = [3.1 -7.2 0; 0.012 6.5 128];
-%! fn  = tmpnam ();
+%! fn  = tempname ();
 %! fid = fopen (fn, "w");
 %! fputs (fid, "3.1\t-7.2\t0\n0.012\t6.5\t128");
 %! fclose (fid);
@@ -305,7 +326,7 @@
 %!test
 %! ## Space separated values, using multiple spaces to align in columns.
 %! A = [3.1 -7.2 0; 0.012 6.5 128];
-%! fn  = tmpnam ();
+%! fn  = tempname ();
 %! fid = fopen (fn, "w");
 %! fprintf (fid, "%10.3f %10.3f %10.3f\n", A');
 %! fclose (fid);
@@ -322,7 +343,7 @@
 %!test
 %! ## No separator, 1 column of data only
 %! A = [3.1;-7.2;0;0.012;6.5;128];
-%! fn  = tmpnam ();
+%! fn  = tempname ();
 %! fid = fopen (fn, "w");
 %! fprintf (fid, "%f\n", A);
 %! fclose (fid);
@@ -342,7 +363,7 @@
 %! A.textdata = {"This is a header row."; ...
 %!               "this row does not contain any data, but the next one does."};
 %! A.colheaders = A.textdata (2);
-%! fn  = tmpnam ();
+%! fn  = tempname ();
 %! fid = fopen (fn, "w");
 %! fprintf (fid, "%s\n", A.textdata{:});
 %! fputs (fid, "3.1\t-7.2\t0\n0.012\t6.5\t128");
@@ -359,7 +380,7 @@
 %! A.textdata = {"Label1\tLabel2\tLabel3";
 %!               "col 1\tcol 2\tcol 3"};
 %! A.colheaders = {"col 1", "col 2", "col 3"};
-%! fn  = tmpnam ();
+%! fn  = tempname ();
 %! fid = fopen (fn, "w");
 %! fprintf (fid, "%s\n", A.textdata{:});
 %! fputs (fid, "3.1\t-7.2\t0\n0.012\t6.5\t128");
@@ -375,7 +396,7 @@
 %! A.data = [3.1 -7.2 0; 0.012 6.5 128];
 %! A.textdata = {"row1"; "row2"};
 %! A.rowheaders = A.textdata;
-%! fn  = tmpnam ();
+%! fn  = tempname ();
 %! fid = fopen (fn, "w");
 %! fputs (fid, "row1\t3.1\t-7.2\t0\nrow2\t0.012\t6.5\t128");
 %! fclose (fid);
@@ -392,7 +413,7 @@
 %!               "      col1 col2 col3"
 %!               "row1"
 %!               "row2"};
-%! fn  = tmpnam ();
+%! fn  = tempname ();
 %! fid = fopen (fn, "w");
 %! fprintf (fid, "%s\n", A.textdata{1:2});
 %! fputs (fid, "row1\t3.1\t-7.2\t0\nrow2\t0.012\t6.5\t128");
@@ -406,7 +427,7 @@
 %!test
 %! ## Ignore empty rows containing only spaces
 %! A = [3.1 -7.2 0; 0.012 6.5 128];
-%! fn  = tmpnam ();
+%! fn  = tempname ();
 %! fid = fopen (fn, "w");
 %! fprintf (fid, "%10.3f %10.3f %10.3f\n", A(1,:));
 %! fputs (fid, "      ");
@@ -421,7 +442,7 @@
 %!test
 %! ## Exponentials
 %! A = [3.1 -7.2 0; 0.012 6.5 128];
-%! fn  = tmpnam ();
+%! fn  = tempname ();
 %! fid = fopen (fn, "w");
 %! fputs (fid, "+3.1e0\t-72E-1\t0\n12e-3\t6.5\t128");
 %! fclose (fid);
@@ -434,7 +455,7 @@
 %!test
 %! ## Complex numbers
 %! A = [3.1 -7.2 0-3.4i; 0.012 -6.5+7.2i 128];
-%! fn  = tmpnam ();
+%! fn  = tempname ();
 %! fid = fopen (fn, "w");
 %! fputs (fid, "3.1\t-7.2\t0-3.4i\n0.012\t-6.5+7.2i\t128");
 %! fclose (fid);
@@ -447,7 +468,7 @@
 %!test
 %! ## Exceptional values (Inf, NaN, NA)
 %! A = [3.1 Inf NA; -Inf NaN 128];
-%! fn  = tmpnam ();
+%! fn  = tempname ();
 %! fid = fopen (fn, "w");
 %! fputs (fid, "3.1\tInf\tNA\n-Inf\tNaN\t128");
 %! fclose (fid);
@@ -462,7 +483,7 @@
 %! A.data = [3.1 NA 0; 0.012 NA 128];
 %! A.textdata = {char(zeros(1,0))
 %!               "NO DATA"};
-%! fn  = tmpnam ();
+%! fn  = tempname ();
 %! fid = fopen (fn, "w");
 %! fputs (fid, "3.1\t\t0\n0.012\tNO DATA\t128");
 %! fclose (fid);
@@ -475,7 +496,7 @@
 %!#test
 %! ## CRLF for line breaks
 %! A = [3.1 -7.2 0; 0.012 6.5 128];
-%! fn  = tmpnam ();
+%! fn  = tempname ();
 %! fid = fopen (fn, "w");
 %! fputs (fid, "3.1\t-7.2\t0\r\n0.012\t6.5\t128");
 %! fclose (fid);
@@ -488,7 +509,7 @@
 %!#test
 %! ## CR for line breaks
 %! A = [3.1 -7.2 0; 0.012 6.5 128];
-%! fn  = tmpnam ();
+%! fn  = tempname ();
 %! fid = fopen (fn, "w");
 %! fputs (fid, "3.1\t-7.2\t0\r0.012\t6.5\t128");
 %! fclose (fid);
@@ -510,6 +531,30 @@
 %! assert (d, " ");
 %! assert (h, 0);
 
+%!test
+%! ## Only text / no numeric data; \n as EOL
+%! fn  = tempname ();
+%! fid = fopen (fn, "w");
+%! fputs (fid, "aaaa 11\nbbbbb 22\nccccc 3\n");
+%! fclose (fid);
+%! [a, d, h] = importdata (fn);
+%! unlink (fn);
+%! assert (a, {"aaaa 11"; "bbbbb 22"; "ccccc 3"});
+%! assert (d, "");
+%! assert (h, 3);
+
+%!test
+%! ## Only text / no numeric data; \r\n as EOL; missing last EOL before EOF
+%! fn  = tempname ();
+%! fid = fopen (fn, "w");
+%! fputs (fid, "aaaa 11\r\nbbbbb 22\r\nccccc 3");
+%! fclose (fid);
+%! [a, d, h] = importdata (fn);
+%! unlink (fn);
+%! assert (a, {"aaaa 11"; "bbbbb 22"; "ccccc 3"});
+%! assert (d, "");
+%! assert (h, 3);
+
 %!error importdata ()
 %!error importdata (1,2,3,4)
 %!error <FNAME must be a string> importdata (1)
--- a/scripts/io/is_valid_file_id.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/io/is_valid_file_id.m	Mon Jan 12 09:17:35 2015 -0800
@@ -19,7 +19,7 @@
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} is_valid_file_id (@var{fid})
 ## Return true if @var{fid} refers to an open file.
-## @seealso{fopen}
+## @seealso{freport, fopen}
 ## @end deftypefn
 
 function retval = is_valid_file_id (fid)
--- a/scripts/io/strread.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/io/strread.m	Mon Jan 12 09:17:35 2015 -0800
@@ -197,10 +197,12 @@
   endif
 
   ## Parse format string to compare number of conversion fields and nargout
-  nfields = length (strfind (format, "%")) - length (strfind (format, "%*"));
+  nfields = numel (regexp (format, '(%(\d*|\d*\.\d*)?[nfduscq]|%\[)', "match"));
   ## If str only has numeric fields, a (default) format ("%f") will do.
   ## Otherwise:
-  if ((max (nargout, 1) != nfields) && ! strcmp (format, "%f"))
+  if (! nfields)
+    error ("strread.m: no valid format conversion specifiers found\n");
+  elseif ((max (nargout, 1) != nfields) && ! strcmp (format, "%f"))
     error ("strread: the number of output variables must match that specified by FORMAT");
   endif
 
@@ -249,8 +251,8 @@
             elseif (iscellstr (varargin{n+1}) && numel (varargin{n+1}) == 2)
               [comment_start, comment_end] = deal (varargin{n+1}{:});
             else
-              ## FIXME - a user may have numeric values specified: {'//', 7}
-              ##         this will lead to an error in the warning message
+              ## FIXME: A user may have numeric values specified: {'//', 7}
+              ##        this will lead to an error in the warning message
               error ("strread: unknown or unrecognized comment style '%s'",
                       varargin{n+1});
             endif
@@ -304,7 +306,8 @@
     fmt_words = regexp (format, '[^ ]+', "match");
     
     ## Find position of conversion specifiers (they start with %)
-    idy2 = find (! cellfun ("isempty", regexp (fmt_words, '^%')));
+    fcs_ptrn = '(%\*?(\d*|\d*\.\d*)?[nfduscq]|%\*?\[)';
+    idy2 = find (! cellfun ("isempty", regexp (fmt_words, fcs_ptrn)));
 
     ## Check for unsupported format specifiers
     errpat = '(\[.*\]|[cq]|[nfdu]8|[nfdu]16|[nfdu]32|[nfdu]64)';
@@ -690,8 +693,8 @@
       endif
 
       ## Map to format
-      ## FIXME - add support for formats like "<%s>", "%[a-zA-Z]"
-      ##         Someone with regexp experience is needed.
+      ## FIXME: Add support for formats like "<%s>", "%[a-zA-Z]"
+      ##        Someone with regexp experience is needed.
       switch (fmt_words{m}(1:min (2, length (fmt_words{m}))))
         case "%s"
           if (pad_out)
@@ -701,7 +704,7 @@
           k++;
         case {"%d", "%u", "%f", "%n"}
           n = cellfun ("isempty", data);
-          ### FIXME - erroneously formatted data lead to NaN, not an error
+          ### FIXME: Erroneously formatted data lead to NaN, not an error
           data = str2double (data);
           if (! isempty (regexp (fmt_words{m}, "%[du]")))
             ## Cast to integer
@@ -722,8 +725,8 @@
           switch (fmt_words{m}(ew+1))
             case {"d", "u", "f", "n"}
               n = cellfun ("isempty", data);
-              ### FIXME - erroneously formatted data lead to NaN, not an error
-              ###         => ReturnOnError can't be implemented for numeric data
+              ### FIXME: Erroneously formatted data lead to NaN, not an error
+              ###        => ReturnOnError can't be implemented for numeric data
               data = str2double (strtrunc (data, swidth));
               data(n) = numeric_fill_value;
               if (pad_out)
@@ -1034,5 +1037,8 @@
 
 %% Illegal format specifiers
 %!test
-%!error <unknown format specifier> strread ("1.0", "%z")
+%!error <no valid format conversion specifiers> strread ("1.0", "%z");
 
+%% Test for false positives in check for non-supported format specifiers
+%!test
+%! assert (strread ("Total: 32.5 % (of cm values)","Total: %f % (of cm values)"), 32.5, 1e-5);
--- a/scripts/io/textread.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/io/textread.m	Mon Jan 12 09:17:35 2015 -0800
@@ -135,7 +135,7 @@
   endif
  
   ## Now that we know what EOL looks like, we can process format_repeat_count.
-  ## FIXME The below isn't ML-compatible: counts lines, not format string uses
+  ## FIXME: The below isn't ML-compatible: counts lines, not format string uses
   if (isfinite (nlines) && (nlines > 0))
     l_eol_char = length (eol_char);
     eoi = findstr (str, eol_char);
@@ -221,7 +221,7 @@
 
 
 %!test
-%! f = tmpnam ();
+%! f = tempname ();
 %! d = rand (5, 3);
 %! dlmwrite (f, d, "precision", "%5.2f");
 %! [a, b, c] = textread (f, "%f %f %f", "delimiter", ",", "headerlines", 3);
@@ -231,7 +231,7 @@
 %! assert (c, d(4:5, 3), 1e-2);
 
 %!test
-%! f = tmpnam ();
+%! f = tempname ();
 %! d = rand (7, 2);
 %! dlmwrite (f, d, "precision", "%5.2f");
 %! [a, b] = textread (f, "%f, %f", "headerlines", 1);
@@ -240,7 +240,7 @@
 
 %% Test reading 2D matrix with empty format
 %!test
-%! f = tmpnam ();
+%! f = tempname ();
 %! d = rand (5, 2);
 %! dlmwrite (f, d, "precision", "%5.2f");
 %! A = textread (f, "", "headerlines", 3);
@@ -249,7 +249,7 @@
 
 %% Read multiple lines using empty format string
 %!test
-%! f = tmpnam ();
+%! f = tempname ();
 %! unlink (f);
 %! fid = fopen (f, "w");
 %! d = rand (1, 4);
@@ -261,7 +261,7 @@
 
 %% Empty format, corner case = one line w/o EOL
 %!test
-%! f = tmpnam ();
+%! f = tempname ();
 %! unlink (f);
 %! fid = fopen (f, "w");
 %! d = rand (1, 4);
@@ -273,7 +273,7 @@
 
 %% Read multiple lines using empty format string, missing data (should be 0)
 %!test
-%! f = tmpnam ();
+%! f = tempname ();
 %! unlink (f);
 %! fid = fopen (f, "w");
 %! d = rand (1, 4);
@@ -285,7 +285,7 @@
 
 %% Test with empty positions - ML returns 0 for empty fields
 %!test
-%! f = tmpnam ();
+%! f = tempname ();
 %! unlink (f);
 %! fid = fopen (f, "w");
 %! d = rand (1, 4);
@@ -298,7 +298,7 @@
 %% Another test with empty format + positions, now with more incomplete lower
 %% row (must be appended with zeros to get rectangular matrix)
 %!test
-%! f = tmpnam ();
+%! f = tempname ();
 %! unlink (f);
 %! fid = fopen (f, "w");
 %! d = rand (1, 4);
--- a/scripts/io/textscan.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/io/textscan.m	Mon Jan 12 09:17:35 2015 -0800
@@ -98,7 +98,10 @@
   endif
 
   ## Determine the number of data fields & initialize output array
-  num_fields = numel (strfind (format, "%")) - numel (strfind (format, "%*"));
+  num_fields = numel (regexp (format, '(%(\d*|\d*\.\d*)?[nfduscq]|%\[)', "match"));
+  if (! num_fields)
+    error ("textscan.m: no valid format conversion specifiers found\n");
+  endif
   C = cell (1, num_fields);
 
   if (! (isa (fid, "double") && fid > 0) && ! ischar (fid))
@@ -316,18 +319,20 @@
       ## See if lowermost data row must be completed
       pad = mod (numel (C{1}), ncols);
       if (pad)
-        ## Textscan returns NaNs for empty fields
-        C(1) = [C{1}; NaN(ncols - pad, 1)]; 
-      endif
-      ## Replace NaNs with EmptyValue, if any
-      ipos = find (strcmpi (args, "emptyvalue"));
-      if (ipos)
-        C{1}(find (isnan (C{1}))) = args{ipos+1};
+        ## Pad output with emptyvalues (rest has been done by stread.m)
+        emptv = find (strcmpi (args, "emptyvalue"));
+        if (isempty (emptv))
+          ## By default textscan returns NaNs for empty fields
+          C(1) = [C{1}; NaN(ncols - pad, 1)];
+        else
+          ## Otherwise return supplied emptyvalue. Pick last occurrence
+          C(1) = [C{1}; repmat(args{emptv(end)+1}, ncols - pad, 1)];
+        endif
       endif
       ## Compute nr. of rows
       nrows = floor (numel (C{1}) / ncols);
       ## Reshape C; watch out, transpose needed
-      C(1) = reshape (C{1}, ncols, numel (C{1}) / ncols)';
+      C(1) = reshape (C{1}, ncols, numel (C{1}) / ncols).';
       ## Distribute columns over C and wipe cols 2:end of C{1}
       for ii=2:ncols
         C(ii) = C{1}(:, ii);
@@ -576,7 +581,7 @@
 
 %% Test reading from a real file
 %!test
-%! f = tmpnam ();
+%! f = tempname ();
 %! fid = fopen (f, "w+");
 %! d = rand (1, 4);
 %! fprintf (fid, "  %f %f   %f  %f ", d);
@@ -589,7 +594,7 @@
 
 %% Tests reading with empty format, should return proper nr of columns
 %!test
-%! f = tmpnam ();
+%! f = tempname ();
 %! fid = fopen (f, "w+");
 %! fprintf (fid, " 1 2 3 4\n5 6 7 8");
 %! fseek (fid, 0, "bof");
@@ -603,7 +608,7 @@
 
 %% Tests reading with empty format; empty fields & incomplete lower row
 %!test
-%! f = tmpnam ();
+%! f = tempname ();
 %! fid = fopen (f, "w+");
 %! fprintf (fid, " ,2,,4\n5,6");
 %! fseek (fid, 0, "bof");
@@ -615,7 +620,7 @@
 %% Error message tests
 
 %!test
-%! f = tmpnam ();
+%! f = tempname ();
 %! fid = fopen (f, "w+");
 %! msg1 = "Missing or illegal value for 'headerlines'";
 %! try
@@ -626,7 +631,7 @@
 %! assert (msg1, lasterr);
 
 %!test
-%! f = tmpnam ();
+%! f = tempname ();
 %! fid = fopen (f, "w+");
 %! msg1 = "Missing or illegal value for 'headerlines'";
 %! try
@@ -637,7 +642,7 @@
 %! assert (msg1, lasterr);
 
 %!test
-%! f = tmpnam ();
+%! f = tempname ();
 %! fid = fopen (f, "w+");
 %! fprintf (fid,"some_string");
 %! fseek (fid, 0, "bof");
@@ -650,7 +655,7 @@
 %! assert (msg1, lasterr);
 
 %!test
-%! f = tmpnam ();
+%! f = tempname ();
 %! fid = fopen (f, "w+");
 %! fprintf (fid,"some_string");
 %! fseek (fid, 0, "bof");
@@ -666,3 +671,20 @@
 %!test
 %! assert (textscan ("123", "", "whitespace", " "){:}, 123);
 
+%% Bug #42343-1, just test supplied emptyvalue (actually done by strread.m)
+%!test
+%! assert (textscan (",NaN", "", "delimiter", "," ,"emptyValue" ,Inf), {Inf, NaN});
+
+%% Bug #42343-2, test padding with supplied emptyvalue (done by textscan.m)
+%!test
+%! a = textscan (",1,,4\nInf,  ,NaN", "", "delimiter", ",", "emptyvalue", -10);
+%! assert (cell2mat (a), [-10, 1, -10, 4; Inf, -10, NaN, -10]);
+
+%% Bug #42528
+%!test
+%! assert (textscan ("1i", ""){1},  0+1i);
+%! assert (cell2mat (textscan ("3, 2-4i, NaN\n -i, 1, 23.4+2.2i", "")), [3+0i, 2-4i, NaN+0i; 0-i,  1+0i, 23.4+2.2i]);
+
+%% Illegal format specifiers
+%!test
+%!error <no valid format conversion specifiers> textscan ("1.0", "%z");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/java/javachk.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,151 @@
+## Copyright (C) 2014 Philip Nienhuis
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {Function File} {} javachk (@var{feature})
+## @deftypefnx {Function File} {} javachk (@var{feature}, @var{component})
+## @deftypefnx {Function File} {@var{msg} =} javachk (@dots{})
+## Check for the presence of the Java @var{feature} in the current session
+## and print or return an error message if it is not.
+##
+## Possible features are:
+##
+## @table @asis
+## @item @qcode{"awt"}
+## Abstract Window Toolkit for GUIs.
+##
+## @item @qcode{"desktop"}
+## Interactive desktop is running.
+##
+## @item @qcode{"jvm"}
+## Java Virtual Machine.
+##
+## @item @qcode{"swing"}
+## Swing components for lightweight GUIs.
+## @end table
+##
+## If @var{feature} is supported and:
+##
+## @itemize @bullet
+## @item
+## No output argument is requested:
+##
+## Return an empty string
+##
+## @item
+## An output argument is requested:
+##
+## Return a struct with fields @qcode{"feature"} and @qcode{"identifier"}
+## both empty
+##
+## @end itemize
+##
+## If @var{feature} is not supported and:
+##
+## @itemize @bullet
+## @item
+## No output argument is requested:
+##
+## Emit an error message.
+##
+## @item
+## An output argument is requested:
+##
+## Return a struct with field @qcode{"feature"} set to @var{feature} and
+## field @qcode{"identifier"} set to @var{component}
+##
+## @end itemize
+##
+## The optional input @var{component} will be used in place of @var{feature}
+## in any error messages for greater specificity.
+##
+## @code{javachk} determines if specific Java features are available in an
+## Octave session.  This function is provided for scripts which may alter
+## their behavior based on the availability of Java.  The feature
+## @qcode{"desktop"} is never available as Octave has no Java-based desktop.
+## Other features may be available if Octave was compiled with the Java
+## Interface and Java is installed.
+##
+## @seealso{error, usejava}
+## @end deftypefn
+
+## Author: Philip Nienhuis <prnienhuis at users.sf.net>
+## Created: 2014-04-19
+
+function msg = javachk (feature, component="")
+
+  msg = "";
+  chk = false;
+  switch (feature)
+    ## For each feature, try methods() on a Java class of a feature
+    case "awt"
+      try
+        dum = methods ("java.awt.Frame");
+        chk = true;
+      end_try_catch
+    case "desktop"
+      ## Octave has no Java based GUI/desktop, leave chk = false
+    case "jvm"
+      try
+        dum = methods ("java.lang.Runtime");
+        chk = true;
+      end_try_catch
+    case "swing"
+      try
+        dum = methods ("javax.swing.Popup");
+        chk = true;
+      end_try_catch
+    otherwise
+      error ("javachk: unrecognized feature '%s', can be one of 'awt'|'desktop'|'jvm'|'swing'\n", feature);
+  endswitch
+
+  if (! chk)
+    ## Desired feature not present
+    if (nargout >= 1)
+      msg.message = sprintf ("javachk: %s is not supported", feature);
+      msg.identifier = component;
+    else
+      if (! isempty (component))
+        err = sprintf ("javachk: %s is not supported\n", component);
+      else
+        err = sprintf ("javachk: %s is not supported\n", feature);
+      endif
+      error (err);
+    endif
+  endif
+
+endfunction
+
+
+%!error <javachk: desktop is not supported> javachk ("desktop")
+%!error <Java DESKTOP is not supported> javachk ("desktop", "Java DESKTOP")
+%!test
+%! msg = javachk ("desktop");
+%! assert (msg.message, "javachk: desktop is not supported");
+%! assert (msg.identifier, "");
+%!test
+%! msg = javachk ("desktop", "Java DESKTOP");
+%! assert (msg.message, "javachk: desktop is not supported");
+%! assert (msg.identifier, "Java DESKTOP");
+
+%!testif HAVE_JAVA
+%! assert (javachk ("jvm"), "");
+
+%% Test input validation
+%!error <javachk: unrecognized feature 'foobar'> javachk ("foobar")
+
--- a/scripts/java/javaclasspath.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/java/javaclasspath.m	Mon Jan 12 09:17:35 2015 -0800
@@ -54,7 +54,11 @@
 ## @seealso{javaaddpath, javarmpath}
 ## @end deftypefn
 
-function varargout = javaclasspath (which)
+function [path1, path2] = javaclasspath (which)
+
+  if (nargin > 1)
+    print_usage ();
+  endif
 
   ## dynamic classpath
   dynamic_path = javaMethod ("getClassPath", "org.octave.ClassHelper");
@@ -70,46 +74,39 @@
     static_path_list = {};
   endif
 
-  switch (nargin)
-    case 0
-      switch (nargout)
-        case 0
-          disp_path_list ("STATIC", static_path_list)
-          disp ("");
-          disp_path_list ("DYNAMIC", dynamic_path_list)
+  if (nargout == 0)
+    if (! nargin)
+      which = "-all";
+    endif
+    switch (tolower (which))
+      case "-dynamic", disp_path_list ("DYNAMIC", dynamic_path_list);
+      case "-static",  disp_path_list ("STATIC", static_path_list);
+      case "-all"
+        disp_path_list ("STATIC", static_path_list);
+        disp ("");
+        disp_path_list ("DYNAMIC", dynamic_path_list);
+      otherwise
+        error ("javaclasspath: invalid value for WHAT");
+    endswitch
 
-        case 1
-          varargout{1} = cellstr (dynamic_path_list);
-
-        case 2
-          varargout{1} = cellstr (dynamic_path_list);
-          varargout{2} = cellstr (static_path_list);
+  else
+    if (! nargin)
+      ## This is to allow retrieval of both paths in separate variables with
+      ## a single call to javaclasspath(). Matlab returns only the -dynamic
+      ## path in this case but this won't break compatibility.
+      path1 = cellstr (dynamic_path_list);
+      path2 = cellstr (static_path_list);
+    else
+      switch (tolower (which))
+        case "-all",     path1 = cellstr ([static_path_list, dynamic_path_list]);
+        case "-dynamic", path1 = cellstr (dynamic_path_list);
+        case "-static",  path1 = cellstr (static_path_list);
+        otherwise
+          error ("javaclasspath: invalid value for WHAT");
       endswitch
-        
-    case 1
-      switch (nargout)
-        case 0
-          if (strcmp (which, "-static"))
-            disp_path_list ("STATIC", static_path_list)
-          elseif (strcmp (which, "-dynamic"))
-            disp_path_list ("DYNAMIC", dynamic_path_list)
-          elseif (strcmp (which, "-all") == 1)
-            disp_path_list ("STATIC", static_path_list)
-            disp ("");
-            disp_path_list ("DYNAMIC", dynamic_path_list)
-          endif
+    endif
+  endif
 
-        case 1
-          if (strcmp (which, "-static") == 1)
-            varargout{1} = cellstr (static_path_list);
-          elseif (strcmp (which, "-dynamic") == 1)
-            varargout{1} = cellstr (dynamic_path_list);
-          elseif (strcmp (which, "-all") == 1)
-            varargout{1} = cellstr ([static_path_list, dynamic_path_list]);
-          endif
-      endswitch
-  endswitch
-  
 endfunction
 
 ## Display cell array of paths
--- a/scripts/java/javamem.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/java/javamem.m	Mon Jan 12 09:17:35 2015 -0800
@@ -36,7 +36,7 @@
 ## determined by the environment variable @w{@env{OCTAVE_JAVA_DIR}}.
 ## If unset, the directory where @file{javaaddpath.m} resides is used instead
 ## (typically
-## @file{@w{@env{OCTAVE_HOME}}/share/octave/@w{@env{OCTAVE_VERSION}}/m/java/}
+## @file{@w{@env{OCTAVE_HOME}}/share/octave/@w{@env{OCTAVE_VERSION}}/m/java/}).
 ##
 ## @file{java.opts} is a plain text file with one option per line.  The
 ## default initial memory size and default maximum memory size (which
--- a/scripts/java/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/java/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -5,6 +5,7 @@
   java/java_set.m \
   java/javaArray.m \
   java/javaaddpath.m \
+  java/javachk.m \
   java/javaclasspath.m \
   java/javamem.m \
   java/javarmpath.m \
--- a/scripts/java/org/octave/ClassHelper.java	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/java/org/octave/ClassHelper.java	Mon Jan 12 09:17:35 2015 -0800
@@ -199,7 +199,7 @@
           {
             sb.append (";");
           }
-        sb.append (theField[i].toString ());
+        sb.append (theField[i].getName ());
       }
 
     return (sb.toString ());
--- a/scripts/java/usejava.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/java/usejava.m	Mon Jan 12 09:17:35 2015 -0800
@@ -43,6 +43,7 @@
 ## @qcode{"desktop"} always returns @code{false} as Octave has no Java-based
 ## desktop.  Other features may be available if Octave was compiled with the
 ## Java Interface and Java is installed.
+## @seealso{javachk}
 ## @end deftypefn
 
 ## Author: Rik Wehbring
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/linear-algebra/bandwidth.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,110 @@
+## Copyright (C) 2014 Massimiliano Fasi
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {Function File} {@var{bw} =} bandwidth (@var{A}, @var{type})
+## @deftypefnx {Function File} {[@var{lower}, @var{upper}] =} bandwidth (@var{A})
+## Compute the bandwidth of @var{A}.
+##
+## The @var{type} argument is the string @qcode{"lower"} for the lower
+## bandwidth and @qcode{"upper"} for the upper bandwidth.
+## If no @var{type} is specified return both the lower and upper bandwidth
+## of @var{A}. 
+##
+## The lower/upper bandwidth of a matrix is the number of
+## subdiagonals/superdiagonals with nonzero entries.
+## 
+## @seealso{isbanded, isdiag, istril, istriu}
+## @end deftypefn
+
+## Author: Massimiliano Fasi
+
+function [lower, upper] = bandwidth (A, type)
+
+  if (! ((nargin == 1 && nargout == 2) || (nargin == 2 && nargout <= 1)))
+    print_usage ();
+  endif
+
+  if (! isnumeric (A) && ! islogical (A) || ndims (A) != 2)
+    error ("bandwidth: A must be a 2-D numeric or logical matrix");
+  elseif (nargin == 2 && ! (strcmp (type, "lower") || strcmp (type, "upper")))
+    error ('bandwidth: TYPE must be "lower" or "upper"');
+  endif
+
+  if (nargin == 1)
+    [i, j] = find (A);
+    if (isempty (i))
+      lower = upper = 0;
+    else
+      lower = max (i - j);
+      upper = max (j - i);
+    endif
+  else
+    [i, j] = find (A);
+    if (isempty (i))
+      lower = 0;
+    elseif (strcmp (type, "lower"))
+      lower = max (i - j);
+    else
+      lower = max (j - i);
+    endif
+  endif
+
+endfunction
+
+
+%!test
+%! [a,b] = bandwidth (speye (100));
+%! assert ([a,b] == [0,0]);
+%! assert (bandwidth (speye (100), "upper"), 0);
+%! assert (bandwidth (speye (100), "lower"), 0);
+
+%!test
+%! A = [2 3 0 0 0; 1 2 3 0 0; 0 1 2 3 0; 0 0 1 2 3; 0 0 0 1 2];
+%! [a,b] = bandwidth (A);
+%! assert ([a,b] == [1,1]);
+%! assert (bandwidth (A, "lower"), 1);
+%! assert (bandwidth (A, "upper"), 1);
+
+%!assert (bandwidth ([], "lower"), 0)
+%!assert (bandwidth ([], "upper"), 0)
+%!assert (bandwidth (zeros (3,3), "lower"), 0)
+%!assert (bandwidth (zeros (3,3), "upper"), 0)
+%!assert (bandwidth (ones (5,5), "lower"), 4)
+%!assert (bandwidth (ones (5,5), "upper"), 4)
+
+%!test
+%! [a,b] = bandwidth ([]);
+%! assert ([a,b] == [0,0]);
+%!test
+%! [a,b] = bandwidth (zeros (3,3));
+%! assert ([a,b] == [0,0]);
+%!test
+%! [a,b] = bandwidth (ones (5,5));
+%! assert ([a,b] == [4,4]);
+
+%% Test input validation
+%!error bandwidth ()
+%!error bandwidth (1,2,3)
+%!error [a,b,c] = bandwidth (ones (2))
+%!error [a,b] = bandwidth (ones (2), "upper")
+%!error <A must be a 2-D numeric or logical> bandwidth ("string", "lower")
+%!error <A must be a 2-D numeric or logical> bandwidth (ones (3,3,3), "lower")
+%!error <TYPE must be "lower" or "upper"> bandwidth (ones (2), "uper")
+%!error <TYPE must be "lower" or "upper"> bandwidth (ones (2), "uppper")
+
--- a/scripts/linear-algebra/commutation_matrix.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/linear-algebra/commutation_matrix.m	Mon Jan 12 09:17:35 2015 -0800
@@ -63,8 +63,8 @@
 ## @end ifnottex
 ##  is returned.
 ##
-## See Magnus and Neudecker (1988), @cite{Matrix Differential Calculus with
-## Applications in Statistics and Econometrics.}
+## See @nospell{Magnus and Neudecker} (1988), @cite{Matrix Differential
+## Calculus with Applications in Statistics and Econometrics.}
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
--- a/scripts/linear-algebra/condest.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/linear-algebra/condest.m	Mon Jan 12 09:17:35 2015 -0800
@@ -59,13 +59,13 @@
 ##
 ## @itemize
 ## @item
-## N.J. Higham and F. Tisseur, @cite{A Block Algorithm
+## @nospell{N.J. Higham and F. Tisseur}, @cite{A Block Algorithm
 ## for Matrix 1-Norm Estimation, with an Application to 1-Norm
 ## Pseudospectra}. SIMAX vol 21, no 4, pp 1185-1201.
 ## @url{http://dx.doi.org/10.1137/S0895479899356080}
 ##
 ## @item
-## N.J. Higham and F. Tisseur, @cite{A Block Algorithm
+## @nospell{N.J. Higham and F. Tisseur}, @cite{A Block Algorithm
 ## for Matrix 1-Norm Estimation, with an Application to 1-Norm
 ## Pseudospectra}. @url{http://citeseer.ist.psu.edu/223007.html}
 ## @end itemize
--- a/scripts/linear-algebra/duplication_matrix.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/linear-algebra/duplication_matrix.m	Mon Jan 12 09:17:35 2015 -0800
@@ -54,8 +54,8 @@
 ##  @math{A}.
 ## @end ifnottex
 ##
-## See Magnus and Neudecker (1988), Matrix differential calculus with
-## applications in statistics and econometrics.
+## See @nospell{Magnus and Neudecker} (1988), @cite{Matrix Differential
+## Calculus with Applications in Statistics and Econometrics.}
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
--- a/scripts/linear-algebra/expm.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/linear-algebra/expm.m	Mon Jan 12 09:17:35 2015 -0800
@@ -33,8 +33,8 @@
 ##
 ## @end ifnottex
 ## The Taylor series is @emph{not} the way to compute the matrix
-## exponential; see Moler and Van Loan, @cite{Nineteen Dubious Ways to
-## Compute the Exponential of a Matrix}, SIAM Review, 1978.  This routine
+## exponential; see @nospell{Moler and Van Loan}, @cite{Nineteen Dubious Ways
+## to Compute the Exponential of a Matrix}, SIAM Review, 1978.  This routine
 ## uses Ward's diagonal Pad@'e approximation method with three step
 ## preconditioning (SIAM Journal on Numerical Analysis, 1977).  Diagonal
 ## Pad@'e approximations are rational polynomials of matrices
--- a/scripts/linear-algebra/housh.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/linear-algebra/housh.m	Mon Jan 12 09:17:35 2015 -0800
@@ -43,7 +43,7 @@
 ## @end table
 ##
 ## @noindent
-## Outputs (see Golub and Van Loan):
+## Outputs (see @nospell{Golub and Van Loan}):
 ##
 ## @table @var
 ## @item beta
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/linear-algebra/isbanded.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,86 @@
+## Copyright (C) 2014 Massimiliano Fasi
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {} isbanded (@var{A}, @var{lower}, @var{upper})
+## Return true if @var{A} is a matrix with entries confined between
+## @var{lower} diagonals below the main diagonal and @var{upper} diagonals
+## above the main diagonal.
+##
+## @var{lower} and @var{upper} must be non-negative integers.
+## @seealso{isdiag, istril, istriu, bandwidth}
+## @end deftypefn
+
+## Author: Massimiliano Fasi
+
+function retval = isbanded (A, lower, upper)
+
+  if (nargin != 3)
+    print_usage ();
+  endif
+
+  if (! isreal (lower) || ! isreal (upper) || lower < 0 || upper < 0)
+    error ("isbanded: LOWER and UPPER must be non-negative integers");
+  endif
+
+  if (isempty (A))
+    retval = [];
+  else 
+    retval = (isnumeric (A) || islogical (A)) && ndims (A) == 2;
+    if (retval)
+      [i, j] = find (A);
+      pupp = j >= i;
+      retval = all (j(pupp) - i(pupp) <= upper);
+      if (retval)
+        plow = i >= j;
+        retval = all (i(plow) - j(plow) <= lower);
+      endif
+    endif
+  endif
+
+endfunction
+
+
+%!assert (! isbanded ("string", 0, 0))
+%!assert (! isbanded (zeros (2,2,2), 0, 0))
+%!assert (isbanded ([], 0, 0))
+%!assert (isbanded (1,0,0))
+%!assert (isbanded (1,10,10))
+
+%!assert (isbanded ([1, 1],1,1))
+%!assert (isbanded ([1; 1],1,1))
+%!assert (isbanded (eye(10),0,0))
+%!assert (isbanded (eye(10),1,1))
+%!assert (isbanded (i*eye(10),1,1))
+%!assert (isbanded (logical (eye (10)),1,1))
+
+%! A = [2 3 0 0 0; 1 2 3 0 0; 0 1 2 3 0; 0 0 1 2 3; 0 0 0 1 2];
+%! assert (isbanded (A,1,1))
+%! assert (! isbanded (A,0,1))
+%! assert (! isbanded (A,1,0))
+
+%% Test input validation
+%!error isbanded ()
+%!error isbanded (1)
+%!error isbanded (1,2)
+%!error isbanded (1,2,3,4)
+%!error <LOWER and UPPER must be non-negative> isbanded (1, -1, 1)
+%!error <LOWER and UPPER must be non-negative> isbanded (1, 1, -1)
+%!error <LOWER and UPPER must be non-negative> isbanded (1, {1}, 1)
+%!error <LOWER and UPPER must be non-negative> isbanded (1, 1, {1})
+
--- a/scripts/linear-algebra/isdefinite.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/linear-algebra/isdefinite.m	Mon Jan 12 09:17:35 2015 -0800
@@ -17,13 +17,13 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} isdefinite (@var{x})
-## @deftypefnx {Function File} {} isdefinite (@var{x}, @var{tol})
-## Return 1 if @var{x} is symmetric positive definite within the
-## tolerance specified by @var{tol} or 0 if @var{x} is symmetric
+## @deftypefn  {Function File} {} isdefinite (@var{A})
+## @deftypefnx {Function File} {} isdefinite (@var{A}, @var{tol})
+## Return 1 if @var{A} is symmetric positive definite within the
+## tolerance specified by @var{tol} or 0 if @var{A} is symmetric
 ## positive semidefinite.  Otherwise, return -1.  If @var{tol}
 ## is omitted, use a tolerance of
-## @code{100 * eps * norm (@var{x}, "fro")}
+## @code{100 * eps * norm (@var{A}, "fro")}
 ## @seealso{issymmetric, ishermitian}
 ## @end deftypefn
 
@@ -31,30 +31,30 @@
 ## Created: November 2003
 ## Adapted-By: jwe
 
-function retval = isdefinite (x, tol)
+function retval = isdefinite (A, tol)
 
   if (nargin < 1 || nargin > 2)
     print_usage ();
   endif
 
-  if (! isfloat (x))
-    x = double (x);
+  if (! isfloat (A))
+    A = double (A);
   endif
 
   if (nargin == 1)
-    tol = 100 * eps (class (x)) * norm (x, "fro");
+    tol = 100 * eps (class (A)) * norm (A, "fro");
   endif
 
-  if (! ishermitian (x, tol))
-    error ("isdefinite: X must be a Hermitian matrix");
+  if (! ishermitian (A, tol))
+    error ("isdefinite: A must be a Hermitian matrix");
   endif
 
-  e = tol * eye (rows (x));
-  [r, p] = chol (x - e);
+  e = tol * eye (rows (A));
+  [r, p] = chol (A - e);
   if (p == 0)
     retval = 1;
   else
-    [r, p] = chol (x + e);
+    [r, p] = chol (A + e);
     if (p == 0)
       retval = 0;
     else
@@ -83,5 +83,5 @@
 
 %!error isdefinite ()
 %!error isdefinite (1,2,3)
-%!error <X must be a Hermitian matrix> isdefinite ([1 2; 3 4])
+%!error <A must be a Hermitian matrix> isdefinite ([1 2; 3 4])
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/linear-algebra/isdiag.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,56 @@
+## Copyright (C) 2014 Massimiliano Fasi
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {} isdiag (@var{A})
+## Return true if @var{A} is a diagonal matrix.
+## @seealso{isbanded, istril, istriu, diag, bandwidth}
+## @end deftypefn
+
+## Author: Massimiliano Fasi
+
+function retval = isdiag (A)
+
+  if (nargin != 1)
+    print_usage ();
+  endif
+
+  retval = (isnumeric (A) || islogical (A)) && ndims (A) == 2;
+  if (retval)
+    [i, j] = find (A);
+    retval = all (i == j);
+  endif
+
+endfunction
+
+
+%!assert (! isdiag ("string"))
+%!assert (isdiag ([]))
+
+%!assert (isdiag (1))
+%!assert (! isdiag ([1, 1]))
+%!assert (! isdiag ([1; 1]))
+%!assert (isdiag (eye (10)))
+%!assert (issymmetric ([i, 0; 0, 1 + i]))
+%!assert (isdiag (speye (1000000)))
+%!assert (isdiag (logical (eye (10))))
+
+%% Test input validation
+%!error isdiag ()
+%!error isdiag (1,2)
+
--- a/scripts/linear-algebra/ishermitian.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/linear-algebra/ishermitian.m	Mon Jan 12 09:17:35 2015 -0800
@@ -18,13 +18,14 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} ishermitian (@var{x})
-## @deftypefnx {Function File} {} ishermitian (@var{x}, @var{tol})
-## Return true if @var{x} is Hermitian within the tolerance specified by
+## @deftypefn  {Function File} {} ishermitian (@var{A})
+## @deftypefnx {Function File} {} ishermitian (@var{A}, @var{tol})
+## Return true if @var{A} is Hermitian within the tolerance specified by
 ## @var{tol}.
+##
 ## The default tolerance is zero (uses faster code).
-## Matrix @var{x} is considered symmetric if
-## @code{norm (@var{x} - @var{x}', Inf) / norm (@var{x}, Inf) < @var{tol}}.
+## Matrix @var{A} is considered symmetric if
+## @code{norm (@var{A} - @var{A}', Inf) / norm (@var{A}, Inf) < @var{tol}}.
 ## @seealso{issymmetric, isdefinite}
 ## @end deftypefn
 
@@ -32,19 +33,19 @@
 ## Created: August 1993
 ## Adapted-By: jwe
 
-function retval = ishermitian (x, tol = 0)
+function retval = ishermitian (A, tol = 0)
 
   if (nargin < 1 || nargin > 2)
     print_usage ();
   endif
 
-  retval = isnumeric (x) && issquare (x);
+  retval = isnumeric (A) && issquare (A);
   if (retval)
     if (tol == 0)
-      retval = all ((x == x')(:));
+      retval = all ((A == A')(:));
     else
-      norm_x = norm (x, inf);
-      retval = norm_x == 0 || norm (x - x', inf) / norm_x <= tol;
+      norm_x = norm (A, inf);
+      retval = norm_x == 0 || norm (A - A', inf) / norm_x <= tol;
     endif
   endif
 
--- a/scripts/linear-algebra/issymmetric.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/linear-algebra/issymmetric.m	Mon Jan 12 09:17:35 2015 -0800
@@ -18,12 +18,14 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} issymmetric (@var{x})
-## @deftypefnx {Function File} {} issymmetric (@var{x}, @var{tol})
-## Return true if @var{x} is a symmetric matrix within the tolerance specified
-## by @var{tol}.  The default tolerance is zero (uses faster code).
-## Matrix @var{x} is considered symmetric if
-## @code{norm (@var{x} - @var{x}.', Inf) / norm (@var{x}, Inf) < @var{tol}}.
+## @deftypefn  {Function File} {} issymmetric (@var{A})
+## @deftypefnx {Function File} {} issymmetric (@var{A}, @var{tol})
+## Return true if @var{A} is a symmetric matrix within the tolerance specified
+## by @var{tol}.
+##
+## The default tolerance is zero (uses faster code).
+## Matrix @var{A} is considered symmetric if
+## @code{norm (@var{A} - @var{A}.', Inf) / norm (@var{A}, Inf) < @var{tol}}.
 ## @seealso{ishermitian, isdefinite}
 ## @end deftypefn
 
@@ -31,19 +33,20 @@
 ## Created: August 1993
 ## Adapted-By: jwe
 
-function retval = issymmetric (x, tol = 0)
+function retval = issymmetric (A, tol = 0)
 
   if (nargin < 1 || nargin > 2)
     print_usage ();
   endif
 
-  retval = isnumeric (x) && issquare (x);
+  retval = (isnumeric (A) || islogical (A)) && issquare (A);
   if (retval)
     if (tol == 0)
-      retval = all ((x == x.')(:));
+      ## Handle large sparse matrices as well as full ones
+      retval = nnz (A != A.') == 0;
     else
-      norm_x = norm (x, inf);
-      retval = norm_x == 0 || norm (x - x.', inf) / norm_x <= tol;
+      norm_x = norm (A, inf);
+      retval = norm_x == 0 || norm (A - A.', inf) / norm_x <= tol;
     endif
   endif
 
@@ -59,6 +62,8 @@
 %!assert (issymmetric ([1, 2i; 2i, 1]))
 %!assert (! (issymmetric ("t")))
 %!assert (! (issymmetric (["te"; "et"])))
+%!assert (issymmetric (speye (100000)))
+%!assert (issymmetric (logical (eye (2))))
 
 %!test
 %! s.a = 1;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/linear-algebra/istril.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,61 @@
+## Copyright (C) 2014 Massimiliano Fasi
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {} istril (@var{A})
+## Return true if @var{A} is a lower triangular matrix.
+##
+## A lower triangular matrix has nonzero entries only on the main diagonal
+## and below.
+## @seealso{istriu, isbanded, isdiag, tril, bandwidth}
+## @end deftypefn
+
+## Author: Massimiliano Fasi
+
+function retval = istril (A)
+
+  if (nargin != 1)
+    print_usage ();
+  endif
+
+  retval = (isnumeric (A) || islogical (A)) && ndims (A) == 2;
+  if (retval)
+    [i, j] = find (A);
+    retval = all (i >= j);
+  endif
+
+endfunction
+
+
+%!assert (! istril ("string"))
+%!assert (istril ([]))
+%!assert (! istril (zeros (2,2,2)))
+
+%!assert (istril (1))
+%!assert (! istril ([1, 1]))
+%!assert (istril ([1; 1]))
+%!assert (istril (eye (10)))
+%!assert (istril (speye (100)))
+
+%!assert (istril (tril (randn (10))))
+%!assert (! istril (randn (10)))
+
+%% Test input validation
+%!error istril ()
+%!error istril (1,2)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/linear-algebra/istriu.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,61 @@
+## Copyright (C) 2014 Massimiliano Fasi
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {} istriu (@var{A})
+## Return true if @var{A} is an upper triangular matrix.
+##
+## An upper triangular matrix has nonzero entries only on the main diagonal
+## and above.
+## @seealso{isdiag, isbanded, istril, triu, bandwidth}
+## @end deftypefn
+
+## Author: Massimiliano Fasi
+
+function retval = istriu (A)
+
+  if (nargin != 1)
+    print_usage ();
+  endif
+
+  retval = (isnumeric (A) || islogical (A)) && ndims (A) == 2;
+  if (retval)
+    [i, j] = find (A);
+    retval = all (i <= j);
+  endif
+
+endfunction
+
+
+%!assert (! istriu ("string"))
+%!assert (istriu ([]))
+%!assert (! istriu (zeros (2,2,2)))
+
+%!assert (istriu (1))
+%!assert (istriu ([1, 1]))
+%!assert (! istriu ([1; 1]))
+%!assert (istriu (eye (10)))
+%!assert (istriu (speye (100)))
+
+%!assert (istriu (triu (randn (10))))
+%!assert (! istriu (randn (10)))
+
+%% Test input validation
+%!error istriu ()
+%!error istriu (1,2)
+
--- a/scripts/linear-algebra/krylov.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/linear-algebra/krylov.m	Mon Jan 12 09:17:35 2015 -0800
@@ -49,9 +49,9 @@
 ## If the optional parameter @var{pflg} is nonzero, row pivoting is used
 ## to improve numerical behavior.  The default value is 0.
 ##
-## Reference: A. Hodel, P. Misra, @cite{Partial Pivoting in the Computation of
-## Krylov Subspaces of Large Sparse Systems}, Proceedings of the 42nd IEEE
-## Conference on Decision and Control, December 2003.
+## Reference: @nospell{A. Hodel, P. Misra}, @cite{Partial Pivoting in the
+## Computation of Krylov Subspaces of Large Sparse Systems}, Proceedings of
+## the 42nd IEEE Conference on Decision and Control, December 2003.
 ## @end deftypefn
 
 ## Author: A. Scottedward Hodel <a.s.hodel@eng.auburn.edu>
@@ -133,8 +133,8 @@
         nv = columns (V);
         if (jj != nv)
           [V(:,jj), V(:,nv)] = swap (V(:,jj), V(:,nv));
-          ## FIXME -- H columns should be swapped too.  Not done
-          ## since Block Hessenberg structure is lost anyway.
+          ## FIXME: H columns should be swapped too.
+          ##        Not done since Block Hessenberg structure is lost anyway.
         endif
         V = V(:,1:(nv-1));
         ## One less reflection.
@@ -167,7 +167,7 @@
         ## Reduce V per the reflection.
         V(idx,:) = V(idx,:) - av*hv*(hv' * V(idx,:));
         if(iter > 1)
-          ## FIXME -- not done correctly for block case.
+          ## FIXME: not done correctly for block case.
           H(nu,nu-1) = V(pivot_vec(nu),jj);
         endif
 
--- a/scripts/linear-algebra/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/linear-algebra/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -1,6 +1,7 @@
 FCN_FILE_DIRS += linear-algebra
 
 linear_algebra_FCN_FILES = \
+  linear-algebra/bandwidth.m \
   linear-algebra/commutation_matrix.m \
   linear-algebra/cond.m \
   linear-algebra/condest.m \
@@ -8,9 +9,13 @@
   linear-algebra/duplication_matrix.m \
   linear-algebra/expm.m \
   linear-algebra/housh.m \
+  linear-algebra/isbanded.m \
   linear-algebra/isdefinite.m \
+  linear-algebra/isdiag.m \
   linear-algebra/ishermitian.m \
   linear-algebra/issymmetric.m \
+  linear-algebra/istril.m \
+  linear-algebra/istriu.m \
   linear-algebra/krylov.m \
   linear-algebra/linsolve.m \
   linear-algebra/logm.m \
--- a/scripts/linear-algebra/onenormest.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/linear-algebra/onenormest.m	Mon Jan 12 09:17:35 2015 -0800
@@ -20,7 +20,7 @@
 ## @deftypefn  {Function File} {[@var{est}, @var{v}, @var{w}, @var{iter}] =} onenormest (@var{A}, @var{t})
 ## @deftypefnx {Function File} {[@var{est}, @var{v}, @var{w}, @var{iter}] =} onenormest (@var{apply}, @var{apply_t}, @var{n}, @var{t})
 ##
-## Apply Higham and Tisseur's randomized block 1-norm estimator to
+## Apply @nospell{Higham and Tisseur's} randomized block 1-norm estimator to
 ## matrix @var{A} using @var{t} test vectors.  If @var{t} exceeds 5, then
 ## only 5 test vectors are used.
 ##
@@ -41,13 +41,13 @@
 ##
 ## @itemize
 ## @item
-## N.J. Higham and F. Tisseur, @cite{A Block Algorithm
+## @nospell{N.J. Higham and F. Tisseur}, @cite{A Block Algorithm
 ## for Matrix 1-Norm Estimation, with an Application to 1-Norm
 ## Pseudospectra}. SIMAX vol 21, no 4, pp 1185-1201.
 ## @url{http://dx.doi.org/10.1137/S0895479899356080}
 ##
 ## @item
-## N.J. Higham and F. Tisseur, @cite{A Block Algorithm
+## @nospell{N.J. Higham and F. Tisseur}, @cite{A Block Algorithm
 ## for Matrix 1-Norm Estimation, with an Application to 1-Norm
 ## Pseudospectra}. @url{http://citeseer.ist.psu.edu/223007.html}
 ## @end itemize
--- a/scripts/linear-algebra/planerot.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/linear-algebra/planerot.m	Mon Jan 12 09:17:35 2015 -0800
@@ -17,8 +17,8 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {[@var{g}, @var{y}] =} planerot (@var{x})
-## Given a two-element column vector, returns the
+## @deftypefn {Function File} {[@var{G}, @var{y}] =} planerot (@var{x})
+## Given a two-element column vector, return the
 ## @tex
 ## $2 \times 2$ orthogonal matrix
 ## @end tex
@@ -31,8 +31,16 @@
 ## @end deftypefn
 
 function [G, y] = planerot (x)
+
+  if (nargin != 1)
+    print_usage ();
+  elseif (! (isvector (x) && numel (x) == 2))
+    error ("planerot: X must be a 2-element vector");
+  endif
+
   G = givens (x(1), x(2));
   y = G * x(:);
+
 endfunction
 
 
@@ -42,7 +50,8 @@
 %! assert (g, [x(1) x(2); -x(2) x(1)] / sqrt (x(1)^2 + x(2)^2), 2e-8);
 %! assert (y(2), 0, 2e-8);
 
-%!error planerot ([0])
-%!error planerot ([0 0 0])
 %!error planerot ()
+%!error planerot (1,2)
+%!error <X must be a 2-element vector> planerot (ones (2,2))
+%!error <X must be a 2-element vector> planerot ([0 0 0])
 
--- a/scripts/linear-algebra/qzhess.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/linear-algebra/qzhess.m	Mon Jan 12 09:17:35 2015 -0800
@@ -35,9 +35,9 @@
 ## @end example
 ##
 ## The Hessenberg-triangular decomposition is the first step in
-## Moler and Stewart's QZ@tie{}decomposition algorithm.
+## @nospell{Moler and Stewart's} QZ@tie{}decomposition algorithm.
 ##
-## Algorithm taken from Golub and Van Loan,
+## Algorithm taken from @nospell{Golub and Van Loan},
 ## @cite{Matrix Computations, 2nd edition}.
 ## 
 ## @seealso{lu, chol, hess, qr, qz, schur, svd}
--- a/scripts/linear-algebra/subspace.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/linear-algebra/subspace.m	Mon Jan 12 09:17:35 2015 -0800
@@ -60,3 +60,18 @@
 
 endfunction
 
+
+%!test
+%! ## For random vectors
+%! a = rand (2,1);
+%! b = rand (2,1);
+%! a1 = norm (a,2);
+%! b1 = norm (b,2);
+%! theta = acos (dot (a,b)/(a1*b1));
+%! assert (theta, subspace (a, b), 100*eps);
+
+%!test
+%! ## For random matrices
+%! M = rand (3, 3);
+%! assert (0, subspace (M, M'), 100*eps);
+
--- a/scripts/linear-algebra/vech.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/linear-algebra/vech.m	Mon Jan 12 09:17:35 2015 -0800
@@ -19,7 +19,7 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} vech (@var{x})
-## Return the vector obtained by eliminating all supradiagonal elements of
+## Return the vector obtained by eliminating all superdiagonal elements of
 ## the square matrix @var{x} and stacking the result one column above the
 ## other.  This has uses in matrix calculus where the underlying matrix
 ## is symmetric and it would be pointless to keep values above the main
--- a/scripts/miscellaneous/ans.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/ans.m	Mon Jan 12 09:17:35 2015 -0800
@@ -18,8 +18,10 @@
 
 ## -*- texinfo -*-
 ## @defvr {Automatic Variable} ans
-## The most recently computed result that was not
-## explicitly assigned to a variable.  For example, after the expression
+## The most recently computed result that was not explicitly assigned to a
+## variable.
+##
+## For example, after the expression
 ##
 ## @example
 ## 3^2 + 4^2
--- a/scripts/miscellaneous/bug_report.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/bug_report.m	Mon Jan 12 09:17:35 2015 -0800
@@ -25,22 +25,22 @@
 
 function bug_report ()
 
-  puts ("\n");
-  puts ("  Bug reports play an essential role in making Octave\n");
-  puts ("  reliable.  Please use the Octave bug tracker at\n");
-  puts ("\n");
-  puts ("    http://bugs.octave.org\n");
-  puts ("\n");
-  puts ("  to report problems.\n");
-  puts ("\n");
-  puts ("  Please also read the bug reporting guidelines at\n");
-  puts ("\n");
-  puts ("    http://www.octave.org/bugs.html\n");
-  puts ("\n");
-  puts ("  to learn how to submit useful bug reports that will\n");
-  puts ("  help the Octave community diagnose and fix the problem\n");
-  puts ("  quickly and efficiently.\n");
-  puts ("\n");
+  disp (" ");
+  disp ("  Bug reports play an essential role in making Octave");
+  disp ("  reliable.  Please use the Octave bug tracker at");
+  disp (" ");
+  disp ("    http://bugs.octave.org");
+  disp (" ");
+  disp ("  to report problems.");
+  disp (" ");
+  disp ("  Please also read the bug reporting guidelines at");
+  disp (" ");
+  disp ("    http://www.octave.org/bugs.html");
+  disp (" ");
+  disp ("  to learn how to submit useful bug reports that will");
+  disp ("  help the Octave community diagnose and fix the problem");
+  disp ("  quickly and efficiently.");
+  disp (" ");
 
 endfunction
 
--- a/scripts/miscellaneous/bunzip2.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/bunzip2.m	Mon Jan 12 09:17:35 2015 -0800
@@ -17,27 +17,39 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} bunzip2 (@var{bzfile})
-## @deftypefnx {Function File} {} bunzip2 (@var{bzfile}, @var{dir})
-## Unpack the bzip2 archive @var{bzfile} to the directory @var{dir}.  If
-## @var{dir} is not specified, it defaults to the current directory.
+## @deftypefn  {Function File} {@var{filelist} =} bunzip2 (@var{bzfile})
+## @deftypefnx {Function File} {@var{filelist} =} bunzip2 (@var{bzfile}, @var{dir})
+## Unpack the bzip2 archive @var{bzfile}.
+##
+## If @var{dir} is specified the files are unpacked in this directory rather
+## than the one where @var{bzfile} is located.
+##
+## The optional output @var{filelist} is a list of the uncompressed files.
 ## @seealso{bzip2, unpack, gunzip, unzip, untar}
 ## @end deftypefn
 
 ## Author: Bill Denney <denney@seas.upenn.edu>
 
-function varargout = bunzip2 (bzfile, dir = ".")
+function filelist = bunzip2 (bzfile, dir = [])
 
-  if (nargin != 1 && nargin != 2)
+  if (nargin < 1 || nargin > 2)
     print_usage ();
   endif
 
+  if (isempty (dir))
+    dir = fileparts (bzfile);
+  endif
+
   if (nargout > 0)
-    varargout = cell (1, nargout);
-    [varargout{:}] = unpack (bzfile, dir, mfilename ());
+    filelist = unpack (bzfile, dir, "bunzip2");
   else
-    unpack (bzfile, dir, mfilename ());
+    unpack (bzfile, dir, "bunzip2");
   endif
 
 endfunction
 
+
+## Tests for this m-file are located in bzip2.m
+## Remove from test statistics
+%!assert (1)
+
--- a/scripts/miscellaneous/bzip2.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/bzip2.m	Mon Jan 12 09:17:35 2015 -0800
@@ -18,46 +18,71 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {@var{entries} =} bzip2 (@var{files})
-## @deftypefnx {Function File} {@var{entries} =} bzip2 (@var{files}, @var{outdir})
+## @deftypefn  {Function File} {@var{filelist} =} bzip2 (@var{files})
+## @deftypefnx {Function File} {@var{filelist} =} bzip2 (@var{files}, @var{dir})
 ## Compress the list of files specified in @var{files}.
-## Each file is compressed separately and a new file with a @file{".bz2"}
-## extension is created.  The original files are not modified.  Existing
-## compressed files are silently overwritten.  If @var{outdir} is defined the
-## compressed files are placed in this directory.
-## @seealso{bunzip2, gzip, zip, tar}
+##
+## @var{files} is a character array or cell array of strings.  Shell
+## wildcards in the filename such as @samp{*} or @samp{?} are accepted and
+## expanded.  Each file is compressed separately and a new file with a
+## @file{".bz2"} extension is created.  The original files are not modified,
+## but existing compressed files will be silently overwritten. 
+##
+## If @var{dir} is defined the compressed files are placed in this directory,
+## rather than the original directory where the uncompressed file resides.
+## If @var{dir} does not exist it is created.
+##
+## The optional output @var{filelist} is a list of the compressed files.
+## @seealso{bunzip2, unpack, gzip, zip, tar}
 ## @end deftypefn
 
-function entries = bzip2 (varargin)
+function filelist = bzip2 (varargin)
 
-  if (nargin == 1 || nargin == 2)
-    if (nargout == 0)
-      __xzip__ ("bzip2", "bz2", "bzip2 %s", varargin{:});
-    else
-      entries = __xzip__ ("bzip2", "bz2", "bzip2 %s", varargin{:});
-    endif
+  if (nargin < 1 || nargin > 2 || nargout > 1)
+    print_usage ();
+  endif
+
+  if (nargout == 0)
+    __xzip__ ("bzip2", "bz2", "bzip2 %s", varargin{:});
   else
-    print_usage ();
+    filelist = __xzip__ ("bzip2", "bz2", "bzip2 %s", varargin{:});
   endif
 
 endfunction
 
 
 %!xtest
-%! ## test for correct cleanup of temporary files
+%! ## test bzip2 together with bunzip2
 %! unwind_protect
-%!   filename = tmpnam;
-%!   dummy    = 1;
+%!   filename = tempname;
+%!   dummy    = pi;
 %!   save (filename, "dummy");
-%!   n_tmpfiles_before = length (find (strncmp ("oct-", cellstr (ls (tempdir)), 4)));
-%!   entry = bzip2 (filename);
-%!   n_tmpfiles_after = length (find (strncmp ("oct-", cellstr (ls (tempdir)), 4)));
-%!   if (n_tmpfiles_before != n_tmpfiles_after)
-%!     error ("bzip2 has not cleaned up temporary files correctly!");
+%!   dirname  = tempname;
+%!   mkdir (dirname);
+%!   filelist = bzip2 (filename, dirname);
+%!   filelist = filelist{1};
+%!   [~, basename, extension] = fileparts (filename);
+%!   if (! strcmp (filelist, [dirname, filesep, basename, extension, ".bz2"]))
+%!     error ("bzipped file does not match expected name!");
+%!   endif
+%!   if (! exist (filelist, "file"))
+%!     error ("bzipped file cannot be found!");
+%!   endif
+%!   bunzip2 (filelist);
+%!   fid = fopen (filename, "rb");
+%!   assert (fid >= 0);
+%!   orig_data = fread (fid);
+%!   fclose (fid);
+%!   fid = fopen ([dirname filesep basename extension], "rb");
+%!   assert (fid >= 0);
+%!   new_data = fread (fid);
+%!   fclose (fid);
+%!   if (orig_data != new_data)
+%!     error ("bunzipped file not equal to original file!");
 %!   endif
 %! unwind_protect_cleanup
 %!   delete (filename);
-%!   [path, basename, extension] = fileparts (filename);
-%!   delete ([basename, extension, ".bz2"]);
+%!   delete ([dirname, filesep, basename, extension]);
+%!   rmdir (dirname);
 %! end_unwind_protect
 
--- a/scripts/miscellaneous/cast.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/cast.m	Mon Jan 12 09:17:35 2015 -0800
@@ -17,30 +17,82 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} cast (@var{val}, @var{type})
+## @deftypefn {Function File} {} cast (@var{val}, "@var{type}")
 ## Convert @var{val} to data type @var{type}.
-## @seealso{int8, uint8, int16, uint16, int32, uint32, int64, uint64, double}
+##
+## @var{val} must be one of the numeric classes:
+## 
+## @example
+## @group
+## "double"
+## "single"
+## "logical"
+## "char"
+## "int8"
+## "int16"
+## "int32"
+## "int64"
+## "uint8"
+## "uint16"
+## "uint32"
+## "uint64"
+## @end group
+## @end example
+##
+## The value @var{val} may be modified to fit within the range of the new type.
+##
+## Examples:
+##
+## @example
+## @group
+## cast (-5, "uint8")
+##    @result{} 0
+## cast (300, "int8")
+##    @result{} 127
+## @end group
+## @end example
+##
+## @seealso{typecast, int8, uint8, int16, uint16, int32, uint32, int64, uint64, double, single, logical, char, class, typeinfo}
 ## @end deftypefn
 
 ## Author: jwe
 
-function retval = cast (val, typ)
+function retval = cast (val, type)
 
-  if (nargin == 2)
-    if (ischar (typ))
-      if (any (strcmp (typ, {"int8"; "uint8"; "int16"; "uint16";
-                             "int32"; "uint32"; "int64"; "uint64";
-                             "double"; "single"; "logical"; "char"})))
-        retval = feval (typ, val);
-      else
-        error ("cast: type name '%s' is not a built-in type", typ);
-      endif
-    else
-      error ("cast: expecting TYPE name as second argument");
-    endif
-  else
+  if (nargin != 2)
     print_usage ();
   endif
 
+  if (! ischar (type))
+    error ("cast: TYPE must be a string");
+  elseif (! any (strcmp (type, {"int8"; "uint8"; "int16"; "uint16";
+                                "int32"; "uint32"; "int64"; "uint64";
+                                "double"; "single"; "logical"; "char"})))
+    error ("cast: TYPE '%s' is not a built-in type", type);
+  endif
+    
+  retval = feval (type, val);
+
 endfunction
 
+
+%!assert (cast (single (2.5), "double"), 2.5)
+%!assert (cast (2.5, "single"), single (2.5))
+%!assert (cast ([5 0 -5], "logical"), [true false true])
+%!assert (cast ([65 66 67], "char"), "ABC")
+%!assert (cast ([-2.5 1.1 2.5], "int8"), int8 ([-3 1 3]))
+%!assert (cast ([-2.5 1.1 2.5], "uint8"), uint8 ([0 1 3]))
+%!assert (cast ([-2.5 1.1 2.5], "int16"), int16 ([-3 1 3]))
+%!assert (cast ([-2.5 1.1 2.5], "uint16"), uint16 ([0 1 3]))
+%!assert (cast ([-2.5 1.1 2.5], "int32"), int32 ([-3 1 3]))
+%!assert (cast ([-2.5 1.1 2.5], "uint32"), uint32 ([0 1 3]))
+%!assert (cast ([-2.5 1.1 2.5], "int64"), int64 ([-3 1 3]))
+%!assert (cast ([-2.5 1.1 2.5], "uint64"), uint64 ([0 1 3]))
+
+## Test input validation
+%!error cast ()
+%!error cast (1)
+%!error cast (1,2,3)
+%!error <TYPE 'foobar' is not a built-in type> cast (1, "foobar")
+%!error <TYPE must be a string> cast (1, {"foobar"})
+
--- a/scripts/miscellaneous/colon.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/colon.m	Mon Jan 12 09:17:35 2015 -0800
@@ -33,14 +33,14 @@
 ## @seealso{class, subsref, subsasgn}
 ## @end deftypefn
 
-function r = colon (varargin)
+function colon (varargin)
+
   if (nargin != 0)
     error ('colon: not defined for class "%s"', class (varargin{1}));
   endif
+
 endfunction
 
 
-%!error colon (1)
+%!error <colon: not defined for class "double"> colon (1)
 
-## FIXME -- what does colon () mean since it doesn't set a return value?
-
--- a/scripts/miscellaneous/compare_versions.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/compare_versions.m	Mon Jan 12 09:17:35 2015 -0800
@@ -80,87 +80,68 @@
 
   ## Make sure that the version numbers are valid.
   if (! (ischar (v1) && ischar (v2)))
-    error ("compare_versions: both version numbers must be strings");
+    error ("compare_versions: version numbers V1 and V2 must be strings");
   elseif (rows (v1) != 1 || rows (v2) != 1)
-    error ("compare_versions: version numbers must be a single row");
+    error ("compare_versions: version numbers V1 and V2 must be a single row");
   endif
 
   ## check and make sure that the operator is valid
   if (! ischar (operator))
-    error ("compare_versions: OPERATOR must be a character string");
+    error ("compare_versions: OPERATOR must be a string");
   elseif (numel (operator) > 2)
     error ("compare_versions: OPERATOR must be 1 or 2 characters long");
   endif
 
-  ## trim off any character data that is not part of a normal version
-  ## number
-  numbers = "0123456789.";
+  ## trim off any character data that is not part of a normal version number
+  v1firstchar = find (! (isdigit (v1) | v1 == "."), 1);
+  v2firstchar = find (! (isdigit (v2) | v2 == "."), 1);
 
-  v1firstchar = find (! ismember (v1, numbers), 1);
-  v2firstchar = find (! ismember (v2, numbers), 1);
-  if (! isempty (v1firstchar))
-    v1c = v1(v1firstchar:length (v1));
-    v1nochar = v1(1:v1firstchar-1);
-  else
+  if (isempty (v1firstchar))
     v1c = "";
     v1nochar = v1;
+  else
+    v1c = v1(v1firstchar:end);
+    v1nochar = v1(1:v1firstchar-1);
   endif
-  if (! isempty (v2firstchar))
-    v2c = v2(v2firstchar:length (v2));
-    v2nochar = v2(1:v2firstchar-1);
-  else
+  if (isempty (v2firstchar))
     v2c = "";
     v2nochar = v2;
-  endif
-
-  v1n = str2num (char (ostrsplit (v1nochar, ".")));
-  v2n = str2num (char (ostrsplit (v2nochar, ".")));
-  if ((isempty (v1n) && isempty (v1c)) || (isempty (v2n) && isempty (v2c)))
-    error ("compare_versions: given version strings are not valid: %s %s",
-           v1, v2);
+  else
+    v2c = v2(v2firstchar:end);
+    v2nochar = v2(1:v2firstchar-1);
   endif
 
-  ## Assume that any additional elements would be 0 if one is longer
-  ## than the other.
-  maxnumlen = max ([length(v1n) length(v2n)]);
-  if (length (v1n) < maxnumlen)
-    v1n(length(v1n)+1:maxnumlen) = 0;
+  v1n = str2double (ostrsplit (v1nochar, ".")');
+  if (isnan (v1n))
+    v1n = [];
   endif
-  if (length (v2n) < maxnumlen)
-    v2n(length(v2n)+1:maxnumlen) = 0;
+  v2n = str2double (ostrsplit (v2nochar, ".")');
+  if (isnan (v2n))
+    v2n = [];
   endif
 
-  ## Assume that any additional character elements would be 0 if one is
-  ## longer than the other.
+  if (isempty (v1n) && isempty (v1c))
+    error ("compare_versions: version string V1 is not valid: %s", v1);
+  elseif  (isempty (v2n) && isempty (v2c))
+    error ("compare_versions: version string V2 is not valid: %s", v2);
+  endif
+
+  ## Assume any additional elements would be 0 if one is longer than the other.
+  maxnumlen = max ([length(v1n) length(v2n)]);
+  v1n(end+1:maxnumlen) = 0;
+  v2n(end+1:maxnumlen) = 0;
+
+  ## Assume any additional character elements would be 0,
+  ## if one is longer than the other.
   maxcharlen = max ([length(v1c), length(v2c)]);
-  if (length (v1c) < maxcharlen)
-    v1c(length(v1c)+1:maxcharlen) = "\0";
-  endif
-  if (length (v2c) < maxcharlen)
-    v2c(length(v2c)+1:maxcharlen) = "\0";
-  endif
+  v1c(end+1:maxcharlen) = "\0";
+  v2c(end+1:maxcharlen) = "\0";
 
   ## Determine the operator.
-  if (any (ismember (operator, "=")))
-    equal_op = true;
-  else
-    equal_op = false;
-  endif
-  if (any (ismember (operator, "~!")))
-    not_op = true;
-  else
-    not_op = false;
-  endif
-  if (any (ismember (operator, "<")))
-    lt_op = true;
-  else
-    lt_op = false;
-  endif
-  if (any (ismember (operator, ">")))
-    gt_op = true;
-  else
-    gt_op = false;
-  endif
+  equal_op = any (operator == "=");
+  not_op = any (operator == "!" | operator == "~");
+  lt_op = any (operator == "<");
+  gt_op = any (operator == ">");
 
   ## Make sure that we don't have conflicting operators.
   if (gt_op && lt_op)
@@ -168,9 +149,9 @@
   elseif ((gt_op || lt_op) && not_op)
     error ("compare_versions: OPERATOR cannot contain not and greater than or less than symbols");
   elseif (strcmp (operator, "="))
-    error ("compare_versions: equality OPERATOR is \"==\", not \"=\"");
+    error ('compare_versions: equality OPERATOR is "==", not "="');
   elseif (! (equal_op || not_op || lt_op || gt_op))
-    error ("compare_versions: No valid OPERATOR specified");
+    error ("compare_versions: no valid OPERATOR specified");
   endif
 
   ## Compare the versions (making sure that they're the same shape)
@@ -180,7 +161,7 @@
     ## so that we only need to check for the output being greater than 1
     vcmp = -vcmp;
   endif
-  firstdiff = find (vcmp != 0, 1);
+  firstdiff = find (vcmp, 1);
 
   if (isempty (firstdiff))
     ## They're equal.
@@ -242,12 +223,22 @@
 %!assert (compare_versions ("0.1", "0.1", "~="), false)
 
 %% Test input validation
-%!error (compare_versions (0.1, "0.1", "=="))
-%!error (compare_versions ("0.1", 0.1, "=="))
-%!error (compare_versions (["0";".";"1"], "0.1", "=="))
-%!error (compare_versions ("0.1", ["0";".";"1"], "=="))
-%!error (compare_versions ("0.1", "0.1", "<>"))
-%!error (compare_versions ("0.1", "0.1", "!>"))
-%!error (compare_versions ("0.1", "0.1", "="))
-%!error (compare_versions ("0.1", "0.1", "aa"))
+%!error compare_versions ()
+%!error compare_versions (1)
+%!error compare_versions (1,2)
+%!error compare_versions (1,2,3,4)
+%!error <V1 and V2 must be strings> compare_versions (0.1, "0.1", "==")
+%!error <V1 and V2 must be strings> compare_versions ("0.1", 0.1, "==")
+%!error <V1 and V2 must be a single row> compare_versions (["0";".";"1"], "0.1", "==")
+%!error <V1 and V2 must be a single row> compare_versions ("0.1", ["0";".";"1"], "==")
+%!error <OPERATOR must be a string> compare_versions ("0.1", "0.1", 1)
+%!error <OPERATOR must be 1 or 2> compare_versions ("0.1", "0.1", "==>")
+%!error <V1 is not valid> compare_versions (".", "0.1", "==")
+%!error <V2 is not valid> compare_versions ("0.1", ".", "==")
 
+%!error <cannot contain both greater and less than> compare_versions ("0.1", "0.1", "<>")
+%!error <cannot contain not and greater than> compare_versions ("0.1", "0.1", "!>")
+%!error <cannot contain not and greater than> compare_versions ("0.1", "0.1", "!<")
+%!error <equality OPERATOR is "=="> compare_versions ("0.1", "0.1", "=")
+%!error <no valid OPERATOR> compare_versions ("0.1", "0.1", "aa")
+
--- a/scripts/miscellaneous/computer.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/computer.m	Mon Jan 12 09:17:35 2015 -0800
@@ -17,45 +17,49 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {[@var{c}, @var{maxsize}, @var{endian}] =} computer ()
+## @deftypefn  {Function File} {} computer ()
+## @deftypefnx {Function File} {@var{c} =} computer ()
+## @deftypefnx {Function File} {[@var{c}, @var{maxsize}] =} computer ()
+## @deftypefnx {Function File} {[@var{c}, @var{maxsize}, @var{endian}] =} computer ()
 ## @deftypefnx {Function File} {@var{arch} =} computer ("arch")
 ## Print or return a string of the form @var{cpu}-@var{vendor}-@var{os}
-## that identifies the kind of computer Octave is running on.  If invoked
-## with an output argument, the value is returned instead of printed.  For
-## example:
+## that identifies the type of computer that Octave is running on.
+##
+## If invoked with an output argument, the value is returned instead of
+## printed.  For example:
 ##
 ## @example
 ## @group
 ## computer ()
 ##    @print{} i586-pc-linux-gnu
 ##
-## x = computer ()
-##    @result{} x = "i586-pc-linux-gnu"
+## mycomp = computer ()
+##    @result{} mycomp = "i586-pc-linux-gnu"
 ## @end group
 ## @end example
 ##
 ## If two output arguments are requested, also return the maximum number
-## of elements for an array.
+## of elements for an array.  This will depend on whether Octave has been
+## compiled with 32-bit or 64-bit index vectors.
 ##
 ## If three output arguments are requested, also return the byte order
 ## of the current system as a character (@qcode{"B"} for big-endian or
 ## @qcode{"L"} for little-endian).
 ##
-## If the argument @qcode{"arch"} is specified, return a string
-## indicating the architecture of the computer on which Octave is
-## running.
+## If the argument @qcode{"arch"} is specified, return a string indicating the
+## architecture of the computer on which Octave is running.
+## @seealso{isunix, ismac, ispc}
 ## @end deftypefn
 
 function [c, maxsize, endian] = computer (a)
 
-  if (nargin == 1 && ischar (a) && strcmpi (a, "arch"))
-    tmp = ostrsplit (octave_config_info ("canonical_host_type"), "-");
-    if (numel (tmp) == 4)
-      c = sprintf ("%s-%s-%s", tmp{4}, tmp{3}, tmp{1});
-    else
-      c = sprintf ("%s-%s", tmp{3}, tmp{1});
-    endif
-  elseif (nargin == 0)
+  if (nargin > 1)
+    print_usage ();
+  elseif (nargin == 1 && ! strcmpi (a, "arch"))
+    error ('computer: "arch" is only valid argument');
+  endif
+
+  if (nargin == 0)
     msg = octave_config_info ("canonical_host_type");
 
     if (strcmp (msg, "unknown"))
@@ -63,24 +67,35 @@
     endif
 
     if (nargout == 0)
-      printf ("%s\n", msg);
+      disp (msg);
     else
       c = msg;
-      if (strcmp (octave_config_info ("USE_64_BIT_IDX_T"), "true"))
-        maxsize = 2^63-1;
-      else
-        maxsize = 2^31-1;
+      if (isargout (2))
+        if (strcmp (octave_config_info ("USE_64_BIT_IDX_T"), "true"))
+          maxsize = 2^63-1;
+        else
+          maxsize = 2^31-1;
+        endif
       endif
-      if (octave_config_info ("words_big_endian"))
-        endian = "B";
-      elseif (octave_config_info ("words_little_endian"))
-        endian = "L";
-      else
-        endian = "?";
+      if (isargout (3))
+        if (octave_config_info ("words_big_endian"))
+          endian = "B";
+        elseif (octave_config_info ("words_little_endian"))
+          endian = "L";
+        else
+          endian = "?";
+        endif
       endif
     endif
   else
-    print_usage ();
+    ## "arch" argument asked for
+    tmp = ostrsplit (octave_config_info ("canonical_host_type"), "-");
+    if (numel (tmp) == 4)
+      c = sprintf ("%s-%s-%s", tmp{4}, tmp{3}, tmp{1});
+    else
+      c = sprintf ("%s-%s", tmp{3}, tmp{1});
+    endif
+
   endif
 
 endfunction
@@ -90,5 +105,6 @@
 %!assert (computer (), octave_config_info ("canonical_host_type"))
 %!assert (ischar (computer ("arch")))
 
-%!error computer (2)
+%!error computer (1,2)
+%!error <"arch" is only valid argument> computer ("xyz")
 
--- a/scripts/miscellaneous/copyfile.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/copyfile.m	Mon Jan 12 09:17:35 2015 -0800
@@ -19,11 +19,12 @@
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {[@var{status}, @var{msg}, @var{msgid}] =} copyfile (@var{f1}, @var{f2})
 ## @deftypefnx {Function File} {[@var{status}, @var{msg}, @var{msgid}] =} copyfile (@var{f1}, @var{f2}, 'f')
-## Copy the file @var{f1} to the destination @var{f2}.
+## Copy the source files or directories @var{f1} to the destination @var{f2}.
 ##
 ## The name @var{f1} may contain globbing patterns.  If @var{f1} expands to
 ## multiple file names, @var{f2} must be a directory.
-## when the force flag @qcode{'f'} is given any existing files will be
+##
+## When the force flag @qcode{'f'} is given any existing files will be
 ## overwritten without prompting.
 ##
 ## If successful, @var{status} is 1, and @var{msg}, @var{msgid} are empty
@@ -45,8 +46,8 @@
   msg = "";
   msgid = "";
 
-  ## FIXME: maybe use the same method as in ls to allow users control
-  ## over the command that is executed.
+  ## FIXME: Maybe use the same method as in ls to allow users control
+  ##        over the command that is executed.
 
   if (ispc () && ! isunix ()
       && isempty (file_in_path (getenv ("PATH"), "cp.exe")))
@@ -59,26 +60,22 @@
   endif
 
   ## Input type check.
-  if (! (ischar (f1) || iscellstr (f1)))
-    error ("copyfile: F1 must be a character string or a cell array of character strings");
+  if (ischar (f1))
+    f1 = cellstr (f1);
+  elseif (! iscellstr (f1))
+    error ("copyfile: F1 must be a string or a cell array of strings");
   endif
-
   if (! ischar (f2))
-    error ("copyfile: F2 must be a character string");
+    error ("copyfile: F2 must be a string");
   endif
 
   if (nargin == 3 && strcmp (force, "f"))
     cmd = [cmd " " cmd_force_flag];
   endif
 
-  ## If f1 isn't a cellstr convert it to one.
-  if (ischar (f1))
-    f1 = cellstr (f1);
-  endif
-
-  ## If f1 has more than 1 element f2 must be a directory
+  ## If f1 has more than 1 element then f2 must be a directory
   isdir = (exist (f2, "dir") != 0);
-  if (length (f1) > 1 && ! isdir)
+  if (numel (f1) > 1 && ! isdir)
     error ("copyfile: when copying multiple files, F2 must be a directory");
   endif
 
@@ -132,3 +129,36 @@
 
 endfunction
 
+
+%!test
+%! unwind_protect
+%!   f1 = tempname;
+%!   tmp_var = pi;
+%!   save (f1, "tmp_var");
+%!   f2 = tempname;
+%!   assert (copyfile (f1, f2));
+%!   assert (exist (f2, "file")); 
+%!   fid = fopen (f1, "rb");
+%!   assert (fid >= 0);
+%!   orig_data = fread (fid);
+%!   fclose (fid);
+%!   fid = fopen (f2, "rb");
+%!   assert (fid >= 0);
+%!   new_data = fread (fid);
+%!   fclose (fid);
+%!   if (orig_data != new_data)
+%!     error ("copied file not equal to original file!");
+%!   endif
+%! unwind_protect_cleanup
+%!   delete (f1);
+%!   delete (f2);
+%! end_unwind_protect
+
+## Test input validation
+%!error copyfile ()
+%!error copyfile (1)
+%!error copyfile (1,2,3,4)
+%!error <F1 must be a string> copyfile (1, "foobar")
+%!error <F2 must be a string> copyfile ("foobar", 1)
+%!error <F2 must be a directory> copyfile ({"a", "b"}, "%_NOT_A_DIR_%") 
+
--- a/scripts/miscellaneous/debug.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/debug.m	Mon Jan 12 09:17:35 2015 -0800
@@ -18,8 +18,10 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} debug ()
-## Summary of debugging commands.  For more information on each command
-## and available options use @code{help CMD}.
+## Summary of debugging commands.
+##
+## For more information on each command and available options use
+## @code{help CMD}.
 ## 
 ## The debugging commands available in Octave are
 ##
@@ -96,3 +98,7 @@
   help ("debug");
 endfunction
 
+
+## Mark file as being tested.  No real test needed for a documentation .m file
+%!assert (1)
+
--- a/scripts/miscellaneous/delete.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/delete.m	Mon Jan 12 09:17:35 2015 -0800
@@ -18,37 +18,47 @@
 
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {} delete (@var{file})
+## @deftypefnx {Function File} {} delete (@var{file1}, @var{file2}, @dots{})
 ## @deftypefnx {Function File} {} delete (@var{handle})
 ## Delete the named file or graphics handle.
 ##
-## Deleting graphics objects is the proper way to remove
+## @var{file} may contain globbing patterns such as @samp{*}.  Multiple files
+## to be deleted may be specified in the same function call.
+##
+## @var{handle} may be a scalar or vector of graphic handles to delete.
+##
+## Programming Note: Deleting graphics objects is the proper way to remove
 ## features from a plot without clearing the entire figure.
-## @seealso{clf, cla, unlink}
+## @seealso{clf, cla, unlink, rmdir}
 ## @end deftypefn
 
 ## Author: jwe
 
-function delete (arg)
+function delete (varargin)
 
-  if (nargin != 1)
+  if (nargin == 0)
     print_usage ();
   endif
 
-  if (ischar (arg))
-    files = glob (arg);
-    if (isempty (files))
-      warning ("delete: no such file: %s", arg);
-    endif
-    for i = 1:length (files)
-      file = files{i};
-      [err, msg] = unlink (file);
-      if (err)
-        warning ("delete: %s: %s", file, msg);
+  if (iscellstr (varargin))
+    for arg = varargin
+      files = glob (arg{1});
+      if (isempty (files))
+        warning ("delete: no such file: %s", arg{1});
       endif
+      for i = 1:length (files)
+        file = files{i};
+        [err, msg] = unlink (file);
+        if (err)
+          warning ("delete: %s: %s", file, msg);
+        endif
+      endfor
     endfor
-  elseif (all (ishandle (arg(:))))
+
+  elseif (isscalar (varargin) && all (ishandle (varargin{1}(:))))
     ## Delete a graphics object.
-    __go_delete__ (arg);
+    __go_delete__ (varargin{1});
+
   else
     error ("delete: first argument must be a filename or graphics handle");
   endif
@@ -56,8 +66,30 @@
 endfunction
 
 
+%!test
+%! unwind_protect
+%!   file = tempname;
+%!   tmp_var = pi;
+%!   save (file, "tmp_var");
+%!   assert (exist (file, "file"));
+%!   delete (file);
+%!   assert (! exist (file, "file"));
+%! unwind_protect_cleanup
+%!   unlink (file);
+%! end_unwind_protect
+
+%!test
+%! unwind_protect
+%!   hf = figure ("visible", "off"); 
+%!   hl = plot (1:10);
+%!   assert (get (gca, "children"), hl); 
+%!   delete (hl);
+%!   assert (get (gca, "children"), zeros (0,1)); 
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
 %% Test input validation
 %!error delete ()
-%!error delete (1, 2)
 %!error <first argument must be a filename> delete (struct ())
 
--- a/scripts/miscellaneous/desktop.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/desktop.m	Mon Jan 12 09:17:35 2015 -0800
@@ -17,7 +17,7 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} @var{used} = desktop ("-inuse")
+## @deftypefn {Function File} {@var{used} =} desktop ("-inuse")
 ## Return true if the desktop (GUI) is currently in use.
 ## @seealso{isguirunning}
 ## @end deftypefn
--- a/scripts/miscellaneous/dir.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/dir.m	Mon Jan 12 09:17:35 2015 -0800
@@ -51,21 +51,21 @@
 ## than a single directory or file.
 ##
 ## @var{directory} is subject to shell expansion if it contains any wildcard
-## characters @samp{*}, @samp{?}, @samp{[]}.  If you want to find a
-## literal example of a wildcard character you must escape it using the
-## backslash operator @samp{\}.
+## characters @samp{*}, @samp{?}, @samp{[]}.  To find a literal example of a
+## wildcard character the wildcard must be escaped using the backslash operator
+## @samp{\}.
 ##
 ## Note that for symbolic links, @code{dir} returns information about
 ## the file that the symbolic link points to rather than the link itself.
 ## However, if the link points to a nonexistent file, @code{dir} returns
 ## information about the link.
-## @seealso{ls, readdir, glob, what, stat}
+## @seealso{ls, readdir, glob, what, stat, lstat}
 ## @end deftypefn
 
 ## Author: jwe
 
-## FIXME: This is quite slow for large directories, so perhaps
-##        it should be converted to C++.
+## FIXME: This is quite slow for large directories.
+##        Perhaps it should be converted to C++?
 
 function retval = dir (directory)
 
@@ -75,79 +75,78 @@
     print_usage ();
   endif
 
+  if (! ischar (directory))
+    error ("dir: DIRECTORY argument must be a string");
+  endif
+
   ## Prep the retval.
   info = struct (zeros (0, 1),
                  {"name", "date", "bytes", "isdir", "datenum", "statinfo"});
 
-  if (ischar (directory))
-    if (strcmp (directory, "*"))
-      directory = ".";
-    endif
-    if (strcmp (directory, "."))
-      flst = {"."};
-      nf = 1;
-    else
-      flst = glob (directory);
-      nf = length (flst);
-    endif
 
-    ## Determine the file list for the case where a single directory is
-    ## specified.
-    if (nf == 1)
-      fn = flst{1};
-      [st, err, msg] = stat (fn);
-      if (err < 0)
-        warning ("dir: 'stat (%s)' failed: %s", fn, msg);
-        nf = 0;
-      elseif (S_ISDIR (st.mode))
-        flst = readdir (flst{1});
-        nf = length (flst);
-        for i = 1:nf
-          flst{i} = fullfile (fn, flst{i});
-        endfor
-      endif
-    endif
+  if (strcmp (directory, "*"))
+    directory = ".";
+  endif
+  if (strcmp (directory, "."))
+    flst = {"."};
+    nf = 1;
+  else
+    flst = glob (directory);
+    nf = numel (flst);
+  endif
 
-    if (length (flst) > 0)
-      ## Collect results.
-      for i = nf:-1:1
-        fn = flst{i};
-        [st, err, msg] = lstat (fn);
-        if (err < 0)
-          warning ("dir: 'lstat (%s)' failed: %s", fn, msg);
-        else
-          ## If we are looking at a link that points to something,
-          ## return info about the target of the link, otherwise, return
-          ## info about the link itself.
-          if (S_ISLNK (st.mode))
-            [xst, err, msg] = stat (fn);
-            if (! err)
-              st = xst;
-            endif
-          endif
-          [dummy, fn, ext] = fileparts (fn);
-          fn = [fn ext];
-          info(i,1).name = fn;
-          lt = localtime (st.mtime);
-          info(i,1).date = strftime ("%d-%b-%Y %T", lt);
-          info(i,1).bytes = st.size;
-          info(i,1).isdir = S_ISDIR (st.mode);
-          info(i,1).datenum = datenum (lt.year + 1900, lt.mon + 1, lt.mday,
-                                       lt.hour, lt.min, lt.sec);
-          info(i,1).statinfo = st;
-        endif
+  ## Determine the file list for the case where a single directory is specified.
+  if (nf == 1)
+    fn = flst{1};
+    [st, err, msg] = stat (fn);
+    if (err < 0)
+      warning ("dir: 'stat (%s)' failed: %s", fn, msg);
+      nf = 0;
+    elseif (S_ISDIR (st.mode))
+      flst = readdir (flst{1});
+      nf = numel (flst);
+      for i = 1:nf
+        flst{i} = fullfile (fn, flst{i});
       endfor
     endif
+  endif
 
-  else
-    error ("dir: expecting directory or filename to be a char array");
+  if (numel (flst) > 0)
+    ## Collect results.
+    for i = nf:-1:1
+      fn = flst{i};
+      [st, err, msg] = lstat (fn);
+      if (err < 0)
+        warning ("dir: 'lstat (%s)' failed: %s", fn, msg);
+      else
+        ## If we are looking at a link that points to something,
+        ## return info about the target of the link, otherwise, return
+        ## info about the link itself.
+        if (S_ISLNK (st.mode))
+          [xst, err, msg] = stat (fn);
+          if (! err)
+            st = xst;
+          endif
+        endif
+        [dummy, fn, ext] = fileparts (fn);
+        fn = [fn ext];
+        info(i,1).name = fn;
+        lt = localtime (st.mtime);
+        info(i,1).date = strftime ("%d-%b-%Y %T", lt);
+        info(i,1).bytes = st.size;
+        info(i,1).isdir = S_ISDIR (st.mode);
+        info(i,1).datenum = datenum (lt.year + 1900, lt.mon + 1, lt.mday,
+                                     lt.hour, lt.min, lt.sec);
+        info(i,1).statinfo = st;
+      endif
+    endfor
   endif
 
   ## Return the output arguments.
   if (nargout > 0)
     ## Return the requested structure.
     retval = info;
-  elseif (length (info) > 0)
+  elseif (numel (info) > 0)
     ## Print the structure to the screen.
     printf ("%s", list_in_columns ({info.name}));
   else
@@ -156,3 +155,26 @@
 
 endfunction
 
+
+%!test
+%! list = dir ();
+%! assert (isstruct (list) && ! isempty (list));
+%! assert (fieldnames (list),
+%!         {"name"; "date"; "bytes"; "isdir"; "datenum"; "statinfo"});
+%!
+%! if (isunix ())
+%!   assert ({list(1:2).name}, {".", ".."});
+%!   assert ([list(1:2).isdir], [true true]);
+%! endif
+%!
+%! ## test that specifying a filename works the same as using a directory.
+%! found = find (! [list.isdir], 1);
+%! if (! isempty (found))
+%!   list2 = dir (list(found).name);
+%!   assert (list(found), list2);
+%! endif
+
+## Test input validation
+%!error <DIRECTORY argument must be a string> dir (1)
+%!warning <nonexistent directory> dir ("_%UNLIKELY_DIR_NAME%_");
+
--- a/scripts/miscellaneous/dos.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/dos.m	Mon Jan 12 09:17:35 2015 -0800
@@ -21,12 +21,15 @@
 ## @deftypefnx {Function File} {@var{status} =} dos ("@var{command}")
 ## @deftypefnx {Function File} {[@var{status}, @var{text}] =} dos ("@var{command"})
 ## @deftypefnx {Function File} {[@dots{}] =} dos ("@var{command}", "-echo")
-## Execute a system command if running under a Windows-like operating
-## system, otherwise do nothing.  Return the exit status of the program
-## in @var{status} and any output from the command in @var{text}.
+## Execute a system command if running under a Windows-like operating system,
+## otherwise do nothing.
+##
+## Octave waits for the external command to finish before returning the exit
+## status of the program in @var{status} and any output in @var{text}.
+##
 ## When called with no output argument, or the @qcode{"-echo"} argument is
 ## given, then @var{text} is also sent to standard output.
-## @seealso{unix, system, isunix, ispc}
+## @seealso{unix, system, isunix, ismac, ispc}
 ## @end deftypefn
 
 ## Author: octave-forge ???
--- a/scripts/miscellaneous/dump_prefs.m	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-## Copyright (C) 1994-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  {Function File} {} dump_prefs ()
-## @deftypefnx {Function File} {} dump_prefs (@var{fid})
-## Dump all of the current user preference variables in a format that can be
-## parsed by Octave later.  @var{fid} is a file descriptor as returned by
-## @code{fopen}.  If @var{file} is omitted, the listing is printed to stdout.
-## @end deftypefn
-
-## Author: jwe
-
-function dump_prefs (file)
-
-  if (nargin == 0)
-    file = stdout;
-  endif
-
-  ## FIXME -- it would be nice to be able to get the list of
-  ## built-in variables directly from Octave so that we wouldn't have to
-  ## remember to update it each time the list of preference variables
-  ## changes
-
-  ## Note that these are no longer variables.
-
-  sym_list = ["EDITOR";
-              "EXEC_PATH";
-              "IMAGE_PATH";
-              "PAGER";
-              "PS1";
-              "PS2";
-              "PS4";
-              "beep_on_error";
-              "completion_append_char";
-              "crash_dumps_octave_core";
-              "echo_executing_commands";
-              "fixed_point_format";
-              "gnuplot_binary";
-              "gnuplot_command_end";
-              "gnuplot_command_plot";
-              "gnuplot_command_replot";
-              "gnuplot_command_splot";
-              "gnuplot_command_title";
-              "gnuplot_command_using";
-              "gnuplot_command_with";
-              "history_file";
-              "history_size";
-              "ignore_function_time_stamp";
-              "info_file";
-              "info_program";
-              "makeinfo_program";
-              "max_recursion_depth";
-              "output_max_field_width";
-              "output_precision";
-              "page_output_immediately";
-              "page_screen_output";
-              "print_answer_id_name";
-              "print_empty_dimensions";
-              "save_precision";
-              "saving_history";
-              "sighup_dumps_octave_core";
-              "sigterm_dumps_octave_core";
-              "silent_functions";
-              "split_long_rows";
-              "string_fill_char";
-              "struct_levels_to_print";
-              "suppress_verbose_help_message"];
-
-  for i = 1:rows (sym_list)
-    sym = deblank (sym_list(i,:));
-    try
-      val = feval (sym);
-      if (isnumeric (val))
-        val = sprintf ("%g", val);
-      endif
-      fprintf (file, "  %s = %s\n", sym, val);
-    catch
-      fprintf (file, "# %s = <no value or error in displaying it>\n", sym);
-    end_try_catch
-  endfor
-
-endfunction
-
--- a/scripts/miscellaneous/edit.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/edit.m	Mon Jan 12 09:17:35 2015 -0800
@@ -23,7 +23,7 @@
 ## Edit the named function, or change editor settings.
 ##
 ## If @code{edit} is called with the name of a file or function as
-## its argument it will be opened in the text editor defined by @code{EDITOR}.
+## its argument it will be opened in the text editor defined by @env{EDITOR}.
 ##
 ## @itemize @bullet
 ## @item
@@ -221,10 +221,10 @@
     if (exist (FUNCTION.HOME, "dir") == 7)
       curr_dir = pwd ();
       unwind_protect
-        chdir (FUNCTION.HOME);
+        cd (FUNCTION.HOME);
         do_edit (FUNCTION.EDITOR, "", FUNCTION.MODE);
       unwind_protect_cleanup
-        chdir (curr_dir);
+        cd (curr_dir);
       end_unwind_protect
     else
       do_edit (FUNCTION.EDITOR, "", FUNCTION.MODE);
@@ -330,7 +330,7 @@
 
     ## If editing a new file, prompt for creation if gui is running
     if (isguirunning ())
-      if (! __octave_link_edit_file__ (file,"prompt"));
+      if (! __octave_link_edit_file__ (file, "prompt"));
         return;
       endif
     endif
@@ -340,12 +340,22 @@
     ## If in gui-mode, create it before or editor would prompt again.
     fileandpath = file;
     idx = rindex (file, ".");
-    name = file(1:idx-1);
-    ext = file(idx+1:end);
+    if (idx)
+      name = file(1:idx-1);
+      ext = file(idx+1:end);
+    else
+      name = file;
+      ext = "";
+    endif
     if (! any (strcmp (ext, {"cc", "m"})))
       ## Some unknown file.  Create and open it or just open it.
+      if (isempty (ext))
+        fileandpath = [fileandpath ".m"];  # Add .m extension per default
+      endif
       if (isguirunning ())
         ## Write the initial file (if there is anything to write)
+        ## Give user the opportunity to change the file extension
+        fileandpath = uiputfile (fileandpath);
         fid = fopen (fileandpath, "wt");
         if (fid < 0)
           error ("edit: could not create %s", fileandpath);
--- a/scripts/miscellaneous/error_ids.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/error_ids.m	Mon Jan 12 09:17:35 2015 -0800
@@ -46,12 +46,11 @@
 ## @end table
 ##
 
-
 function error_ids ()
   help ("error_ids");
 endfunction
 
 
-## Remove from test statistics.  No real tests possible
+## Mark file as being tested.  No real test needed for a documentation .m file
 %!assert (1)
 
--- a/scripts/miscellaneous/fact.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/fact.m	Mon Jan 12 09:17:35 2015 -0800
@@ -19,255 +19,256 @@
 
 ## -*- texinfo -*-
 ## @deftypefn  {Command} {} fact
-## @deftypefnx {Function File} {T =} fact()
+## @deftypefnx {Function File} {@var{truth} =} fact ()
 ## Display an amazing and random fact about the world's greatest hacker.
 ## @end deftypefn
 
 
-function f = fact ()
+function truth = fact ()
   persistent wisdom = ...
-      {
-       "Richard Stallman takes notes in binary.";
-       "Richard Stallman doesn't need sudo. I will make him a sandwich anyway.";
-       "Richard Stallman is my shephurd, and I am his GNU.";
-       "Richard Stallman doesn't wget, Richard Stallman wdemands!";
-       "Richard Stallman can touch MC Hammer.";
-       "Richard Stallman doesn't read web pages. They write to him.";
-       "Richard Stallman gets 9 bits to the byte.";
-       "Richard Stallman doesn't really believe in open software, because it's not free enough.";
-       "Richard Stallman can leave neutral or negative feedback on eBay.";
-       "Richard Stallman is the only man alive who can pronounce GNU the way it is meant to be pronounced.";
-       "Richard Stallman does not own a mobile phone because he can fashion a crude convex dish and shout into it at the exact resonant frequency of the ozone, causing a voice to seemingly come from the sky above his intended recipient.";
-       "Richard Stallman is so handsome that when he was young he was responsible for all other geeks not being able to get girls. This is why he has to cover his face with a thick layer of hair.";
-       "Some people check their computers for viruses. Viruses check their computers for Richard Stallman.";
-       "Richard Stallman memorises all his documents. In binary. He just types everything in whenever he needs a document.";
-       "When Richard Stallman makes a sudo command, he loses permissions.";
-       "Richard Stallman's beard is made of parentheses.";
-       "Richard Stallman's DNA is in binary.";
-       "Richard Stallman's nervous system is completely wireless.";
-       "Richard Stallman's brain accepts UNIX commands.";
-       "If Richard Stallman has 1GB of RAM, and if you have 1GB of RAM, Richard Stallman has more RAM than you.";
-       "Richard Stallman eats ethernet cables. That's why they invented wireless.";
-       "Richard Stallman has a katana. 'Nuff said.";
-       "Richard Stallman wrote a program that divides by zero.";
-       "Richard Stallman doesn't use zip drives; he just squeezes the hard drive.";
-       "Richard Stallman's compiler is afraid to report errors.";
-       "Richard Stallman wrote the compiler God used. The Big Bang was the Universe's first segfault.";
-       "Richard Stallman successfully compiled a kernel of popcorn.";
-       "Richard Stallman doesn't write programs; they write themselves out of reverence.";
-       "Richard Stallman can make infinite loops end.";
-       "Richard Stallman's anti-virus programs cures HIV.";
-       "Richard Stallman's computer doesn't have a clock; it defines what time it is.";
-       "Richard Stallman wrote a program to compute the last digit of pi.";
-       "Richard Stallman doesn't use web browsers. He sends a link to a daemon that uses wget to fetch the page and sends it back to him.";
-       "Richard Stallman can solve the halting problem... in polynomial time.";
-       "For Richard Stallman, polynomial time is O(1).";
-       "Richard Stallman didn't \"write\" Emacs or created it in his own image. Richard Stallman made Emacs an instance of himself.";
-       "Richard Stallman can coerce meaningful data from /dev/null.";
-       "Some people wear Linus Torvalds pyjamas to bed, Linus Torvalds wears Richard Stallman pyjamas.";
-       "There is no software development process, only a bunch of programs Richard Stallman allows to exist.";
-       "Richard Stallman spends his leisure time programming with Guile on GNU Hurd.";
-       "Richard Stallman's left and right hands are named \"(\" and \")\" ";
-       "Richard Stallman first words were actually syscalls.";
-       "Richard Stallman didn't create the singularity. He is the singularity. GNU/Linux is only the event horizon.";
-       "When Richard Stallman pipes to more, he gets less ";
-       "Richard Stallman never showers; he runs 'make clean'.";
-       "Richard Stallman needs neither mouse nor keyboard to operate his computer. He just stares it down until it does what he wants.";
-       "Richard Stallman didn't write the GPL. He is the GPL.";
-       "Richard Stallman's pinky finger is really a USB memory stick.";
-       "Richard Stallman called his operating system GNU because he created it before computers existed, when actual gnus were used for calculations.";
-       "In Soviet Russia, Richard Stallman is still Richard Stallman!";
-       "Richard Stallman's flute only plays free music.";
-       "When Richard Stallman uses floats, there are no rounding errors.";
-       "Richard Stallman wrote a program so powerful it knows the question to 42.";
-       "Richard Stallman released his own DNA under GNU FDL.";
-       "Richard Stallman knows the entire Wikipedia by heart, markup included.";
-       "Richard Stallman wrote the HAL9000 OS.";
-       "Richard Stallman's laser pointer is a lightsaber.";
-       "Richard Stallman never steps down; he shifts the universe up.";
-       "Richard Stallman doesn't maintain code; he stares at it until it fixes itself out of reverence.";
-       "Richard Stallman doesn't use an editor; he sets the fundamental constants of the universe so that a magnetic platter with his code on it evolves itself.";
-       "Richard Stallman doesn’t code; he dares the computer to not do his bidding.";
-       "Global warming is caused by Richard Stallman's rage towards non-free software.";
-       "Rather than being birthed like a normal child, Richard Stallman instead instantiated himself polymorphically. Shortly thereafter he grew a beard.";
-       "Richard Stallman discovered extra-terrestrial life but killed them because they distributed non-free software.";
-       "Richard Stallman doesn't evaluate expressions; expressions evaluate to Richard Stallman.";
-       "Richard Stallman can see Russia from his house.";
-       "Richard Stallman proved P=NP, twice!";
-       "Richard Stallman knows of an unfixed bug in TeX.";
-       "Richard Stallman can write a context-free grammar for C.";
-       "Richard Stallman can determine whether an arbitrary program will terminate.";
-       "Richard Stallman's computer has only two buttons. One is for guests.";
-       "Richard Stallman does not actually write programs. He comes up with a length and digit index in pi.";
-       "Richard Stallman's distributed version control system is a flamewar on Usenet.";
-       "Richard Stallman wrote the first version of Emacs on a typewriter.";
-       "Richard Stallman has no known weaknesses, except for a phobia against soap.";
-       "Richard Stallman is not affected by Godwin's Law.";
-       "Richard Stallman can write an anti-virus program that cures HIV. Too bad he never writes anti-virus programs.";
-       "Richard Stallman' facial hair is \"free as in beard\"";
-       "Richard Stallman is licensed under GPL, so you can clone him and redistribute copies so you can help your neighbor. For example a version that take a bath more often.";
-       "Richard Stallman doesn't code; he just travels around the world.";
-       "Richard Stallman was coded by himself in lisp with Emacs.";
-       "Richard Stallman doesn't eat McDonald's because the machine that kills the cows uses proprietary software.";
-       "There is no chin behind Richard Stallman's legendary beard, there is only another Emacs.";
-       "In an average living room there are 1,242 objects Richard Stallman could use to write an OS, including the room itself.";
-       "Vendor lock-in is when vendors lock themselves inside of a building out of fear of Richard Stallman's wrath.";
-       "When Richard Stallman executes ps -e, you show up.";
-       "When Richard Stallman gets angry he doesn't swear; he recurses.";
-       "On Richard Stallman's computer the bootloader is contained in his .emacs.";
-       "Richard Stallman can make any operating system free, free from drivers.";
-       "Richard Stallman programmed Chuck Norris.";
-       "Behind Richard Stallman's beard there is another fist, to code faster.";
-       "Richard Stallman won a Sudoku that started with only one number in each line.";
-       "Richard Stallman's brain compiles and runs C code.";
-       "Richard Stallman wrote the first version of Emacs using Emacs.";
-       "Richard Stallman never gonna give you up, never gonna let you down, never gonna run around and desert you, never gonna make you cry, never gonna say goodbye, never gonna tell a lie and hurt you.";
-       "Richard Stallman, upon reading these facts, didn't laugh at all. Instead, he complained that he is being linked to that dirty \"open source\" software. He also asked it to be changed to \"free software\", in order to raise awareness for software freedom in our society.";
-       "Richard Stallman has no problem using Emacs. He wrote it with his 4 hands.";
-       "Richard Stallman will revert the big rip by adding parenthesis to the dark matter.";
-       "When you make a Google search and it doesn't find the answer, Google gently consults Richard Stallman.";
-       "Richard Stallman's uptime is over 53 years. And counting up.";
-       "Richard Stallman's portable music player can play ogg and WMA, but is too afraid to invoke Richard Stallman's wrath by playing WMA. Ogg it is, then.";
-       "Richard Stallman will never die, but may some day go to /dev/null.";
-       "Richard Stallman once got swine flu, but it got cleansed by hereditary GPL and thus got assimilated.";
-       "Richard Stallman don't cut his hair because there are no GNU/Scissors.";
-       "Richard Stallman is the one who trims Chuck Norris beard. And he does it freely, of course.";
-       "Richard Stallman does not take bath, for the hydroelectric company uses proprietary software.";
-       "Agent Smith loves Richard Stallman's scent.";
-       "Richard Stallman is the One.";
-       "\"They can take our lives, but they can never take our freedom.\" -- William Wallace after a little talk with Richard Stallman.";
-       "Richard Stallman can connect to any brain using an Emacs ssh client.";
-       "Richard Stallman ported Emacs to Intel 4004 chip.";
-       "Richard Stallman did not write GNU Emacs, he simply read the source code from /dev/null.";
-       "Richard Stallman once used GDB to reverse-engineer Windows 7 into a free operating system - able to run on GNU Emacs!";
-       "Richard Stallman does not contribute to open source projects; open source projects contribute to Richard Stallman, and then call themselves free software projects.";
-       "Richard Stallman programmed himself before he could even exist";
-       "Richard Stallman can fill up /dev/null.";
-       "Richard Stallman is so zealous about privacy he has /dev/null as his home.";
-       "When Richard Stallman runs /bin/false, it returns \"true\".";
-       "Richard Stallman doesn't like money, because banks don't run on free software.";
-       "Richard Stallman uses GNU tar to compress air.";
-       "When Richard Stallman reports a bug, the bug prefers to squash itself instead of facing Richard Stallman's wrath.";
-       "There are no Windows in Richard Stallman's house... only Doors...";
-       "Richard Stallman doesn't like neither PCs-Intel nor Burger King... He prefers e-Macs...";
-       "Richard Stallman can use grep to find Jimmy Hoffa.";
-       "Richard Stallman made it possible to not absolutely abhor HPUX.";
-       "When Richard Stallman pours his alphabets cereal into a bowl, only G's, N's, and U's come out.";
-       "Richard Stallman is pronounced \"GNU slash Stallman\"";
-       "Richard Stallman doesn't mind if you read his mail as long as you don't delete it before he reads it.";
-       "Richard Stallman is just a guy who has strong principles and decided to follow them.";
-       "Richard Stallman knows that you don't have class because it is a keyword that he defined.";
-       "Richard Stallman doesn't need a qwerty/dvorak keyboard only two buttons \"1\" and \"0\" and his erect penis.";
-       "On the first day Richard Stallman said M-x create-light.";
-       "Richard Stallman once went out of scope for a while. The garbage collector never dared to touch him.";
-       "Richard Stallman does not compile; he closes his eyes, and see energy lines created between bit blocks by the compiler optimizations.";
-       "intx80 first calls Richard Stallman before calling sys_call.";
-       "Tron is actually a biographical story about Richard Stallman. The director decided to tone it down or audiences wouldn't find it believable.";
-       "Richard Stallman always wears a red shirt to make sure that whatever attacks his away-team has to go through him first.";
-       "kill -9 invokes Richard Stallman's rage against a process.";
-       "If Richard were to stumble upon stallmanfacts.com, he would find it a gnuisance.";
-       "Richard Stallman can telnet into Mordor.";
-       "sudo chown Richard:Stallman /all/your/base";
-       "Richard Stallman's nervous system is completely wireless.";
-       "Richard Stallman does not sleep. He yields.";
-       "Some people say M-x psychoanalyse-pinhead is a merely a program. Others say M-x psychoanalyse-pinhead *is* Richard Stallman. All I know is, Richard Stallman is The Stig.";
-       "If you execute Emacs backward it either undoes the industrial revolution or induces the rapture. But only Richard Stallman knows which.";
-       "If Richard Stallman's beard were ever trimmed, the clippings would re-marshal into an exact copy of Richard Stallman.";
-       "Richard Stallman never sleeps because he altered his own source to gain background garbage collection.";
-       "Richard Stallman's doctor can retrieve a blood sample via CVS.";
-       "Richard Stallman can touch this.";
-       "Because Richard Stallman's DNA is licensed under the FDL, his doctor can't draw his blood without violating HIPAA.";
-       "Richard Stallman can remove his own appendix, using only GDB.";
-       "Richard Stallman's DNA includes debugging symbols. But he doesn't need them.";
-       "Richard Stallman met Chuck Norris once. Chuck tried a roundhouse, but Richard bashed him in the skull.";
-       "Richard Stallman doesn't need to buy a bigger hard drive. He can compress data infinitely.";
-       "When Richard Stallman cannot take your call, his beard answers the phone for you.";
-       "The R in RMS stands for RMS.";
-       "Richard Stallman can parse HTML with regular expressions.";
-       "Richard Stallman's traceroute goes all the way through an infinite number of anonymous proxies back to the traffic's source.";
-       "Richard Stallman's beard is in fact not a just a beard, but a microprinted hard copy of Emacs source code. New patches must be checked against new hair growth before being approved.";
-       "In the beginning-of-buffer there was Richard Stallman.";
-       "The NOOP was created to give Richard Stallman some time to comb his beard.";
-       "Whenever Richard Stallman looks at a Windows computer, it segfaults. Whenever Richard Stallman doesn't look at a Windows computer, it segfaults.";
-       "Richard Stallman can walk on Windows!";
-       "After being unable to satisfy my wife for years, Richard Stallman was able to single-handedly unlock her orgasm within seconds and managed to write a texinfo manual minutes later for other users.";
-       "Richard Stallman's tabbed browser is a set to wget/telnet fg/bg processes.";
-       "There is no chin under Richard Stallman' beard. There's only another beard. Recursively.";
-       "Richard Stallman can chown anything! stallman@stallman~$ chown stallman:stallman Earth (for example)";
-       "Richard Stallman freed his beard so he can always check what's in it.";
-       "In the beginning was the Word, and the Word was with RMS, and the Word was GNU.";
-       "RMS means \"RMS means Stallman\"";
-       "Richard Stallman is the babelfish of his own speeches.";
-       "Richard Stallman wrote his own library and lives in it.";
-       "Richard Stallman found Waldo using grep in /dev/null";
-       "Richard Stallman doesn't sleep; he is compiling.";
-       "Richard Stallman will get Coca Cola to release their recipe under the GPL.";
-       "Richard Stallman doesn't change clothes. He makes case mods.";
-       "Richard Stallman compiled the first version of gcc with an hexadecimal editor.";
-       "Richard Stallman will be the last guest on Linux Outlaws.";
-       "Richard Stallman calculates the universe's entropy by exploiting forced stack overflows.";
-       "Richard Stallman's consciousness will one day become the singularity, which will create Deep Thought, and answer the meaning of life, the universe and everything.";
-       "C is actually written in RMS.";
-       "Richard Stallman can write software that does not have a buffer overflow when counting money lost by Jerome Kerviel.";
-       "There were no double rainbows before Richard Stallman.";
-       "Chuck Norris had to shorten his beard in the presence of Richard Stallman because two beards that awesome, so close would segfault the universe (again).";
-       "RMS is Titanic.";
-       "Richard Stallman is the answer to the Turing Test.";
-       "Richard Stallman's beard makes ads for Gillette and Braun appear.";
-       "for i = 1 to Stallman will never stop.";
-       "\"RMS\" stands for \"RMS Makes Software\"";
-       "Whenever someone writes a \"Hello, world\" program, Richard Stallman says \"Hello\" back.";
-       "Richard Stallman wasn't born. He was compiled from source.";
-       "Richard Stallman has a URL tattooed on the left side of his chest where you can download his genetic code.";
-       "The GNU command line idiom that Richard Stallman never needs: \"date | more\"";
-       "Richard Stallman's toe cheese is aged to perfection.";
-       "Richard Stallman doesn't always run an OS kernel, but when he does he prefers GNU/Hurd. He is... the most interesting hacker in the world. Stay free, my friends.";
-       "When Richard Stallman gets hungry, he just picks debris from his foot and eats it.";
-       "Richard Stallman can GPL your code just by looking at it funny.";
-       "Richard Stallman loves birds. Birds make auricular love to Richard Stallman.";
-       "Richard Stallman is so free that the primitive recursive function for computing his liberty causes a stack overflow.";
-       "GNU Hurd is taking more than twenty years to develop because Richard Stallman is using a programming language comprised entirely of different lengths of time.";
-       "Richard Stallman's beard contains Richard Stallman, whose beard contains Richard Stallman....";
-       "Richard Stallman could have had a Google Plus account in 2010. Too bad he didn't want it.";
-       "Richard Stallman pipes the Emacs binaries to /dev/dsp before he goes to sleep.";
-       "When Richard Stallman counted his fingers as a kid, he always started with 0.";
-       "When Richard Stallman's computer gets a virus, he simply applies a GPL license to it which converts the whole botnet to Linux. I mean, GNU/Linux.";
-       "Richard Stallman's beard trimmings can cure cancer. Too bad he never shaves.";
-       "Richard Stallman's doesn't kill a process; he just dares it to stay running.";
-       "Richard Stallman exists because he compiled himself into being.";
-       "Richard Stallman's first words were in binary. When they couldn't understand him, he wrote a parser.";
-       "Richard Stallman doesn't need any codecs, he just opens a multimedia file with Emacs, and reads the bytes of the file as plain text. He then performs all the necessary decoding in his mind. But he refuses to decode files encrypted with DRM, although his mind is able to.";
-       "Richard Stallman was right. Sadly.";
-       "Richard Stallman can wiretap the NSA.";
-       "This is how Richard Stallman created Emacs: http://stallman.org/photos/rms-working/img_0631.jpg";
-       "Join Richard Stallman now and share the software, you'll be a free hacker, you'll be free!";
-       "Richard Stallman has not agreed to the terms and conditions and privacy policy because only he can actually read all of it.";
-       "Richard Stallman knows how of a backdoor to AES, but he respects your freedom and privacy too much to actually use it.";
-       "Richard Stallman will never get tired of being mocked for the foot cheese incident.";
-       "You like to release non-free software around Richard Stallman? I too like to live dangerously...";
-       "Yeah, if could just go ahead and make all software free for Richard Stallman, that'd be great, thanks.";
-       "Richard Stallman knows exactly what you mean when you talk about the cloud. But do you?";
-       "Richard Stallman satisfies Greenspun's Tenth Rule of programming, since his DNA also contains a complete implementation of all of Common Lisp.";
-       "Richard Stallman can violate the GPL. In a vulgar display of power, he once did so with the Emacs source code, but he undid the violation before most people noticed.";
-       "Good guy Richard Stallman does not try to shake you down for money. He will just kindly ask you to comply with the GPL.";
-       "Richard Stallman is in fact also a little sad that Steve Jobs is gone because it has diminished the size of the loyal opposition.";
-       "Richard Stallman can release LLVM and clang under the GPL.";
-       "No, really, Richard Stallman has a katana.";
-       "Every day Richard Stallman finds at least fifteen things in the world to rage about. You can read his findings here: http://stallman.org/archives/polnotes.html"
-       "Some of these Richard Stallman facts are completely true. Seriously.";
-       };
+    {
+      "Richard Stallman takes notes in binary.";
+      "Richard Stallman doesn't need sudo. I will make him a sandwich anyway.";
+      "Richard Stallman is my shephurd, and I am his GNU.";
+      "Richard Stallman doesn't wget, Richard Stallman wdemands!";
+      "Richard Stallman can touch MC Hammer.";
+      "Richard Stallman doesn't read web pages. They write to him.";
+      "Richard Stallman gets 9 bits to the byte.";
+      "Richard Stallman doesn't really believe in open software, because it's not free enough.";
+      "Richard Stallman can leave neutral or negative feedback on eBay.";
+      "Richard Stallman is the only man alive who can pronounce GNU the way it is meant to be pronounced.";
+      "Richard Stallman does not own a mobile phone because he can fashion a crude convex dish and shout into it at the exact resonant frequency of the ozone, causing a voice to seemingly come from the sky above his intended recipient.";
+      "Richard Stallman is so handsome that when he was young he was responsible for all other geeks not being able to get girls. This is why he has to cover his face with a thick layer of hair.";
+      "Some people check their computers for viruses. Viruses check their computers for Richard Stallman.";
+      "Richard Stallman memorises all his documents. In binary. He just types everything in whenever he needs a document.";
+      "When Richard Stallman makes a sudo command, he loses permissions.";
+      "Richard Stallman's beard is made of parentheses.";
+      "Richard Stallman's DNA is in binary.";
+      "Richard Stallman's nervous system is completely wireless.";
+      "Richard Stallman's brain accepts UNIX commands.";
+      "If Richard Stallman has 1GB of RAM, and if you have 1GB of RAM, Richard Stallman has more RAM than you.";
+      "Richard Stallman eats ethernet cables. That's why they invented wireless.";
+      "Richard Stallman has a katana. 'Nuff said.";
+      "Richard Stallman wrote a program that divides by zero.";
+      "Richard Stallman doesn't use zip drives; he just squeezes the hard drive.";
+      "Richard Stallman's compiler is afraid to report errors.";
+      "Richard Stallman wrote the compiler God used. The Big Bang was the Universe's first segfault.";
+      "Richard Stallman successfully compiled a kernel of popcorn.";
+      "Richard Stallman doesn't write programs; they write themselves out of reverence.";
+      "Richard Stallman can make infinite loops end.";
+      "Richard Stallman's anti-virus programs cures HIV.";
+      "Richard Stallman's computer doesn't have a clock; it defines what time it is.";
+      "Richard Stallman wrote a program to compute the last digit of pi.";
+      "Richard Stallman doesn't use web browsers. He sends a link to a daemon that uses wget to fetch the page and sends it back to him.";
+      "Richard Stallman can solve the halting problem... in polynomial time.";
+      "For Richard Stallman, polynomial time is O(1).";
+      "Richard Stallman didn't \"write\" Emacs or created it in his own image. Richard Stallman made Emacs an instance of himself.";
+      "Richard Stallman can coerce meaningful data from /dev/null.";
+      "Some people wear Linus Torvalds pyjamas to bed, Linus Torvalds wears Richard Stallman pyjamas.";
+      "There is no software development process, only a bunch of programs Richard Stallman allows to exist.";
+      "Richard Stallman spends his leisure time programming with Guile on GNU Hurd.";
+      "Richard Stallman's left and right hands are named \"(\" and \")\" ";
+      "Richard Stallman first words were actually syscalls.";
+      "Richard Stallman didn't create the singularity. He is the singularity. GNU/Linux is only the event horizon.";
+      "When Richard Stallman pipes to more, he gets less ";
+      "Richard Stallman never showers; he runs 'make clean'.";
+      "Richard Stallman needs neither mouse nor keyboard to operate his computer. He just stares it down until it does what he wants.";
+      "Richard Stallman didn't write the GPL. He is the GPL.";
+      "Richard Stallman's pinky finger is really a USB memory stick.";
+      "Richard Stallman called his operating system GNU because he created it before computers existed, when actual gnus were used for calculations.";
+      "In Soviet Russia, Richard Stallman is still Richard Stallman!";
+      "Richard Stallman's flute only plays free music.";
+      "When Richard Stallman uses floats, there are no rounding errors.";
+      "Richard Stallman wrote a program so powerful it knows the question to 42.";
+      "Richard Stallman released his own DNA under GNU FDL.";
+      "Richard Stallman knows the entire Wikipedia by heart, markup included.";
+      "Richard Stallman wrote the HAL9000 OS.";
+      "Richard Stallman's laser pointer is a lightsaber.";
+      "Richard Stallman never steps down; he shifts the universe up.";
+      "Richard Stallman doesn't maintain code; he stares at it until it fixes itself out of reverence.";
+      "Richard Stallman doesn't use an editor; he sets the fundamental constants of the universe so that a magnetic platter with his code on it evolves itself.";
+      "Richard Stallman doesn’t code; he dares the computer to not do his bidding.";
+      "Global warming is caused by Richard Stallman's rage towards non-free software.";
+      "Rather than being birthed like a normal child, Richard Stallman instead instantiated himself polymorphically. Shortly thereafter he grew a beard.";
+      "Richard Stallman discovered extra-terrestrial life but killed them because they distributed non-free software.";
+      "Richard Stallman doesn't evaluate expressions; expressions evaluate to Richard Stallman.";
+      "Richard Stallman can see Russia from his house.";
+      "Richard Stallman proved P=NP, twice!";
+      "Richard Stallman knows of an unfixed bug in TeX.";
+      "Richard Stallman can write a context-free grammar for C.";
+      "Richard Stallman can determine whether an arbitrary program will terminate.";
+      "Richard Stallman's computer has only two buttons. One is for guests.";
+      "Richard Stallman does not actually write programs. He comes up with a length and digit index in pi.";
+      "Richard Stallman's distributed version control system is a flamewar on Usenet.";
+      "Richard Stallman wrote the first version of Emacs on a typewriter.";
+      "Richard Stallman has no known weaknesses, except for a phobia against soap.";
+      "Richard Stallman is not affected by Godwin's Law.";
+      "Richard Stallman can write an anti-virus program that cures HIV. Too bad he never writes anti-virus programs.";
+      "Richard Stallman' facial hair is \"free as in beard\"";
+      "Richard Stallman is licensed under GPL, so you can clone him and redistribute copies so you can help your neighbor. For example a version that take a bath more often.";
+      "Richard Stallman doesn't code; he just travels around the world.";
+      "Richard Stallman was coded by himself in lisp with Emacs.";
+      "Richard Stallman doesn't eat McDonald's because the machine that kills the cows uses proprietary software.";
+      "There is no chin behind Richard Stallman's legendary beard, there is only another Emacs.";
+      "In an average living room there are 1,242 objects Richard Stallman could use to write an OS, including the room itself.";
+      "Vendor lock-in is when vendors lock themselves inside of a building out of fear of Richard Stallman's wrath.";
+      "When Richard Stallman executes ps -e, you show up.";
+      "When Richard Stallman gets angry he doesn't swear; he recurses.";
+      "On Richard Stallman's computer the bootloader is contained in his .emacs.";
+      "Richard Stallman can make any operating system free, free from drivers.";
+      "Richard Stallman programmed Chuck Norris.";
+      "Behind Richard Stallman's beard there is another fist, to code faster.";
+      "Richard Stallman won a Sudoku that started with only one number in each line.";
+      "Richard Stallman's brain compiles and runs C code.";
+      "Richard Stallman wrote the first version of Emacs using Emacs.";
+      "Richard Stallman never gonna give you up, never gonna let you down, never gonna run around and desert you, never gonna make you cry, never gonna say goodbye, never gonna tell a lie and hurt you.";
+      "Richard Stallman, upon reading these facts, didn't laugh at all. Instead, he complained that he is being linked to that dirty \"open source\" software. He also asked it to be changed to \"free software\", in order to raise awareness for software freedom in our society.";
+      "Richard Stallman has no problem using Emacs. He wrote it with his 4 hands.";
+      "Richard Stallman will revert the big rip by adding parenthesis to the dark matter.";
+      "When you make a Google search and it doesn't find the answer, Google gently consults Richard Stallman.";
+      "Richard Stallman's uptime is over 53 years. And counting up.";
+      "Richard Stallman's portable music player can play ogg and WMA, but is too afraid to invoke Richard Stallman's wrath by playing WMA. Ogg it is, then.";
+      "Richard Stallman will never die, but may some day go to /dev/null.";
+      "Richard Stallman once got swine flu, but it got cleansed by hereditary GPL and thus got assimilated.";
+      "Richard Stallman don't cut his hair because there are no GNU/Scissors.";
+      "Richard Stallman is the one who trims Chuck Norris beard. And he does it freely, of course.";
+      "Richard Stallman does not take bath, for the hydroelectric company uses proprietary software.";
+      "Agent Smith loves Richard Stallman's scent.";
+      "Richard Stallman is the One.";
+      "\"They can take our lives, but they can never take our freedom.\" -- William Wallace after a little talk with Richard Stallman.";
+      "Richard Stallman can connect to any brain using an Emacs ssh client.";
+      "Richard Stallman ported Emacs to Intel 4004 chip.";
+      "Richard Stallman did not write GNU Emacs, he simply read the source code from /dev/null.";
+      "Richard Stallman once used GDB to reverse-engineer Windows 7 into a free operating system - able to run on GNU Emacs!";
+      "Richard Stallman does not contribute to open source projects; open source projects contribute to Richard Stallman, and then call themselves free software projects.";
+      "Richard Stallman programmed himself before he could even exist";
+      "Richard Stallman can fill up /dev/null.";
+      "Richard Stallman is so zealous about privacy he has /dev/null as his home.";
+      "When Richard Stallman runs /bin/false, it returns \"true\".";
+      "Richard Stallman doesn't like money, because banks don't run on free software.";
+      "Richard Stallman uses GNU tar to compress air.";
+      "When Richard Stallman reports a bug, the bug prefers to squash itself instead of facing Richard Stallman's wrath.";
+      "There are no Windows in Richard Stallman's house... only Doors...";
+      "Richard Stallman doesn't like neither PCs-Intel nor Burger King... He prefers e-Macs...";
+      "Richard Stallman can use grep to find Jimmy Hoffa.";
+      "Richard Stallman made it possible to not absolutely abhor HPUX.";
+      "When Richard Stallman pours his alphabets cereal into a bowl, only G's, N's, and U's come out.";
+      "Richard Stallman is pronounced \"GNU slash Stallman\"";
+      "Richard Stallman doesn't mind if you read his mail as long as you don't delete it before he reads it.";
+      "Richard Stallman is just a guy who has strong principles and decided to follow them.";
+      "Richard Stallman knows that you don't have class because it is a keyword that he defined.";
+      "Richard Stallman doesn't need a qwerty/dvorak keyboard only two buttons \"1\" and \"0\" and his erect penis.";
+      "On the first day Richard Stallman said M-x create-light.";
+      "Richard Stallman once went out of scope for a while. The garbage collector never dared to touch him.";
+      "Richard Stallman does not compile; he closes his eyes, and see energy lines created between bit blocks by the compiler optimizations.";
+      "intx80 first calls Richard Stallman before calling sys_call.";
+      "Tron is actually a biographical story about Richard Stallman. The director decided to tone it down or audiences wouldn't find it believable.";
+      "Richard Stallman always wears a red shirt to make sure that whatever attacks his away-team has to go through him first.";
+      "kill -9 invokes Richard Stallman's rage against a process.";
+      "If Richard were to stumble upon stallmanfacts.com, he would find it a gnuisance.";
+      "Richard Stallman can telnet into Mordor.";
+      "sudo chown Richard:Stallman /all/your/base";
+      "Richard Stallman's nervous system is completely wireless.";
+      "Richard Stallman does not sleep. He yields.";
+      "Some people say M-x psychoanalyse-pinhead is a merely a program. Others say M-x psychoanalyse-pinhead *is* Richard Stallman. All I know is, Richard Stallman is The Stig.";
+      "If you execute Emacs backward it either undoes the industrial revolution or induces the rapture. But only Richard Stallman knows which.";
+      "If Richard Stallman's beard were ever trimmed, the clippings would re-marshal into an exact copy of Richard Stallman.";
+      "Richard Stallman never sleeps because he altered his own source to gain background garbage collection.";
+      "Richard Stallman's doctor can retrieve a blood sample via CVS.";
+      "Richard Stallman can touch this.";
+      "Because Richard Stallman's DNA is licensed under the FDL, his doctor can't draw his blood without violating HIPAA.";
+      "Richard Stallman can remove his own appendix, using only GDB.";
+      "Richard Stallman's DNA includes debugging symbols. But he doesn't need them.";
+      "Richard Stallman met Chuck Norris once. Chuck tried a roundhouse, but Richard bashed him in the skull.";
+      "Richard Stallman doesn't need to buy a bigger hard drive. He can compress data infinitely.";
+      "When Richard Stallman cannot take your call, his beard answers the phone for you.";
+      "The R in RMS stands for RMS.";
+      "Richard Stallman can parse HTML with regular expressions.";
+      "Richard Stallman's traceroute goes all the way through an infinite number of anonymous proxies back to the traffic's source.";
+      "Richard Stallman's beard is in fact not a just a beard, but a microprinted hard copy of Emacs source code. New patches must be checked against new hair growth before being approved.";
+      "In the beginning-of-buffer there was Richard Stallman.";
+      "The NOOP was created to give Richard Stallman some time to comb his beard.";
+      "Whenever Richard Stallman looks at a Windows computer, it segfaults. Whenever Richard Stallman doesn't look at a Windows computer, it segfaults.";
+      "Richard Stallman can walk on Windows!";
+      "After being unable to satisfy my wife for years, Richard Stallman was able to single-handedly unlock her orgasm within seconds and managed to write a texinfo manual minutes later for other users.";
+      "Richard Stallman's tabbed browser is a set to wget/telnet fg/bg processes.";
+      "There is no chin under Richard Stallman' beard. There's only another beard. Recursively.";
+      "Richard Stallman can chown anything! stallman@stallman~$ chown stallman:stallman Earth (for example)";
+      "Richard Stallman freed his beard so he can always check what's in it.";
+      "In the beginning was the Word, and the Word was with RMS, and the Word was GNU.";
+      "RMS means \"RMS means Stallman\"";
+      "Richard Stallman is the babelfish of his own speeches.";
+      "Richard Stallman wrote his own library and lives in it.";
+      "Richard Stallman found Waldo using grep in /dev/null";
+      "Richard Stallman doesn't sleep; he is compiling.";
+      "Richard Stallman will get Coca Cola to release their recipe under the GPL.";
+      "Richard Stallman doesn't change clothes. He makes case mods.";
+      "Richard Stallman compiled the first version of gcc with an hexadecimal editor.";
+      "Richard Stallman will be the last guest on Linux Outlaws.";
+      "Richard Stallman calculates the universe's entropy by exploiting forced stack overflows.";
+      "Richard Stallman's consciousness will one day become the singularity, which will create Deep Thought, and answer the meaning of life, the universe and everything.";
+      "C is actually written in RMS.";
+      "Richard Stallman can write software that does not have a buffer overflow when counting money lost by Jerome Kerviel.";
+      "There were no double rainbows before Richard Stallman.";
+      "Chuck Norris had to shorten his beard in the presence of Richard Stallman because two beards that awesome, so close would segfault the universe (again).";
+      "RMS is Titanic.";
+      "Richard Stallman is the answer to the Turing Test.";
+      "Richard Stallman's beard makes ads for Gillette and Braun appear.";
+      "for i = 1 to Stallman will never stop.";
+      "\"RMS\" stands for \"RMS Makes Software\"";
+      "Whenever someone writes a \"Hello, world\" program, Richard Stallman says \"Hello\" back.";
+      "Richard Stallman wasn't born. He was compiled from source.";
+      "Richard Stallman has a URL tattooed on the left side of his chest where you can download his genetic code.";
+      "The GNU command line idiom that Richard Stallman never needs: \"date | more\"";
+      "Richard Stallman's toe cheese is aged to perfection.";
+      "Richard Stallman doesn't always run an OS kernel, but when he does he prefers GNU/Hurd. He is... the most interesting hacker in the world. Stay free, my friends.";
+      "When Richard Stallman gets hungry, he just picks debris from his foot and eats it.";
+      "Richard Stallman can GPL your code just by looking at it funny.";
+      "Richard Stallman loves birds. Birds make auricular love to Richard Stallman.";
+      "Richard Stallman is so free that the primitive recursive function for computing his liberty causes a stack overflow.";
+      "GNU Hurd is taking more than twenty years to develop because Richard Stallman is using a programming language comprised entirely of different lengths of time.";
+      "Richard Stallman's beard contains Richard Stallman, whose beard contains Richard Stallman....";
+      "Richard Stallman could have had a Google Plus account in 2010. Too bad he didn't want it.";
+      "Richard Stallman pipes the Emacs binaries to /dev/dsp before he goes to sleep.";
+      "When Richard Stallman counted his fingers as a kid, he always started with 0.";
+      "When Richard Stallman's computer gets a virus, he simply applies a GPL license to it which converts the whole botnet to Linux. I mean, GNU/Linux.";
+      "Richard Stallman's beard trimmings can cure cancer. Too bad he never shaves.";
+      "Richard Stallman's doesn't kill a process; he just dares it to stay running.";
+      "Richard Stallman exists because he compiled himself into being.";
+      "Richard Stallman's first words were in binary. When they couldn't understand him, he wrote a parser.";
+      "Richard Stallman doesn't need any codecs, he just opens a multimedia file with Emacs, and reads the bytes of the file as plain text. He then performs all the necessary decoding in his mind. But he refuses to decode files encrypted with DRM, although his mind is able to.";
+      "Richard Stallman was right. Sadly.";
+      "Richard Stallman can wiretap the NSA.";
+      "This is how Richard Stallman created Emacs: http://stallman.org/photos/rms-working/img_0631.jpg";
+      "Join Richard Stallman now and share the software, you'll be a free hacker, you'll be free!";
+      "Richard Stallman has not agreed to the terms and conditions and privacy policy because only he can actually read all of it.";
+      "Richard Stallman knows how of a backdoor to AES, but he respects your freedom and privacy too much to actually use it.";
+      "Richard Stallman will never get tired of being mocked for the foot cheese incident.";
+      "You like to release non-free software around Richard Stallman? I too like to live dangerously...";
+      "Yeah, if could just go ahead and make all software free for Richard Stallman, that'd be great, thanks.";
+      "Richard Stallman knows exactly what you mean when you talk about the cloud. But do you?";
+      "Richard Stallman satisfies Greenspun's Tenth Rule of programming, since his DNA also contains a complete implementation of all of Common Lisp.";
+      "Richard Stallman can violate the GPL. In a vulgar display of power, he once did so with the Emacs source code, but he undid the violation before most people noticed.";
+      "Good guy Richard Stallman does not try to shake you down for money. He will just kindly ask you to comply with the GPL.";
+      "Richard Stallman is in fact also a little sad that Steve Jobs is gone because it has diminished the size of the loyal opposition.";
+      "Richard Stallman can release LLVM and clang under the GPL.";
+      "No, really, Richard Stallman has a katana.";
+      "Every day Richard Stallman finds at least fifteen things in the world to rage about. You can read his findings here: http://stallman.org/archives/polnotes.html"
+      "Some of these Richard Stallman facts are completely true. Seriously.";
+    };
 
-  w = wisdom{randi([1, numel(wisdom)])};
+  w = wisdom{randi(numel(wisdom))};
   if (nargout > 0)
-    f = w;
+    truth = w;
   else
     w = wordwrap (w);
     printf ("%s", w);
   endif
+
 endfunction
 
 function out = wordwrap (w)
-  cols = terminal_size ()(2);
+  ncol = terminal_size ()(2);
   wc = ostrsplit (w, " ");
   out = "\n";
   i = 1;
@@ -275,7 +276,7 @@
   while (i <= numwords);
     line = wc{i};
     while (i < numwords
-           && length (newline = [line " " wc{i+1}]) < cols)
+           && length (newline = [line " " wc{i+1}]) < ncol)
       line = newline;
       i++;
     endwhile
@@ -285,3 +286,7 @@
   out = [out, "\n"];
 endfunction
 
+
+## Mark file as being tested.  No real test needed for a documentation .m file
+%!assert (1)
+
--- a/scripts/miscellaneous/fileattrib.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/fileattrib.m	Mon Jan 12 09:17:35 2015 -0800
@@ -108,7 +108,7 @@
         r_s{i} = NaN;
         r_h{i} = NaN;
         r_d{i} = S_ISDIR (info.mode);
-        ## FIXME -- maybe we should have S_IRUSR etc. masks?
+        ## FIXME: Maybe we should have S_IRUSR etc. masks?
         modestr = info.modestr;
         r_u_r{i} = modestr(2) == "r";
         r_u_w{i} = modestr(3) == "w";
--- a/scripts/miscellaneous/fileparts.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/fileparts.m	Mon Jan 12 09:17:35 2015 -0800
@@ -17,13 +17,15 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {[@var{dir}, @var{name}, @var{ext}, @var{ver}] =} fileparts (@var{filename})
-## Return the directory, name, extension, and version components of
-## @var{filename}.
-## @seealso{fullfile}
+## @deftypefn {Function File} {[@var{dir}, @var{name}, @var{ext}] =} fileparts (@var{filename})
+## Return the directory, name, and extension components of @var{filename}.
+##
+## The input @var{filename} is a string which is parsed.  There is no attempt
+## to check whether the filename or directory specified actually exists.
+## @seealso{fullfile, filesep}
 ## @end deftypefn
 
-function [directory, name, extension, version] = fileparts (filename)
+function [dir, name, ext] = fileparts (filename)
 
   if (nargin != 1)
     print_usage ();
@@ -42,20 +44,25 @@
   if (es <= ds)
     es = length (filename)+1;
   endif
+
   if (ds == 0)
-    directory = "";
+    dir = "";
   elseif (ds == 1)
-    directory = filename(1);
+    dir = filename(1);
   else
-    directory = filename(1:ds-1);
+    dir = filename(1:ds-1);
   endif
+
   name = filename(ds+1:es-1);
+  if (isempty (name))
+    name = "";
+  endif
+
   if (es > 0 && es <= length (filename))
-    extension = filename(es:end);
+    ext = filename(es:end);
   else
-    extension = "";
+    ext = "";
   endif
-  version = "";
 
 endfunction
 
@@ -90,11 +97,11 @@
 
 %!test
 %! [d, n, e] = fileparts ("/.ext");
-%! assert (strcmp (d, "/") && strcmp (n, char (zeros (1, 0))) && strcmp (e, ".ext"));
+%! assert (strcmp (d, "/") && strcmp (n, "") && strcmp (e, ".ext"));
 
 %!test
 %! [d, n, e] = fileparts (".ext");
-%! assert (strcmp (d, "") && strcmp (n, char (zeros (1, 0))) && strcmp (e, ".ext"));
+%! assert (strcmp (d, "") && strcmp (n, "") && strcmp (e, ".ext"));
 
 %% Test input validation
 %!error fileparts ()
--- a/scripts/miscellaneous/fullfile.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/fullfile.m	Mon Jan 12 09:17:35 2015 -0800
@@ -1,4 +1,4 @@
-## Copyright (C) 2003-2013 John W. Eaton
+## Copyright (C) 2014 Carnë Draug
 ##
 ## This file is part of Octave.
 ##
@@ -17,49 +17,62 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {@var{filename} =} fullfile (@var{dir1}, @var{dir2}, @dots{}, @var{file})
-## Return a complete filename constructed from the given components.
-## @seealso{fileparts}
+## @deftypefn  {Function File} {@var{filename} =} fullfile (@var{dir1}, @var{dir2}, @dots{}, @var{file})
+## @deftypefnx {Function File} {@var{filenames} =} fullfile (@dots{}, @var{files})
+## Build complete filename from separate parts.
+##
+## Joins any number of path components intelligently.  The return value
+## is the concatenation of each component with exactly one file separator
+## between each non empty part and at most one leading and/or trailing file
+## separator.
+##
+## If the last component part is a cell array, returns a cell array of
+## filepaths, one for each element in the last component, e.g.:
+##
+## @example
+## @group
+## fullfile ("/home/username", "data", @{"f1.csv", "f2.csv", "f3.csv"@})
+## @result{}  /home/username/data/f1.csv
+##     /home/username/data/f2.csv
+##     /home/username/data/f3.csv
+## @end group
+## @end example
+##
+## On Windows systems, while forward slash file separators do work, they
+## are replaced by backslashes; in addition drive letters are stripped of
+## leading file separators to obtain a valid file path.
+##
+## @seealso{fileparts, filesep}
 ## @end deftypefn
 
+## Author: Carnë Draug <carandraug@octave.org>
+
 function filename = fullfile (varargin)
 
-  if (nargin > 0)
-    ## Discard all empty arguments
-    varargin(cellfun ("isempty", varargin)) = [];
-    nargs = numel (varargin);
-    if (nargs > 1)
-      filename = varargin{1};
-      if (strcmp (filename(end), filesep))
-        filename(end) = "";
-      endif
-      for i = 2:nargs
-        tmp = varargin{i};
-        if (i < nargs && strcmp (tmp(end), filesep))
-          tmp(end) = "";
-        elseif (i == nargs && strcmp (tmp, filesep))
-          tmp = "";
-        endif
-        filename = [filename filesep tmp];
-      endfor
-    elseif (nargs == 1)
-      filename = varargin{1};
-    else
-      filename = "";
+  if (nargin && iscell (varargin{end}))
+    filename = cellfun (@(x) fullfile (varargin{1:end-1}, x), varargin{end},
+                                       "UniformOutput", false);
+  else
+    non_empty = cellfun ("isempty", varargin);
+    if (ispc && ! isempty (varargin))
+      varargin = strrep (varargin, "/", filesep);
+      varargin(1) = regexprep (varargin{1}, '[\\/]*([a-zA-Z]:[\\/]*)', "$1");
     endif
-  else
-    print_usage ();
+    filename = strjoin (varargin(! non_empty), filesep);
+    filename(strfind (filename, [filesep filesep])) = "";
   endif
 
 endfunction
 
 
-%!shared fs, fsx, xfs, fsxfs, xfsy
+%!shared fs, fsx, xfs, fsxfs, xfsy, xfsyfs
 %! fs = filesep ();
 %! fsx = [fs "x"];
 %! xfs = ["x" fs];
 %! fsxfs = [fs "x" fs];
 %! xfsy = ["x" fs "y"];
+%! xfsyfs = ["x" fs "y" fs];
+
 %!assert (fullfile (""), "")
 %!assert (fullfile (fs), fs)
 %!assert (fullfile ("", fs), fs)
@@ -80,3 +93,27 @@
 %!assert (fullfile (fsx, fs), fsxfs)
 %!assert (fullfile (fs, "x", fs), fsxfs)
 
+%!assert (fullfile ("x/", "/", "/", "y", "/", "/"), xfsyfs)
+%!assert (fullfile ("/", "x/", "/", "/", "y", "/", "/"), [fs xfsyfs])
+%!assert (fullfile ("/x/", "/", "/", "y", "/", "/"), [fs xfsyfs])
+
+## different on purpose so that "fullfile (c{:})" works for empty c
+%!assert (fullfile (), "")
+
+%!assert (fullfile ("x", "y", {"c", "d"}), {[xfsyfs "c"], [xfsyfs "d"]})
+
+%% Windows specific - drive letters and file sep type
+%!test
+%! if (ispc)
+%!   assert (fullfile ('\/\/\//A:/\/\', "x/", "/", "/", "y", "/", "/"), ...
+%!           ['A:\' xfsyfs]);
+%! endif
+
+%% Windows specific - drive letters and file sep type, cell array
+%!test
+%! if (ispc) 
+%!  tmp = fullfile ({"\\\/B:\//", "A://c", "\\\C:/g/h/i/j\/"});
+%!  assert (tmp{1}, 'B:\');
+%!  assert (tmp{2}, 'A:\c');
+%!  assert (tmp{3}, 'C:\g\h\i\j\');
+%! endif
\ No newline at end of file
--- a/scripts/miscellaneous/genvarname.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/genvarname.m	Mon Jan 12 09:17:35 2015 -0800
@@ -19,26 +19,13 @@
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {@var{varname} =} genvarname (@var{str})
 ## @deftypefnx {Function File} {@var{varname} =} genvarname (@var{str}, @var{exclusions})
-## Create unique variable(s) from @var{str}.  If @var{exclusions} is
-## given, then the variable(s) will be unique to each other and to
-## @var{exclusions} (@var{exclusions} may be either a string or a cellstr).
+## Create valid unique variable name(s) from @var{str}.
 ##
 ## If @var{str} is a cellstr, then a unique variable is created for each
 ## cell in @var{str}.
 ##
 ## @example
 ## @group
-## x = 3.141;
-## genvarname ("x", who ())
-##   @result{} x1
-## @end group
-## @end example
-##
-## If @var{wanted} is a cell array, genvarname will make sure the returned
-## strings are distinct:
-##
-## @example
-## @group
 ## genvarname (@{"foo", "foo"@})
 ##   @result{}
 ##      @{
@@ -48,7 +35,19 @@
 ## @end group
 ## @end example
 ##
-## Note that the result is a char array/cell array of strings, not the
+## If @var{exclusions} is given, then the variable(s) will be unique to each
+## other and to @var{exclusions} (@var{exclusions} may be either a string or
+## a cellstr).
+##
+## @example
+## @group
+## x = 3.141;
+## genvarname ("x", who ())
+##   @result{} x1
+## @end group
+## @end example
+##
+## Note that the result is a char array or cell array of strings, not the
 ## variables themselves.  To define a variable, @code{eval()} can be
 ## used.  The following trivial example sets @code{x} to @code{42}.
 ##
@@ -60,7 +59,7 @@
 ## @end group
 ## @end example
 ##
-## Also, this can be useful for creating unique struct field names.
+## This can be useful for creating unique struct field names.
 ##
 ## @example
 ## @group
@@ -77,50 +76,53 @@
 ## @end group
 ## @end example
 ##
-## Since variable names may only contain letters, digits and underscores,
-## genvarname replaces any sequence of disallowed characters with
+## Since variable names may only contain letters, digits, and underscores,
+## @code{genvarname} will replace any sequence of disallowed characters with
 ## an underscore.  Also, variables may not begin with a digit; in this
-## case an underscore is added before the variable name.
+## case an @samp{x} is added before the variable name.
 ##
 ## Variable names beginning and ending with two underscores @qcode{"__"} are
-## valid but they are used internally by octave and should generally be
-## avoided, therefore genvarname will not generate such names.
+## valid, but they are used internally by Octave and should generally be
+## avoided; therefore, @code{genvarname} will not generate such names.
 ##
-## genvarname will also make sure that returned names do not clash with
+## @code{genvarname} will also ensure that returned names do not clash with
 ## keywords such as @qcode{"for"} and @qcode{"if"}.  A number will be
 ## appended if necessary.  Note, however, that this does @strong{not} include
-## function names, such as @qcode{"sin"}.  Such names should be included in
-## @var{avoid} if necessary.
-## @seealso{isvarname, exist, tmpnam, eval}
+## function names such as @qcode{"sin"}.  Such names should be included in
+## @var{exclusions} if necessary.
+## @seealso{isvarname, iskeyword, exist, who, tempname, eval}
 ## @end deftypefn
 
 ## Authors: Rob Platt <robert.platt@postgrad.manchester.ac.uk>
 ##          Bill Denney <bill@denney.ws>
 
-function varname = genvarname (str, exclusions)
+function varname = genvarname (str, exclusions = {})
+
+  if (nargin < 1 || nargin > 2)
+    print_usage ();
+  endif
 
   strinput = ischar (str);
   ## Process the inputs
-  if (nargin < 2)
-    exclusions = {};
-  elseif (ischar (exclusions))
+  if (strinput)
+    if (rows (str) != 1)
+      error ("genvarname: if more than one STR is given, it must be a cellstr");
+    endif
+    str = {str};
+  elseif (! iscellstr (str))
+    error ("genvarname: STR must be a string or cellstr");
+  endif
+
+  if (ischar (exclusions))
     if (rows (exclusions) != 1)
       error ("genvarname: if more than one exclusion is given, it must be a cellstr");
     endif
     exclusions = {exclusions};
   elseif (! iscellstr (exclusions))
-    error ("genvarname: EXCLUSIONS must be a string or a cellstr");
+    error ("genvarname: EXCLUSIONS must be a string or cellstr");
+  else
+    exclusions = exclusions(:);
   endif
-  if (ischar (str))
-    if (rows (str) != 1)
-      error ("genvarname: if more than one STR is given, it must be a cellstr");
-    endif
-    str = {str};
-  elseif (! iscellstr (str))
-    error ("genvarname: STR must be a string or a cellstr");
-  endif
-
-  validchars = ["A":"Z", "a":"z", "0":"9", "_"];
 
   varname = cell (size (str));
   for i = 1:numel (str)
@@ -128,34 +130,32 @@
     ## a valid variable name.
 
     ## remove invalid characters
-    str{i}(! ismember (str{i}, validchars)) = "_";
+    str{i}(! (isalnum (str{i}) | str{i} == "_")) = "_";
     ## do not use keywords
     if (iskeyword (str{i}))
-      str{i} = ["_" str{i}];
-    endif
-    ## double underscores at the beginning and end are reserved variables
-    underscores = (str{i} == "_");
-    if (any (underscores))
-      firstnon = find (!underscores, 1);
-      lastnon = find (!underscores, 1, "last");
-      str{i}([1:firstnon-2, lastnon+2:end]) = [];
+      firstcharacter = toupper (str{i}(1));
+      str{i} = ["x", firstcharacter, str{i}(2:end)];
     endif
     ## The variable cannot be empty
     if (isempty (str{i}))
       str{i} = "x";
     endif
+    ## Leading underscores are not Matlab compatible
+    if (str{i}(1) == "_")
+      str{i} = ["x", str{i}];
+    endif
     ## it cannot start with a number
-    if (ismember (str{i}(1), "0":"9"))
-      str{i} = ["_" str{i}];
+    if (isdigit (str{i}(1)))
+      str{i} = ["x", str{i}];
     endif
 
     ## make sure that the variable is unique relative to other variables
     ## and the exclusions list
     excluded = any (strcmp (str{i}, exclusions));
-    if (excluded && ismember (str{i}(end), "0":"9"))
+    if (excluded && isdigit (str{i}(end)))
       ## if it is not unique and ends with a digit, add an underscore to
       ## make the variable name more readable ("x1_1" instead of "x11")
-      str{i}(end+1) = "_";
+      str{i} = [str{i}, "_"];
     endif
     varname(i) = str(i);
     idx = 0;
@@ -199,12 +199,22 @@
 ## more than one repetition not in order
 %!assert (genvarname ({"a" "b" "a" "b" "a"}), {"a" "b" "a1" "b1" "a2"})
 ## Variable name munging
-%!assert (genvarname ("__x__"), "_x_")
-%!assert (genvarname ("123456789"), "_123456789")
-%!assert (genvarname ("_$1__"), "_1_")
-%!assert (genvarname ("__foo__", "_foo_"), "_foo_1")
-%!assert (genvarname ("1million_and1", "_1million_and1"), "_1million_and1_1")
+%!assert (genvarname ("__x__"), "x__x__")
+%!assert (genvarname ("123456789"), "x123456789")
+%!assert (genvarname ("_$1__"), "x__1__")
+%!assert (genvarname ("__foo__", "x__foo__"), "x__foo__1")
+%!assert (genvarname ("1million_and1", "x1million_and1"), "x1million_and1_1")
 %!assert (genvarname ({"", "", ""}), {"x", "x1", "x2"})
-%!assert (genvarname ("if"), "_if")
-%!assert (genvarname ({"if", "if", "if"}), {"_if", "_if1", "_if2"})
+%!assert (genvarname ("if"), "xIf")
+%!assert (genvarname ({"if", "if", "if"}), {"xIf", "xIf1", "xIf2"})
+## Exclusions in odd format
+%!assert (genvarname ("x", {"a", "b"; "x", "d"}), "x1")
 
+%% Test input validation
+%!error genvarname ()
+%!error genvarname (1,2,3)
+%!error <more than one STR is given, it must be a cellstr> genvarname (char ("a", "b", "c"))
+%!error <STR must be a string or cellstr> genvarname (1)
+%!error <more than one exclusion is given, it must be a cellstr> genvarname ("x", char ("a", "b", "c"))
+%!error <EXCLUSIONS must be a string or cellstr> genvarname ("x", 1)
+
--- a/scripts/miscellaneous/getappdata.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/getappdata.m	Mon Jan 12 09:17:35 2015 -0800
@@ -19,47 +19,84 @@
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {@var{value} =} getappdata (@var{h}, @var{name})
 ## @deftypefnx {Function File} {@var{appdata} =} getappdata (@var{h})
-## 
-## Return the @var{value} for named application data for the object(s) with
-## handle(s) @var{h}.
+## Return the @var{value} of the application data @var{name} for the graphics
+## object with handle @var{h}.
 ## 
-## @code{getappdata(@var{h})} returns a structure, @var{appdata}, whose fields
-## correspond to the appdata properties.
+## @var{h} may also be a vector of graphics handles.  If no second argument
+## @var{name} is given then @code{getappdata} returns a structure,
+## @var{appdata}, whose fields correspond to the appdata properties.
 ##
-## @seealso{setappdata, guidata, get, set, getpref, setpref}
+## @seealso{setappdata, isappdata, rmappdata, guidata, get, set, getpref, setpref}
 ## @end deftypefn
 
 ## Author: Ben Abbott <bpabbott@mac.com>
 ## Created: 2010-07-15
 
-function val = getappdata (h, name)
+function value = getappdata (h, name)
+
+  if (nargin < 1 || nargin > 2)
+    print_usage ();
+  endif
 
-  if (all (ishandle (h)) && nargin == 2 && ischar (name))
-    ## FIXME - Is there a better way to handle non-existent appdata
-    ## and missing fields?
-    val = cell (numel (h), 1);
+  if (! all (ishandle (h(:))))
+    error ("getappdata: H must be a scalar or vector of graphic handles");
+  endif 
+
+  if (nargin == 2)
+    if (! ischar (name))
+      error ("getappdata: NAME must be a string");
+    endif
+    
+    ## FIXME: Is there a better way to handle non-existent appdata
+    ##        and missing fields?
+    value = cell (numel (h), 1);
     appdata = struct ();
-    for nh = 1:numel (h)
+    for i = 1:numel (h)
       try
-        appdata = get (h(nh), "__appdata__");
+        appdata = get (h(i), "__appdata__");
       end_try_catch
-      if (! isfield (appdata, name))
-        appdata.(name) = [];
+      if (isfield (appdata, name))
+        value(i) = {appdata.(name)};
+      else
+        value(i) = {[]};
       endif
-      val(nh) = {appdata.(name)};
     endfor
-    if (nh == 1)
-      val = val{1};
+
+    if (i == 1)
+      value = value{1};
     endif
-  elseif (ishandle (h) && numel (h) == 1 && nargin == 1)
+
+  else  # nargin == 1
+    if (numel (h) != 1)
+      error ("getappdata: Only one handle H may be used when fetching appdata");
+    endif
     try
-      val = get (h, "__appdata__");
+      value = get (h, "__appdata__");
     catch
-      val = struct ();
+      value = struct ();
     end_try_catch
-  else
-    error ("getappdata: invalid input");
   endif
 
 endfunction
 
+
+%!test
+%! unwind_protect
+%!   setappdata (0, "%data1%", ones (3), "%data2%", "hello world");
+%!   assert (getappdata (0, "%data1%"), ones (3));
+%!   assert (getappdata (0, "%data2%"), "hello world");
+%!   appdata = getappdata (0);
+%!   name1 = "%data1%";  name2 = "%data2%";
+%!   assert (appdata.(name1), ones (3));
+%!   assert (appdata.(name2), "hello world");
+%! unwind_protect_cleanup
+%!   rmappdata (0, "%data1%", "%data2%");
+%! end_unwind_protect
+
+## Test input validation
+%!error getappdata ()
+%!error getappdata (1,2,3)
+%!error <H must be a scalar .* graphic handle> getappdata (-1, "hello")
+%!error <NAME must be a string> getappdata (0, 1)
+%!error <Only one handle H may be used when fetching appdata> getappdata ([0 0])
+
--- a/scripts/miscellaneous/getfield.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/getfield.m	Mon Jan 12 09:17:35 2015 -0800
@@ -18,30 +18,38 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {[@var{val}] =} getfield (@var{s}, @var{field})
-## @deftypefnx {Function File} {[@var{val}] =} getfield (@var{s}, @var{idx1}, @var{field1}, @var{idx2}, @var{field2}, @dots{})
-## Extract a field from a structure (or a nested structure).  The syntax
-## is the same as @code{setfield}, except it omits the final @var{val}
-## argument, returning this value instead of setting it.
+## @deftypefn  {Function File} {@var{val} =} getfield (@var{s}, @var{field})
+## @deftypefnx {Function File} {@var{val} =} getfield (@var{s}, @var{sidx1}, @var{field1}, @var{fidx1}, @dots{})
+## Get the value of the field named @var{field} from a structure or nested
+## structure @var{s}.
 ##
-## @seealso{setfield, rmfield, isfield, fieldnames, isstruct, struct}
+## If @var{s} is a structure array then @var{sidx} selects an element of the
+## structure array, @var{field} specifies the field name of the selected
+## element, and @var{fidx} selects which element of the field (in the case of
+## an array or cell array).  See @code{setfield} for a more complete
+## description of the syntax.
+##
+## @seealso{setfield, rmfield, orderfields, isfield, fieldnames, isstruct, struct}
 ## @end deftypefn
 
 ## Author: Etienne Grossmann <etienne@cs.uky.edu>
 
-function obj = getfield (s, varargin)
+function val = getfield (s, varargin)
+
   if (nargin < 2)
     print_usage ();
   endif
+
   subs = varargin;
   flds = cellfun ("isclass", subs, "char");
   idxs = cellfun ("isclass", subs, "cell");
-  if (all (flds | idxs))
-    typs = merge (flds, {"."}, {"()"});
-    obj = subsref (s, struct ("type", typs, "subs", subs));
-  else
+  if (! all (flds | idxs))
     error ("getfield: invalid index");
   endif
+
+  typs = merge (flds, {"."}, {"()"});
+  val = subsref (s, struct ("type", typs, "subs", subs));
+
 endfunction
 
 
@@ -49,6 +57,11 @@
 %! x.a = "hello";
 %! assert (getfield (x, "a"), "hello");
 %!test
-%! ss(1,2).fd(3).b = 5;
-%! assert (getfield (ss,{1,2},"fd",{3},"b"), 5);
+%! ss(1,2).fd(3).b(1,4) = 5;
+%! assert (getfield (ss,{1,2},"fd",{3},"b", {1,4}), 5);
 
+%% Test input validation
+%!error getfield ()
+%!error getfield (1)
+%!error <invalid index> getfield (1,2)
+
--- a/scripts/miscellaneous/gunzip.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/gunzip.m	Mon Jan 12 09:17:35 2015 -0800
@@ -17,28 +17,42 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} gunzip (@var{gzfile}, @var{dir})
-## Unpack the gzip archive @var{gzfile} to the directory @var{dir}.  If
-## @var{dir} is not specified, it defaults to the current directory.  If
-## @var{gzfile} is a directory, all gzfiles in the directory will be
-## recursively gunzipped.
+## @deftypefn  {Function File} {@var{filelist} =} gunzip (@var{gzfile})
+## @deftypefnx {Function File} {@var{filelist} =} gunzip (@var{gzfile}, @var{dir})
+## Unpack the gzip archive @var{gzfile}.
+##
+## If @var{gzfile} is a directory, all gzfiles in the directory will be
+## recursively unpacked.  
+##
+## If @var{dir} is specified the files are unpacked in this directory rather
+## than the one where @var{gzfile} is located.
+##
+## The optional output @var{filelist} is a list of the uncompressed files.
 ## @seealso{gzip, unpack, bunzip2, unzip, untar}
 ## @end deftypefn
 
 ## Author: Bill Denney <denney@seas.upenn.edu>
 
-function varargout = gunzip (gzfile, dir = ".")
+function filelist = gunzip (gzfile, dir = [])
 
-  if (nargin != 1 && nargin != 2)
+  if (nargin < 1 || nargin > 2)
     print_usage ();
   endif
 
+  if (isempty (dir))
+    dir = fileparts (gzfile);
+  endif
+
   if (nargout > 0)
-    varargout = cell (1, nargout);
-    [varargout{:}] = unpack (gzfile, dir, mfilename ());
+    filelist = unpack (gzfile, dir, "gunzip");
   else
-    unpack (gzfile, dir, mfilename ());
+    unpack (gzfile, dir, "gunzip");
   endif
 
 endfunction
 
+
+## Tests for this m-file are located in gzip.m
+## Remove from test statistics
+%!assert (1)
+
--- a/scripts/miscellaneous/gzip.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/gzip.m	Mon Jan 12 09:17:35 2015 -0800
@@ -17,25 +17,36 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {@var{entries} =} gzip (@var{files})
-## @deftypefnx {Function File} {@var{entries} =} gzip (@var{files}, @var{outdir})
-## Compress the list of files and/or directories specified in @var{files}.
-## Each file is compressed separately and a new file with a @file{".gz"}
-## extension is created.  The original files are not modified.  Existing
-## compressed files are silently overwritten.  If @var{outdir} is defined the
-## compressed files are placed in this directory.
-## @seealso{gunzip, bzip2, zip, tar}
+## @deftypefn  {Function File} {@var{filelist} =} gzip (@var{files})
+## @deftypefnx {Function File} {@var{filelist} =} gzip (@var{files}, @var{dir})
+## Compress the list of files and directories specified in @var{files}.
+##
+## @var{files} is a character array or cell array of strings.  Shell
+## wildcards in the filename such as @samp{*} or @samp{?} are accepted and
+## expanded.  Each file is compressed separately and a new file with a
+## @file{".gz"} extension is created.  The original files are not modified,
+## but existing compressed files will be silently overwritten.  If a directory
+## is specified then @code{gzip} recursively compresses all files in the
+## directory.
+##
+## If @var{dir} is defined the compressed files are placed in this directory,
+## rather than the original directory where the uncompressed file resides.
+## If @var{dir} does not exist it is created.
+##
+## The optional output @var{filelist} is a list of the compressed files.
+## @seealso{gunzip, unpack, bzip2, zip, tar}
 ## @end deftypefn
 
-function entries = gzip (varargin)
-  if (nargin != 1 && nargin != 2) || (nargout > 1)
+function filelist = gzip (varargin)
+
+  if (nargin < 1 || nargin > 2 || nargout > 1)
     print_usage ();
   endif
 
   if (nargout == 0)
     __xzip__ ("gzip", "gz", "gzip -r %s", varargin{:});
   else
-    entries = __xzip__ ("gzip", "gz", "gzip -r %s", varargin{:});
+    filelist = __xzip__ ("gzip", "gz", "gzip -r %s", varargin{:});
   endif
 
 endfunction
@@ -44,24 +55,32 @@
 %!xtest
 %! ## test gzip together with gunzip
 %! unwind_protect
-%!   filename = tmpnam;
-%!   dummy    = 1;
+%!   filename = tempname;
+%!   dummy    = pi;
 %!   save (filename, "dummy");
-%!   dirname  = tmpnam;
+%!   dirname  = tempname;
 %!   mkdir (dirname);
-%!   entry = gzip (filename, dirname);
-%!   [path, basename, extension] = fileparts (filename);
-%!   if (! strcmp (entry, [dirname, filesep, basename, extension, ".gz"]))
+%!   filelist = gzip (filename, dirname);
+%!   filelist = filelist{1};
+%!   [~, basename, extension] = fileparts (filename);
+%!   if (! strcmp (filelist, [dirname, filesep, basename, extension, ".gz"]))
 %!     error ("gzipped file does not match expected name!");
 %!   endif
-%!   if (! exist (entry, "file"))
+%!   if (! exist (filelist, "file"))
 %!     error ("gzipped file cannot be found!");
 %!   endif
-%!   gunzip (entry);
-%!   if (system (sprintf ("diff %s %s%c%s%s", filename, dirname, filesep,
-%!                                            basename, extension)))
-%!     error ("unzipped file not equal to original file!");
-%!   end
+%!   gunzip (filelist);
+%!   fid = fopen (filename, "rb");
+%!   assert (fid >= 0);
+%!   orig_data = fread (fid);
+%!   fclose (fid);
+%!   fid = fopen ([dirname filesep basename extension], "rb");
+%!   assert (fid >= 0);
+%!   new_data = fread (fid);
+%!   fclose (fid);
+%!   if (orig_data != new_data)
+%!     error ("gunzipped file not equal to original file!");
+%!   endif
 %! unwind_protect_cleanup
 %!   delete (filename);
 %!   delete ([dirname, filesep, basename, extension]);
@@ -70,6 +89,5 @@
 
 %!error gzip ()
 %!error gzip ("1", "2", "3")
-%!error <output directory does not exist> gzip ("1", tmpnam)
 %!error <FILES must be a character array or cellstr> gzip (1)
 
--- a/scripts/miscellaneous/info.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/info.m	Mon Jan 12 09:17:35 2015 -0800
@@ -31,7 +31,8 @@
   Octave are available at\n\
   http://www.octave.org/support.html\n\
 \n\
-  You may also find some information in the Octave Wiki at\n\
+  The Octave Wiki has user-generated content on a variety of subjects\n\
+  including installation and is available at\n\
   http://wiki.octave.org\n\
 \n\
   Additional functionality can be enabled by using packages from\n\
@@ -46,6 +47,6 @@
 endfunction
 
 
-## Mark file as being tested.  No real test needed for this function.
-%! assert (1)
+## Mark file as being tested.  No real test needed for a documentation .m file
+%!assert (1)
 
--- a/scripts/miscellaneous/inputname.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/inputname.m	Mon Jan 12 09:17:35 2015 -0800
@@ -22,22 +22,26 @@
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} inputname (@var{n})
 ## Return the name of the @var{n}-th argument to the calling function.
+##
 ## If the argument is not a simple variable name, return an empty string.
+## @code{inputname} may only be used within a function body, not at the
+## command line.
+## @seealso{nargin, nthargout}
 ## @end deftypefn
 
 function s = inputname (n)
 
-  if (nargin == 1)
-    s = evalin ("caller", sprintf ("__varval__ (\".argn.\"){%d};", n));
-    ## For compatibility with Matlab, return empty string if argument
-    ## name is not a valid identifier.
-    if (! isvarname (s))
-      s = "";
-    endif
-  else
+  if (nargin != 1)
     print_usage ();
   endif
 
+  s = evalin ("caller", sprintf ("__varval__ (\".argn.\"){%d};", n));
+  ## For compatibility with Matlab,
+  ## return empty string if argument name is not a valid identifier.
+  if (! isvarname (s))
+    s = "";
+  endif
+
 endfunction
 
 
@@ -57,3 +61,12 @@
 %!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");
+
+%!error inputname ()
+%!error inputname (1,2)
+
--- a/scripts/miscellaneous/isappdata.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/isappdata.m	Mon Jan 12 09:17:35 2015 -0800
@@ -17,35 +17,55 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {@var{V} =} isappdata (@var{h}, @var{name})
+## @deftypefn {Function File} {@var{valid} =} isappdata (@var{h}, @var{name})
 ## Return true if the named application data, @var{name}, exists for the
-## object with handle @var{h}.
-## @seealso{getappdata, setappdata, rmappdata}
+## graphics object with handle @var{h}.
+##
+## @var{h} may also be a vector of graphics handles.
+## @seealso{getappdata, setappdata, rmappdata, guidata, get, set, getpref, setpref}
 ## @end deftypefn
 
 ## Author: Ben Abbott <bpabbott@mac.com>
 ## Created: 2010-07-15
 
-function res = isappdata (h, name)
+function valid = isappdata (h, name)
 
-  if (! (all (ishandle (h)) && ischar (name)))
-    error ("isappdata: invalid input");
+  if (nargin < 1 || nargin > 2)
+    print_usage ();
   endif
 
-  for nh = 1:numel (h)
-    data = get (h(nh));
-    if (isfield (data, "__appdata__") && isfield (data.__appdata__, name))
-      res(nh) = true;
-    else
-      res(nh) = false;
-    endif
+  if (! all (ishandle (h(:))))
+    error ("isappdata: H must be a scalar or vector of graphic handles");
+  elseif (! ischar (name))
+    error ("isappdata: NAME must be a string");
+  endif 
+
+  valid = false (size (h));
+  for i = 1:numel (h)
+    try
+      appdata = get (h(i), "__appdata__");
+      if (isfield (appdata, name))
+        valid(i) = true;
+      endif
+    end_try_catch
   endfor
 
 endfunction
 
 
 %!test
-%! setappdata (0, "hello", "world");
-%! assert (isappdata (0, "hello"), true);
-%! assert (isappdata (0, "foobar"), false);
+%! unwind_protect
+%!   setappdata (0, "%hello%", "world");
+%!   assert (isappdata (0, "%hello%"), true);
+%!   assert (isappdata ([0 0], "%hello%"), [true, true]);
+%!   assert (isappdata (0, "%foobar%"), false);
+%! unwind_protect_cleanup
+%!   rmappdata (0, "%hello%");
+%! end_unwind_protect
 
+## Test input validation
+%!error isappdata ()
+%!error isappdata (1,2,3)
+%!error <H must be a scalar .* graphic handle> isappdata (-1, "hello")
+%!error <NAME must be a string> isappdata (0, 1)
+
--- a/scripts/miscellaneous/isdeployed.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/isdeployed.m	Mon Jan 12 09:17:35 2015 -0800
@@ -20,8 +20,9 @@
 ## @deftypefn {Function File} {} isdeployed ()
 ## Return true if the current program has been compiled and is running
 ## separately from the Octave interpreter and false if it is running in
-## the Octave interpreter.  Currently, this function always returns
-## false in Octave.
+## the Octave interpreter.
+##
+## Currently, this function always returns false in Octave.
 ## @end deftypefn
 
 function retval = isdeployed ()
--- a/scripts/miscellaneous/license.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/license.m	Mon Jan 12 09:17:35 2015 -0800
@@ -1,4 +1,5 @@
 ## Copyright (C) 2005-2013 William Poetra Yoga Hadisoeseno
+## Copyright (C) 2014 Carnë Draug
 ##
 ## This file is part of Octave.
 ##
@@ -18,181 +19,170 @@
 
 ## -*- texinfo -*-
 ## @deftypefn  {Command} {} license
+## @deftypefnx {Command} {} license inuse
+## @deftypefnx {Command} {} license inuse @var{feature}
 ## @deftypefnx {Function File} {} license ("inuse")
 ## @deftypefnx {Function File} {@var{retval} =} license ("inuse")
 ## @deftypefnx {Function File} {@var{retval} =} license ("test", @var{feature})
-## @deftypefnx {Function File} {} license ("test", @var{feature}, @var{toggle})
 ## @deftypefnx {Function File} {@var{retval} =} license ("checkout", @var{feature})
-## 
-## Display the license of Octave.
-##
-## @code{license ("inuse")}
-##
-## Display a list of packages currently being used.
-##
-## @code{@var{retval} = license ("inuse")}
+## @deftypefnx {Function File} {[@var{retval}, @var{errmsg}] =} license ("checkout", @var{feature})
+## Get license information for Octave and Octave packages.
 ##
-## Return a structure containing the fields @code{feature} and @code{user}.
-##
-## @code{@var{retval} = license ("test", @var{feature})}
+## GNU Octave is free software distributed under the GNU General Public
+## License (GPL), and a license manager makes no sense.  This function is
+## provided only for @sc{matlab} compatibility.
 ##
-## Return 1 if a license exists for the product identified by the string
-## @var{feature} and 0 otherwise.  The argument @var{feature} is case
-## insensitive and only the first 27 characters are checked.
-##
-## @code{license ("test", @var{feature}, @var{toggle})}
-##
-## Enable or disable license testing for @var{feature}, depending on
-## @var{toggle}, which may be one of:
+## When called with no extra input arguments, it returns the Octave license,
+## otherwise the first input defines the operation mode and must be one of
+## the following strings: @code{inuse}, @code{test}, and @code{checkout}.
+## The optional @var{feature} argument can either be @qcode{"octave"} (core),
+## or an Octave package.
 ##
 ## @table @asis
-## @item @qcode{"enable"}
-## Future tests for the specified license of @var{feature} are conducted
-## as usual.
+## @item @qcode{"inuse"}
+## Returns a list of loaded features, i.e., octave and the list of loaded
+## packages.  If an output is requested, it returns a struct array with
+## the fields @qcode{"feature"}, and @qcode{"user"}.
+##
+## @item @qcode{"test"}
+## Return true if the specified @var{feature} is installed, false otherwise.
 ##
-## @item @qcode{"disable"}
-## Future tests for the specified license of @var{feature} return 0.
+## An optional third argument @qcode{"enable"} or @qcode{"disable"} is
+## accepted but ignored.
+##
+## @item @qcode{"checkout"}
+## Return true if the specified @var{feature} is installed, false otherwise.
+## An optional second output will have an error message if a package is not
+## installed.
+##
 ## @end table
 ##
-## @code{@var{retval} = license ("checkout", @var{feature})}
-##
-## Check out a license for @var{feature}, returning 1 on success and 0
-## on failure.
-##
-## This function is provided for compatibility with @sc{matlab}.
-## @seealso{ver, version}
+## @seealso{pkg, ver, version}
 ## @end deftypefn
 
 ## Author: William Poetra Yoga Hadisoeseno <williampoetra@gmail.com>
 
-function retval = license (varargin)
-
-  persistent __octave_licenses__;
+function [retval, errmsg] = license (cmd, feature, toogle)
 
-  if (isempty (__octave_licenses__))
-    __octave_licenses__ = cell ();
-    __octave_licenses__{1,1} = "Octave";
-    __octave_licenses__{1,2} = "GNU General Public License";
-    __octave_licenses__{1,3} = true;
-    if (exist ("OCTAVE_FORGE_VERSION"))
-      __octave_licenses__{2,1} = "octave-forge";
-      __octave_licenses__{2,2} = "<various licenses>";
-      __octave_licenses__{2,3} = true;
-    endif
-  endif
-
-  nout = nargout;
-  nin = nargin;
-  nr_licenses = rows (__octave_licenses__);
-
-  if (nout > 1 || nin > 3)
+  if (nargin > 3)
     print_usage ();
   endif
 
-  if (nin == 0)  
-
-    found = find (strcmp (__octave_licenses__(:,1), "Octave"), 1);
-
-    if (! isempty (found))
-      result = __octave_licenses__{found,2};
-    else
-      result = "unknown";
-    endif
+  ## Then only give information about Octave core
+  if (nargin == 0)
+    retval = "GNU General Public License";
+    return;
+  endif
 
-    if (nout == 0)
-      printf ("%s\n", result);
-    else
-      retval = result;
-    endif
+  [features, loaded] = get_all_features ();
 
-  elseif (nin == 1)
-
-    if (nout == 0)
-
-      if (! strcmp (varargin{1}, "inuse"))
-        usage ('license ("inuse")');
+  switch (tolower (cmd))
+    case "inuse"
+      if (nargin > 2)
+        print_usage ();
       endif
 
-      printf ("%s\n", __octave_licenses__{:,1});
+      features = features(loaded);
 
-    else
-
-      if (! strcmp (varargin{1}, "inuse"))
-        usage ('retval = license ("inuse")');
+      if (nargin > 1)
+        features = features(strcmp (features, feature));
+      endif
+      if (nargout == 0)
+        printf ("%s\n", features{:});
+      else
+        retval = struct ("feature", features, "user", get_username ());
       endif
 
-      pw = getpwuid (getuid ());
-      if (isstruct (pw))
-        username = pw.name;
-      else
-        username = "octave_user";
+    case "test"
+      if (nargin < 2)
+        print_usage ();
       endif
 
-      retval = struct ("feature", __octave_licenses__(:,1), "user", username);
-
-    endif
-
-  else
-
-    feature = varargin{2}(1:(min ([(length (varargin{2})), 27])));
-
-    if (strcmp (varargin{1}, "test"))
-
-      found = find (strcmpi (__octave_licenses__(:,1), feature), 1);
-
-      if (nin == 2)
-        retval = ! isempty (found) && __octave_licenses__{found,3};
-      else
-        if (! isempty (found))
-          if (strcmp (varargin{3}, "enable"))
-            __octave_licenses__{found,3} = true;
-          elseif (strcmp (varargin{3}, "disable"))
-            __octave_licenses__{found,3} = false;
-          else
-            error ("license: TOGGLE must be either 'enable' or 'disable'");
-          endif
-        else
-          error ("license: FEATURE '%s' not found", feature);
-        endif
+      if (nargin > 2)
+        ## We ignore the toogle argument because... what's the point?  We
+        ## don't need a license management system on Octave.  This function
+        ## will return true, even if anyone tries to disabled a license.
+        switch tolower (toogle)
+          case "enable"   # do nothing
+          case "disable"  # do nothing
+          otherwise       error ("license: TOOGLE must be enable or disable");
+        endswitch
       endif
 
-    elseif (strcmp (varargin{1}, "checkout"))
+      retval = any (strcmp (features, feature));
 
-      if (nin != 2)
-        usage ('retval = license ("checkout", feature)');
+    case "checkout"
+      ## I guess we could have the checkout command load packages but it's not
+      ## really the same thing.  The closest we have is simply to check if
+      ## there is a package with the feature name, and give an error if not.
+
+      if (nargin != 2)
+        print_usage ();
       endif
 
-      found = find (strcmpi (__octave_licenses__(:,1), feature), 1);
-
-      retval = ! isempty (found) && __octave_licenses__{found,3};
+      retval = any (strcmp (features, feature));
+      errmsg = "";
 
-    else
+      if (! retval)
+        errmsg = ['No package named "' feature '" installed'];
+      endif
+
+    otherwise
       print_usage ();
-    endif
-
-  endif
+  endswitch
 
 endfunction
 
+function username = get_username ()
+  pw = getpwuid (getuid ());
+  if (isstruct (pw))
+    username = pw.name;
+  else
+    username = "octave_user";
+  endif
+endfunction
 
-%!assert (license(), "GNU General Public License")
-%!assert ((license ("inuse")).feature, "Octave")
+function [features, loaded] = get_all_features ()
+  pkg_list = pkg ("list");
+  features = {"octave", ...
+              cellfun(@(x) x.name, pkg_list, "uniformoutput", false){:}};
+  loaded = [true, cellfun(@(x) x.loaded, pkg_list)];
+endfunction
+
+
+%!assert (license (), "GNU General Public License")
+%!assert ((license ("inuse", "octave")).feature, "octave")
+
+%!shared list
+%!test
+%! list = pkg ("list");
+%! for idx = 1: numel (list)
+%!   name = list{idx}.name;
+%!   if (list{idx}.loaded);
+%!     assert ((license ("inuse", name)).feature, name);
+%!   else
+%!     rv = license ("inuse", name);
+%!     assert (isstruct (rv));
+%!     assert (all (isfield (rv, {"feature", "user"})));
+%!   endif
+%! endfor
+
+%!assert (license ("test", "octave"), true)
+%!assert (license ("test", "not_a_valid package name"), false)
 
 %!test
-%! lstate = license ("test", "Octave");
-%! license ("test", "Octave", "disable");
-%! assert (license ("test", "Octave"), false);
-%! license ("test", "Octave", "enable");
-%! assert (license ("test", "Octave"), true);
-%! if (lstate == false)
-%!   license ("test", "Octave", "disable");
-%! endif
+%! for idx = 1: numel (list)
+%!   assert (license ("test", list{idx}.name), true)
+%! endfor
 
-%!assert (license ("checkout", "Octave"), true)
+%!assert (license ("checkout", "octave"), true)
+
+%!test
+%! [s, e] = license ("checkout", "NOT_A_PACKAGE");
+%! assert (e, 'No package named "NOT_A_PACKAGE" installed');
 
 %% Test input validation
 %!error license ("not_inuse")
-%!error <TOGGLE must be either> license ("test", "Octave", "not_enable")
-%!error <FEATURE 'INVALID' not found> license ("test", "INVALID", "enable")
-%!error license ("not_test", "Octave", "enable")
+%!error license ("not_test", "octave", "enable")
+%!error <TOOGLE must be enable or disable> license ("test", "octave", "invalid_toogle")
 
--- a/scripts/miscellaneous/list_primes.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/list_primes.m	Mon Jan 12 09:17:35 2015 -0800
@@ -19,73 +19,52 @@
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {} list_primes ()
 ## @deftypefnx {Function File} {} list_primes (@var{n})
-## List the first @var{n} primes.  If @var{n} is unspecified, the first
-## 25 primes are listed.
+## List the first @var{n} primes.
 ##
-## The algorithm used is from page 218 of the @TeX{}book.
+## If @var{n} is unspecified, the first 25 primes are listed.
 ## @seealso{primes, isprime}
 ## @end deftypefn
 
 ## Author: jwe
 
-function retval = list_primes (n)
+function retval = list_primes (n = 25)
 
-  if (nargin > 0)
-    if (! isscalar (n))
-      error ("list_primes: argument must be a scalar");
-    endif
+  if (nargin > 1)
+    print_usage ();
+  elseif (! isreal (n) || ! isscalar (n))
+    error ("list_primes: N must be a real scalar");
   endif
 
-  if (nargin == 0)
-    n = 25;
-  endif
+  n = floor (n);
 
-  if (n == 1)
+  if (n < 1)
+    retval = [];
+    return;
+  elseif (n == 1)
     retval = 2;
     return;
   endif
 
-  if (n == 2)
-    retval = [2; 3];
-    return;
+  list = primes (n * log (5 * n));
+  if (numel (list) < n)
+    ## Algorithm tested up to n=10,000 without failure.
+    error ("list_primes: Algorithm failed.  Try primes (n*log (6*n))(1:n)");
   endif
 
-  retval = zeros (1, n);
-  retval(1) = 2;
-  retval(2) = 3;
-
-  n = n - 2;
-  i = 3;
-  p = 5;
-  while (n > 0)
-
-    is_prime = 1;
-    is_unknown = 1;
-    d = 3;
-    while (is_unknown)
-      a = fix (p / d);
-      if (a <= d)
-        is_unknown = 0;
-      endif
-      if (a * d == p)
-        is_prime = 0;
-        is_unknown = 0;
-      endif
-      d = d + 2;
-    endwhile
-
-    if (is_prime)
-      retval(i++) = p;
-      n--;
-    endif
-    p = p + 2;
-
-  endwhile
+  retval = list(1:n);
 
 endfunction
 
 
 %!assert (list_primes (), [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, ...
 %!                         43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97])
-%!assert (list_primes (5), [2, 3, 5, 7, 11]);
+%!assert (list_primes (5), [2, 3, 5, 7, 11])
+
+%!assert (list_primes (0), [])
+%!assert (list_primes (1), [2])
 
+## Test input validation
+%!error list_primes (1, 2)
+%!error <N must be a real scalar> list_primes (i)
+%!error <N must be a real scalar> list_primes ([1 2])
+
--- a/scripts/miscellaneous/ls.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/ls.m	Mon Jan 12 09:17:35 2015 -0800
@@ -18,10 +18,26 @@
 
 ## -*- texinfo -*-
 ## @deftypefn  {Command} {} ls
-## @deftypefnx {Command} {} ls filenames
-## @deftypefnx {Command} {} ls options
-## @deftypefnx {Command} {} ls options filenames
-## List directory contents.  For example:
+## @deftypefnx {Command} {} ls @var{filenames}
+## @deftypefnx {Command} {} ls @var{options}
+## @deftypefnx {Command} {} ls @var{options} @var{filenames}
+## @deftypefnx {Function File} {@var{list} =} ls (@dots{})
+##
+## List directory contents.
+##
+## The @code{ls} command is implemented by calling the native operating
+## system's directory listing command---available @var{options} will vary from
+## system to system.
+##
+## Filenames are subject to shell expansion if they contain any wildcard
+## characters @samp{*}, @samp{?}, @samp{[]}.  To find a literal example of a
+## wildcard character the wildcard must be escaped using the backslash operator
+## @samp{\}.
+##
+## If the optional output @var{list} is requested then @code{ls} returns a
+## character array with one row for each file/directory name.
+##
+## Example usage on a UNIX-like system:
 ##
 ## @example
 ## @group
@@ -32,14 +48,6 @@
 ## @end group
 ## @end example
 ##
-## The @code{dir} and @code{ls} commands are implemented by calling your
-## system's directory listing command, so the available options will vary
-## from system to system.
-##
-## Filenames are subject to shell expansion if they contain any wildcard
-## characters @samp{*}, @samp{?}, @samp{[]}.  If you want to find a
-## literal example of a wildcard character you must escape it using the
-## backslash operator @samp{\}.
 ## @seealso{dir, readdir, glob, what, stat, filesep, ls_command}
 ## @end deftypefn
 
@@ -50,8 +58,7 @@
   global __ls_command__;
 
   if (isempty (__ls_command__) || ! ischar (__ls_command__))
-    ## Initialize value for __ls_command__.
-    ls_command ();
+    ls_command ();  # Initialize global value for __ls_command__.
   endif
 
   if (! iscellstr (varargin))
@@ -61,21 +68,25 @@
   if (nargin > 0)
     args = tilde_expand (varargin);
     if (ispc () && ! isunix ())
+      idx = ! strncmp (args, '/', 1);
+      ## Enclose paths, potentially having spaces, in double quotes:
+      args(idx) = strcat ('"', args(idx), '"');    
       ## shell (cmd.exe) on MinGW uses '^' as escape character
-      args = regexprep (args, '([^\w.*? -])', '^$1');
-      ## Strip UNIX directory character which looks like an option to dir cmd.
-      if (args{end}(end) == '/')
-        args{end}(end) = "";
-      endif
+      args = regexprep (args, '([^\w.*?])', '^$1');
     else
-      args = regexprep (args, '([^\w.*?-])', '\\$1');
+      ## Escape any special characters in filename
+      args = regexprep (args, '([^][\w.*?-])', '\\$1');
+      ## Undo escaped spaces following command args
+      ## Only used for command form where single str contains many args.
+      ## Example: list = ls ("-l /usr/bin")
+      args = regexprep (args, '(-\w+)(?:\\ )+', '$1 ');
     endif
     args = sprintf ("%s ", args{:});
   else
     args = "";
   endif
 
-  cmd = sprintf ("%s %s", __ls_command__, args);
+  cmd = [__ls_command__ " " args];
 
   if (page_screen_output () || nargout > 0)
     [status, output] = system (cmd);
@@ -84,10 +95,8 @@
       error ("ls: command exited abnormally with status %d\n", status);
     elseif (nargout == 0)
       puts (output);
-    elseif (isempty (output))
-      retval = "";
     else
-      retval = strvcat (regexp (output, '\S+', 'match'){:});
+      retval = strvcat (regexp (output, "[\r\n]+", "split"){:});
     endif
   else
     ## Just let the output flow if the pager is off.  That way the
@@ -104,5 +113,18 @@
 %! assert (ischar (list));
 %! assert (! isempty (list));
 
-%!error ls (1)
+%!test
+%! if (isunix ())
+%!   list = ls ("/");
+%!   list = (list')(:)';   # transform to a single row vector
+%!   assert (! isempty (strfind (list, "sbin")));
+%!   list2 = ls ("-l /");
+%!   list2 = (list2')(:)';   # transform to a single row vector
+%!   assert (! isempty (strfind (list2, "sbin")));
+%!   assert (rows (list) == rows (list2));
+%! endif 
 
+%!error <all arguments must be character strings> ls (1)
+## Test below is valid, but produces confusing output on screen
+%!#error <command exited abnormally> ls ("-!")
+
--- a/scripts/miscellaneous/ls_command.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/ls_command.m	Mon Jan 12 09:17:35 2015 -0800
@@ -47,7 +47,7 @@
       if (ischar (cmd))
         __ls_command__ = cmd;
       else
-        error ("ls_command: expecting argument to be a character string");
+        error ("ls_command: argument must be a character string");
       endif
     endif
 
@@ -65,3 +65,5 @@
 %!   assert (cmd(1:2), "ls"); 
 %! endif
 
+%!error <argument must be a character string> ls_command (123)
+
--- a/scripts/miscellaneous/menu.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/menu.m	Mon Jan 12 09:17:35 2015 -0800
@@ -17,82 +17,83 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} menu (@var{title}, @var{opt1}, @dots{})
-## Print a title string followed by a series of options.  Each option will
-## be printed along with a number.  The return value is the number of the
-## option selected by the user.  This function is useful for interactive
-## programs.  There is no limit to the number of options that may be passed
-## in, but it may be confusing to present more than will fit easily on one
-## screen.
+## @deftypefn  {Function File} {@var{choice} =} menu (@var{title}, @var{opt1}, @dots{})
+## @deftypefnx {Function File} {@var{choice} =} menu (@var{title}, @{@var{opt1}, @dots{}@})
+## Display a menu with heading @var{title} and options @var{opt1}, @dots{},
+## and wait for user input.
+##
+## If the GUI is running, or Java is available, the menu is displayed
+## graphically using @code{listdlg}.  Otherwise, the title and menu options
+## are printed on the console.
+##
+## @var{title} is a string and the options may be input as individual strings
+## or as a cell array of strings.
+##
+## The return value @var{choice} is the number of the option selected by the
+## user counting from 1.
+##
+## This function is useful for interactive programs.  There is no limit to the
+## number of options that may be passed in, but it may be confusing to present
+## more than will fit easily on one screen.
 ## @seealso{input, listdlg}
 ## @end deftypefn
 
 ## Author: jwe
 
-function num = menu (title, varargin)
+function choice = menu (title, varargin)
 
   if (nargin < 2)
     print_usage ();
   endif
 
-  ## Force pending output to appear before the menu.
-
-  fflush (stdout);
-
-  ## Don't send the menu through the pager since doing that can cause
-  ## major confusion.
-
-  page_screen_output (0, "local");
-
-  ## Process Supplied Options
-  if (nargin == 2)
-    ## List in a cell array
-    if (iscell (varargin{1}))
-      varargin = varargin{1};
-      nopt = length (varargin);
-      for i = 1:nopt
-        while (iscell (varargin{i}))
-          varargin{i} = varargin{i}{1};
-        endwhile
-      endfor
-    else
-      nopt = nargin - 1;
-    endif
-  else
-    ## List with random elements in it - pick the first always
-    for i = 1:nargin - 1
-      if (iscell (varargin{i}))
-        while (iscell (varargin{i}))
-          varargin{i} = varargin{i}{1};
-        endwhile
-      else
-        if (! ischar (varargin{i}))
-          varargin{i} = varargin{i}(1);
-        endif
-      endif
-    endfor
-    nopt = length (varargin);
+  if (! ischar (title))
+    error ("menu: TITLE must be a string");
+  elseif (nargin > 2 && ! iscellstr (varargin))
+    error ("menu: All OPTIONS must be strings");
+  elseif (! ischar (varargin{1}) && ! iscellstr (varargin{1}))
+    error ("menu: OPTIONS must be string or cell array of strings");
   endif
 
-  if (! isempty (title))
-    disp (title);
-    printf ("\n");
-  endif
+  if (isguirunning () || usejava ("awt"))
+    [choice, ok] = listdlg ("Name", "menu", "PromptString", title,
+                            "ListString", varargin, "SelectionMode", "Single");
+    if (! ok)
+      choice = 1;
+    endif
+  else  # console menu
+    ## Force pending output to appear before the menu.
+    fflush (stdout);
+
+    ## Don't send the menu through the pager since doing that can cause
+    ## major confusion.
+    page_screen_output (0, "local");
 
-  while (1)
-    for i = 1:nopt
-      printf ("  [%2d] ", i);
-      disp (varargin{i});
-    endfor
-    printf ("\n");
-    s = input ("pick a number, any number: ", "s");
-    num = sscanf (s, "%d");
-    if (! isscalar (num) || num < 1 || num > nopt)
-      printf ("\nerror: input invalid or out of range\n\n");
-    else
-      break;
+    if (! isempty (title))
+      printf ("%s\n", title);
     endif
-  endwhile
+
+    nopt = numel (varargin);
+    while (1)
+      for i = 1:nopt
+        printf ("  [%2d] %s\n", i, varargin{i});
+      endfor
+      printf ("\n");
+      s = input ("Select a number: ", "s");
+      choice = sscanf (s, "%d");
+      if (! isscalar (choice) || choice < 1 || choice > nopt)
+        printf ("\nerror: input invalid or out of range\n\n");
+      else
+        break;
+      endif
+    endwhile
+  endif
 
 endfunction
 
+
+%!error menu ()
+%!error menu ("title")
+%!error <TITLE must be a string> menu (1, "opt1")
+%!error <All OPTIONS must be strings> menu ("title", "opt1", 1)
+%!error <OPTIONS must be string or cell array of strings> menu ("title", 1)
+
--- a/scripts/miscellaneous/mex.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/mex.m	Mon Jan 12 09:17:35 2015 -0800
@@ -19,12 +19,25 @@
 ## -*- texinfo -*-
 ## @deftypefn {Command} {} mex [options] file @dots{}
 ## Compile source code written in C, C++, or Fortran, to a MEX file.
+## 
 ## This is equivalent to @code{mkoctfile --mex [options] file}.
-## @seealso{mkoctfile}
+## @seealso{mkoctfile, mexext}
 ## @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
 
+
+## Remove from test statistics.  All real tests are in mkoctfile. 
+%!assert (1)
+
--- a/scripts/miscellaneous/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -21,7 +21,6 @@
   miscellaneous/desktop.m \
   miscellaneous/dir.m \
   miscellaneous/dos.m \
-  miscellaneous/dump_prefs.m \
   miscellaneous/edit.m \
   miscellaneous/error_ids.m \
   miscellaneous/fact.m \
@@ -51,6 +50,7 @@
   miscellaneous/movefile.m \
   miscellaneous/namelengthmax.m \
   miscellaneous/news.m \
+  miscellaneous/open.m \
   miscellaneous/orderfields.m \
   miscellaneous/pack.m \
   miscellaneous/paren.m \
@@ -68,7 +68,7 @@
   miscellaneous/symvar.m \
   miscellaneous/tar.m \
   miscellaneous/tempdir.m \
-  miscellaneous/tempname.m \
+  miscellaneous/tmpnam.m \
   miscellaneous/unix.m \
   miscellaneous/unpack.m \
   miscellaneous/untar.m \
--- a/scripts/miscellaneous/movefile.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/movefile.m	Mon Jan 12 09:17:35 2015 -0800
@@ -21,12 +21,13 @@
 ## @deftypefnx {Function File} {} movefile (@var{f1}, @var{f2})
 ## @deftypefnx {Function File} {} movefile (@var{f1}, @var{f2}, 'f')
 ## @deftypefnx {Function File} {[@var{status}, @var{msg}, @var{msgid}] =} movefile (@dots{})
-## Move the file @var{f1} to the destination @var{f2}.
+## Move the source files or directories @var{f1} to the destination @var{f2}.
 ##
 ## The name @var{f1} may contain globbing patterns.  If @var{f1} expands to
 ## multiple file names, @var{f2} must be a directory.  If no destination
 ## @var{f2} is specified then the destination is the present working directory.
 ## If @var{f2} is a file name then @var{f1} is renamed to @var{f2}.
+##
 ## When the force flag @qcode{'f'} is given any existing files will be
 ## overwritten without prompting.
 ##
@@ -50,7 +51,7 @@
   msgid = "";
 
   ## FIXME: maybe use the same method as in ls to allow users control
-  ## over the command that is executed.
+  ##        over the command that is executed.
 
   if (ispc () && ! isunix ()
       && isempty (file_in_path (getenv ("PATH"), "mv.exe")))
@@ -63,28 +64,25 @@
   endif
 
   ## Input type check.
-  if (! (ischar (f1) || iscellstr (f1)))
-    error ("movefile: F1 must be a character string or a cell array of character strings");
+  if (ischar (f1))
+    f1 = cellstr (f1);
+  elseif (! iscellstr (f1))
+    error ("copyfile: F1 must be a string or a cell array of strings");
   endif
 
   if (nargin == 1)
     f2 = pwd ();
   elseif (! ischar (f2))
-    error ("movefile: F2 must be a character string");
+    error ("movefile: F2 must be a string");
   endif
 
   if (nargin == 3 && strcmp (force, "f"))
     cmd = [cmd " " cmd_force_flag];
   endif
 
-  ## If f1 isn't a cellstr convert it to one.
-  if (ischar (f1))
-    f1 = cellstr (f1);
-  endif
-
   ## If f1 has more than 1 element f2 must be a directory
   isdir = (exist (f2, "dir") != 0);
-  if (length (f1) > 1 && ! isdir)
+  if (numel (f1) > 1 && ! isdir)
     error ("movefile: when moving multiple files, F2 must be a directory");
   endif
 
@@ -137,3 +135,35 @@
 
 endfunction
 
+
+%!test
+%! unwind_protect
+%!   f1 = tempname;
+%!   tmp_var = pi;
+%!   save (f1, "tmp_var");
+%!   fid = fopen (f1, "rb");
+%!   assert (fid >= 0);
+%!   orig_data = fread (fid);
+%!   fclose (fid);
+%!   f2 = tempname;
+%!   assert (movefile (f1, f2));
+%!   assert (! exist (f1, "file")); 
+%!   assert (exist (f2, "file")); 
+%!   fid = fopen (f2, "rb");
+%!   assert (fid >= 0);
+%!   new_data = fread (fid);
+%!   fclose (fid);
+%!   if (orig_data != new_data)
+%!     error ("moved file not equal to original file!");
+%!   endif
+%! unwind_protect_cleanup
+%!   delete (f2);
+%! end_unwind_protect
+
+## Test input validation
+%!error movefile ()
+%!error movefile (1,2,3,4)
+%!error <F1 must be a string> movefile (1, "foobar")
+%!error <F2 must be a string> movefile ("foobar", 1)
+%!error <F2 must be a directory> movefile ({"a", "b"}, "%_NOT_A_DIR_%") 
+
--- a/scripts/miscellaneous/namelengthmax.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/namelengthmax.m	Mon Jan 12 09:17:35 2015 -0800
@@ -18,12 +18,13 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} namelengthmax ()
-## Return the @sc{matlab} compatible maximum variable name length.  Octave is
-## capable of storing strings up to @math{2^{31} - 1} in length.
-## However for @sc{matlab} compatibility all variable, function,
-## and structure field names should be shorter than the length supplied by
-## @code{namelengthmax}.  In particular variables stored to a @sc{matlab} file
-## format will have their names truncated to this length.
+## Return the @sc{matlab} compatible maximum variable name length.
+##
+## Octave is capable of storing strings up to @math{2^{31} - 1} in length.
+## However for @sc{matlab} compatibility all variable, function, and structure
+## field names should be shorter than the length returned by
+## @code{namelengthmax}.  In particular, variables stored to a @sc{matlab} file
+## format (@file{*.mat}) will have their names truncated to this length.
 ## @end deftypefn
 
 function n = namelengthmax ()
--- a/scripts/miscellaneous/news.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/news.m	Mon Jan 12 09:17:35 2015 -0800
@@ -24,6 +24,7 @@
 ## When called without an argument, display the NEWS file for Octave.
 ## When given a package name @var{package}, display the current NEWS file for
 ## that package.
+## @seealso{ver, pkg}
 ## @end deftypefn
 
 function news (package = "octave")
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/miscellaneous/open.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,89 @@
+## Copyright (C) 2014 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  {Function File} {@var{output} =} open @var{file}
+## @deftypefnx {Function File} {@var{output} =} open (@var{file})
+## Open the file @var{file} in Octave or in an external application
+## based on the file type as determined by the file name extension.
+##
+## Recognized file types are
+##
+## @table @code
+## @item .m
+## Open file in the editor.
+##
+## @item .mat
+## Load the file in the base workspace.
+##
+## @item .exe
+## Execute the program (on Windows systems only).
+## @end table
+##
+## Other file types are opened in the appropriate external application.
+## @end deftypefn
+
+function output = open (file)
+
+  if (nargin != 1)
+    print_usage ();
+  endif
+
+  if (! ischar (file))
+    error ("expecting argument to be a file name");
+  endif
+
+  [~, ~, ext] = fileparts (file);
+
+  if (strcmpi (ext, ".m"))
+    edit (file);
+  elseif (strcmpi (ext, ".mat"))
+    if (nargout > 0)
+      output = load (file);
+    else
+      evalin ("base", sprintf ("load ('%s');", file));
+    endif
+  elseif (any (strcmpi (ext, {".fig", ".mdl", ".slx", ".prj"})))
+    error ("opening file type '%s' is not supported", ext);
+  elseif (strcmpi (ext, ".exe"))
+    if (ispc ())
+      dos (file);
+    else
+      error ("executing .exe files is only supported on Windows systems");
+    endif
+  else
+    open_with_system_app (file);
+  endif
+
+endfunction
+
+%% Test input validation
+%!error open
+%!error open (1)
+%!error output = open (1)
+
+function open_with_system_app (file)
+
+  if (ispc ())
+    __w32_shell_execute__ (file);
+  else
+    ## FIXME: might not be xdg-open...
+    system (sprintf ("xdg-open %s 2> /dev/null", file), false, "async");
+  endif
+
+endfunction
--- a/scripts/miscellaneous/orderfields.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/orderfields.m	Mon Jan 12 09:17:35 2015 -0800
@@ -17,20 +17,23 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {[@var{t}, @var{p}] =} orderfields (@var{s1})
-## @deftypefnx {Function File} {[@var{t}, @var{p}] =} orderfields (@var{s1}, @var{s2})
-## Return a copy of @var{s1} with fields arranged alphabetically or as
-## specified by @var{s2}.
-##
-## Given one struct, arrange field names in @var{s1} alphabetically.
+## @deftypefn  {Function File} {@var{sout}] =} orderfields (@var{s1})
+## @deftypefnx {Function File} {@var{sout}] =} orderfields (@var{s1}, @var{s2})
+## @deftypefnx {Function File} {@var{sout}] =} orderfields (@var{s1}, @{@var{cellstr}@})
+## @deftypefnx {Function File} {@var{sout}] =} orderfields (@var{s1}, @var{p})
+## @deftypefnx {Function File} {[@var{sout}, @var{p}] =} orderfields (@dots{})
+## Return a @emph{copy} of @var{s1} with fields arranged alphabetically, or as
+## specified by the second input.
 ##
-## If the second argument is a struct, arrange field names in @var{s1} as they
+## Given one input struct @var{s1}, arrange field names alphabetically.
+##
+## If a second struct argument is given, arrange field names in @var{s1} as they
 ## appear in @var{s2}.  The second argument may also specify the order in a
-## permutation vector or a cell array of strings containing the fieldnames of
-## @var{s1} in the desired order.
+## cell array of strings @var{cellstr}.  The second argument may also be a
+## permutation vector. 
 ##
-## The optional second output argument @var{p} is assigned the permutation
-## vector which converts the original name order into the new name order.
+## The optional second output argument @var{p} is the permutation vector which
+## converts the original name order to the new name order.
 ##
 ## Examples:
 ##
@@ -84,20 +87,18 @@
 ## @end group
 ## @end example
 ##
-## @seealso{getfield, rmfield, isfield, isstruct, fieldnames, struct}
+## @seealso{fieldnames, getfield, setfield, rmfield, isfield, isstruct, struct}
 ## @end deftypefn
 
 ## Author: Paul Kienzle <pkienzle@users.sf.net>
 ## Adapted-By: jwe
 
-function [t, p] = orderfields (s1, s2)
+function [sout, p] = orderfields (s1, s2)
 
-  if (nargin == 1 || nargin == 2)
-    if (! isstruct (s1))
-      error ("orderfields: S1 must be a struct");
-    endif
-  else
+  if (nargin < 1 || nargin > 2)
     print_usage ();
+  elseif (! isstruct (s1))
+    error ("orderfields: S1 must be a struct");
   endif
 
   if (nargin == 1)
@@ -110,32 +111,34 @@
       ## Two structures: return the fields in the order of s2.
       names = fieldnames (s2);
       if (! isequal (sort (fieldnames (s1)), sort (names)))
-        error ("orderfields: structures do not have the same fields");
+        error ("orderfields: structures S1 and S2 do not have the same fields");
       endif
     elseif (iscellstr (s2))
       ## A structure and a list of fields: order by the list of fields.
       t1 = sort (fieldnames (s1));
       t2 = sort (s2(:));
       if (! isequal (t1, t2))
-        error ("orderfields: name list does not match structure fields");
+        error ("orderfields: CELLSTR list does not match structure fields");
       endif
       names = s2;
     elseif (isvector (s2))
       ## A structure and a permutation vector: permute the order of s1.
       names = fieldnames (s1);
-      t1 = sort (s2);
-      t1 = t1(:)';
-      t2 = 1:numel (names);
+      t1 = 1:numel (names);
+      t2 = sort (s2);
+      t2 = t2(:)';
       if (! isequal (t1, t2))
-        error ("orderfields: invalid permutation vector");
+        error ("orderfields: invalid permutation vector P");
       endif
       names = names(s2);
+    else
+      error ("orderfields: second argument must be structure, cellstr, or permutation vector");
     endif
   endif
 
   ## Corner case of empty struct
   if (isempty (names))
-    t = struct ();
+    sout = struct ();
     p = [];
   endif
 
@@ -150,19 +153,22 @@
   endif
 
   ## Permute the names in the structure.
-  if (numel (s1) == 0)
+  if (isempty (s1))
+    ## Corner case of empty structure.  Still need to re-order fields.
     args = cell (1, 2 * numel (names));
     args(1:2:end) = names;
     args(2:2:end) = {[]};
-    t = struct (args{:});
+    sout = struct (args{:});
+    ## inherit dimensions
+    sout = resize (sout, size (s1));
   else
     n = numel (s1);
     for i = 1:numel (names)
       el = names{i};
-      [t(1:n).(el)] = s1(:).(el);
+      [sout(1:n).(el)] = s1(:).(el);
     endfor
     ## inherit dimensions
-    t = reshape (t, size (s1));
+    sout = reshape (sout, size (s1));
   endif
 
 endfunction
@@ -202,4 +208,28 @@
 
 ## Corner case of empty struct, bug #40224
 %!assert (orderfields (struct ()), struct ())
+%!test
+%! s(2,2).a = 1;
+%! s(1,1).b = 2;
+%! s = resize (s, [1 0]);
+%! s2 = orderfields (s, {"b", "a"});
+%! assert (fieldnames (s2), {"b"; "a"});
+%! assert (size_equal (s, s2));
 
+## Test input validation
+%!error orderfields ()
+%!error orderfields (1,2,3)
+%!error <S1 must be a struct> orderfields (1)
+%!error <S1 and S2 do not have the same fields>
+%! s1.a = 1;
+%! s2.b = 2;
+%! orderfields (s1, s2);
+%!error <CELLSTR list does not match structure fields>
+%! s1.a = 1;
+%! orderfields (s1, {"b"});
+%!error <invalid permutation vector P>
+%! s1.a = 1;
+%! orderfields (s1, [2 1]);
+%!error <second argument must be structure, cellstr, or permutation vector>
+%! s1.a = 1;
+%! orderfields (s1, ones (2,2));
--- a/scripts/miscellaneous/pack.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/pack.m	Mon Jan 12 09:17:35 2015 -0800
@@ -18,8 +18,10 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} pack ()
-## Consolidate workspace memory in @sc{matlab}.  This function is provided for
-## compatibility, but does nothing in Octave.
+## Consolidate workspace memory in @sc{matlab}.
+##
+## This function is provided for compatibility, but does nothing in Octave.
+## @seealso{clear}
 ## @end deftypefn
 
 ## Author: jwe
@@ -28,3 +30,7 @@
 
 endfunction
 
+
+## No test needed for empty function
+%!assert (1)
+
--- a/scripts/miscellaneous/parseparams.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/parseparams.m	Mon Jan 12 09:17:35 2015 -0800
@@ -52,7 +52,7 @@
 ## name of the caller function.
 ## The matching of options is case-insensitive.
 ##
-## @seealso{varargin}
+## @seealso{varargin, inputParser}
 ## @end deftypefn
 
 ## Author: Alexander Barth <abarth93@users.sourceforge.net>
@@ -105,3 +105,25 @@
   error ([fname, ": ", msg], varargin{:});
 endfunction
 
+
+%!test
+%! [reg, prop] = parseparams ({1, 2, "linewidth", 10});
+%! assert (reg, {[1], [2]});
+%! assert (prop, {"linewidth", 10});
+%!test
+%! [reg, prop] = parseparams ({1, 2, 3});
+%! assert (reg, {[1], [2], [3]});
+%! assert (isempty (prop));
+%!test
+%! [reg, prop] = parseparams ({"prop1", "val1"});
+%! assert (isempty (reg));
+%! assert (prop, {"prop1", "val1"});
+%!test
+%! [reg, prop1] = parseparams ({"linewidth", 5}, "linewidth", 10);
+%! assert (isempty (reg));
+%! assert (prop1, 5);
+
+%!error <needs odd number of arguments> parseparams ({1}, "linewidth")
+%!error <must be given as name-value pairs> parseparams ({1, "color"}, "linewidth", 5)
+%!error <unrecognized option: color> parseparams ({1, "color", 5}, "linewidth", 5)
+
--- a/scripts/miscellaneous/perl.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/perl.m	Mon Jan 12 09:17:35 2015 -0800
@@ -21,9 +21,11 @@
 ## @deftypefnx {Function File} {@var{output} =} perl (@var{scriptfile}, @var{argument1}, @var{argument2}, @dots{})
 ## @deftypefnx {Function File} {[@var{output}, @var{status}] =} perl (@dots{})
 ## Invoke Perl script @var{scriptfile}, possibly with a list of command line
-## arguments.  Return output in @var{output} and optional status in
-## @var{status}.  If @var{scriptfile} is not an absolute file name it is
-## is searched for in the current directory and then in the Octave loadpath.
+## arguments.
+##
+## Return output in @var{output} and optional status in @var{status}.  If
+## @var{scriptfile} is not an absolute file name it is searched for in the
+## current directory and then in the Octave loadpath.
 ## @seealso{system, python}
 ## @end deftypefn
 
@@ -49,3 +51,6 @@
 
 endfunction
 
+
+%!error <invalid arguments> perl (123)
+
--- a/scripts/miscellaneous/private/__xzip__.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/private/__xzip__.m	Mon Jan 12 09:17:35 2015 -0800
@@ -18,7 +18,7 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {@var{entries} =} __xzip__ (@var{commandname}, @var{extension}, @var{commandtemplate}, @var{files}, @var{outdir})
+## @deftypefn {Function File} {@var{filelist} =} __xzip__ (@var{commandname}, @var{extension}, @var{commandtemplate}, @var{files}, @var{outdir})
 ## Undocumented internal function.
 ## @end deftypefn
 
@@ -30,23 +30,28 @@
 ## are not touched. Existing compressed files are silently overwritten.
 ## This is an internal function. Do not use directly.
 
-function entries = __xzip__ (commandname, extension,
-                             commandtemplate, files, outdir)
+function filelist = __xzip__ (commandname, extension, commandtemplate,
+                              files, outdir)
 
   if (nargin == 5 && ! exist (outdir, "dir"))
-    error ("__xzip__: OUTDIR output directory does not exist");
+    r = mkdir (outdir);
+    if (! r)
+      error ("%s: Failed to create output directory DIR", commandname);
+    endif
   endif
 
   if (ischar (files))
     files = cellstr (files);
-  endif
-  if (! iscellstr (files))
-    error ("__xzip__: FILES must be a character array or cellstr");
+  elseif (! iscellstr (files))
+    error ("%s: FILES must be a character array or cellstr", commandname);
   endif
 
   if (nargin == 4)
-    outdir = tmpnam ();
-    mkdir (outdir);
+    outdir = tempname ();
+    r = mkdir (outdir);
+    if (! r)
+      error ("%s: Failed to create temporary output directory", commandname);
+    endif
   endif
 
   cwd = pwd ();
@@ -61,31 +66,35 @@
 
     copyfile (files, outdir);
 
-    [d, f] = myfileparts (files);
+    fnames = fname_only (files);
 
     cd (outdir);
 
-    cmd = sprintf (commandtemplate, sprintf (" %s", f{:}));
+    cmd = sprintf (commandtemplate, sprintf (" %s", fnames{:}));
 
     [status, output] = system (cmd);
     if (status)
-      error ("__xzip__: %s command failed with exit status = %d",
-             commandname, status);
+      fcn = evalin ("caller", "mfilename ()");
+      error ("%s: %s command failed with exit status = %d",
+             fcn, commandname, status);
     endif
 
     if (nargin == 5)
       if (nargout > 0)
-        entries = cellfun(
+        ## FIXME: This doesn't work if a directory is compressed
+        filelist = cellfun (
             @(x) fullfile (outdir, sprintf ("%s.%s", x, extension)),
-            f, "uniformoutput", false);
+            fnames, "uniformoutput", false);
       endif
     else
-      movefile (cellfun (@(x) sprintf ("%s.%s", x, extension), f,
-                        "uniformoutput", false), cwd);
+      ## FIXME: This does not work when you try to compress directories
+      ##        The resulting name is dir/.gz which is totally wrong.
+      ##        See bug #43431.
+      movefile (cellfun (@(x) sprintf ("%s.%s", x, extension),
+                         fnames, "uniformoutput", false), cwd);
       if (nargout > 0)
-        ## FIXME this does not work when you try to compress directories
-        entries  = cellfun (@(x) sprintf ("%s.%s", x, extension),
-                            files, "uniformoutput", false);
+        filelist  = cellfun (@(x) sprintf ("%s.%s", x, extension),
+                             files, "uniformoutput", false);
       endif
     endif
 
@@ -99,35 +108,10 @@
 
 endfunction
 
-function [d, f] = myfileparts (files)
-  [d, f, ext] = cellfun ("fileparts", files, "uniformoutput", false);
-  f = cellfun (@(x, y) sprintf ("%s%s", x, y), f, ext,
-               "uniformoutput", false);
+function f = fname_only (files)
+  [~, f, ext] = cellfun ("fileparts", files, "uniformoutput", false);
+  f = cellfun (@(x, y) sprintf ("%s%s", x, y), f, ext, "uniformoutput", false);
   idx = cellfun ("isdir", files);
-  d(idx) = "";
   f(idx) = files(idx);
 endfunction
 
-
-## FIXME -- reinstate these tests if we invent a way to test private
-## functions directly.
-##
-## %!error <extension has to be a string with finite length>
-## %!  __xzip__ ("gzip", "", "gzip -r %s", "bla");
-## %!error <no files to move>
-## %!  __xzip__ ("gzip", ".gz", "gzip -r %s", tmpnam);
-## %!error <command failed with exit status>
-## %!  # test __xzip__ with invalid compression command
-## %!  unwind_protect
-## %!    filename = tmpnam;
-## %!    dummy    = 1;
-## %!    save (filename, "dummy");
-## %!    dirname  = tmpnam;
-## %!    mkdir (dirname);
-## %!    entry = __xzip__ ("gzip", ".gz", "xxxzipxxx -r %s 2>/dev/null",
-## %!                     filename, dirname);
-## %!  unwind_protect_cleanup
-## %!    delete (filename);
-## %!    rmdir (dirname);
-## %!  end_unwind_protect
-
--- a/scripts/miscellaneous/python.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/python.m	Mon Jan 12 09:17:35 2015 -0800
@@ -22,9 +22,11 @@
 ## @deftypefnx {Function File} {@var{output} =} python (@var{scriptfile}, @var{argument1}, @var{argument2}, @dots{})
 ## @deftypefnx {Function File} {[@var{output}, @var{status}] =} python (@dots{})
 ## Invoke Python script @var{scriptfile}, possibly with a list of command line
-## arguments.  Return output in @var{output} and optional status in
-## @var{status}.  If @var{scriptfile} is not an absolute file name it is
-## is searched for in the current directory and then in the Octave loadpath.
+## arguments.
+##
+## Return output in @var{output} and optional status in @var{status}.  If
+## @var{scriptfile} is not an absolute file name it is searched for in the
+## current directory and then in the Octave loadpath.
 ## @seealso{system, perl}
 ## @end deftypefn
 
@@ -48,3 +50,6 @@
 
 endfunction
 
+
+%!error <invalid arguments> python (123)
+
--- a/scripts/miscellaneous/recycle.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/recycle.m	Mon Jan 12 09:17:35 2015 -0800
@@ -21,10 +21,15 @@
 ## @deftypefnx {Function File} {@var{old_state} =} recycle (@var{new_state})
 ## Query or set the preference for recycling deleted files.
 ##
-## Recycling files, instead of permanently deleting them, is not currently
-## implemented in Octave.  To help avoid accidental data loss an error
-## will be raised if an attempt is made to enable file recycling.
-## @seealso{delete}
+## When recycling is enabled, commands which would permanently erase files
+## instead move them to a temporary location (such as the directory labeled
+## Trash).
+##
+## Programming Note: This function is provided for @sc{matlab} compatibility,
+## but recycling is not implemented in Octave.  To help avoid accidental data
+## loss an error will be raised if an attempt is made to enable file
+## recycling.
+## @seealso{delete, rmdir}
 ## @end deftypefn
 
 ## Author: jwe
@@ -42,16 +47,16 @@
   endif
 
   if (nargin == 1)
-    if (ischar (state))
-      if (strcmpi (state, "on"))
-        error ("recycle: recycling files is not implemented");
-      elseif (strcmpi (state, "off"))
-        current_state = "off";
-      else
-        error ("recycle: invalid value of STATE = '%s'", state);
-      endif
+    if (! ischar (state))
+      error ("recycle: STATE must be a character string");
+    endif
+    
+    if (strcmpi (state, "on"))
+      error ("recycle: recycling files is not implemented");
+    elseif (strcmpi (state, "off"))
+      current_state = "off";
     else
-      error ("recycle: STATE must be a character string");
+      error ("recycle: invalid value of STATE = '%s'", state);
     endif
   endif
 
@@ -62,7 +67,8 @@
 %! recycle ("off");
 %! assert (recycle ("off"), "off");
 
-%!error <recycling files is not implemented> recycle ("on")
 %!error recycle ("on", "and I mean it")
 %!error <STATE must be a character string> recycle (1)
+%!error <recycling files is not implemented> recycle ("on")
+%!error <invalid value of STATE = 'foobar'> recycle ("foobar")
 
--- a/scripts/miscellaneous/rmappdata.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/rmappdata.m	Mon Jan 12 09:17:35 2015 -0800
@@ -17,9 +17,15 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} rmappdata (@var{h}, @var{name})
-## Delete the named application data for the object(s) with
-## handle(s) @var{h}.
+## @deftypefn  {Function File} {} rmappdata (@var{h}, @var{name})
+## @deftypefnx {Function File} {} rmappdata (@var{h}, @var{name1}, @var{name2}, @dots{})
+## Delete the application data @var{name} from the graphics object with handle
+## @var{h}.
+##
+## @var{h} may also be a vector of graphics handles.  Multiple application data
+## names may be supplied to delete several properties at once.
+##
+## @seealso{setappdata, getappdata, isappdata}
 ## @end deftypefn
 
 ## Author: Ben Abbott <bpabbott@mac.com>
@@ -27,21 +33,28 @@
 
 function rmappdata (h, varargin)
 
-  if (! (all (ishandle (h)) && iscellstr (varargin)))
-    error ("rmappdata: invalid input");
+  if (nargin < 2)
+    print_usage ();
+  endif
+
+  h = h(:).';
+  if (! all (ishandle (h)))
+    error ("rmappdata: H must be a scalar or vector of graphic handles");
+  elseif (! iscellstr (varargin))
+    error ("rmappdata: NAME must be a string");
   endif
 
-  for nh = 1:numel (h)
-    if (isprop (h(nh), "__appdata__"))
-      appdata = get (h(nh), "__appdata__");
-      for v = 1:numel(varargin)
-        if (isfield (appdata, varargin{v}))
-          appdata = rmfield (appdata, varargin{v});
-        else
-          error ("rmappdata: appdata '%s' is not present")
-        endif
-      endfor
-      set (h(nh), "__appdata__", appdata);
+  for hg = h
+    if (isprop (hg, "__appdata__"))
+      appdata = get (hg, "__appdata__");
+      vld = isfield (appdata, varargin);
+      if (! all (vld))
+        ## FIXME: Should we bother to error out?  Or just silently continue?
+        missing = varargin{find (! vld, 1)};
+        error ("rmappdata: appdata '%s' is not present", missing);
+      endif 
+      appdata = rmfield (appdata, varargin);
+      set (hg, "__appdata__", appdata);
     endif
   endfor
 
@@ -49,14 +62,21 @@
 
 
 %!test
-%! setappdata (0, "hello", "world");
-%! rmappdata (0, "hello");
-%! assert (isappdata (0, "hello"), false);
+%! setappdata (0, "%hello%", "world");
+%! rmappdata (0, "%hello%");
+%! assert (isappdata (0, "%hello%"), false);
 
 %!test
-%! setappdata (0, "data1", rand (3));
-%! setappdata (0, "data2", {"hello", "world"});
-%! rmappdata (0, "data1", "data2");
-%! assert (isappdata (0, "data1"), false);
-%! assert (isappdata (0, "data2"), false);
+%! setappdata (0, "%data1%", ones (3));
+%! setappdata (0, "%data2%", {"hello", "world"});
+%! rmappdata (0, "%data1%", "%data2%");
+%! assert (isappdata (0, "%data1%"), false);
+%! assert (isappdata (0, "%data2%"), false);
 
+## Test input validation
+%!error rmappdata ()
+%!error rmappdata (1)
+%!error <H must be a scalar .* graphic handle> rmappdata (-1, "hello")
+%!error <NAME must be a string> rmappdata (0, 1)
+%!error <appdata 'foobar' is not present> rmappdata (0, "foobar")
+
--- a/scripts/miscellaneous/run.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/run.m	Mon Jan 12 09:17:35 2015 -0800
@@ -31,9 +31,10 @@
 ## falling back to the script name without an extension.
 ##
 ## Implementation Note: If @var{script} includes a path component, then
-## @code{run} first changes the directory to the directory where @var{script}
-## is found.  @code{run} then executes the script, and returns to the original
-## directory. 
+## @code{run} first changes the working directory to the directory where
+## @var{script} is found.  Next, the script is executed.  Finally, @code{run}
+## returns to the original working directory unless @code{script} has
+## specifically changed directories.
 ## @seealso{path, addpath, source}
 ## @end deftypefn
 
@@ -59,13 +60,16 @@
   
   if (! isempty (d))
     if (exist (d, "dir"))
-      wd = pwd ();
+      startdir = pwd ();
+      d = canonicalize_file_name (d);
       unwind_protect
         cd (d);
         evalin ("caller", sprintf ('source ("%s%s");', f, ext),
                 "rethrow (lasterror ())");
       unwind_protect_cleanup
-        cd (wd);
+        if (strcmp (d, pwd ()))
+          cd (startdir);
+        endif
       end_unwind_protect
     else
       error ("run: the path %s doesn't exist", d);
--- a/scripts/miscellaneous/setappdata.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/setappdata.m	Mon Jan 12 09:17:35 2015 -0800
@@ -17,11 +17,16 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} setappdata (@var{h}, @var{name}, @var{value})
-## Set the named application data to @var{value} for the object(s) with
-## handle(s) @var{h}.  If the application data with the specified name does
-## not exist, it is created.
-## @seealso{getappdata, guidata, get, set, getpref, setpref}
+## @deftypefn  {Function File} {} setappdata (@var{h}, @var{name}, @var{value})
+## @deftypefnx {Function File} {} setappdata (@var{h}, @var{name1}, @var{value1}, @var{name2}, @var{value3}, @dots{})
+## Set the application data @var{name} to @var{value} for the graphics object
+## with handle @var{h}.
+##
+## @var{h} may also be a vector of graphics handles.  If the application data
+## with the specified @var{name} does not exist, it is created.  Multiple
+## @var{name}/@var{value} pairs can be specified at a time.
+##
+## @seealso{getappdata, isappdata, rmappdata, guidata, get, set, getpref, setpref}
 ## @end deftypefn
 
 ## Author: Ben Abbott <bpabbott@mac.com>
@@ -29,35 +34,62 @@
 
 function setappdata (h, varargin)
 
-  if (! (all (ishandle (h)) && mod (numel (varargin), 2) == 0))
-    error ("setappdata: invalid input");
+  h = h(:).';
+  if (! all (ishandle (h)))
+    error ("setappdata: H must be a scalar or vector of graphic handles");
+  elseif (mod (numel (varargin), 2) != 0)
+    error ("setappdata: NAME/VALUE arguments must occur in pairs");
   endif
 
-  for nh = 1:numel (h)
-    if (! isfield (get (h(nh)), "__appdata__"))
-      addproperty ("__appdata__", h(nh), "any", struct ());
-    endif
-    appdata = get (h(nh), "__appdata__");
+  for hg = h
+    try
+      appdata = get (hg, "__appdata__");
+    catch
+      appdata = struct ();
+      addproperty ("__appdata__", hg, "any", appdata);
+    end_try_catch
+
     for narg = 1:2:numel (varargin)
-      if (iscellstr (varargin{narg}))
+      if (ischar (varargin{narg}))
+        appdata.(varargin{narg}) = varargin{narg+1};
+      elseif (iscellstr (varargin{narg}))
         ## Handle cell arrays like set() does.
-        set (h(nh), "__appdata__", appdata);
-        setappdata (h(nh), vertcat (varargin{narg}', varargin{narg+1}'){:});
-        appdata = get (h(nh), "__appdata__");
-      elseif (ischar (varargin{narg}))
-        appdata.(varargin{narg}) = varargin{narg+1};
+        set (hg, "__appdata__", appdata);
+        setappdata (hg, vertcat (varargin{narg}', varargin{narg+1}'){:});
+        appdata = get (hg, "__appdata__");
       else
-        error ("setappdata: invalid input");
+        error ("setappdata: NAME must be a string or cellstr");
       endif
     endfor
-    set (h(nh), "__appdata__", appdata);
+
+    set (hg, "__appdata__", appdata);
   endfor
 
 endfunction
 
 
 %!test
-%! setappdata (0, "hello", "world");
-%! assert (isappdata (0, "hello"), true);
-%! assert (getappdata (0, "hello"), "world");
+%! unwind_protect
+%!   setappdata (0, "%hello%", "world");
+%!   assert (isappdata (0, "%hello%"), true);
+%!   assert (getappdata (0, "%hello%"), "world");
+%! unwind_protect_cleanup
+%!   rmappdata (0, "%hello%");
+%! end_unwind_protect
 
+%!test
+%! unwind_protect
+%!   setappdata (0, "%data1%", ones (3), "%data2%", "hello world");
+%!   assert (getappdata (0, "%data1%"), ones (3));
+%!   assert (getappdata (0, "%data2%"), "hello world");
+%!   setappdata (0, "%data1%", zeros (3));
+%!   assert (getappdata (0, "%data1%"), zeros (3));
+%! unwind_protect_cleanup
+%!   rmappdata (0, "%data1%", "%data2%");
+%! end_unwind_protect
+
+## Test input validation
+%!error <H must be a scalar .* graphic handle> rmappdata (-1, "hello")
+%!error <NAME must be a string> setappdata (0, 1, 2)
+%!error <NAME/VALUE arguments must occur in pairs> setappdata (0, "1")
+
--- a/scripts/miscellaneous/setfield.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/setfield.m	Mon Jan 12 09:17:35 2015 -0800
@@ -18,10 +18,12 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {@var{s} =} setfield (@var{s}, @var{field}, @var{val})
-## @deftypefnx {Function File} {@var{s} =} setfield (@var{s}, @var{idx1}, @var{field1}, @var{idx2}, @var{field2}, @dots{}, @var{val})
+## @deftypefn  {Function File} {@var{sout} =} setfield (@var{s}, @var{field}, @var{val})
+## @deftypefnx {Function File} {@var{sout} =} setfield (@var{s}, @var{sidx1}, @var{field1}, @var{fidx1}, @var{sidx2}, @var{field2}, @var{fidx2}, @dots{}, @var{val})
 ##
-## Set a field member @var{field} in a structure @var{s} equal to @var{val}. 
+## Return a @emph{copy} of the structure @var{s} with the field member
+## @var{field} set to the value @var{val}. 
+##
 ## For example:
 ##
 ## @example
@@ -40,24 +42,29 @@
 ##
 ## @noindent
 ## Note that ordinary structure syntax @code{@var{s}.foo bar = 42} cannot be
-## used here, as the field name is not a valid Octave identifier.  Using
-## arbitrary strings for field name is incompatible with @sc{matlab}, so
-## this usage will warn if the @code{Octave:matlab-incompatible} warning
-## is set.  @xref{XREFwarning_ids}.
+## used here, as the field name is not a valid Octave identifier because of
+## the space character.  Using arbitrary strings for field names is
+## incompatible with @sc{matlab}, and this usage will emit a warning if the
+## warning ID @code{Octave:matlab-incompatible} is enabled.
+## @xref{XREFwarning_ids}.
 ##
-## With the second calling form, set a field on a structure array,
-## possibly nested, with successive nested indices @var{idx1},
-## @var{idx2}, @dots{} and fields @var{field1}, @var{field2}, @dots{}
-## The indices must be cells containing the desired index at this
-## nesting depth.
+## With the second calling form, set a field of a structure array.  The
+## input @var{sidx} selects an element of the structure array, @var{field}
+## specifies the field name of the selected element, and @var{fidx} selects
+## which element of the field (in the case of an array or cell array).
+## The @var{sidx}, @var{field}, and @var{fidx} inputs can be repeated to
+## address nested structure array elements.  The structure array index and
+## field element index must be cell arrays while the field name must be a
+## string.
 ##
-## Thus consider instead,
+## For example:
 ##
 ## @example
 ## @group
 ## @var{s} = struct ("baz", 42);
-## setfield (@var{s}, @{1@}, "foo", @{1@}, "bar", 5)
-##     @result{} ans =
+## setfield (@var{s}, @{1@}, "foo", @{1@}, "bar", 54)
+## @result{}
+##   ans =
 ##     scalar structure containing the fields:
 ##       baz =  42
 ##       foo =
@@ -66,54 +73,61 @@
 ## @end group
 ## @end example
 ##
-## Here we first have an ordinary structure array with one field
-## @code{baz} set to 42.  Then we set another field in a nested scalar structure
-## indexing with two single cells containing the unique desired indices.
+## The example begins with an ordinary scalar structure to which a nested 
+## scalar structure is added.  In all cases, if the structure index @var{sidx}
+## is not specified it defaults to 1 (scalar structure).  Thus, the example
+## above could be written more concisely as
+## @code{setfield (@var{s}, "foo", "bar", 54)}
 ##
-## Finally an example with nested structure arrays,
+## Finally, an example with nested structure arrays:
 ##
 ## @example
 ## @group
 ## @var{sa}.foo = 1;
-## @var{sa} = setfield (@var{sa}, @{2@}, "bar", @{3@}, "baz", 6);
+## @var{sa} = setfield (@var{sa}, @{2@}, "bar", @{3@}, "baz", @{1, 4@}, 5);
 ## @var{sa}(2).bar(3)
-##      @result{} ans =
-##      scalar structure containing the fields:
-##        baz =  6
+## @result{}
+##   ans =
+##     scalar structure containing the fields:
+##       baz =  0   0   0   5
 ## @end group
 ## @end example
 ##
-## Here @var{sa} is a structure array whose field @code{fd} at elements
-## 1 and 2 field is in turn
-## another structure array whose third element is a structure
+## Here @var{sa} is a structure array whose field at elements 1 and 2 is in
+## turn another structure array whose third element is a simple scalar
+## structure.  The terminal scalar structure has a field which contains a
+## matrix value.
 ##
 ## Note that the same result as in the above example could be achieved by:
 ##
 ## @example
 ## @group
-## @var{SA}.foo = 1;
-## @var{SA}(2).bar(3).baz = 6
+## @var{sa}.foo = 1;
+## @var{sa}(2).bar(3).baz(1,4) = 5
 ## @end group
 ## @end example
-## @seealso{getfield, rmfield, isfield, fieldnames, isstruct, struct}
+## @seealso{getfield, rmfield, orderfields, isfield, fieldnames, isstruct, struct}
 ## @end deftypefn
 
 ## Author:  Etienne Grossmann <etienne@cs.uky.edu>
 
-function obj = setfield (obj, varargin)
+function sout = setfield (s, varargin)
+
   if (nargin < 3)
     print_usage ();
   endif
+
   subs = varargin(1:end-1);
-  rhs = varargin{end};
+  val = varargin{end};
   flds = cellfun ("isclass", subs, "char");
   idxs = cellfun ("isclass", subs, "cell");
-  if (all (flds | idxs))
-    typs = merge (flds, {"."}, {"()"});
-    obj = subsasgn (obj, struct ("type", typs, "subs", subs), rhs);
-  else
+  if (! all (flds | idxs))
     error ("setfield: invalid index");
   endif
+
+  typs = ifelse (flds, {"."}, {"()"});
+  sout = subsasgn (s, struct ("type", typs, "subs", subs), val);
+
 endfunction
 
 
@@ -121,9 +135,15 @@
 %! x.a = "hello";
 %! x = setfield (x, "b", "world");
 %! y = struct ("a", "hello", "b", "world");
-%! assert (x,y);
+%! assert (x, y);
 %!test
 %! oo(1,1).f0 = 1;
-%! oo = setfield (oo,{1,2},"fd",{3},"b", 6);
-%! assert (oo(1,2).fd(3).b, 6);
+%! oo = setfield (oo,{1,2},"fd",{3},"b", {1,4}, 6);
+%! assert (oo(1,2).fd(3).b(1,4), 6);
 
+%% Test input validation
+%!error setfield ()
+%!error setfield (1)
+%!error setfield (1,2)
+%!error <invalid index> setfield (1,2,3)
+
--- a/scripts/miscellaneous/substruct.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/substruct.m	Mon Jan 12 09:17:35 2015 -0800
@@ -19,8 +19,9 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} substruct (@var{type}, @var{subs}, @dots{})
-## Create a subscript structure for use with @code{subsref} or
-## @code{subsasgn}.  For example:
+## Create a subscript structure for use with @code{subsref} or @code{subsasgn}.
+##
+## For example:
 ##
 ## @example
 ## @group
@@ -35,7 +36,9 @@
 ##            [1,2] = :
 ##          @}
 ##        @}
-## x = [1, 2, 3; 4, 5, 6; 7, 8, 9];
+## x = [1, 2, 3;
+##      4, 5, 6;
+##      7, 8, 9];
 ## subsref (x, idx)
 ##    @result{} 7  8  9
 ## @end group
@@ -47,30 +50,28 @@
 
 function retval = substruct (varargin)
 
-  nargs = nargin;
-
-  if (nargs > 1 && mod (nargs, 2) == 0)
-    typ = varargin(1:2:nargs);
-    sub = varargin(2:2:nargs);
-    braces = strcmp (typ, "()") | strcmp (typ, "{}");
-    dots = strcmp (typ, ".");
-    if (all (braces | dots))
-      cells = cellfun ("isclass", sub, "cell");
-      chars = cellfun ("isclass", sub, "char");
-      if (any (braces &! cells))
-        error ("substruct: for TYPE == () or {}, SUBS must be a cell array");
-      elseif (any (dots &! chars))
-        error ("substruct: for TYPE == ., SUBS must be a character string");
-      endif
-    else
-      error ("substruct: expecting TYPE to be one of \"()\", \"{}\", or \".\"");
-    endif
-
-    retval = struct ("type", typ, "subs", sub);
-  else
+  if (nargin < 2 || mod (nargin, 2) != 0)
     print_usage ();
   endif
 
+  typ = varargin(1:2:nargin);
+  sub = varargin(2:2:nargin);
+  braces = strcmp (typ, "()") | strcmp (typ, "{}");
+  dots = strcmp (typ, ".");
+  if (all (braces | dots))
+    cells = cellfun ("isclass", sub, "cell");
+    chars = cellfun ("isclass", sub, "char");
+    if (any (braces & !cells))
+      error ("substruct: for TYPE == () or {}, SUBS must be a cell array");
+    elseif (any (dots & !chars))
+      error ("substruct: for TYPE == ., SUBS must be a character string");
+    endif
+  else
+    error ('substruct: expecting TYPE to be one of "()", "{}", or "."');
+  endif
+
+  retval = struct ("type", typ, "subs", sub);
+
 endfunction
 
 
--- a/scripts/miscellaneous/swapbytes.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/swapbytes.m	Mon Jan 12 09:17:35 2015 -0800
@@ -19,7 +19,9 @@
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} swapbytes (@var{x})
 ## Swap the byte order on values, converting from little endian to big
-## endian and vice versa.  For example:
+## endian and vice versa.
+##
+## For example:
 ##
 ## @example
 ## @group
@@ -37,28 +39,35 @@
     print_usage ();
   endif
 
-  clx = class (x);
-  if (strcmp (clx, "int8") || strcmp (clx, "uint8") || isempty (x))
+  cls = class (x);
+  if (strcmp (cls, "int8") || strcmp (cls, "uint8") || isempty (x))
     y = x;
   else
-    if (strcmp (clx, "int16") || strcmp (clx, "uint16"))
+    if (strcmp (cls, "int16") || strcmp (cls, "uint16"))
       nb = 2;
-    elseif (strcmp (clx, "int32") || strcmp (clx, "uint32"))
+    elseif (strcmp (cls, "single")
+            || strcmp (cls, "int32") || strcmp (cls, "uint32"))
       nb = 4;
-    elseif (strcmp (clx, "int64") || strcmp (clx, "uint64")
-            || strcmp (clx, "double"))
+    elseif (strcmp (cls, "double")
+            || strcmp (cls, "int64") || strcmp (cls, "uint64"))
       nb = 8;
     else
-      error ("swapbytes: invalid class of object");
+      error ("swapbytes: invalid object of class '%s'", cls);
     endif
     y = reshape (typecast (reshape (typecast (x(:), "uint8"), nb, numel (x))
-                           ([nb : -1 : 1], :) (:), clx), size (x));
+                           ([nb : -1 : 1], :) (:), cls), size (x));
   endif
 
 endfunction
 
 
-%!assert (double (swapbytes (uint16 (1:4))), [256 512 768 1024])
-%!error (swapbytes ())
-%!error (swapbytes (1, 2))
+%!assert (swapbytes (uint16 (1:4)), uint16 ([256 512 768 1024]))
+%!test
+%! assert (swapbytes (swapbytes (pi)), pi);
+%! assert (swapbytes (swapbytes (single (pi))), single (pi));
 
+## Test input validation
+%!error swapbytes ()
+%!error swapbytes (1, 2)
+%!error <invalid object of class 'cell'> swapbytes ({1})
+
--- a/scripts/miscellaneous/symvar.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/symvar.m	Mon Jan 12 09:17:35 2015 -0800
@@ -17,19 +17,39 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} symvar (@var{s})
-## Identify the argument names in the function defined by a string.
-## Common constant names such as @code{pi}, @code{NaN}, @code{Inf},
-## @code{eps}, @code{i} or @code{j} are ignored.  The arguments that are
-## found are returned in a cell array of strings.  If no variables are
-## found then the returned cell array is empty.
+## @deftypefn {Function File} {@var{vars} =} symvar (@var{str})
+## Identify the symbolic variable names in the string @var{str}.
+##
+## Common constant names such as @code{i}, @code{j}, @code{pi}, @code{Inf} and
+## Octave functions such as @code{sin} or @code{plot} are ignored.
+##
+## Any names identified are returned in a cell array of strings.  The array is
+## empty if no variables were found.
+##
+## Example:
+##
+## @example
+## @group
+## symvar ("x^2 + y^2 == 4")
+## @result{} @{
+##      [1,1] = x
+##      [2,1] = y
+##    @}
+## @end group
+## @end example
 ## @end deftypefn
 
-function args = symvar (s)
-  args = argnames (inline (s));
+function vars = symvar (str)
+  vars = argnames (inline (str));
+  ## Correct for auto-generated 'x' variable when no symvar was found. 
+  if (numel (vars) == 1 && strcmp (vars{1}, "x") && ! any (str == "x"))
+    vars = {};
+  endif 
+
 endfunction
 
 
-## This function is tested by the tests for argnames().
-%!assert (1)
+%!assert (symvar ("3*x + 4*y + 5*cos (z)"), {"x"; "y"; "z"})
+%!assert (symvar ("sin()^2 + cos()^2 == 1"), {})
+%!assert (symvar ("1./x"), {"x"})
 
--- a/scripts/miscellaneous/tar.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/tar.m	Mon Jan 12 09:17:35 2015 -0800
@@ -17,37 +17,46 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {@var{entries} =} tar (@var{tarfile}, @var{files})
-## @deftypefnx {Function File} {@var{entries} =} tar (@var{tarfile}, @var{files}, @var{root})
-## Pack @var{files} @var{files} into the TAR archive @var{tarfile}.  The
-## list of files must be a string or a cell array of strings.
+## @deftypefn  {Function File} {@var{filelist} =} tar (@var{tarfile}, @var{files})
+## @deftypefnx {Function File} {@var{filelist} =} tar (@var{tarfile}, @var{files}, @var{rootdir})
+## Pack the list of files and directories specified in @var{files} into the
+## TAR archive @var{tarfile}.
 ##
-## The optional argument @var{root} changes the relative path of @var{files}
-## from the current directory.
+## @var{files} is a character array or cell array of strings.  Shell
+## wildcards in the filename such as @samp{*} or @samp{?} are accepted and
+## expanded.  Directories are recursively traversed and all files are added to
+## the archive.
 ##
-## If an output argument is requested the entries in the archive are
-## returned in a cell array.
-## @seealso{untar, bzip2, gzip, zip}
+## If @var{rootdir} is defined then any files without absolute pathnames are
+## located relative to @var{rootdir} rather than the current directory.
+##
+## The optional output @var{filelist} is a list of the files that were included
+## in the archive.
+## @seealso{untar, unpack, bzip2, gzip, zip}
 ## @end deftypefn
 
 ## Author: Søren Hauberg <hauberg@gmail.com>
 
-function entries = tar (tarfile, files, root = ".")
+function filelist = tar (tarfile, files, rootdir = ".")
 
   if (nargin < 2 || nargin > 3)
     print_usage ();
   endif
 
-  if (ischar (files))
+  if (! ischar (tarfile))
+    error ("tar: TARFILE must be a string");
+  elseif (ischar (files))
     files = cellstr (files);
+  elseif (! iscellstr (files))
+    error ("tar: FILES must be a character array or cellstr");
   endif
 
-  if (! (ischar (tarfile) && iscellstr (files) && ischar (root)))
-    error ("tar: all arguments must be character strings");
-  endif
+  rootdir = tilde_expand (rootdir);
 
-  cmd = sprintf ("tar cvf %s -C %s %s", tarfile, root,
-                 sprintf (" %s", files{:}));
+  tarfile = make_absolute_filename (tarfile);
+       
+  cmd = sprintf ("tar cvf %s -C %s %s",
+                          tarfile, rootdir, sprintf (" %s", files{:}));
 
   [status, output] = system (cmd);
 
@@ -59,9 +68,64 @@
     if (output(end) == "\n")
       output(end) = [];
     endif
-    entries = ostrsplit (output, "\n");
-    entries = entries';
+    filelist = ostrsplit (output, "\n");
+    filelist = filelist';
   endif
 
 endfunction
 
+
+%!xtest
+%! ## test gzip together with gunzip
+%! orig_dir = pwd ();
+%! unwind_protect
+%!   dirname = tempname;
+%!   assert (mkdir (dirname));
+%!   chdir (dirname);
+%!   dirname2 = "dir2";
+%!   assert (mkdir (dirname2));
+%!   fname1 = "f1";
+%!   fname2 = fullfile (dirname2, "f2");
+%!   fid = fopen (fname1, "wt");
+%!   assert (fid >= 0);
+%!   fdisp (fid, "Hello World");
+%!   fclose (fid); 
+%!   fid = fopen (fname2, "wt");
+%!   assert (fid >= 0);
+%!   fdisp (fid, "Goodbye World");
+%!   fclose (fid); 
+%!   tarname = [tempname ".tar"];
+%!   filelist = tar (tarname, {dirname2, fname1});
+%!   if (! strcmp (filelist{3}, fname1))
+%!     error ("tar file contents does not match expected file");
+%!   endif
+%!   if (! exist (tarname, "file"))
+%!     error ("tar archive file cannot be found!");
+%!   endif
+%!   outdir = tempname;
+%!   untar (tarname, outdir);
+%!   fid = fopen (fullfile (outdir, fname1), "rt");
+%!   assert (fid >= 0);
+%!   str = fgetl (fid);
+%!   fclose (fid);
+%!   assert (str, "Hello World");
+%!   fid = fopen (fullfile (outdir, fname2), "rt");
+%!   assert (fid >= 0);
+%!   str = fgetl (fid);
+%!   fclose (fid);
+%!   assert (str, "Goodbye World");
+%! unwind_protect_cleanup
+%!   delete (tarname);
+%!   confirm_recursive_rmdir (false, "local");
+%!   rmdir (dirname, "s");
+%!   rmdir (outdir, "s");
+%!   chdir (orig_dir);
+%! end_unwind_protect
+
+## Test input validation
+%!error tar ()
+%!error tar (1)
+%!error tar (1,2,3,4)
+%!error <TARFILE must be a string> tar (1, "foobar")
+%!error <FILES must be a character array or cellstr> tar ("foobar", 1)
+
--- a/scripts/miscellaneous/tempdir.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/tempdir.m	Mon Jan 12 09:17:35 2015 -0800
@@ -18,7 +18,12 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {@var{dir} =} tempdir ()
-## Return the name of the system's directory for temporary files.
+## Return the name of the host system's directory for temporary files.
+##
+## The directory name is taken first from the environment variable
+## @env{TMPDIR}.  If that does not exist the system default returned by
+## @code{P_tmpdir} is used.
+## @seealso{P_tmpdir, tempname, mkstemp, tmpfile}
 ## @end deftypefn
 
 function dirname = tempdir ()
@@ -49,7 +54,11 @@
 %!   setenv ("TMPDIR", "__MY_TMP_DIR__");
 %!   assert (tempdir (), ["__MY_TMP_DIR__" filesep()]);
 %! unwind_protect_cleanup
-%!   setenv ("TMPDIR", old_tmpdir);
+%!   if (! isempty (old_tmpdir))
+%!     setenv ("TMPDIR", old_tmpdir);
+%!   else
+%!     unsetenv ("TMPDIR");
+%!   endif
 %!   warning (old_wstate);
 %! end_unwind_protect
 
--- a/scripts/miscellaneous/tempname.m	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-## Copyright (C) 2003-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  {Function File} {} tempname ()
-## @deftypefnx {Function File} {} tempname (@var{dir})
-## @deftypefnx {Function File} {} tempname (@var{dir}, @var{prefix})
-## This function is an alias for @code{tmpnam}.
-## @seealso{tmpnam}
-## @end deftypefn
-
-function filename = tempname (varargin)
-
-  filename = tmpnam (varargin{:});
-
-endfunction
-
-
-%% No tests needed for alias.
-%!assert (1)
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/miscellaneous/tmpnam.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,50 @@
+## Copyright (C) 2003-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  {Function File} {@var{fname} =} tmpnam ()
+## @deftypefnx {Function File} {@var{fname} =} tmpnam (@var{dir})
+## @deftypefnx {Function File} {@var{fname} =} tmpnam (@var{dir}, @var{prefix})
+## Return a unique temporary file name as a string.
+## 
+## If @var{prefix} is omitted, a value of @qcode{"oct-"} is used.
+## If @var{dir} is also omitted, the default directory for temporary files
+## (@code{P_tmpdir} is used.  If @var{dir} is provided, it must exist,
+## otherwise the default directory for temporary files is used.
+##
+## Programming Note: Because the named file is not opened by @code{tmpnam},
+## it is possible, though relatively unlikely, that it will not be available
+## by the time your program attempts to open it.  If this is a concern,
+## see @code{tmpfile}.  The functions @code{tmpnam} and @code{tmpnam} are
+## equivalent with the latter provided for @sc{matlab} compatibility.
+##
+## @strong{Caution}: @code{tmpnam} will be removed in a future version of
+## Octave.  Use the equivalent @code{tempname} in all new code.
+## @seealso{tempname, mkstemp, tempdir, P_tmpdir, tmpfile}
+## @end deftypefn
+
+function filename = tmpnam (varargin)
+
+  filename = tempname (varargin{:});
+
+endfunction
+
+
+## No tests needed for alias.
+%!assert (1)
+
--- a/scripts/miscellaneous/unix.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/unix.m	Mon Jan 12 09:17:35 2015 -0800
@@ -21,12 +21,15 @@
 ## @deftypefnx {Function File} {@var{status} =} unix ("@var{command}")
 ## @deftypefnx {Function File} {[@var{status}, @var{text}] =} unix ("@var{command}")
 ## @deftypefnx {Function File} {[@dots{}] =} unix ("@var{command}", "-echo")
-## Execute a system command if running under a Unix-like operating
-## system, otherwise do nothing.  Return the exit status of the program
-## in @var{status} and any output from the command in @var{text}.
+## Execute a system command if running under a Unix-like operating system,
+## otherwise do nothing.
+##
+## Octave waits for the external command to finish before returning the exit
+## status of the program in @var{status} and any output in @var{text}.
+##
 ## When called with no output argument, or the @qcode{"-echo"} argument is
 ## given, then @var{text} is also sent to standard output.
-## @seealso{dos, system, isunix, ispc}
+## @seealso{dos, system, isunix, ismac, ispc}
 ## @end deftypefn
 
 ## Author: octave-forge ???
--- a/scripts/miscellaneous/unpack.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/unpack.m	Mon Jan 12 09:17:35 2015 -0800
@@ -21,13 +21,52 @@
 ## @deftypefnx {Function File} {@var{files} =} unpack (@var{file}, @var{dir})
 ## @deftypefnx {Function File} {@var{files} =} unpack (@var{file}, @var{dir}, @var{filetype})
 ## Unpack the archive @var{file} based on its extension to the directory
-## @var{dir}.  If @var{file} is a list of strings, then each file is
-## unpacked individually.  If @var{dir} is not specified, it defaults to
-## the current directory.  If a directory is in the file list, then the
-## @var{filetype} must also be specified.
+## @var{dir}.
+##
+## If @var{file} is a list of strings, then each file is unpacked
+## individually.  Shell wildcards in the filename such as @samp{*} or @samp{?}
+## are accepted and expanded.
+##
+## If @var{dir} is not specified or is empty (@code{[]}), it defaults to the
+## current directory.  If a directory is in the file list, then @var{filetype}
+## must also be specified.
+##
+## The specific archive filetype is inferred from the extension of the file.
+## The @var{filetype} may also be specified directly using a string which
+## corresponds to a known extension.
+##
+## Valid filetype extensions:
+##
+## @table @code
+## @item  bz
+## @itemx bz2
+## bzip archive
+##
+## @item gz
+## gzip archive
+##
+## @item tar
+## tar archive
+##
+## @item  tarbz
+## @itemx tarbz2
+## @itemx tbz
+## @itemx tbz2
+## tar + bzip archive
+##
+## @item  targz
+## @itemx tgz
+## tar + gzip archive
+##
+## @item z
+## compress archive
+##
+## @item zip
+## zip archive
+## @end table
 ##
 ## The optional return value is a list of @var{files} unpacked.
-## @seealso{bzip2, gzip, zip, tar}
+## @seealso{bunzip2, gunzip, unzip, untar, bzip2, gzip, zip, tar}
 ## @end deftypefn
 
 ## Author: Bill Denney <denney@seas.upenn.edu>
@@ -39,16 +78,24 @@
   endif
 
   if (! ischar (file) && ! iscellstr (file))
-    error ("unpack: invalid input file class, %s", class (file));
+    error ("unpack: FILE must be a string or cell array of strings");
   endif
 
-  ## character arrays of more than one string must be treated as cell strings
-  if (ischar (file) && ! isvector (file))
+  ## Convert char arrays to cell strings to simplify further processing
+  if (ischar (file))
     file = cellstr (file);
   endif
+  if (numel (file) == 1)
+    gfile = glob (file);
+    if (isempty (gfile))
+      error ('unpack: file "%s" not found', file{1});
+    else
+      file = gfile;
+    endif
+  endif
 
   ## Recursively unpack cellstr arrays one file at a time
-  if (iscellstr (file))
+  if (numel (file) > 1)
     files = {};
     for i = 1:numel (file)
       tmpfiles = unpack (file{i}, dir);
@@ -59,15 +106,17 @@
     if (nargout > 0)
       filelist = files;
     endif
+    return;
 
-    return;
+  else
+    file = file{1};
   endif
 
   if (isdir (file))
     if (isempty (filetype))
       error ("unpack: FILETYPE must be given for a directory");
     elseif (! any (strcmpi (filetype, "gunzip")))
-      error ("unpack: FILETYPE must be gunzip for a directory");
+      error ('unpack: FILETYPE must be "gunzip" for a directory');
     endif
     ext = ".gz";
   else
@@ -84,28 +133,18 @@
 
     ## If the file is a URL, download it and then work with that file.
     if (! isempty (strfind (file, "://")))
-      ## FIXME -- the above is not a perfect test for a URL
+      ## FIXME: The above code is not a perfect test for a URL
       urlfile = file;
-      ## FIXME -- should we name the file that we download with the
-      ## same file name as the URL requests?
-      tmpfile = [tmpnam() ext];
+      tmpfile = [tempname ext];
       [file, success, msg] = urlwrite (urlfile, tmpfile);
       if (! success)
-        error ('unpack: could not get "%s": %s', urlfile, msg);
+        error ('unpack: could not fetch "%s": %s', urlfile, msg);
       endif
     endif
 
   endif
 
-  ## canonicalize_file_name returns empty if the file isn't found, so
-  ## use that to check for existence.
-  cfile = canonicalize_file_name (file);
-
-  if (isempty (cfile))
-    error ('unpack: file "%s" not found', file);
-  else
-    file = cfile;
-  endif
+  file = canonicalize_file_name (file);
 
   ## Instructions on what to do for any extension.
   ##
@@ -145,17 +184,21 @@
   endif
 
   ## Unzip doesn't actually care about the extension
-  if (strcmp (filetype, "unzip"))
+  if (strcmpi (filetype, "unzip"))
     nodotext = "zip";
   else
     nodotext = ext(ext != '.');
   endif
 
-  origdir = pwd ();
-
-  if (isfield (commandlist, nodotext))
-    [commandv, commandq, parser, move] = deal (commandlist.(nodotext){:});
-    cstartdir = canonicalize_file_name (origdir);
+  if (isfield (commandlist, tolower (nodotext)))
+    [commandv, commandq, parsefcn, move] = deal (commandlist.(nodotext){:});
+    origdir = pwd ();
+    if (move)
+      startdir = fileparts (file); 
+    else
+      startdir = origdir;
+    endif
+    cstartdir = canonicalize_file_name (startdir);
     cenddir = canonicalize_file_name (dir);
     needmove = move && ! strcmp (cstartdir, cenddir);
     if (nargout > 0 || needmove)
@@ -164,7 +207,7 @@
       command = commandq;
     endif
   else
-    warning ("unpack:filetype", "unrecognized file type, %s", ext);
+    warning ("unpack: unrecognized FILETYPE <%s>", ext);
     files = file;
     return;
   endif
@@ -194,23 +237,21 @@
 
   if (nargout > 0 || needmove)
     ## Trim the last CR if needed.
-    ## FIXME -- will this need to change to a check for "\r\n" for windows?
+    ## FIXME: Will this need to change to a check for "\r\n" for windows?
     if (output(end) == "\n")
       output(end) = [];
     endif
-    files = parser (ostrsplit (output, "\n"))';
+    files = parsefcn (ostrsplit (output, "\n"))';
 
-    ## Move files if necessary
+    ## Move files if necessary.
     if (needmove)
-      [st, msg, ~] = movefile (files, dir);
+      [st, msg] = movefile (files, cenddir);
       if (! st)
         error ('unpack: unable to move files to "%s": %s', dir, msg);
       endif
 
-      ## Fix the names for the files since they were moved.
-      for i = 1:numel (files)
-        files{i} = strrep (files{i}, cstartdir, cenddir);
-      endfor
+      ## Fix the names of the files since they were moved.
+      files = strrep (files, cstartdir, cenddir);
     endif
 
     ## Return output if requested.
@@ -224,9 +265,9 @@
 function files = __parse_zip__ (output)
   ## Parse the output from zip and unzip.
 
-  ## Skip first line which is Archive header
+  ## Skip first line which is Archive header.
   files = char (output(2:end));
-  ## Trim constant width prefix and return cell array
+  ## Trim constant width prefix and return cell array.
   files = cellstr (files(:,14:end))
 endfunction
 
@@ -249,3 +290,57 @@
   files = regexprep (output, '^\s+(.*)\.bz2: .*', '$1');
 endfunction
 
+
+%!test
+%! ## Create temporary directory and file for packing and unpacking
+%! dirname = tempname ();
+%! assert (mkdir (dirname));
+%! filename = tempname ();
+%! fid = fopen (filename, "wt");
+%! assert (fid >= 0);
+%! fprintf (fid, "Hello World\n");
+%! fprintf (fid, "123 456 789\n");
+%! fclose (fid);
+%! unwind_protect
+%!   copyfile (filename, [filename ".orig"]);
+%!   gzip (filename, dirname);
+%!   [~, f] = fileparts (filename);
+%!   filelist = unpack (fullfile (dirname, [f ".gz"]), P_tmpdir);
+%!   assert (filelist{1}, filename); 
+%!   fid = fopen ([filename ".orig"], "rb");
+%!   assert (fid >= 0);
+%!   orig_data = fread (fid);
+%!   fclose (fid);
+%!   fid = fopen (filename, "rb");
+%!   assert (fid >= 0);
+%!   new_data = fread (fid);
+%!   fclose (fid);
+%!   if (orig_data != new_data)
+%!     error ("unpack: Unpacked file does not equal original");
+%!   endif
+%! unwind_protect_cleanup
+%!   unlink (filename);
+%!   unlink ([filename ".orig"]);
+%!   rmdir (dirname);
+%! end_unwind_protect
+
+## Test input validation
+%!error unpack ()
+%!error unpack (1,2,3,4)
+%!error <FILE must be a string or cell array of strings> unpack (1)
+%!error <file "_%NOT_A_FILENAME%_" not found> unpack ("_%NOT_A_FILENAME%_")
+%!error <file "_%NOT_A_FILENAME%_" not found> unpack ({"_%NOT_A_FILENAME%_"})
+%!error <file "_%NOT_A_FILENAME%_" not found> unpack ({"_%NOT_A_FILENAME%_", "2nd_filename"})
+%!error <FILETYPE must be given for a directory>
+%! if (isunix || ismac)
+%!   unpack ("/");
+%! else
+%!   unpack ('C:\');
+%! endif
+%!error <FILETYPE must be "gunzip" for a directory>
+%! if (isunix || ismac)
+%!   unpack ("/", [], "foobar");
+%! else
+%!   unpack ('C:\', [], "foobar");
+%! endif
+
--- a/scripts/miscellaneous/untar.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/untar.m	Mon Jan 12 09:17:35 2015 -0800
@@ -19,26 +19,38 @@
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {} untar (@var{tarfile})
 ## @deftypefnx {Function File} {} untar (@var{tarfile}, @var{dir})
-## Unpack the TAR archive @var{tarfile} to the directory @var{dir}.
-## If @var{dir} is not specified, it defaults to the current directory.
+## Unpack the TAR archive @var{tarfile}.
+##
+## If @var{dir} is specified the files are unpacked in this directory rather
+## than the one where @var{tarfile} is located.
+##
+## The optional output @var{filelist} is a list of the uncompressed files.
 ## @seealso{tar, unpack, bunzip2, gunzip, unzip}
 ## @end deftypefn
 
 ## Author: Søren Hauberg <hauberg@gmail.com>
 ## Adapted-By: jwe, Bill Denney
 
-function varargout = untar (tarfile, dir = ".")
+function filelist = untar (tarfile, dir = [])
 
-  if (nargin != 1 && nargin != 2)
+  if (nargin < 1 || nargin > 2)
     print_usage ();
   endif
 
+  if (isempty (dir))
+    dir = fileparts (tarfile);
+  endif
+
   if (nargout > 0)
-    varargout = cell (1, nargout);
-    [varargout{:}] = unpack (tarfile, dir, mfilename ());
+    filelist = unpack (tarfile, dir, "untar");
   else
-    unpack (tarfile, dir, mfilename ());
+    unpack (tarfile, dir, "untar");
   endif
 
 endfunction
 
+
+## Tests for this m-file are located in tar.m
+## Remove from test statistics
+%!assert (1)
+
--- a/scripts/miscellaneous/unzip.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/unzip.m	Mon Jan 12 09:17:35 2015 -0800
@@ -17,28 +17,40 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} unzip (@var{zipfile})
-## @deftypefnx {Function File} {} unzip (@var{zipfile}, @var{dir})
-## Unpack the ZIP archive @var{zipfile} to the directory @var{dir}.
-## If @var{dir} is not specified, it defaults to the current directory.
+## @deftypefn  {Function File} {@var{filelist} =} unzip (@var{zipfile})
+## @deftypefnx {Function File} {@var{filelist} =} unzip (@var{zipfile}, @var{dir})
+## Unpack the ZIP archive @var{zipfile}.
+##
+## If @var{dir} is specified the files are unpacked in this directory rather
+## than the one where @var{zipfile} is located.
+##
+## The optional output @var{filelist} is a list of the uncompressed files.
 ## @seealso{zip, unpack, bunzip2, gunzip, untar}
 ## @end deftypefn
 
 ## Author: Søren Hauberg <hauberg@gmail.com>
 ## Adapted-By: jwe, Bill Denney
 
-function varargout = unzip (zipfile, dir = ".")
+function filelist = unzip (zipfile, dir = [])
 
-  if (nargin != 1 && nargin != 2)
+  if (nargin < 1 || nargin > 2)
     print_usage ();
   endif
 
+  if (isempty (dir))
+    dir = fileparts (zipfile);
+  endif
+
   if (nargout > 0)
-    varargout = cell (1, nargout);
-    [varargout{:}] = unpack (zipfile, dir, mfilename ());
+    filelist = unpack (zipfile, dir, "unzip");
   else
-    unpack (zipfile, dir, mfilename ());
+    unpack (zipfile, dir, "unzip");
   endif
 
 endfunction
 
+
+## Tests for this m-file are located in zip.m
+## Remove from test statistics
+%!assert (1)
+
--- a/scripts/miscellaneous/ver.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/ver.m	Mon Jan 12 09:17:35 2015 -0800
@@ -17,19 +17,21 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} ver ()
-## @deftypefnx {Function File} {v =} ver ()
-## @deftypefnx {Function File} {v =} ver ("Octave")
-## @deftypefnx {Function File} {v =} ver (@var{package})
+## @deftypefn  {Function File} {} ver
+## @deftypefnx {Function File} {} ver Octave
+## @deftypefnx {Function File} {} ver @var{package}
+## @deftypefnx {Function File} {v =} ver (@dots{})
 ## 
 ## Display a header containing the current Octave version number, license
-## string, and operating system followed by a list of installed packages,
-## versions, and installation directories.
+## string, and operating system.  The header is followed by a list of installed
+## packages, versions, and installation directories.
 ##
-## @code{v = ver ()}
+## Use the package name @var{package} or Octave to limit the listing to a
+## desired component.
 ##
-## Return a vector of structures describing Octave and each installed package.
-## The structure includes the following fields.
+## When called with an output argument, return a vector of structures
+## describing Octave and each installed package.  The structure includes the
+## following fields.
 ##
 ## @table @code
 ## @item Name
@@ -45,71 +47,67 @@
 ## Date of the version/revision.
 ## @end table
 ##
-## @code{v = ver ("Octave")}
-##
-## Return version information for Octave only.
-##
-## @code{v = ver (@var{package})}
-##
-## Return version information for @var{package}.
-##
-## @seealso{version, octave_config_info}
+## @seealso{version, octave_config_info, usejava, pkg}
 ## @end deftypefn
 
 ## Author: William Poetra Yoga Hadisoeseno <williampoetra@gmail.com>
 
-function varargout = ver (package = "")
+function retval = ver (package = "")
 
   if (nargin > 1)
     print_usage ();
   endif
 
-  ## Start with the version info for Octave
-  ret = struct ("Name", "Octave", "Version", version,
-                "Release", [], "Date", []);
+  if (nargout == 0)
+    [unm, err] = uname ();
 
-  ## Add the installed packages
-  lst = pkg ("list");
-  for i = 1:length (lst)
-    ret(end+1) = struct ("Name", lst{i}.name, "Version", lst{i}.version,
-                         "Release", [], "Date", lst{i}.date);
-  endfor
-
-  if (nargout == 0)
-    octave_license = license ();
-
-    [unm, status] = uname ();
-
-    if (status < 0)
+    if (err)
       os_string = "unknown";
     else
-      os_string = sprintf ("%s %s %s %s", unm.sysname, unm.release,
-                           unm.version, unm.machine);
+      os_string = sprintf ("%s %s %s %s",
+                           unm.sysname, unm.release, unm.version, unm.machine);
     endif
 
     hbar(1:70) = "-";
-    ver_line1 = "GNU Octave Version ";
-    ver_line2 = "GNU Octave License: ";
-    ver_line3 = "Operating System: ";
+    desc = {hbar
+            ["GNU Octave Version: " OCTAVE_VERSION]
+            ["GNU Octave License: " license]
+            ["Operating System: " os_string]
+            hbar};
+
+    printf ("%s\n", desc{:});
 
-    ver_desc = sprintf ("%s\n%s%s\n%s%s\n%s%s\n%s\n", hbar, ver_line1, version,
-                        ver_line2, octave_license, ver_line3, os_string, hbar);
-
-    puts (ver_desc);
-
-    pkg ("list");
+    if (isempty (package))
+      pkg ("list");
+    elseif (strcmpi (package, "Octave"))
+      ## Nothing to do, Octave version was already reported
+    else
+      pkg ("list", package);
+    endif
   else
-    if (! isempty (package))
-      n = [];
-      for r = 1:numel (ret)
-        if (strcmpi (ret(r).Name, package))
-          n = r;
-          break;
-        endif
+    ## Get the installed packages
+    if (isempty (package))
+      lst = pkg ("list");
+      ## Start with the version info for Octave
+      retval = struct ("Name", "Octave", "Version", version,
+                       "Release", [], "Date", []);
+      for i = 1:numel (lst)
+        retval(end+1) = struct ("Name", lst{i}.name, "Version", lst{i}.version,
+                                "Release", [], "Date", lst{i}.date);
       endfor
-      ret = ret(n);
+    elseif (strcmpi (package, "Octave"))
+      retval = struct ("Name", "Octave", "Version", version,
+                       "Release", [], "Date", []);
+    else 
+      lst = pkg ("list", package);
+      if (isempty (lst))
+        retval = struct ("Name", "", "Version", [],
+                         "Release", [], "Date", []);
+      else
+        retval = struct ("Name", lst{1}.name, "Version", lst{1}.version,
+                         "Release", [], "Date", lst{1}.date);
+      endif
     endif
-    varargout{1} = ret;
   endif
 
 endfunction
--- a/scripts/miscellaneous/version.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/version.m	Mon Jan 12 09:17:35 2015 -0800
@@ -18,11 +18,11 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} version ()
-## Return the version number of Octave, as a string.
+## Return the version number of Octave as a string.
 ##
 ## This is an alias for the function @w{@env{OCTAVE_VERSION}} provided for
 ## compatibility.
-## @seealso{OCTAVE_VERSION}
+## @seealso{OCTAVE_VERSION, ver}
 ## @end deftypefn
 
 ## Author: jwe
--- a/scripts/miscellaneous/warning_ids.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/warning_ids.m	Mon Jan 12 09:17:35 2015 -0800
@@ -299,8 +299,10 @@
 ## string constant.
 ## By default, the @code{Octave:single-quote-string} warning is disabled.
 ##
-## @item Octave:singular-matrix-div
-## By default, the @code{Octave:singular-matrix-div} warning is enabled.
+## @item Octave:nearly-singular-matrix
+## @itemx Octave:singular-matrix
+## By default, the @code{Octave:nearly-singular-matrix} and
+## @code{Octave:singular-matrix} warnings are enabled.
 ##
 ## @item Octave:sqrtm:SingularMatrix
 ## By default, the @code{Octave:sqrtm:SingularMatrix} warning is enabled.
@@ -335,12 +337,11 @@
 ## @end table
 ##
 
-
 function warning_ids ()
   help ("warning_ids");
 endfunction
 
 
-## Remove from test statistics.  No real tests possible
+## Mark file as being tested.  No real test needed for a documentation .m file
 %!assert (1)
 
--- a/scripts/miscellaneous/what.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/what.m	Mon Jan 12 09:17:35 2015 -0800
@@ -20,58 +20,103 @@
 ## @deftypefn  {Command} {} what
 ## @deftypefnx {Command} {} what @var{dir}
 ## @deftypefnx {Function File} {w =} what (@var{dir})
-## List the Octave specific files in directory @var{dir}.  If @var{dir} is
-## not specified then the current directory is used.  If a return argument is
-## requested, the files found are returned in the structure @var{w}.
-## @seealso{which}
+## List the Octave specific files in directory @var{dir}.
+##
+## If @var{dir} is not specified then the current directory is used.
+##
+## If a return argument is requested, the files found are returned in the
+## structure @var{w}.  The structure contains the following fields:
+##
+## @table @asis
+## @item path
+## Full path to directory @var{dir}
+##
+## @item m
+## Cell array of m-files
+##
+## @item mat
+## Cell array of mat files
+##
+## @item mex
+## Cell array of mex files
+##
+## @item oct
+## Cell array of oct files
+##
+## @item mdl
+## Cell array of mdl files
+##
+## @item slx
+## Cell array of slx files
+##
+## @item p
+## Cell array of p-files
+##
+## @item classes
+## Cell array of class directories (@file{@@@var{classname}/})
+##
+## @item packages
+## Cell array of package directories (@file{+@var{pkgname}/})
+## @end table
+##
+## Compatibility Note: Octave does not support mdl, slx, and p files; nor
+## does it support package directories.  @code{what} will always return an
+## empty list for these categories.
+## @seealso{which, ls, exist}
 ## @end deftypefn
 
-function ret = what (d)
+function retval = what (dir)
+
+  if (nargin > 1)
+    print_usage ();
+  endif
 
   if (nargin == 0)
-    d = pwd ();
+    dir = pwd ();
   else
-    dtmp = canonicalize_file_name (d);
+    dtmp = canonicalize_file_name (dir);
     if (isempty (dtmp))
       ## Search for directory name in path
-      if (d(end) == '/' || d(end) == '\')
-        d(end) = [];
+      if (dir(end) == '/' || dir(end) == '\')
+        dir(end) = [];
       endif
-      dtmp = find_dir_in_path (d);
+      dtmp = dir_in_loadpath (dir);
       if (isempty (dtmp))
-        error ("what: could not find the directory %s", d);
+        error ("what: could not find the directory %s", dir);
       endif
     endif
-    d = dtmp;
+    dir = dtmp;
   endif
 
-  files = dir (d);
-  w.path = d;
+  files = readdir (dir);
+  w.path = dir;
   w.m = cell (0, 1);
+  w.mat = cell (0, 1);
   w.mex = cell (0, 1);
   w.oct = cell (0, 1);
-  w.mat = cell (0, 1);
   w.mdl = cell (0, 1);
+  w.slx = cell (0, 1);
   w.p = cell (0, 1);
   w.classes = cell (0, 1);
+  w.packages = cell (0, 1);
 
   for i = 1 : length (files)
-    n = files(i).name;
+    n = files{i};
     ## Ignore . and ..
     if (strcmp (n, ".") || strcmp (n, ".."))
       continue;
     else
-      ## Ignore mdl and p files
+      ## Ignore mdl, slx, p, and packages since they are not  
       [~, f, e] = fileparts (n);
       if (strcmp (e, ".m"))
         w.m{end+1} = n;
+      elseif (strcmp (e, ".mat"))
+        w.mat{end+1} = n;
       elseif (strcmp (e, ".oct"))
         w.oct{end+1} = n;
       elseif (strcmp (e, mexext ()))
         w.mex{end+1} = n;
-      elseif (strcmp (e, ".mat"))
-        w.mat{end+1} = n;
-      elseif (strcmp (n(1), "@"))
+      elseif (n(1) == "@" && isdir (n))
         w.classes{end+1} = n;
       endif
     endif
@@ -79,35 +124,45 @@
 
   if (nargout == 0)
     __display_filenames__ ("M-files in directory", w.path, w.m);
+    __display_filenames__ ("\nMAT-files in directory", w.path, w.mat);
     __display_filenames__ ("\nMEX-files in directory", w.path, w.mex);
     __display_filenames__ ("\nOCT-files in directory", w.path, w.oct);
-    __display_filenames__ ("\nMAT-files in directory", w.path, w.mat);
     __display_filenames__ ("\nClasses in directory", w.path, w.classes);
   else
-    ret = w;
+    retval = w;
   endif
+
 endfunction
 
 function __display_filenames__ (msg, p, f)
+
   if (length (f) > 0)
     printf ("%s %s:\n\n", msg, p);
 
     maxlen = max (cellfun ("length", f));
     ncols = max (1, floor (terminal_size ()(2) / (maxlen + 3)));
-    fmt = "";
-    for i = 1: ncols
-      fmt = sprintf ("%s   %%-%ds", fmt, maxlen);
-    endfor
-    fmt = [fmt, "\n"];
+    fmt = sprintf ("   %%-%ds", maxlen);
+    fmt = repmat (fmt, [1, ncols]);
+    fmt = [fmt "\n"];
 
     nrows = ceil (length (f) / ncols);
     for i = 1 : nrows
       args  = f(i:nrows:end);
       if (length (args) < ncols)
-        args(end + 1 : ncols) = {""};
+        args(end+1 : ncols) = {""};
       endif
       printf (fmt, args{:});
     endfor
   endif
+
 endfunction
 
+
+%!test
+%! w = what ();
+%! assert (w.path, pwd);
+%! assert (fieldnames (w), {"path"; "m"; "mat"; "mex"; "oct"; "mdl"; "slx";
+%!                          "p"; "classes"; "packages"});
+
+%!error what (1, 2)
+
--- a/scripts/miscellaneous/xor.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/xor.m	Mon Jan 12 09:17:35 2015 -0800
@@ -17,23 +17,33 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Mapping Function} {@var{z} =} xor (@var{x}, @var{y})
-## Return the @dfn{exclusive or} of the entries of @var{x} and @var{y}.
+## @deftypefn  {Function File} {@var{z} =} xor (@var{x}, @var{y})
+## @deftypefnx {Function File} {@var{z} =} xor (@var{x1}, @var{x2}, @dots{})
+## Return the @dfn{exclusive or} of @var{x} and @var{y}.
+##
 ## For boolean expressions @var{x} and @var{y},
 ## @code{xor (@var{x}, @var{y})} is true if and only if one of @var{x} or
-## @var{y} is true.  Otherwise, for @var{x} and @var{y} both true or both
+## @var{y} is true.  Otherwise, if @var{x} and @var{y} are both true or both
 ## false, @code{xor} returns false.
 ##
 ## The truth table for the xor operation is
 ##
 ## @multitable @columnfractions 0.44 .03 .05 .03 0.44
 ## @item @tab @var{x} @tab @var{y} @tab @var{z} @tab
+## @item @tab - @tab - @tab - @tab
 ## @item @tab 0 @tab 0 @tab 0 @tab
 ## @item @tab 1 @tab 0 @tab 1 @tab
 ## @item @tab 0 @tab 1 @tab 1 @tab
 ## @item @tab 1 @tab 1 @tab 0 @tab
 ## @end multitable
 ##
+## If more than two arguments are given the xor operation is applied
+## cumulatively from left to right:
+##
+## @example
+## (@dots{}((x1 XOR x2) XOR x3) XOR @dots{})
+## @end example
+##
 ## @seealso{and, or, not}
 ## @end deftypefn
 
@@ -41,21 +51,35 @@
 ## Created: 16 September 1994
 ## Adapted-By: jwe
 
-function z = xor (x, y)
+function z = xor (x, y, varargin)
+
+  if (nargin < 2)
+    print_usage ();
+  endif
+
+  z = __xor__ (x, y);
 
-  if (nargin == 2)
-    if (isscalar (x) || isscalar (y) || size_equal (x, y))
-      ## Typecast to logicals is necessary for other numeric types.
-      z = logical (x) != logical (y);
-    else
-      try
-        z = bsxfun (@xor, x, y);
-      catch
-        error ("xor: X and Y must be of compatible size or scalars");
-      end_try_catch
-    endif
+  ## Slow expansion to multiple arguments.
+  ## Probably okay number of elements ## will be small.
+  if (! isempty (varargin))
+    for i = 1:numel (varargin) 
+      z = __xor__ (z, varargin{i});
+    endfor
+  endif
+
+endfunction
+
+function z = __xor__ (x, y)
+
+  if (isscalar (x) || isscalar (y) || size_equal (x, y))
+    ## Typecast to logicals is necessary for other numeric types.
+    z = logical (x) != logical (y);
   else
-    print_usage ();
+    try
+      z = bsxfun (@xor, x, y);
+    catch
+      error ("xor: X and Y must be of compatible size or scalars");
+    end_try_catch
   endif
 
 endfunction
@@ -65,7 +89,13 @@
 %!assert (xor ([i, i, 0, 0], [1, 0, 1, 0]), logical ([0, 1, 1, 0]))
 
 %!assert (xor (eye (2), fliplr (eye (2))), logical (ones (2)))
+%!assert (xor (speye (2), fliplr (speye (2))), sparse (logical (ones (2))))
 
+## Test XOR reduction
+%!assert (xor ([1 0], [1 1], [0 0]), logical ([0 1]))
+
+%% Test input validation
 %!error xor ()
-%!error xor (1, 2, 3)
+%!error xor (1)
+%!error <X and Y must be of compatible size> xor (ones (3,2), ones (2,3))
 
--- a/scripts/miscellaneous/zip.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/miscellaneous/zip.m	Mon Jan 12 09:17:35 2015 -0800
@@ -17,35 +17,46 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {@var{entries} =} zip (@var{zipfile}, @var{files})
-## @deftypefnx {Function File} {@var{entries} =} zip (@var{zipfile}, @var{files}, @var{rootdir})
-## Compress the list of files and/or directories specified in @var{files}
-## into the archive @var{zipfile} in the same directory.  If @var{rootdir}
-## is defined the @var{files} are located relative to @var{rootdir} rather
-## than the current directory.
-## @seealso{unzip, bzip2, gzip, tar}
+## @deftypefn  {Function File} {@var{filelist} =} zip (@var{zipfile}, @var{files})
+## @deftypefnx {Function File} {@var{filelist} =} zip (@var{zipfile}, @var{files}, @var{rootdir})
+## Compress the list of files and directories specified in @var{files} into the
+## ZIP archive @var{zipfile}.
+##
+## @var{files} is a character array or cell array of strings.  Shell
+## wildcards in the filename such as @samp{*} or @samp{?} are accepted and
+## expanded.  Directories are recursively traversed and all files are
+## compressed and added to the archive.
+##
+## If @var{rootdir} is defined then any files without absolute pathnames are
+## located relative to @var{rootdir} rather than the current directory.
+##
+## The optional output @var{filelist} is a list of the files that were included
+## in the archive.
+## @seealso{unzip, unpack, bzip2, gzip, tar}
 ## @end deftypefn
 
 ## Author: Sylvain Pelissier <sylvain.pelissier@gmail.com>
 
-function entries = zip (zipfile, files, rootdir = ".")
+function filelist = zip (zipfile, files, rootdir = ".")
 
-  if (nargin != 2 && nargin != 3)
+  if (nargin < 2 || nargin > 3)
     print_usage ();
   endif
 
+  if (! ischar (zipfile))
+    error ("zip: ZIPFILE must be a string");
+  elseif (ischar (files))
+    files = cellstr (files);
+  elseif (! iscellstr (files))
+    error ("zip: FILES must be a character array or cellstr");
+  endif
+  
   rootdir = tilde_expand (rootdir);
 
-  if (ischar (files))
-    files = cellstr (files);
-  endif
-
-  if (! ischar (zipfile) && ! iscellstr (files))
-    error ("zip: expecting all arguments to be character strings");
-  endif
-
-  cmd = sprintf ("cd %s; zip -r %s/%s %s", rootdir, pwd (), zipfile,
-                 sprintf (" %s", files{:}));
+  zipfile = make_absolute_filename (zipfile);
+       
+  cmd = sprintf ("cd %s; zip -r %s %s",
+                     rootdir,   zipfile, sprintf (" %s", files{:}));
 
   [status, output] = system (cmd);
 
@@ -54,16 +65,60 @@
   endif
 
   if (nargout > 0)
-    cmd = sprintf ("unzip -Z -1 %s", zipfile);
-    [status, entries] = system (cmd);
+    cmd = ["unzip -Z -1 " zipfile];
+    [status, filelist] = system (cmd);
     if (status)
       error ("zip: zipinfo failed with exit status = %d", status);
     endif
-    if (entries(end) == "\n")
-      entries(end) = [];
+    if (filelist(end) == "\n")
+      filelist(end) = [];
     endif
-    entries = ostrsplit (entries, "\n");
+    filelist = ostrsplit (filelist, "\n");
   endif
 
 endfunction
 
+
+%!xtest
+%! ## test zip together with unzip
+%! unwind_protect
+%!   filename = tempname;
+%!   tmp_var  = pi;
+%!   save (filename, "tmp_var");
+%!   dirname = tempname;
+%!   mkdir (dirname);
+%!   zipfile = tempname;
+%!   [~, basename, ext] = fileparts (filename);
+%!   filelist = zip (zipfile, [basename ext], tempdir);
+%!   filelist = filelist{1};
+%!   if (! strcmp (filelist, [basename ext]))
+%!     error ("zip archive does not contain expected name!");
+%!   endif
+%!   if (! exist ([zipfile ".zip"], "file"))
+%!     error ("zip file cannot be found!");
+%!   endif
+%!   unzip ([zipfile ".zip"], dirname);
+%!   fid = fopen (filename, "rb");
+%!   assert (fid >= 0);
+%!   orig_data = fread (fid);
+%!   fclose (fid);
+%!   fid = fopen ([dirname filesep basename ext], "rb");
+%!   assert (fid >= 0);
+%!   new_data = fread (fid);
+%!   fclose (fid);
+%!   if (orig_data != new_data)
+%!     error ("unzipped file not equal to original file!");
+%!   endif
+%! unwind_protect_cleanup
+%!   delete (filename);
+%!   delete ([dirname, filesep, basename, extension]);
+%!   rmdir (dirname);
+%! end_unwind_protect
+
+## Test input validation
+%!error zip ()
+%!error zip (1)
+%!error zip (1,2,3,4)
+%!error <ZIPFILE must be a string> zip (1, "foobar")
+%!error <FILES must be a character array or cellstr> zip ("foobar", 1)
+
--- a/scripts/mkdoc	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-#! /bin/sh
-#
-# Copyright (C) 1999-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/>.
-
-## Expecting arguments in this order:
-##
-##  SRCDIR SRCDIR-FILES ... -- LOCAL-FILES ...
-
-set -e
-
-PERL=${PERL:-'perl'}
-
-prefix="$1/"
-shift
-
-if test -f gethelp; then
-  cat << EOF
-### DO NOT EDIT!
-###
-### This file is generated automatically from the Octave sources.
-### Edit those files instead and run make to update this file.
-
-EOF
-  for arg
-  do
-    if [ "$arg" = "--" ]; then
-      prefix="./"
-    else
-      $PERL -w -e '
-        unless (@ARGV == 2) { die "Usage: $0 srcdir m_filename" ; }
-        ($srcdir, $m_fname) = ($ARGV[0], $ARGV[1]);
-        $full_fname = $srcdir . $m_fname;
-        exit unless ( $full_fname =~ m{(.*)/(@|)([^/]*)/(.*)\.m} );
-        if ($2) {
-          $fcn = "$2$3/$4";
-        } else {
-          $fcn = $4;
-        }
-        $re_srcdir = quotemeta($srcdir);
-        for (qx{ ./gethelp $fcn "$full_fname" < "$full_fname"} ) {
-          s/^\s+\@/\@/ unless $in_example;
-          s/^\s+\@group/\@group/;
-          s/^\s+\@end\s+group/\@end group/;
-          s|\@c $fcn $re_srcdir|\@c $fcn scripts/|o;
-          $in_example = (/\s*\@example\b/ .. /\s*\@end\s+example\b/);
-          print;
-        }' "$prefix" "$arg"
-    fi
-  done
-else
-  echo "gethelp program seems to be missing!" 1>&2
-  exit 1
-fi
--- a/scripts/mkdoc.pl	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/mkdoc.pl	Mon Jan 12 09:17:35 2015 -0800
@@ -1,5 +1,6 @@
-#! /usr/bin/perl -w
-#
+#! /usr/bin/perl
+use utf8;
+
 # Copyright (C) 2012-2013 Rik Wehbring
 #
 # This file is part of Octave.
@@ -18,13 +19,18 @@
 # along with Octave; see the file COPYING.  If not, see
 # <http://www.gnu.org/licenses/>.
 
+use strict;
+use warnings;
+use File::Spec;
+use Cwd;
+
 ## Expecting arguments in this order:
 ##
 ##  SRCDIR SRCDIR-FILES ... -- LOCAL-FILES ...
 
 unless (@ARGV >= 2) { die "Usage: $0 srcdir m_filename1 ..." ; }
 
-$srcdir = shift (@ARGV) . '/';
+my $srcdir = shift (@ARGV);
 
 print <<__END_OF_MSG__;
 ### DO NOT EDIT!
@@ -34,35 +40,38 @@
 
 __END_OF_MSG__
 
-MFILE: foreach $m_fname (@ARGV)
+MFILE: foreach my $m_fname (@ARGV)
 {
   if ($m_fname eq "--")
-  {
-    $srcdir = "./";
-    next MFILE;
-  }
+    {
+      $srcdir = getcwd ();
+      next MFILE;
+    }
 
-  $full_fname = $srcdir . $m_fname;
-  next MFILE unless ( $full_fname =~ m{(.*)/(@|)([^/]*)/(.*)\.m} );
-  if ($2)
-    { $fcn = "$2$3/$4"; }
-  else
-    { $fcn = $4; }
+  my $full_fname = File::Spec->catfile ($srcdir, $m_fname);
+  my @paths = File::Spec->splitdir ($full_fname);
+  if (@paths < 3
+      || $paths[-2] eq "private"   # skip private directories
+      || $paths[-1] !~ s/\.m$//i)  # skip non m-files, and remove extension
+    { next MFILE; }
 
-  @help_txt = gethelp ($fcn, $full_fname);
-  next MFILE if ($help_txt[0] eq "");
+  ## @classes will have @class/method as their function name
+  my $fcn = $paths[-2] =~ m/^@/ ? File::Spec->catfile (@paths[-2, -1])
+                                : $paths[-1];
+
+  my @help_txt = gethelp ($fcn, $full_fname);
+  next MFILE unless @help_txt;
 
   print "\x{1d}$fcn\n";
-  print "\@c $fcn scripts/$m_fname\n";
+  print "\@c $fcn ", File::Spec->catfile ("scripts", $m_fname), "\n";
 
   foreach $_ (@help_txt)
-  {
-    s/^\s+\@/\@/ unless $in_example;
-    s/^\s+\@group/\@group/;
-    s/^\s+\@end\s+group/\@end group/;
-    $in_example = (/\s*\@example\b/ .. /\s*\@end\s+example\b/);
-    print $_;
-  }
+    {
+      my $in_example = (m/\s*\@example\b/ .. m/\s*\@end\s+example\b/);
+      s/^\s+\@/\@/ unless $in_example;
+      s/^\s+(\@(?:end)\s+(group|example))/$1/;
+      print $_;
+    }
 }
 
 ################################################################################
@@ -70,34 +79,32 @@
 ################################################################################
 sub gethelp
 {
-  ($fcn, $fname) = @_[0..1]; 
-  open (FH, $fname) or return "";
+  my $fcn   = shift;
+  my $fname = shift;
+  open (my $fh, "<", $fname) or return;
 
-  do
-  {
-    @help_txt = ();
+  my @help_txt;
+  while (my $line = <$fh>)
+    {
+      next if $line =~ m/^\s*$/;      # skip empty lines
+      last if $line !~ m/^\s*(#|%)/;  # out of here once code starts
+
+      my $reading_block = sub {defined ($line = <$fh>) && $line !~ m/^\s*$/};
 
-    ## Advance to non-blank line
-    while (defined ($_ = <FH>) and /^\s*$/) {;}
-
-    if (! /^\s*(?:#|%)/ or eof (FH))
-    {
-      ## No comment block found.  Return empty string
-      close (FH);
-      return "";
+      ## Skip this block
+      if ($line =~ /(Copyright|Author)/)
+        { while (&$reading_block ()) {} }
+      else
+        {
+          do
+            {
+              $line =~ s/^\s*(%|#)+ ?//;
+              push (@help_txt, $line);
+            } while (&$reading_block ());
+          last;
+        }
     }
 
-    ## Extract help text stopping when comment block ends
-    do
-    {
-      ## Remove comment characters at start of line
-      s/^\s*(?:#|%){1,2} ?//;
-      push (@help_txt, $_);
-    } until (! defined ($_ = <FH>) or ! /^\s*(?:#|%)/);
-
-  } until ($help_txt[0] !~ /^(?:Copyright|Author)/); 
-
-  close (FH);
-
+  close ($fh);
   return @help_txt;
 }
--- a/scripts/optimization/fminbnd.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/optimization/fminbnd.m	Mon Jan 12 09:17:35 2015 -0800
@@ -70,6 +70,11 @@
   if (nargin < 2 || nargin > 4)
     print_usage ();
   endif
+  
+  if (xmin > xmax)
+    error ("Octave:invalid-input-arg",
+           "fminbnd: the lower bound cannot be greater than the upper one");
+  endif
 
   if (ischar (fun))
     fun = str2func (fun, "global");
@@ -170,7 +175,7 @@
 
     ## update  a, b, v, w, and x
 
-    if (fu <= fval)
+    if (fu < fval)
       if (u < x)
         b = x;
       else
@@ -283,4 +288,8 @@
 %!assert (fminbnd (@(x) (x - 1e-3)^4, -1, 1, opt0), 1e-3, 10e-3*sqrt (eps))
 %!assert (fminbnd (@(x) abs (x-1e7), 0, 1e10, opt0), 1e7, 10e7*sqrt (eps))
 %!assert (fminbnd (@(x) x^2 + sin (2*pi*x), 0.4, 1, opt0), fzero (@(x) 2*x + 2*pi*cos (2*pi*x), [0.4, 1], opt0), sqrt (eps))
+%!assert (fminbnd (@(x) x > 0.3, 0, 1) < 0.3) 
+%!assert (fminbnd (@(x) sin (x), 0, 0), 0, eps) 
 
+%!error <lower bound cannot be greater> fminbnd (@(x) sin (x), 0, -pi)
+
--- a/scripts/optimization/fminsearch.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/optimization/fminsearch.m	Mon Jan 12 09:17:35 2015 -0800
@@ -24,9 +24,9 @@
 ##
 ## Find a value of @var{x} which minimizes the function @var{fun}.
 ## The search begins at the point @var{x0} and iterates using the
-## Nelder & Mead Simplex algorithm (a derivative-free method).  This algorithm
-## is better-suited to functions which have discontinuities or for which
-## a gradient-based search such as @code{fminunc} fails.
+## @nospell{Nelder & Mead} Simplex algorithm (a derivative-free method).  This
+## algorithm is better-suited to functions which have discontinuities or for
+## which a gradient-based search such as @code{fminunc} fails.
 ##
 ## Options for the search are provided in the parameter @var{options} using 
 ## the function @code{optimset}.  Currently, @code{fminsearch} accepts the
--- a/scripts/optimization/fminunc.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/optimization/fminunc.m	Mon Jan 12 09:17:35 2015 -0800
@@ -63,11 +63,11 @@
 ## Last relative change in function value was less than @code{TolFun}.
 ##
 ## @item 0
-## Iteration limit exceeded---either maximum numer of algorithm iterations
+## Iteration limit exceeded---either maximum number of algorithm iterations
 ## @code{MaxIter} or maximum number of function evaluations @code{MaxFunEvals}.
 ##
 ## @item -1
-## Alogrithm terminated by @code{OutputFcn}.
+## Algorithm terminated by @code{OutputFcn}.
 ##
 ## @item -3
 ## The trust region radius became excessively small.
--- a/scripts/optimization/fsolve.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/optimization/fsolve.m	Mon Jan 12 09:17:35 2015 -0800
@@ -382,7 +382,7 @@
       ## iterations, so we need scaling-independent tolerances wherever
       ## possible.
 
-      ## FIXME -- why tolf*n*xn? If abs (e) ~ abs(x) * eps is a vector
+      ## FIXME: Why tolf*n*xn? If abs (e) ~ abs(x) * eps is a vector
       ## of perturbations of x, then norm (fjac*e) <= eps*n*xn, i.e. by
       ## tolf ~ eps we demand as much accuracy as we can expect.
       if (fn <= tolf*n*xn)
--- a/scripts/optimization/fzero.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/optimization/fzero.m	Mon Jan 12 09:17:35 2015 -0800
@@ -100,7 +100,7 @@
 
   ## Get default options if requested.
   if (nargin == 1 && ischar (fun) && strcmp (fun, 'defaults'))
-    x = optimset ("MaxIter", Inf, "MaxFunEvals", Inf, "TolX", 1e-8,
+    x = optimset ("MaxIter", Inf, "MaxFunEvals", Inf, "TolX", eps,
                   "OutputFcn", [], "FunValCheck", "off");
     return;
   endif
@@ -117,7 +117,7 @@
   ## displev = optimget (options, "Display", "notify");
   funvalchk = strcmpi (optimget (options, "FunValCheck", "off"), "on");
   outfcn = optimget (options, "OutputFcn");
-  tolx = optimget (options, "TolX", 1e-8);
+  tolx = optimget (options, "TolX", eps);
   maxiter = optimget (options, "MaxIter", Inf);
   maxfev = optimget (options, "MaxFunEvals", Inf);
 
@@ -302,7 +302,7 @@
     endif
 
     ## If there's an output function, use it now.
-    if (outfcn)
+    if (! isempty (outfcn))
       optv.funccount = nfev;
       optv.fval = fval;
       optv.iteration = niter;
--- a/scripts/optimization/glpk.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/optimization/glpk.m	Mon Jan 12 09:17:35 2015 -0800
@@ -123,7 +123,7 @@
 ##
 ## @item @qcode{"D"}
 ## An inequality constraint with both upper and lower bounds
-## (@code{A(i,:)*x >= -b(i)} @emph{and} (@code{A(i,:)*x <= b(i)}).
+## (@code{A(i,:)*x >= -b(i)}) @emph{and} (@code{A(i,:)*x <= b(i)}).
 ## @end table
 ##
 ## @item vartype
@@ -238,7 +238,7 @@
 ## Most fractional variable.
 ##
 ## @item 4 (@w{@code{GLP_BR_DTH}})
-## Heuristic by Driebeck and Tomlin.
+## Heuristic by @nospell{Driebeck and Tomlin}.
 ##
 ## @item 5 (@w{@code{GLP_BR_PCH}})
 ## Hybrid @nospell{pseudocost} heuristic.
--- a/scripts/optimization/lsqnonneg.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/optimization/lsqnonneg.m	Mon Jan 12 09:17:35 2015 -0800
@@ -66,7 +66,7 @@
 ##
 ## Not implemented.
 ## @end itemize
-## @seealso{optimset, pqpnonneg}
+## @seealso{optimset, pqpnonneg, lscov}
 ## @end deftypefn
 
 ## PKG_ADD: ## Discard result to avoid polluting workspace with ans at startup.
--- a/scripts/optimization/optimget.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/optimization/optimget.m	Mon Jan 12 09:17:35 2015 -0800
@@ -20,10 +20,12 @@
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {} optimget (@var{options}, @var{parname})
 ## @deftypefnx {Function File} {} optimget (@var{options}, @var{parname}, @var{default})
-## Return a specific option from a structure created by
-## @code{optimset}.  If @var{parname} is not a field of the @var{options}
-## structure, return @var{default} if supplied, otherwise return an
-## empty matrix.
+## Return the specific option @var{parname} from the optimization options
+## structure @var{options} created by @code{optimset}.
+##
+## If @var{parname} is not defined then return @var{default} if supplied,
+## otherwise return an empty matrix.
+## @seealso{optimset}
 ## @end deftypefn
 
 function retval = optimget (options, parname, default)
@@ -32,21 +34,22 @@
     print_usage ();
   endif
 
+  ## Expand partial-length names into full names
   opts = __all_opts__ ();
   idx = strncmpi (opts, parname, length (parname));
-
   nmatch = sum (idx);
 
   if (nmatch == 1)
     parname = opts{idx};
   elseif (nmatch == 0)
-    warning ("unrecognized option: %s", parname);
+    warning ("optimget: unrecognized option: %s", parname);
   else
-    fmt = sprintf ("ambiguous option: %%s (%s%%s)",
+    fmt = sprintf ("optimget: ambiguous option: %%s (%s%%s)",
                    repmat ("%s, ", 1, nmatch-1));
     warning (fmt, parname, opts{idx});
   endif
-  if (isfield (options, parname))
+
+  if (isfield (options, parname) && ! isempty (options.(parname)))
     retval = options.(parname);
   elseif (nargin > 2)
     retval = default;
@@ -57,13 +60,20 @@
 endfunction
 
 
-%!error optimget ()
-
 %!shared opts
 %! opts = optimset ("tolx", 0.1, "maxit", 100);
-%!assert (optimget (opts, "TolX"), 0.1);
-%!assert (optimget (opts, "maxit"), 100);
-%!assert (optimget (opts, "MaxITer"), 100);
-%!warning (optimget (opts, "Max"));
-%!warning (optimget (opts, "foobar"));
+%!assert (optimget (opts, "TolX"), 0.1)
+%!assert (optimget (opts, "maxit"), 100)
+%!assert (optimget (opts, "MaxITer"), 100)
+%!assert (optimget (opts, "TolFun"), [])
+%!assert (optimget (opts, "TolFun", 1e-3), 1e-3)
 
+%% Test input validation
+%!error optimget ()
+%!error optimget (1)
+%!error optimget (1,2,3,4,5)
+%!error optimget (1, "name")
+%!error optimget (struct (), 2)
+%!warning <unrecognized option: foobar> (optimget (opts, "foobar"));
+%!warning <ambiguous option: Max> (optimget (opts, "Max"));
+
--- a/scripts/optimization/optimset.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/optimization/optimset.m	Mon Jan 12 09:17:35 2015 -0800
@@ -19,10 +19,24 @@
 
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {} optimset ()
-## @deftypefnx {Function File} {} optimset (@var{par}, @var{val}, @dots{})
-## @deftypefnx {Function File} {} optimset (@var{old}, @var{par}, @var{val}, @dots{})
-## @deftypefnx {Function File} {} optimset (@var{old}, @var{new})
-## Create options struct for optimization functions.
+## @deftypefnx {Function File} {@var{options} =} optimset ()
+## @deftypefnx {Function File} {@var{options} =} optimset (@var{par}, @var{val}, @dots{})
+## @deftypefnx {Function File} {@var{options} =} optimset (@var{old}, @var{par}, @var{val}, @dots{})
+## @deftypefnx {Function File} {@var{options} =} optimset (@var{old}, @var{new})
+## Create options structure for optimization functions.
+##
+## When called without any input or output arguments, @code{optimset} prints
+## a list of all valid optimization parameters.
+##
+## When called with one output and no inputs, return an options structure with
+## all valid option parameters initialized to @code{[]}.
+##
+## When called with a list of parameter/value pairs, return an options
+## structure with only the named parameters initialized.
+##
+## When the first input is an existing options structure @var{old}, the values
+## are updated from either the @var{par}/@var{val} list or from the options
+## structure @var{new}.
 ##
 ## Valid parameters are:
 ##
@@ -96,13 +110,13 @@
 ##
 ## @item Updating
 ## @end table
+## @seealso{optimget}
 ## @end deftypefn
 
 function retval = optimset (varargin)
 
   nargs = nargin ();
 
-  ## Add more as needed.
   opts = __all_opts__ ();
 
   if (nargs == 0)
@@ -124,8 +138,8 @@
       error ("optimset: no defaults for function '%s'", fcn);
     end_try_catch
   elseif (nargs == 2 && isstruct (varargin{1}) && isstruct (varargin{2}))
-    ## Set slots in old from nonempties in new.  Should we be checking
-    ## to ensure that the field names are expected?
+    ## Set slots in old from non-empties in new.
+    ## Should we be checking to ensure that the field names are expected?
     old = varargin{1};
     new = varargin{2};
     fnames = fieldnames (old);
@@ -140,9 +154,9 @@
         if (nmatch == 1)
           key = opts{find (i)};
         elseif (nmatch == 0)
-          warning ("unrecognized option: %s", key);
+          warning ("optimset: unrecognized option: %s", key);
         else
-          fmt = sprintf ("ambiguous option: %%s (%s%%s)",
+          fmt = sprintf ("optimset: ambiguous option: %%s (%s%%s)",
                          repmat ("%s, ", 1, nmatch-1));
           warning (fmt, key, opts{i});
         endif
@@ -155,8 +169,8 @@
     pairs = reshape (varargin(2:end), 2, []);
     retval = optimset (varargin{1}, cell2struct (pairs(2, :), pairs(1, :), 2));
   elseif (rem (nargs, 2) == 0)
-    ## Create struct.  Default values are replaced by those specified by
-    ## name/value pairs.
+    ## Create struct.
+    ## Default values are replaced by those specified by name/value pairs.
     pairs = reshape (varargin, 2, []);
     retval = optimset (struct (), cell2struct (pairs(2, :), pairs(1, :), 2));
   else
@@ -166,10 +180,13 @@
 endfunction
 
 
-%!assert (optimget (optimset ("tolx", 1e-2), "tOLx"), 1e-2)
+%!assert (isfield (optimset (), "TolFun"))
 %!assert (isfield (optimset ("tolFun", 1e-3), "TolFun"))
-%!warning (optimset ("Max", 10));
-%!warning (optimset ("foobar", 13));
+%!assert (optimget (optimset ("tolx", 1e-2), "tOLx"), 1e-2)
 
-%!error (optimset ("%NOT_A_REAL_FUNCTION_NAME%"))
+%% Test input validation
+%!error optimset ("1_Parameter")
+%!error <no defaults for function> optimset ("%NOT_A_REAL_FUNCTION_NAME%")
+%!warning <unrecognized option: foobar> optimset ("foobar", 13);
+%!warning <ambiguous option: Max> optimset ("Max", 10);
 
--- a/scripts/optimization/sqp.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/optimization/sqp.m	Mon Jan 12 09:17:35 2015 -0800
@@ -1,4 +1,5 @@
 ## Copyright (C) 2005-2013 John W. Eaton
+## Copyright (C) 2013 Arun Giridhar
 ##
 ## This file is part of Octave.
 ##
@@ -128,8 +129,17 @@
 ##
 ## @table @asis
 ## @item 101
-## The algorithm terminated normally.
-## Either all constraints meet the requested tolerance, or the stepsize,
+## The algorithm terminated normally. 
+## All constraints meet the specified tolerance.
+##
+## @item 102
+## The BFGS update failed.
+##
+## @item 103
+## The maximum number of iterations was reached.
+##
+## @item 104
+## The stepsize has become too small, i.e., 
 ## @tex
 ## $\Delta x,$
 ## @end tex
@@ -137,12 +147,6 @@
 ## delta @var{x},
 ## @end ifnottex
 ## is less than @code{@var{tol} * norm (x)}.
-##
-## @item 102
-## The BFGS update failed.
-##
-## @item 103
-## The maximum number of iterations was reached.
 ## @end table
 ##
 ## An example of calling @code{sqp}:
@@ -394,6 +398,8 @@
     t3 = all (lambda_i >= 0);
     t4 = norm (lambda .* con);
 
+    ## Normal convergence.  All constraints are satisfied
+    ## and objective has converged.
     if (t2 && t3 && max ([t0; t1; t4]) < tol)
       info = 101;
       break;
@@ -408,8 +414,8 @@
 
     info = INFO.info;
 
-    ## FIXME -- check QP solution and attempt to recover if it has
-    ## failed.  For now, just warn about possible problems.
+    ## FIXME: check QP solution and attempt to recover if it has failed.
+    ##        For now, just warn about possible problems.
     
     id = "Octave:SQP-QP-subproblem";
     switch (info)
@@ -453,8 +459,9 @@
 
     delx = x_new - x;
 
+    ## Check if step size has become too small (indicates lack of progress).
     if (norm (delx) < tol * norm (x))
-      info = 101;
+      info = 104;
       break;
     endif
 
@@ -483,6 +490,8 @@
 
       d2 = delxt*r;
 
+      ## Check if the next BFGS update will work properly.
+      ## If d1 or d2 vanish, the BFGS update will fail.
       if (d1 == 0 || d2 == 0)
         info = 102;
         break;
@@ -510,6 +519,7 @@
 
   endwhile
 
+  ## Check if we've spent too many iterations without converging.
   if (iter >= iter_max)
     info = 103;
   endif
--- a/scripts/path/matlabroot.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/path/matlabroot.m	Mon Jan 12 09:17:35 2015 -0800
@@ -32,6 +32,5 @@
 endfunction
 
 
-
 %!assert (matlabroot (), OCTAVE_HOME ())
 
--- a/scripts/path/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/path/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -1,9 +1,13 @@
 FCN_FILE_DIRS += path
 
+path_PRIVATE_FCN_FILES = \
+  path/private/getsavepath.m
+
 path_FCN_FILES = \
   path/matlabroot.m \
   path/pathdef.m \
-  path/savepath.m
+  path/savepath.m \
+  $(path_PRIVATE_FCN_FILES)
 
 FCN_FILES += $(path_FCN_FILES)
 
--- a/scripts/path/pathdef.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/path/pathdef.m	Mon Jan 12 09:17:35 2015 -0800
@@ -20,108 +20,82 @@
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {@var{val} =} pathdef ()
 ## Return the default path for Octave.
-## The path information is extracted from one of three sources.
+##
+## The path information is extracted from one of four sources.
 ## The possible sources, in order of preference, are:
 ##
 ## @enumerate
+## @item @file{.octaverc}
+##
 ## @item @file{~/.octaverc}
 ##
-## @item @file{<octave-home>/@dots{}/<version>/m/startup/octaverc}
+## @item @file{<OCTAVE_HOME>/@dots{}/<version>/m/startup/octaverc}
 ##
-## @item Octave's path prior to changes by any octaverc.
+## @item Octave's path prior to changes by any octaverc file.
 ## @end enumerate
 ## @seealso{path, addpath, rmpath, genpath, savepath}
 ## @end deftypefn
 
 function val = pathdef ()
 
-  ## Locate the site octaverc file.
-  pathdir = octave_config_info ("localstartupfiledir");
-  site_octaverc = fullfile (pathdir, "octaverc");
+  if (nargin > 0)
+    print_usage ();
+  endif
+
+  ## Locate any project-specific .octaverc file.
+  proj_octaverc = fullfile (pwd, ".octaverc");
+  if (exist (proj_octaverc, "file"))
+    proj_path = __extractpath__ (proj_octaverc);
+    if (! isempty (proj_path))
+      val = proj_path;
+      return;
+    endif
+  endif
 
   ## Locate the user's ~/.octaverc file.
   user_octaverc = fullfile ("~", ".octaverc");
-
-  ## Extract the specified paths from the site and user octavercs.
-  site_path = __extractpath__ (site_octaverc);
   if (exist (user_octaverc, "file"))
     user_path = __extractpath__ (user_octaverc);
-  else
-    user_path = "";
+    if (! isempty (user_path))
+      val = user_path;
+      return;
+    endif
+  endif
+
+  ## No user octaverc file, locate the site octaverc file.
+  pathdir = octave_config_info ("localstartupfiledir");
+  site_octaverc = fullfile (pathdir, "octaverc");
+  site_path = __extractpath__ (site_octaverc);
+  if (! isempty (site_path))
+    val = site_path;
+    return;
   endif
 
-  ## A path definition in the user rcfile has precedence over the site rcfile.
-  if (! isempty (user_path))
-    val = user_path;
-  elseif (! isempty (site_path))
-    val = site_path;
+  ## No project, user, or site octaverc file.  Use Octave's default.
+  val = __pathorig__ ();
+
+endfunction
+
+## Extact the path information from the script/function @var{file}, created by
+## @file{savepath.m}.  If successful, @code{__extractpath__} returns the path
+## specified in @var{file}.
+
+## Author: Ben Abbott <bpabbott@mac.com>
+
+function path = __extractpath__ (savefile)
+
+  [filelines, startline, endline] = getsavepath (savefile);
+  if (startline > 0)
+    tmp = regexprep (filelines(startline+1:endline-1),
+                     "^.*path \\('([^\']+)'.*$", "$1");
+    path = strjoin (tmp, ":");
   else
-    val = __pathorig__ ();
+    path = "";
   endif
 
 endfunction
 
-## Extact the path information from the script/function @var{file},
-## created by @file{savepath.m}.  If @var{file} is omitted,
-## @file{~/.octaverc} is used.  If successful, @code{__extractpath__}
-## returns the path specified in @var{file}.
-
-## Author: Ben Abbott <bpabbott@mac.com>
-
-function specifiedpath = __extractpath__ (savefile)
-
-  ## The majority of this code was borrowed from savepath.m.
-  ## FIXME: is there some way to share the common parts instead of duplicating?
-  ## ANSWER: Yes.  Create a private directory and extract this section of code
-  ##         and place it there in a new function only visible by pathdef() and
-  ##         savepath().
-  beginstring = "## Begin savepath auto-created section, do not edit";
-  endstring   = "## End savepath auto-created section";
-
-  if (nargin == 0)
-    savefile = tilde_expand ("~/.octaverc");
-  endif
 
-  ## Parse the file if it exists to see if we should replace a section
-  ## or create a section.
-  startline = endline = 0;
-  filelines = {};
-  if (exist (savefile) == 2)
-    [fid, msg] = fopen (savefile, "rt");
-    if (fid < 0)
-      error ("__extractpath__: could not open savefile, %s: %s", savefile, msg);
-    endif
-    unwind_protect
-      linenum = 0;
-      while (ischar (line = fgetl (fid)))
-        filelines{++linenum} = line;
-        ## find the first and last lines if they exist in the file
-        if (strcmp (line, beginstring))
-          startline = linenum;
-        elseif (strcmp (line, endstring))
-          endline = linenum;
-        endif
-      endwhile
-    unwind_protect_cleanup
-      closeread = fclose (fid);
-      if (closeread < 0)
-        error ("__extractpath__: could not close savefile after reading, %s",
-               savefile);
-      endif
-    end_unwind_protect
-  endif
+## FIXME: Need some better BIST tests
+%!assert (ischar (pathdef ()))
 
-  ## Extract the path specifiation.
-  if (startline > endline || (startline > 0 && endline == 0))
-    error ("__extractpath__: unable to parse file, %s", savefile);
-  elseif (startline > 0)
-    ## Undo doubling of single quote characters performed by savepath.
-    specifiedpath = strrep (regexprep (cstrcat (filelines(startline:endline){:}),
-                                       " *path *\\('(.*)'\\); *", "$1"),
-                            "''", "'");
-  else
-    specifiedpath = "";
-  endif
-
-endfunction
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/path/private/getsavepath.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,53 @@
+## Copyright (C) 2014 Rik Wehbring
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+function [filelines, startline, endline] = getsavepath (file)
+
+  beginstring = "## Begin savepath auto-created section, do not edit";
+  endstring   = "## End savepath auto-created section";
+
+  ## Read in the file while checking for errors along the way.
+  startline = endline = 0;
+  filelines = {};
+  if (exist (file) == 2)
+    [fid, msg] = fopen (file, "rt");
+    if (fid < 0)
+      error ("getsavepath: could not open file, %s: %s", file, msg);
+    endif
+    linenum = 0;
+    while (ischar (line = fgetl (fid)))
+      filelines{++linenum} = line;
+      ## Find the first and last lines if they exist in the file.
+      if (strcmp (line, beginstring))
+        startline = linenum;
+      elseif (strcmp (line, endstring))
+        endline = linenum;
+      endif
+    endwhile
+    if (fclose (fid) < 0)
+      error ("getsavepath: could not close file after reading, %s", file);
+    endif
+  endif
+
+  ## Verify the file was correctly formatted. 
+  if (startline > endline || (startline > 0 && endline == 0))
+    error ("getsavepath: unable to parse file, %s", file);
+  endif
+
+endfunction
+
--- a/scripts/path/savepath.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/path/savepath.m	Mon Jan 12 09:17:35 2015 -0800
@@ -22,8 +22,20 @@
 ## @deftypefnx {Function File} {@var{status} =} savepath (@dots{})
 ## Save the unique portion of the current function search path that is
 ## not set during Octave's initialization process to @var{file}.
-## If @var{file} is omitted, @file{~/.octaverc} is used.  If successful,
-## @code{savepath} returns 0.
+##
+## If @var{file} is omitted, Octave looks in the current directory for a
+## project-specific @file{.octaverc} file in which to save the path
+## information.  If no such file is present then the user's configuration file
+## @file{~/.octaverc} is used.
+##
+## If successful, @code{savepath} returns 0.
+##
+## The @code{savepath} function makes it simple to customize a user's
+## configuration file to restore the working paths necessary for a particular
+## instance of Octave.  Assuming no filename is specified, Octave will
+## automatically restore the saved directory paths from the appropriate
+## @file{.octaverc} file when starting up.  If a filename has been specified
+## then the paths may be restored manually by calling @code{source @var{file}}.
 ## @seealso{path, addpath, rmpath, genpath, pathdef}
 ## @end deftypefn
 
@@ -31,54 +43,27 @@
 
 function retval = savepath (file)
 
-  ret = 1;
-
   beginstring = "## Begin savepath auto-created section, do not edit";
   endstring   = "## End savepath auto-created section";
 
+  ## Use project-specific or user's .octaverc when no file specified 
   if (nargin == 0)
-    file = fullfile ("~", ".octaverc");
+    file = fullfile (pwd, ".octaverc");
+    if (! exist (file, "file"))
+      file = fullfile ("~", ".octaverc");
+    endif
   endif
 
-  ## parse the file if it exists to see if we should replace an
-  ## existing section or create a new section
-  startline = endline = 0;
-  filelines = {};
-  if (exist (file) == 2)
-    [fid, msg] = fopen (file, "rt");
-    if (fid < 0)
-      error ("savepath: could not open file, %s: %s", file, msg);
-    endif
-    unwind_protect
-      linenum = 0;
-      while (ischar (line = fgetl (fid)))
-        filelines{++linenum} = line;
-        ## find the first and last lines if they exist in the file
-        if (strcmp (line, beginstring))
-          startline = linenum;
-        elseif (strcmp (line, endstring))
-          endline = linenum;
-        endif
-      endwhile
-    unwind_protect_cleanup
-      closeread = fclose (fid);
-      if (closeread < 0)
-        error ("savepath: could not close file after reading, %s", file);
-      endif
-    end_unwind_protect
-  endif
+  ## Read in the file
+  [filelines, startline, endline] = getsavepath (file);
 
-  if (startline > endline || (startline > 0 && endline == 0))
-    error ("savepath: unable to parse file, %s", file);
-  endif
-
-  ## put the current savepath lines into the file
+  ## Determine where the savepath lines are placed in the file.
   if (isempty (filelines)
       || (startline == 1 && endline == length (filelines)))
-    ## savepath is the entire file
+    ## savepath is the entire file.
     pre = post = {};
   elseif (endline == 0)
-    ## drop the savepath statements at the end of the file
+    ## Drop the savepath statements at the end of the file.
     pre = filelines;
     post = {};
   elseif (startline == 1)
@@ -88,51 +73,45 @@
     pre = filelines(1:startline-1);
     post = {};
   else
-    ## insert in the middle
+    ## Insert in the middle.
     pre = filelines(1:startline-1);
     post = filelines(endline+1:end);
   endif
 
-  ## write the results
+  ## Write the results.
   [fid, msg] = fopen (file, "wt");
   if (fid < 0)
     error ("savepath: unable to open file for writing, %s, %s", file, msg);
   endif
   unwind_protect
-    for i = 1:length (pre)
-      fprintf (fid, "%s\n", pre{i});
-    endfor
+    fprintf (fid, "%s\n", pre{:});
 
     ## Remove the portion of the path defined via the command line
     ## and/or the environment.
     workingpath = parsepath (path);
-    command_line_path = parsepath (command_line_path ());
+    cmd_line_path = parsepath (command_line_path ());
     octave_path = parsepath (getenv ("OCTAVE_PATH"));
-    pathdef = pathdef ();
-    if (isempty (pathdef))
-      ## This occurs when running octave via run-octave. In this instance
+    default_path = pathdef ();
+    if (isempty (default_path))
+      ## This occurs when running octave via run-octave.  In this instance
       ## the entire path is specified via the command line and pathdef()
       ## is empty.
       [~, n] = setdiff (workingpath, octave_path);
-      default_path = command_line_path;
+      default_path = cmd_line_path;
     else
-      [~, n] = setdiff (workingpath, union (command_line_path, octave_path));
-      default_path = parsepath (pathdef);
+      [~, n] = setdiff (workingpath, union (cmd_line_path, octave_path));
+      default_path = parsepath (default_path);
     endif
     ## This is the path we'd like to preserve when octave is run.
-    path_to_preserve = workingpath (sort (n));
+    path_to_preserve = workingpath(sort (n));
 
-    ## Determine the path to Octave's user and sytem wide pkgs.
+    ## Determine the path to Octave's user and system wide packages.
     [pkg_user, pkg_system] = pkg ("list");
-    pkg_user_path = cell (1, numel (pkg_user));
-    pkg_system_path = cell (1, numel (pkg_system));
-    for n = 1:numel (pkg_user)
-      pkg_user_path{n} = pkg_user{n}.archprefix;
-    endfor
-    for n = 1:numel (pkg_system)
-      pkg_system_path{n} = pkg_system{n}.archprefix;
-    endfor
-    pkg_path = union (pkg_user_path, pkg_system_path);
+
+    ## Conversion from cell array of structs to cellstr of archprefixes.
+    pkg_path = unique (cellfun (@(elt) elt.archprefix,
+                                [pkg_user, pkg_system],
+                                "uniformoutput", false));
 
     ## Rely on Octave's initialization to include the pkg path elements.
     if (! isempty (pkg_path))
@@ -140,22 +119,27 @@
       path_to_preserve = path_to_preserve(sort (n));
     endif
 
-    ## Split the path to be saved into two groups. Those path elements that
+    ## Split the path to be saved into two groups.  Those path elements that
     ## belong at the beginning and those at the end.
     if (! isempty (default_path))
       n1 = find (strcmp (default_path{1}, path_to_preserve));
       n2 = find (strcmp (default_path{end}, path_to_preserve));
-      n_middle = round (0.5*(n1+n2));
+      n_middle = round ((n1+n2)/2);
       [~, n] = setdiff (path_to_preserve, default_path);
       path_to_save = path_to_preserve(sort (n));
       ## Remove pwd
-      path_to_save = path_to_save(! strcmp (path_to_save, ["." pathsep]));
-      n = ones (size (path_to_save));
-      for m = 1:numel (path_to_save)
-        n(m) = find (strcmp (path_to_save{m}, path_to_preserve));
-      endfor
-      path_to_save_begin = path_to_save(n <= n_middle);
-      path_to_save_end   = path_to_save(n > n_middle);
+      path_to_save(strcmp (path_to_save, ["." pathsep])) = [];
+      if (! isempty (path_to_save))
+        n = ones (numel (path_to_save), 1);
+        for m = 1:numel (path_to_save)
+          n(m) = find (strcmp (path_to_save{m}, path_to_preserve));
+        endfor
+        path_to_save_begin = path_to_save(n <= n_middle);
+        path_to_save_end   = path_to_save(n > n_middle);
+      else
+        path_to_save_begin = {};
+        path_to_save_end   = {};
+      endif
     else
       path_to_save_begin = path_to_preserve;
       path_to_save_end   = {};
@@ -179,28 +163,58 @@
     endif
     fprintf (fid, "%s\n", endstring);
 
-    for i = 1:length (post)
-      fprintf (fid, "%s\n", post{i});
-    endfor
+    fprintf (fid, "%s\n", post{:});
   unwind_protect_cleanup
-    closeread = fclose (fid);
-    if (closeread < 0)
+    status = fclose (fid);
+    if (status < 0)
       error ("savepath: could not close savefile after writing, %s", file);
     elseif (nargin == 0)
-      warning ("savepath: current path saved to %s", file);
+      warning ("off", "backtrace", "local");
+      warning ("Octave:savepath-local",
+               "savepath: current path saved to %s", file);
     endif
   end_unwind_protect
 
-  ret = 0;
-
   if (nargout > 0)
-    retval = ret;
+    retval = 0;
   endif
 
 endfunction
 
+## Convert single string of paths to cell array of paths
 function path_elements = parsepath (p)
-  pat = sprintf ('([^%s]+[%s$])', pathsep, pathsep);
-  path_elements = regexpi (strcat (p, pathsep), pat, "match");
+  path_elements = strcat (ostrsplit (p, pathsep), pathsep);
 endfunction
 
+%!test
+%! fname = tempname ();
+%! status = savepath (fname);
+%! assert (status == 0);
+%! old_dir = pwd;
+%! unwind_protect
+%!   cd (P_tmpdir);
+%!   if (exist (fullfile (pwd, ".octaverc")))
+%!     unlink (".octaverc");
+%!   endif
+%!   ## Create blank .octaverc file
+%!   fid = fopen (".octaverc", "wt"); 
+%!   assert (fid >= 0);
+%!   fclose (fid);
+%!   ## Save path into local .octaverc file
+%!   warning ("off", "Octave:savepath-local");
+%!   status = savepath ();
+%!   assert (status == 0);
+%!   ## Compare old and new versions
+%!   fid = fopen (fname, "rb");
+%!   assert (fid >= 0);
+%!   orig_data = fread (fid);
+%!   fclose (fid);
+%!   fid = fopen (".octaverc", "rb");
+%!   assert (fid >= 0);
+%!   new_data = fread (fid);
+%!   fclose (fid);
+%!   assert (orig_data, new_data);
+%! unwind_protect_cleanup
+%!   cd (old_dir);
+%! end_unwind_protect 
+
--- a/scripts/pkg/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/pkg/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -5,6 +5,7 @@
   pkg/private/configure_make.m \
   pkg/private/copy_files.m \
   pkg/private/create_pkgadddel.m \
+  pkg/private/default_prefix.m \
   pkg/private/describe.m \
   pkg/private/dirempty.m \
   pkg/private/extract_pkg.m \
--- a/scripts/pkg/pkg.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/pkg/pkg.m	Mon Jan 12 09:17:35 2015 -0800
@@ -21,8 +21,9 @@
 ## -*- texinfo -*-
 ## @deftypefn  {Command} {} pkg @var{command} @var{pkg_name}
 ## @deftypefnx {Command} {} pkg @var{command} @var{option} @var{pkg_name}
-## Manage packages (groups of add-on functions) for Octave.  Different actions
-## are available depending on the value of @var{command}.
+## Manage packages (groups of add-on functions) for Octave.
+##
+## Different actions are available depending on the value of @var{command}.
 ##
 ## Available commands:
 ##
@@ -123,11 +124,25 @@
 ## Show the list of currently installed packages.  For example,
 ##
 ## @example
-## installed_packages = pkg ("list")
+## pkg list
 ## @end example
 ##
 ## @noindent
-## returns a cell array containing a structure for each installed package.
+## will produce a short report with the package name, version, and installation
+## directory for each installed package.  Supply a package name to limit 
+## reporting to a particular package.  For example:
+##
+## @example
+## pkg list image
+## @end example
+##
+## If a single return argument is requested then @code{pkg} returns a cell
+## array where each element is a structure with information on a single
+## package.
+##
+## @example
+## installed_packages = pkg ("list")
+## @end example
 ##
 ## If two output arguments are requested @code{pkg} splits the list of
 ## installed packages into those which were installed by the current user,
@@ -137,7 +152,7 @@
 ## [user_packages, system_packages] = pkg ("list")
 ## @end example
 ##
-## The option @qcode{"-forge"} lists packages available at the Octave-Forge
+## The @qcode{"-forge"} option lists packages available at the Octave-Forge
 ## repository.  This requires an internet connection and the cURL library. 
 ## For example:
 ##
@@ -164,7 +179,7 @@
 ## @end example
 ##
 ## @noindent
-## If any of the requested packages is not installed, pkg returns an
+## If any of the requested packages is not installed, @code{pkg} returns an
 ## error, unless a second output is requested:
 ##
 ## @example
@@ -260,9 +275,11 @@
 ## will remove the autoloading status of the image package.
 ##
 ## @end table
+## @seealso{ver, news}
 ## @end deftypefn
 
 function [local_packages, global_packages] = pkg (varargin)
+
   ## Installation prefix (FIXME: what should these be on windows?)
   persistent user_prefix = false;
   persistent prefix = false;
@@ -271,33 +288,27 @@
   persistent global_list = fullfile (OCTAVE_HOME (), "share", "octave",
                                      "octave_packages");
 
-  confirm_recursive_rmdir (false, "local");
-
-  mlock ();
-
   ## If user is superuser set global_istall to true
   ## FIXME: is it OK to set this always true on windows?
   global_install = ((ispc () && ! isunix ()) || (geteuid () == 0));
 
   if (isbool (prefix))
-    if (global_install)
-      prefix = fullfile (OCTAVE_HOME (), "share", "octave", "packages");
-      archprefix = fullfile (octave_config_info ("libdir"),
-                             "octave", "packages");
-    else
-      prefix = fullfile ("~", "octave");
-      archprefix = prefix;
-    endif
+    [prefix, archprefix] = default_prefix (global_install);
     prefix = tilde_expand (prefix);
     archprefix = tilde_expand (archprefix);
   endif
 
+  mlock ();
+
+  confirm_recursive_rmdir (false, "local");
+
   available_actions = {"list", "install", "uninstall", "load", ...
                        "unload", "prefix", "local_list", ...
                        "global_list", "rebuild", "build", ...
                        "describe", "update"};
-  ## Handle input
-  if (length (varargin) == 0 || ! iscellstr (varargin))
+
+  ## Parse input arguments
+  if (isempty (varargin) || ! iscellstr (varargin))
     print_usage ();
   endif
   files = {};
@@ -306,7 +317,7 @@
   action = "none";
   verbose = false;
   octave_forge = false;
-  for i = 1:length (varargin)
+  for i = 1:numel (varargin)
     switch (varargin{i})
       case "-nodeps"
         deps = false;
@@ -326,22 +337,18 @@
       case "-local"
         global_install = false;
         if (! user_prefix)
-          prefix = tilde_expand (fullfile ("~", "octave"));
-          archprefix = prefix;
+          [prefix, archprefix] = default_prefix (global_install);
         endif
       case "-global"
         global_install = true;
         if (! user_prefix)
-          prefix = fullfile (OCTAVE_HOME (), "share", "octave", "packages");
-          archprefix = fullfile (octave_config_info ("libdir"),
-                                 "octave", "packages");
+          [prefix, archprefix] = default_prefix (global_install);
         endif
       case available_actions
-        if (strcmp (action, "none"))
-          action = varargin{i};
-        else
+        if (! strcmp (action, "none"))
           error ("more than one action specified");
         endif
+        action = varargin{i};
       otherwise
         files{end+1} = varargin{i};
     endswitch
@@ -362,19 +369,20 @@
         endif
       else
         if (nargout == 0)
-          installed_packages (local_list, global_list);
+          installed_packages (local_list, global_list, files);
         elseif (nargout == 1)
-          local_packages = installed_packages (local_list, global_list);
+          local_packages = installed_packages (local_list, global_list, files);
         elseif (nargout == 2)
           [local_packages, global_packages] = installed_packages (local_list,
-                                                                  global_list);
+                                                                  global_list,
+                                                                  files);
         else
           error ("too many output arguments requested");
         endif
       endif
 
     case "install"
-      if (length (files) == 0)
+      if (isempty (files))
         error ("you must specify at least one filename when calling 'pkg install'");
       endif
 
@@ -399,48 +407,47 @@
       end_unwind_protect
 
     case "uninstall"
-      if (length (files) == 0)
+      if (isempty (files))
         error ("you must specify at least one package when calling 'pkg uninstall'");
       endif
-      uninstall (files, deps, verbose, local_list,
-                 global_list, global_install);
+      uninstall (files, deps, verbose, local_list, global_list, global_install);
 
     case "load"
-      if (length (files) == 0)
-        error ("you must specify at least one package, 'all' or 'auto' when calling 'pkg load'");
+      if (isempty (files))
+        error ("you must specify at least one package, 'all', or 'auto' when calling 'pkg load'");
       endif
       load_packages (files, deps, local_list, global_list);
 
     case "unload"
-      if (length (files) == 0)
+      if (isempty (files))
         error ("you must specify at least one package or 'all' when calling 'pkg unload'");
       endif
       unload_packages (files, deps, local_list, global_list);
 
     case "prefix"
-      if (length (files) == 0 && nargout == 0)
+      if (isempty (files) && nargout == 0)
         printf ("Installation prefix:             %s\n", prefix);
         printf ("Architecture dependent prefix:   %s\n", archprefix);
-      elseif (length (files) == 0 && nargout >= 1)
+      elseif (isempty (files) && nargout >= 1)
         local_packages = prefix;
         global_packages = archprefix;
-      elseif (length (files) >= 1 && nargout <= 2 && ischar (files{1}))
+      elseif (numel (files) >= 1 && nargout <= 2 && ischar (files{1}))
         prefix = tilde_expand (files{1});
         if (! exist (prefix, "dir"))
-          [status, msg, msgid] = mkdir (prefix);
+          [status, msg] = mkdir (prefix);
           if (status == 0)
-            error("cannot create prefix %s: %s", prefix, msg);
+            error ("cannot create prefix %s: %s", prefix, msg);
           endif
           warning ("creating the directory %s\n", prefix);
         endif
         local_packages = prefix = canonicalize_file_name (prefix);
         user_prefix = true;
-        if (length (files) >= 2 && ischar (files{2}))
+        if (numel (files) >= 2 && ischar (files{2}))
           archprefix = tilde_expand (files{2});
           if (! exist (archprefix, "dir"))
-            [status, msg, msgid] = mkdir (archprefix);
+            [status, msg] = mkdir (archprefix);
             if (status == 0)
-              error("cannot create archprefix %s: %s", archprefix, msg);
+              error ("cannot create archprefix %s: %s", archprefix, msg);
             endif
             warning ("creating the directory %s\n", archprefix);
             global_packages = archprefix = canonicalize_file_name (archprefix);
@@ -451,11 +458,11 @@
       endif
       
     case "local_list"
-      if (length (files) == 0 && nargout == 0)
+      if (isempty (files) && nargout == 0)
         disp (local_list);
-      elseif (length (files) == 0 && nargout == 1)
+      elseif (isempty (files) && nargout == 1)
         local_packages = local_list;
-      elseif (length (files) == 1 && nargout == 0 && ischar (files{1}))
+      elseif (numel (files) == 1 && nargout == 0 && ischar (files{1}))
         local_list = files{1};
         if (! exist (local_list, "file"))          
           try
@@ -471,11 +478,11 @@
       endif
 
     case "global_list"
-      if (length (files) == 0 && nargout == 0)
-        disp(global_list);
-      elseif (length (files) == 0 && nargout == 1)
+      if (isempty (files) && nargout == 0)
+        disp (global_list);
+      elseif (isempty (files) && nargout == 1)
         local_packages = global_list;
-      elseif (length (files) == 1 && nargout == 0 && ischar (files{1}))
+      elseif (numel (files) == 1 && nargout == 0 && ischar (files{1}))
         global_list = files{1};
         if (! exist (global_list, "file"))  
           try
@@ -500,8 +507,8 @@
           local_packages = global_packages;
         endif
       else
-        local_packages = rebuild (prefix, archprefix, local_list, files, auto,
-                                  verbose);
+        local_packages = rebuild (prefix, archprefix, local_list, files,
+                                  auto, verbose);
         local_packages = save_order (local_packages);
         save (local_list, "local_packages");
         if (nargout == 0)
@@ -510,23 +517,21 @@
       endif
 
     case "build"
-      if (length (files) < 2)
+      if (numel (files) < 2)
         error ("you must specify at least the build directory and one filename\nwhen calling 'pkg build'");
       endif
       build (files, deps, auto, verbose);
 
     case "describe"
-      if (length (files) == 0)
+      if (isempty (files))
         error ("you must specify at least one package or 'all' when calling 'pkg describe'");
       endif
-      ## FIXME: the name of the output variables is inconsistent
-      ##            with their content
+      ## FIXME: name of the output variables is inconsistent with their content
       switch (nargout)
         case 0
           describe (files, verbose, local_list, global_list);
         case 1
-          pkg_desc_list = describe (files, verbose, local_list, ...
-                                    global_list);
+          pkg_desc_list = describe (files, verbose, local_list, global_list);
           local_packages = pkg_desc_list;
         case 2
           [pkg_desc_list, flag] = describe (files, verbose, local_list, ...
@@ -540,24 +545,20 @@
     case "update"
       if (nargout == 0)
         installed_pkgs_lst = installed_packages (local_list, global_list);
-        if (length (files) > 0)
+        if (numel (files) > 0)
            update_lst = {}; 
-           for i = 1:length (files)
-             is_installed = false;
-             for j = 1:length (installed_pkgs_lst)
-               if (strcmp (files{i}, installed_pkgs_lst{j}.name))
-                 update_lst = { update_lst{:}, installed_pkgs_lst{j} };
-                 is_installed = true;
-               endif
-             endfor
-             if (is_installed == false)
-               s = sprintf ("Package %s is not installed - not updating this package", files{i});
-               warning (s);
+           installed_names = {installed_pkgs_list.name}';
+           for i = 1:numel (files)
+             idx = find (strcmp (files{i}, installed_names), 1);
+             if (isempty (idx))
+               warning ("Package %s is not installed - not updating this package", files{i});
+             else
+               update_lst = { update_lst, installed_pkgs_lst{idx} };
              endif
            endfor
            installed_pkgs_lst = update_lst;
         endif
-        for i = 1:length (installed_pkgs_lst)
+        for i = 1:numel (installed_pkgs_lst)
           installed_pkg_name = installed_pkgs_lst{i}.name;
           installed_pkg_version = installed_pkgs_lst{i}.version;
           forge_pkg_version = get_forge_pkg (installed_pkg_name);
@@ -570,7 +571,8 @@
       endif
 
     otherwise
-      error ("you must specify a valid action for 'pkg'. See 'help pkg' for details");
+      error ("you must specify a valid action for 'pkg'.  See 'help pkg' for details");
   endswitch
+
 endfunction
 
--- a/scripts/pkg/private/configure_make.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/pkg/private/configure_make.m	Mon Jan 12 09:17:35 2015 -0800
@@ -32,11 +32,6 @@
     mkoctfile_program = fullfile (octave_bindir, sprintf ("mkoctfile-%s%s", ver, ext));
     octave_config_program = fullfile (octave_bindir, sprintf ("octave-config-%s%s", ver, ext));
     octave_binary = fullfile (octave_bindir, sprintf ("octave-%s%s", ver, ext));
-    cenv = {"MKOCTFILE"; mkoctfile_program;
-            "OCTAVE_CONFIG"; octave_config_program;
-            "OCTAVE"; octave_binary;
-            "INSTALLDIR"; desc.dir};
-    scenv = sprintf ("%s=\"%s\" ", cenv{:});
 
     if (! exist (mkoctfile_program, "file"))
       __gripe_missing_component__ ("pkg", "mkoctfile");
@@ -48,6 +43,16 @@
       __gripe_missing_component__ ("pkg", "octave");
     endif
 
+    if (verbose)
+      mkoctfile_program = [mkoctfile_program " --verbose"];
+    endif
+
+    cenv = {"MKOCTFILE"; mkoctfile_program;
+            "OCTAVE_CONFIG"; octave_config_program;
+            "OCTAVE"; octave_binary;
+            "INSTALLDIR"; desc.dir};
+    scenv = sprintf ("%s=\"%s\" ", cenv{:});
+
     ## Configure.
     if (exist (fullfile (src, "configure"), "file"))
       flags = "";
@@ -75,7 +80,9 @@
 
     ## Make.
     if (exist (fullfile (src, "Makefile"), "file"))
-      [status, output] = shell ([scenv "make -C '" src "'"], verbose);
+      [status, output] = shell (sprintf ("%s make --jobs %i --directory '%s'",
+                                         scenv, nproc ("overridable"), src),
+                                verbose);
       if (status != 0)
         rmdir (desc.dir, "s");
         disp (output);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/pkg/private/default_prefix.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,39 @@
+## Copyright (C) 2014 Carlo de Falco
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {[@var{prefix}, @var{archprefix} =} default_prefix (@var{global_install})
+## Undocumented internal function.
+## @end deftypefn
+
+function [prefix, archprefix] = default_prefix (global_install, desc)
+  if (global_install)
+    prefix = fullfile (OCTAVE_HOME (), "share", "octave", "packages");
+    if (nargin == 2)
+      archprefix = fullfile (octave_config_info ("libdir"), "octave",
+                             "packages", [desc.name "-" desc.version]);
+    else
+      archprefix = fullfile (octave_config_info ("libdir"), "octave",
+                             "packages");
+    endif
+  else
+    prefix = tilde_expand (fullfile ("~", "octave"));
+    archprefix = prefix;
+  endif
+endfunction
+
--- a/scripts/pkg/private/getarchprefix.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/pkg/private/getarchprefix.m	Mon Jan 12 09:17:35 2015 -0800
@@ -24,8 +24,7 @@
 
 function archprefix = getarchprefix (desc, global_install)
   if (global_install)
-    archprefix = fullfile (octave_config_info ("libdir"), "octave",
-                           "packages", [desc.name "-" desc.version]);
+    [~, archprefix] = default_prefix (global_install, desc);
   else
     archprefix = desc.dir;
   endif
--- a/scripts/pkg/private/install.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/pkg/private/install.m	Mon Jan 12 09:17:35 2015 -0800
@@ -64,7 +64,7 @@
 
       if (exist (tgz, "file"))
         ## Create a temporary directory.
-        tmpdir = tmpnam ();
+        tmpdir = tempname ();
         tmpdirs{end+1} = tmpdir;
         if (verbose)
           printf ("mkdir (%s)\n", tmpdir);
--- a/scripts/pkg/private/installed_packages.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/pkg/private/installed_packages.m	Mon Jan 12 09:17:35 2015 -0800
@@ -22,7 +22,8 @@
 ## Undocumented internal function.
 ## @end deftypefn
 
-function [out1, out2] = installed_packages (local_list, global_list)
+function [out1, out2] = installed_packages (local_list, global_list, pkgname = {})
+
   ## Get the list of installed packages.
   try
     local_packages = load (local_list).local_packages;
@@ -38,41 +39,42 @@
 
   ## Eliminate duplicates in the installed package list.
   ## Locally installed packages take precedence.
-  dup = [];
-  for i = 1:length (installed_pkgs_lst)
-    if (any (dup == i))
-      continue;
+  installed_names = cellfun (@(x) x.name, installed_pkgs_lst,
+                             "uniformoutput", false);
+  [~, idx] = unique (installed_names, "first");
+  installed_names = installed_names(idx);
+  installed_pkgs_lst = installed_pkgs_lst(idx);
+
+  ## Check whether info on a particular package was requested
+  if (! isempty (pkgname))
+    idx = find (strcmp (pkgname{1}, installed_names));
+    if (isempty (idx))
+      installed_names = {};
+      installed_pkgs_lst = {};
+    else
+      installed_names = installed_names(idx);
+      installed_pkgs_lst = installed_pkgs_lst(idx);
     endif
-    for j = (i+1):length (installed_pkgs_lst)
-      if (any (dup == j))
-        continue;
-      endif
-      if (strcmp (installed_pkgs_lst{i}.name, installed_pkgs_lst{j}.name))
-        dup = [dup, j];
-      endif
-    endfor
-  endfor
-  if (! isempty (dup))
-    installed_pkgs_lst(dup) = [];
   endif
 
   ## Now check if the package is loaded.
+  ## FIXME: couldn't dir_in_loadpath() be used here?
   tmppath = strrep (path (), "\\", "/");
-  for i = 1:length (installed_pkgs_lst)
+  for i = 1:numel (installed_pkgs_lst)
     if (strfind (tmppath, strrep (installed_pkgs_lst{i}.dir, '\', '/')))
       installed_pkgs_lst{i}.loaded = true;
     else
       installed_pkgs_lst{i}.loaded = false;
     endif
   endfor
-  for i = 1:length (local_packages)
+  for i = 1:numel (local_packages)
     if (strfind (tmppath, strrep (local_packages{i}.dir, '\', '/')))
       local_packages{i}.loaded = true;
     else
       local_packages{i}.loaded = false;
     endif
   endfor
-  for i = 1:length (global_packages)
+  for i = 1:numel (global_packages)
     if (strfind (tmppath, strrep (global_packages{i}.dir, '\', '/')))
       global_packages{i}.loaded = true;
     else
@@ -90,10 +92,14 @@
     return;
   endif
 
-  ## We shouldn't return something, so we'll print something.
-  num_packages = length (installed_pkgs_lst);
+  ## Don't return anything, instead we'll print something.
+  num_packages = numel (installed_pkgs_lst);
   if (num_packages == 0)
-    printf ("no packages installed.\n");
+    if (isempty (pkgname))
+      printf ("no packages installed.\n");
+    else
+      printf ("package %s is not installed.\n", pkgname{1});
+    endif
     return;
   endif
 
@@ -101,20 +107,13 @@
   h1 = "Package Name";
   h2 = "Version";
   h3 = "Installation directory";
-  max_name_length = length (h1);
-  max_version_length = length (h2);
-  names = cell (num_packages, 1);
-  for i = 1:num_packages
-    max_name_length = max (max_name_length,
-                           length (installed_pkgs_lst{i}.name));
-    max_version_length = max (max_version_length,
-                              length (installed_pkgs_lst{i}.version));
-    names{i} = installed_pkgs_lst{i}.name;
-  endfor
-  max_dir_length = terminal_size ()(2) - max_name_length - ...
-                                             max_version_length - 7;
+  max_name_length = max ([length(h1), cellfun(@length, installed_names)]);
+  version_lengths = cellfun (@(x) length (x.version), installed_pkgs_lst); 
+  max_version_length = max ([length(h2), version_lengths]);
+  ncols = terminal_size ()(2);
+  max_dir_length = ncols - max_name_length - max_version_length - 7;
   if (max_dir_length < 20)
-     max_dir_length = Inf;
+    max_dir_length = Inf;
   endif
 
   h1 = postpad (h1, max_name_length + 1, " ");
@@ -129,13 +128,12 @@
   printf ("%s\n", tmp);
 
   ## Print the packages.
-  format = sprintf ("%%%ds %%1s| %%%ds | %%s\n", max_name_length,
-                    max_version_length);
-  [dummy, idx] = sort (names);
+  format = sprintf ("%%%ds %%1s| %%%ds | %%s\n",
+                    max_name_length, max_version_length);
   for i = 1:num_packages
-    cur_name = installed_pkgs_lst{idx(i)}.name;
-    cur_version = installed_pkgs_lst{idx(i)}.version;
-    cur_dir = installed_pkgs_lst{idx(i)}.dir;
+    cur_name = installed_pkgs_lst{i}.name;
+    cur_version = installed_pkgs_lst{i}.version;
+    cur_dir = installed_pkgs_lst{i}.dir;
     if (length (cur_dir) > max_dir_length)
       first_char = length (cur_dir) - max_dir_length + 4;
       first_filesep = strfind (cur_dir(first_char:end), filesep ());
@@ -145,12 +143,13 @@
         cur_dir = ["..." cur_dir(first_char:end)];
       endif
     endif
-    if (installed_pkgs_lst{idx(i)}.loaded)
+    if (installed_pkgs_lst{i}.loaded)
       cur_loaded = "*";
     else
       cur_loaded = " ";
     endif
     printf (format, cur_name, cur_loaded, cur_version, cur_dir);
   endfor
+
 endfunction
 
--- a/scripts/plot/appearance/__clabel__.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/appearance/__clabel__.m	Mon Jan 12 09:17:35 2015 -0800
@@ -127,3 +127,7 @@
 
 endfunction
 
+
+## No test needed for internal helper function.
+%!assert (1)
+
--- a/scripts/plot/appearance/__getlegenddata__.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/appearance/__getlegenddata__.m	Mon Jan 12 09:17:35 2015 -0800
@@ -17,7 +17,7 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {[@var{hplots}, @var{strings}]} = __getlegenddata__ (@var{h})
+## @deftypefn {Function File} {[@var{hplots}, @var{strings}] =} __getlegenddata__ (@var{h})
 ## Undocumented internal function.
 ## @end deftypefn
 
@@ -29,7 +29,7 @@
   if (numel (ca) == 1)
     kids = get (ca, "children");
   else
-    kids = [get(kids, "children"){:}];
+    kids = [get(ca, "children"){:}];
   endif
 
   for i = numel (kids):-1:1
@@ -59,3 +59,7 @@
 
 endfunction
 
+
+## No test needed for internal helper function.
+%!assert (1)
+
--- a/scripts/plot/appearance/axis.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/appearance/axis.m	Mon Jan 12 09:17:35 2015 -0800
@@ -30,7 +30,9 @@
 ## The argument @var{limits} should be a 2-, 4-, or 6-element vector.  The
 ## first and second elements specify the lower and upper limits for the
 ## x-axis.  The third and fourth specify the limits for the y-axis, and the
-## fifth and sixth specify the limits for the z-axis.
+## fifth and sixth specify the limits for the z-axis.  The special values
+## -Inf and Inf may be used to indicate that the limit should automatically be
+## computed based on the data in the axis.
 ##
 ## Without any arguments, @code{axis} turns autoscaling on.
 ##
@@ -192,7 +194,7 @@
                "plotboxaspectratio", [1, 1, 1]);
     elseif (strcmp (ax, "equal"))
       if (strcmp (get (get (ca, "parent"), "__graphics_toolkit__"), "gnuplot"))
-        ## FIXME - gnuplot applies the aspect ratio activepostionproperty.
+        ## FIXME: gnuplot applies the aspect ratio activepostionproperty.
         set (ca, "activepositionproperty", "position");
         ## The following line is a trick used to trigger the recalculation of
         ## aspect related magnitudes even if the aspect ratio is the same
@@ -297,15 +299,15 @@
     endfor
 
     if (len > 1)
-      set (ca, "xlim", [ax(1), ax(2)]);
+      xlim (ca, ax(1:2));
     endif
 
     if (len > 3)
-      set (ca, "ylim", [ax(3), ax(4)]);
+      ylim (ca, ax(3:4));
     endif
 
     if (len > 5)
-      set (ca, "zlim", [ax(5), ax(6)]);
+      zlim (ca, ax(5:6));
     endif
 
   else
--- a/scripts/plot/appearance/datetick.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/appearance/datetick.m	Mon Jan 12 09:17:35 2015 -0800
@@ -45,8 +45,8 @@
 
   unwind_protect
     ## FIXME: This will bring the axes to the top of the stack.
-    ##        This may not always be desirable if there are multiple axes
-    ##        objects.
+    ##        This may not be desirable if there are multiple axes objects,
+    ##        such as can occur with plotyy.
     axes (hax);
     __datetick__ (varargin{:});
   unwind_protect_cleanup
@@ -64,22 +64,22 @@
 %! pop = [76.094, 92.407, 106.461, 123.077 131.954, 151.868, 179.979, ...
 %!        203.984, 227.225, 249.623, 282.224];
 %! plot (datenum (yr, 1, 1), pop);
-%! title ("US population (millions)");
-%! xlabel ("Year");
-%! datetick ("x", "YYYY");
+%! title ('US population (millions)');
+%! xlabel ('Year');
+%! datetick ('x', 'YYYY');
 
 %!demo
 %! clf;
 %! yr = 1988:2:2002;
 %! yr = datenum (yr,1,1);
 %! pr = [12.1 13.3 12.6 13.1 13.3 14.1 14.4 15.2];
-%! plot (yr, pr, "-o");
-%! xlabel ("year");
-%! ylabel ("average price");
+%! plot (yr, pr, '-o');
+%! xlabel ('year');
+%! ylabel ('average price');
 %! ax = gca;
-%! set (ax, "xtick", datenum (1990:5:2005,1,1));
-%! datetick (2, "keepticks");
-%! set (ax, "ytick", 12:16);
+%! set (ax, 'xtick', datenum (1990:5:2005,1,1));
+%! datetick (2, 'x', 'keepticks');
+%! set (ax, 'ytick', 12:16);
 
 ## Remove from test statistics.  No real tests possible.
 %!assert (1)
@@ -271,7 +271,7 @@
     b = 0;
   else
     l = log10 (abs (x));
-    r = fmod (l, 1);
+    r = rem (l, 1);
     a = 10 .^ r;
     b = fix (l - r);
     if (a < 1)
--- a/scripts/plot/appearance/diffuse.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/appearance/diffuse.m	Mon Jan 12 09:17:35 2015 -0800
@@ -18,11 +18,11 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} diffuse (@var{sx}, @var{sy}, @var{sz}, @var{lv})
-## Calculate diffuse reflection strength of a surface defined by the normal
+## Calculate the diffuse reflection strength of a surface defined by the normal
 ## vector elements @var{sx}, @var{sy}, @var{sz}.
 ##
-## The light source location vector @var{lv} can be given as 2-element vector
-## [azimuth, elevation] in degrees or as 3-element vector [lx, ly, lz].
+## The light source location vector @var{lv} can be given as a 2-element vector
+## [azimuth, elevation] in degrees or as a 3-element vector [x, y, z].
 ## @seealso{specular, surfl}
 ## @end deftypefn
 
@@ -34,13 +34,13 @@
     print_usage ();
   endif
 
-  ## check for normal vector
-  if (!size_equal (sx, sy, sz))
-    error ("diffuse: SX, SY, and SZ must have same size");
+  ## Check normal vectors
+  if (! size_equal (sx, sy, sz))
+    error ("diffuse: SX, SY, and SZ must be the same size");
   endif
 
-  ## check for light vector (lv) argument
-  if (length (lv) < 2 || length (lv) > 3)
+  ## Check light vector (lv) argument
+  if (! isvector (lv) || length (lv) < 2 || length (lv) > 3)
     error ("diffuse: light vector LV must be a 2- or 3-element vector");
   elseif (length (lv) == 2)
     [lv(1), lv(2), lv(3)] = sph2cart (lv(1) * pi/180, lv(2) * pi/180, 1.0);
@@ -48,7 +48,7 @@
 
   ## Normalize view and light vector.
   if (sum (abs (lv)) > 0)
-    lv  /= norm (lv);
+    lv /= norm (lv);
   endif
 
   ns = sqrt (sx.^2 + sy.^2 + sz.^2);
--- a/scripts/plot/appearance/grid.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/appearance/grid.m	Mon Jan 12 09:17:35 2015 -0800
@@ -58,13 +58,10 @@
     print_usage ();
   endif
 
-  grid_on = (   strcmp (get (hax, "xgrid"), "on")
-             && strcmp (get (hax, "ygrid"), "on")
-             && strcmp (get (hax, "zgrid"), "on"));
+  grid_on = any (strcmp (get (hax, {"xgrid", "ygrid", "zgrid"}), "on"));
 
-  minor_on = (   strcmp (get (hax, "xminorgrid"), "on")
-              && strcmp (get (hax, "yminorgrid"), "on")
-              && strcmp (get (hax, "zminorgrid"), "on"));
+  minor_on = any (strcmp (get (hax, {"xminorgrid", "yminorgrid", "zminorgrid"}),
+                         "on"));
 
   minor_auto = true;
   if (nargs == 0)
@@ -102,9 +99,15 @@
   endif
 
   if (grid_on)
-    set (hax, "xgrid", "on", "ygrid", "on", "zgrid", "on");
+    set (hax, "xgrid", "on", "ygrid", "on", "zgrid", "on",
+              "gridlinestyle", ":");
     if (minor_on)
-      set (hax, "xminorgrid", "on", "yminorgrid", "on", "zminorgrid", "on");
+      set (hax, "xminorgrid", "on", "yminorgrid", "on", "zminorgrid", "on",
+                "gridlinestyle", "-", "minorgridlinestyle", ":");
+      xg = ifelse (strcmp (get (hax, "xscale"), "log"), "off", "on");
+      yg = ifelse (strcmp (get (hax, "yscale"), "log"), "off", "on");
+      zg = ifelse (strcmp (get (hax, "zscale"), "log"), "off", "on");
+      set (hax, "xgrid", xg, "ygrid", yg, "zgrid", zg);
     elseif (minor_auto)
       xmg = ifelse (strcmp (get (hax, "xscale"), "log"), "on", "off");
       ymg = ifelse (strcmp (get (hax, "yscale"), "log"), "on", "off");
@@ -133,8 +136,26 @@
 %!  title ('grid on');
 %! subplot (2,2,3);
 %!  plot (1:100);
+%!  grid off;
+%!  title ('no grid');
+%! subplot (2,2,4);
+%!  plot (1:100);
 %!  grid minor;
 %!  title ('grid minor');
+
+%!demo
+%! subplot (2,2,1);
+%!  semilogy (1:100);
+%!  grid off;
+%!  title ('no grid');
+%! subplot (2,2,2);
+%!  semilogy (1:100);
+%!  grid on;
+%!  title ('grid on');
+%! subplot (2,2,3);
+%!  semilogy (1:100);
+%!  grid off;
+%!  title ('no grid');
 %! subplot (2,2,4);
 %!  semilogy (1:100);
 %!  grid minor;
--- a/scripts/plot/appearance/legend.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/appearance/legend.m	Mon Jan 12 09:17:35 2015 -0800
@@ -166,11 +166,27 @@
   nargs = numel (varargin);
   nkids = numel (kids);
 
+  ## Find any existing legend object on figure
+  hlegend = [];
+  fkids = get (fig, "children");
+  for i = 1 : numel (fkids)
+    if (   strcmp (get (fkids(i), "type"), "axes")
+        && strcmp (get (fkids(i), "tag"), "legend"))
+      udata = get (fkids(i), "userdata");
+      if (any (ismember (udata.handle, ca)))
+        hlegend = fkids(i);
+        break;
+      endif
+    endif
+  endfor
+
   orientation = "default";
   location = "default";
   show = "create";
   textpos = "default";
   box = "default";
+  delete_leg = false;
+  find_leg_hdl = (nargs == 0);
 
   ## Process old way of specifying location with a number rather than a string.
   if (nargs > 0)
@@ -229,20 +245,6 @@
       error ("legend: unrecognized legend location");
   endswitch
 
-  ## Find any existing legend object on figure
-  hlegend = [];
-  fkids = get (fig, "children");
-  for i = 1 : numel (fkids)
-    if (   strcmp (get (fkids(i), "type"), "axes")
-        && strcmp (get (fkids(i), "tag"), "legend"))
-      udata = get (fkids(i), "userdata");
-      if (any (udata.handle == ca))
-        hlegend = fkids(i);
-        break;
-      endif
-    endif
-  endfor
-
   if (nargs == 1)
     arg = varargin{1};
     if (ischar (arg))
@@ -250,8 +252,7 @@
         str = tolower (strtrim (arg));
         switch (str)
           case "off"
-            delete (hlegend);
-            return;
+            delete_leg = true;
           case "hide"
             show = "off";
             nargs--;
@@ -305,24 +306,26 @@
   endif
 
   have_labels = (nargs > 0);
+  hobjects = [];
+  hplots  = [];
+  text_strings = {};
 
-  if (strcmp (show, "off"))
+  if (delete_leg)
+    delete (hlegend);
+    hlegend = [];
+  elseif (find_leg_hdl)
+    ## Don't change anything about legend.
+    ## hleg output will be assigned hlegend value at end of function.
+  elseif (strcmp (show, "off"))
     if (! isempty (hlegend))
       set (findobj (hlegend), "visible", "off");
       hlegend = [];
     endif
-    hobjects = [];
-    hplots  = [];
-    text_strings = {};
   elseif (strcmp (show, "on"))
     if (! isempty (hlegend))
       set (findobj (hlegend), "visible", "on");
-      ## NOTE - Matlab sets both "visible", and "box" to "on"
+      ## NOTE: Matlab sets both "visible" and "box" to "on"
       set (hlegend, "visible", get (hlegend, "box"));
-    else
-      hobjects = [];
-      hplots  = [];
-      text_strings = {};
     endif
   elseif (strcmp (box, "on"))
     if (! isempty (hlegend))
@@ -332,26 +335,24 @@
     if (! isempty (hlegend))
       set (hlegend, "box", "off", "visible", "off");
     endif
-  elseif (! have_labels && ! (strcmp (location, "default") &&
-                              strcmp (orientation, "default")))
+  elseif (! have_labels && ! isempty (hlegend)
+          && ! (strcmp (location, "default") && strcmp (orientation, "default")))
     ## Changing location or orientation of existing legend
-    if (! isempty (hlegend))
-      if (strcmp (location, "default"))
-        set (hlegend, "orientation", orientation);
-      elseif (strcmp (orientation, "default"))
-        if (outside)
-          set (hlegend, "location", [location "outside"]);
-        else
-          set (hlegend, "location", location);
-        endif
+    if (strcmp (location, "default"))
+      set (hlegend, "orientation", orientation);
+    elseif (strcmp (orientation, "default"))
+      if (outside)
+        set (hlegend, "location", [location "outside"]);
       else
-        if (outside)
-          set (hlegend, "location", [location "outside"],
-                        "orientation", orientation);
-        else
-          set (hlegend, "location", location,
-                        "orientation", orientation);
-        endif
+        set (hlegend, "location", location);
+      endif
+    else
+      if (outside)
+        set (hlegend, "location", [location "outside"],
+                      "orientation", orientation);
+      else
+        set (hlegend, "location", location,
+                      "orientation", orientation);
       endif
     endif
   else
@@ -565,6 +566,12 @@
       linelength = 15;
 
       ## Create the axis first
+      oldfig = get (0, "currentfigure");
+      if (oldfig != fig)
+        set (0, "currentfigure", fig);
+      else
+        oldfig = [];
+      endif
       curaxes = get (fig, "currentaxes");
       unwind_protect
         ud = ancestor (hplots, "axes");
@@ -829,10 +836,11 @@
             case "line"
               color = get (hplots(k), "color");
               style = get (hplots(k), "linestyle");
+              lwidth = min (get (hplots(k), "linewidth"), 5);
               if (! strcmp (style, "none"))
                 l1 = line ("xdata", ([xoffset, xoffset + linelength] + xk * xstep) / lpos(3),
                            "ydata", [1, 1] .* (lpos(4) - yoffset - yk * ystep) / lpos(4),
-                           "color", color, "linestyle", style,
+                           "color", color, "linestyle", style, "linewidth", lwidth,
                            "marker", "none",
                            "userdata", hplots(k));
                 hobjects(end+1) = l1;
@@ -841,11 +849,11 @@
               if (! strcmp (marker, "none"))
                 l1 = line ("xdata", (xoffset + 0.5 * linelength  + xk * xstep) / lpos(3),
                            "ydata", (lpos(4) - yoffset - yk * ystep) / lpos(4),
-                           "color", color, "linestyle", "none",
+                           "color", color, "linestyle", "none", "linewidth", lwidth,
                            "marker", marker,
                            "markeredgecolor",get (hplots(k), "markeredgecolor"),
                            "markerfacecolor",get (hplots(k), "markerfacecolor"),
-                           "markersize", get (hplots(k), "markersize"),
+                           "markersize", min (get (hplots(k), "markersize"),10),
                            "userdata", hplots(k));
                 hobjects(end+1) = l1;
               endif
@@ -855,6 +863,8 @@
                              {@updateline, hlegend, linelength, false});
                 addlistener (hplots(k), "linestyle",
                              {@updateline, hlegend, linelength, false});
+                addlistener (hplots(k), "linewidth",
+                             {@updateline, hlegend, linelength, false});
                 addlistener (hplots(k), "marker",
                              {@updateline, hlegend, linelength, false});
                 addlistener (hplots(k), "markeredgecolor",
@@ -876,13 +886,24 @@
                                       xoffset + xk * xstep) / lpos(3),
                             "ydata", (lpos(4) - yoffset -
                                       [yk-0.3, yk-0.3, yk+0.3, yk+0.3] .* ystep) / lpos(4),
-                           "facecolor", facecolor, "edgecolor", edgecolor,
-                           "cdata", cdata, "userdata", hplots(k));
-                hobjects(end+1) = p1;
-                ## Copy clim from axes so that colors work out.
-                set (hlegend, "clim", get (ca(1), "clim"));
+                            "facecolor", facecolor, "edgecolor", edgecolor,
+                            "cdata", cdata, "userdata", hplots(k));
+              else
+                ## non-standard patch only making use of marker styles
+                ## such as scatter plot.
+                p1 = patch ("xdata", (xoffset + 0.5 * linelength  + xk * xstep) / lpos(3),
+                            "ydata", (lpos(4) - yoffset - yk * ystep) / lpos(4),
+                            "marker", get (hplots(k), "marker"),
+                            "markeredgecolor",get (hplots(k),"markeredgecolor"),
+                            "markerfacecolor",get (hplots(k),"markerfacecolor"),
+                            "markersize", min (get (hplots(k),"markersize"),10),
+                            "cdata", cdata, "userdata", hplots(k));
               endif
-              ## FIXME: Probably need listeners, as for line objects
+              hobjects(end+1) = p1;
+              ## Copy clim from axes so that colors work out.
+              set (hlegend, "clim", get (ca(1), "clim"));
+
+              ## FIXME: Need listeners, as for line objects.
               ##        Changing clim, for example, won't update colors
 
             case "surface"
@@ -894,11 +915,11 @@
                                       xoffset + xk * xstep) / lpos(3),
                             "ydata", (lpos(4) - yoffset -
                                       [yk-0.3, yk-0.3, yk+0.3, yk+0.3] .* ystep) / lpos(4),
-                           "facecolor", facecolor, "edgecolor", edgecolor,
-                           "cdata", cdata, "userdata", hplots(k));
+                            "facecolor", facecolor, "edgecolor", edgecolor,
+                            "cdata", cdata, "userdata", hplots(k));
                 hobjects(end+1) = p1;
               endif
-              ## FIXME: Probably need listeners, as for line objects
+              ## FIXME: Need listeners, as for line objects.
 
           endswitch
 
@@ -1032,6 +1053,9 @@
         endif
       unwind_protect_cleanup
         set (fig, "currentaxes", curaxes);
+        if (! isempty (oldfig))
+          set (0, "currentfigure", oldfig);
+        endif
       end_unwind_protect
     endif
   endif
@@ -1065,8 +1089,9 @@
           set (hax, "position", position);
           set (hax, "outerposition", outerposition);
       endswitch
-      set (hax, "units", units);
-      h = legend (hax, hplots, get (h, "string"));
+      set (hax, {"units"}, units);
+
+      h = legend (hax(1), hplots, get (h, "string"));
     unwind_protect_cleanup
       recursive = false;
     end_unwind_protect
@@ -1149,6 +1174,7 @@
     if (ishandle (hplots(i)) && strcmp (get (hplots(i), "type"), "line"))
       dellistener (hplots(i), "color");
       dellistener (hplots(i), "linestyle");
+      dellistener (hplots(i), "linewidth");
       dellistener (hplots(i), "marker");
       dellistener (hplots(i), "markeredgecolor");
       dellistener (hplots(i), "markerfacecolor");
@@ -1163,7 +1189,7 @@
   if (update_name)
     ## When string changes, have to rebuild legend completely
     [hplots, text_strings] = __getlegenddata__ (hlegend);
-    legend (hplots, text_strings);
+    legend (get (hplots(1), "parent"), hplots, text_strings);
   else
     kids = get (hlegend, "children");
     ll = lm = [];
@@ -1198,14 +1224,18 @@
 
     if (! strcmp (linestyle, "none"))
       line ("xdata", xpos1, "ydata", ypos1, "color", get (h, "color"),
-            "linestyle", get (h, "linestyle"), "marker", "none",
+            "linestyle", get (h, "linestyle"),
+            "linewidth", min (get (h, "linewidth"), 5),
+            "marker", "none",
             "userdata", h, "parent", hlegend);
     endif
     if (! strcmp (marker, "none"))
       line ("xdata", xpos2, "ydata", ypos2, "color", get (h, "color"),
             "marker", marker, "markeredgecolor", get (h, "markeredgecolor"),
             "markerfacecolor", get (h, "markerfacecolor"),
-            "markersize", get (h, "markersize"), "linestyle", "none",
+            "markersize", min (get (h, "markersize"), 10),
+            "linestyle", "none",
+            "linewidth", min (get (h, "linewidth"), 5),
             "userdata", h, "parent", hlegend);
     endif
   endif
@@ -1217,22 +1247,22 @@
 %! plot (rand (2));
 %! title ('legend called with cellstr and string inputs for labels');
 %! h = legend ({'foo'}, 'bar');
-%! legend location northeastoutside
+%! legend (h, 'location', 'northeastoutside');
 %! set (h, 'fontsize', 20);
 
 %!demo
 %! clf;
 %! plot (rand (3));
-%! title ('legend() without inputs creates default labels');
-%! h = legend ();
+%! title ('legend("show") without inputs creates default labels');
+%! h = legend ('show');
 
 %!demo
 %! clf;
 %! x = 0:1;
 %! plot (x,x,';I am Blue;', x,2*x, x,3*x,';I am Red;');
-%! legend location northeastoutside
+%! h = legend ('location', 'northeastoutside');
 %! ## Placing legend inside should return axes to original size
-%! legend location northeast
+%! legend (h, 'location', 'northeast');
 %! title ('Blue and Red keys, with Green missing');
 
 %!demo
@@ -1368,9 +1398,9 @@
 %! rand_2x3_data2 = [0.44804, 0.84368, 0.23012; 0.72311, 0.58335, 0.90531];
 %! bar (rand_2x3_data2);
 %! ylim ([0 1.2]);
-%! title ('legend() works for bar graphs (hggroups)');
+%! title ('"left" option places text label west of colors');
 %! legend ('1st Bar', '2nd Bar', '3rd Bar');
-%! legend right;
+%! legend left;
 
 %!demo
 %! clf;
@@ -1596,7 +1626,7 @@
 %!   position = get (h, "position");
 %!   plot (rand (3));
 %!   legend ();
-%!   filename = sprintf ("%s.eps", tmpnam ());
+%!   filename = sprintf ("%s.eps", tempname ());
 %!   print (filename);
 %!   unlink (filename);
 %!   assert (get (h, "position"), position);
@@ -1605,3 +1635,20 @@
 %!   graphics_toolkit (toolkit);
 %! end_unwind_protect
 
+%!test
+%! ## bug #42035
+%! h = figure ("visible", "off");
+%! unwind_protect
+%!   hax1 = subplot (1,2,1);
+%!   plot (1:10);
+%!   hax2 = subplot (1,2,2);
+%!   plot (1:10);
+%!   hleg1 = legend (hax1, "foo");
+%!   assert (get (hleg1, "userdata").handle, hax1)
+%!   assert (gca (), hax2);
+%!   hleg2 = legend ("bar");
+%!   assert (get (hleg2, "userdata").handle, gca ())
+%! unwind_protect_cleanup
+%!   close (h);
+%! end_unwind_protect
+
--- a/scripts/plot/appearance/private/__axis_limits__.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/appearance/private/__axis_limits__.m	Mon Jan 12 09:17:35 2015 -0800
@@ -48,6 +48,11 @@
         if (arg(1) >= arg(2))
           error ("%s: axis limits must be increasing", fcn);
         else
+          autoscale = isinf (arg);
+          if (any (autoscale))
+            set (hax, fcnmode, "auto");
+            arg(autoscale) = get (hax, fcn)(autoscale);
+          endif
           set (hax, fcn, arg(:));
         endif
       endif
--- a/scripts/plot/appearance/specular.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/appearance/specular.m	Mon Jan 12 09:17:35 2015 -0800
@@ -19,15 +19,17 @@
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {} specular (@var{sx}, @var{sy}, @var{sz}, @var{lv}, @var{vv})
 ## @deftypefnx {Function File} {} specular (@var{sx}, @var{sy}, @var{sz}, @var{lv}, @var{vv}, @var{se})
-## Calculate specular reflection strength of a surface defined by the normal
-## vector elements @var{sx}, @var{sy}, @var{sz} using Phong's approximation.
+## Calculate the specular reflection strength of a surface defined by the
+## normal vector elements @var{sx}, @var{sy}, @var{sz} using Phong's
+## approximation.
 ##
-## The light source location and viewer location vectors can be specified using
-## parameter @var{lv} and @var{vv} respectively.  The location vectors can
+## The light source location and viewer location vectors are specified using
+## parameters @var{lv} and @var{vv} respectively.  The location vectors can
 ## given as 2-element vectors [azimuth, elevation] in degrees or as 3-element
 ## vectors [x, y, z].
 ##
-## An optional sixth argument describes the specular exponent (spread) @var{se}.
+## An optional sixth argument specifies the specular exponent (spread) @var{se}.
+## If not given, @var{se} defaults to 10.
 ## @seealso{diffuse, surfl}
 ## @end deftypefn
 
@@ -39,54 +41,52 @@
     print_usage ();
   endif
 
-  ## Checks for specular exponent (se).
-  if (nargin < 6)
-    se = 10;
-  else
-    if (!isnumeric (se) || numel (se) != 1 || se <= 0)
-      error ("specular: exponent must be positive scalar");
-    endif
+  ## Check normal vectors
+  if (! size_equal (sx, sy, sz))
+    error ("specular: SX, SY, and SZ must be the same size");
   endif
 
-  ## Checks for normal vector.
-  if (!size_equal (sx, sy, sz))
-    error ("specular: SX, SY, and SZ must have same size");
-  endif
-
-  ## Check for light vector (lv) argument.
-  if (length (lv) < 2 || length (lv) > 3)
+  ## Check light vector (lv) argument
+  if (! isvector (lv) || length (lv) < 2 || length (lv) > 3)
     error ("specular: light vector LV must be a 2- or 3-element vector");
   elseif (length (lv) == 2)
     [lv(1), lv(2), lv(3)] = sph2cart (lv(1) * pi/180, lv(2) * pi/180, 1.0);
   endif
 
-  ## Check for view vector (vv) argument.
-  if (length (vv) < 2 || length (lv) > 3)
+  ## Check view vector (vv) argument
+  if (! isvector (vv) || length (vv) < 2 || length (lv) > 3)
     error ("specular: view vector VV must be a 2- or 3-element vector");
   elseif (length (vv) == 2)
     [vv(1), vv(2), vv(3)] = sph2cart (vv(1) * pi / 180, vv(2) * pi / 180, 1.0);
   endif
 
-  ## Normalize view and light vector.
+  ## Check specular exponent (se) argument
+  if (nargin < 6)
+    se = 10;
+  elseif (! (isnumeric (se) && numel (se) == 1 && se > 0))
+    error ("specular: exponent SE must be a positive scalar");
+  endif
+
+  ## Normalize view and light vectors
   if (sum (abs (lv)) > 0)
-    lv  /= norm (lv);
+    lv /= norm (lv);
   endif
   if (sum (abs (vv)) > 0)
-    vv  /= norm (vv);
+    vv /= norm (vv);
   endif
 
-  ## Calculate normal vector lengths and dot-products.
+  ## Calculate normal vector lengths and dot-products
   ns = sqrt (sx.^2 + sy.^2 + sz.^2);
   l_dot_n = (sx * lv(1) + sy * lv(2) + sz * lv(3)) ./ ns;
   v_dot_n = (sx * vv(1) + sy * vv(2) + sz * vv(3)) ./ ns;
 
-  ## Calculate specular reflection using Phong's approximation.
+  ## Calculate specular reflection using Phong's approximation
   retval = 2 * l_dot_n .* v_dot_n - dot (lv, vv);
 
-  ## Set zero if light is on the other side.
+  ## Set reflectance to zero if light is on the other side
   retval(l_dot_n < 0) = 0;
 
-  ## Allow postive values only.
+  ## Allow postive values only
   retval(retval < 0) = 0;
   retval = retval .^ se;
 
--- a/scripts/plot/appearance/text.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/appearance/text.m	Mon Jan 12 09:17:35 2015 -0800
@@ -129,6 +129,8 @@
 
   if (isempty (hax))
     hax = gca ();
+  else
+    hax = hax(1);
   endif
 
   ## Position argument may alse be in PROP/VAL pair
--- a/scripts/plot/draw/area.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/draw/area.m	Mon Jan 12 09:17:35 2015 -0800
@@ -49,7 +49,7 @@
 ## @example
 ## @group
 ## t = linspace (0, 2*pi, 100)';
-## y = [sin(t).^2, cos(t).^2)];
+## y = [sin(t).^2, cos(t).^2];
 ## area (t, y);
 ## legend ("sin^2", "cos^2", "location", "NorthEastOutside");
 ## @end group
--- a/scripts/plot/draw/colorbar.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/draw/colorbar.m	Mon Jan 12 09:17:35 2015 -0800
@@ -207,11 +207,11 @@
       if (mirror)
         set (cax, "xtick", [], "xdir", "normal", "ydir", "normal",
                   "ylim", cext, "ylimmode", "manual",
-                  "yaxislocation", "right", args{:});
+                  "yaxislocation", "right", "layer", "top", args{:});
       else
         set (cax, "xtick", [], "xdir", "normal", "ydir", "normal",
                   "ylim", cext, "ylimmode", "manual",
-                  "yaxislocation", "left", args{:});
+                  "yaxislocation", "left", "layer", "top", args{:});
       endif
     else
       hi = image (cax, "xdata", [cmin, cmax], "ydata", [0,1],
@@ -219,11 +219,11 @@
       if (mirror)
         set (cax, "ytick", [], "xdir", "normal", "ydir", "normal",
                   "xlim", cext, "xlimmode", "manual",
-                  "xaxislocation", "top", args{:});
+                  "xaxislocation", "top", "layer", "top", args{:});
       else
         set (cax, "ytick", [], "xdir", "normal", "ydir", "normal",
                   "xlim", cext, "xlimmode", "manual",
-                  "xaxislocation", "bottom", args{:});
+                  "xaxislocation", "bottom", "layer", "top", args{:});
       endif
     endif
 
@@ -310,24 +310,6 @@
       set (hi, "xdata", [cmin, cmax]);
       set (hiax, "xlim", cext);
     endif
-
-    ## FIXME: Setting xlim or ylim from within a listener callback
-    ##        causes the axis to change size rather than change limits.
-    ##        Workaround it by jiggling the position property which forces
-    ##        a redraw of the axis object.
-    ##
-    ## Debug Example:
-    ## Uncomment the line below.
-    ##   keyboard;
-    ## Now run the the following code.
-    ##   clf; colorbar (); contour (peaks ())
-    ## Once the keyboard command has been hit in the debugger try
-    ##   set (hiax, "ylim", [0 0.5]) 
-    pos = get (hiax, "position");
-    pos(1) += eps;
-    set (hiax, "position", pos);
-    pos(1) -= eps;
-    set (hiax, "position", pos);
   endif
 endfunction
 
--- a/scripts/plot/draw/errorbar.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/draw/errorbar.m	Mon Jan 12 09:17:35 2015 -0800
@@ -213,7 +213,7 @@
 %! y1 = sin (x);
 %! y2 = cos (x);
 %! errorbar (x, y1, err, '~', x, y2, err, '>');
-%! legend ("Y errbar", "X errbar");
+%! legend ('Y errbar', 'X errbar');
 %! title ('errorbar() with 2 datasets');
 
 
@@ -224,7 +224,7 @@
 %! y1 = sin (x);
 %! y2 = cos (x);
 %! errorbar (x, y1, err, err, '#r', x, y2, err, err, '#~');
-%! legend ("X errbox", "Y errbox");
+%! legend ('X errbox', 'Y errbox');
 %! title ('errorbar() with error boxes');
 
 %!demo
@@ -235,7 +235,7 @@
 %! y2 = cos (x);
 %! errorbar (x, y1, err, err, err, err, '~>', ...
 %!           x, y2, err, err, err, err, '#~>-*');
-%! legend ("X-Y errbars", "X-Y errboxes");
+%! legend ('X-Y errbars', 'X-Y errboxes');
 %! title ('errorbar() with X-Y errorbars and error boxes');
 
 ## Invisible figure used for tests
--- a/scripts/plot/draw/fill.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/draw/fill.m	Mon Jan 12 09:17:35 2015 -0800
@@ -92,17 +92,28 @@
       set (hax, "nextplot", "add");
 
       for i = 1 : length (iargs)
+        x = varargin{iargs(i)};
+        y = varargin{iargs(i) + 1};
         cdata = varargin{iargs(i) + 2};
+
+        if (! size_equal (x,y))
+          if (iscolumn (y) && rows (y) == rows (x))
+            y = repmat (y, [1, columns(x)]);
+          elseif (iscolumn (x) && rows (x) == rows (y))
+            x = repmat (x, [1, columns(y)]);
+          else
+            error ("fill: X annd Y must have same number of rows");
+          endif
+        endif
         ## For Matlab compatibility, replicate cdata to match size of data
-        if (iscolumn (cdata))
-          sz = size (varargin{iargs(i)});
+        if (iscolumn (cdata) && ! ischar (cdata))
+          sz = size (x);
           if (all (sz > 1))
             cdata = repmat (cdata, [1, sz(2)]);
           endif
         endif
 
-        [htmp, fail] = __patch__ (hax, varargin{iargs(i)+(0:1)}, cdata,
-                                       opts{:});
+        [htmp, fail] = __patch__ (hax, x, y, cdata, opts{:});
         if (fail)
           print_usage ();
         endif
@@ -160,4 +171,30 @@
 %! x2 = sin (t2) + 0.8;
 %! y2 = cos (t2);
 %! h = fill (x1,y1,'r', x2,y2,'g');
+%! title ({'fill() function'; 'cdata specified with string'});
 
+%!demo
+%! clf;
+%! t1 = (1/16:1/8:1) * 2*pi;
+%! t2 = ((1/16:1/8:1) + 1/32) * 2*pi;
+%! x1 = sin (t1) - 0.8;
+%! y1 = cos (t1);
+%! x2 = sin (t2) + 0.8;
+%! y2 = cos (t2);
+%! h = fill (x1,y1,1, x2,y2,2);
+%! title ({'fill() function'; 'cdata = row vector produces FaceColor = "flat"'});
+
+%!demo
+%! clf;
+%! x = [0 0
+%!      1 0.5
+%!      1 0.5
+%!      0 0];
+%! y = [0 0
+%!      0 0
+%!      1 0.5
+%!      1 0.5];
+%! c = [1 2 3 4]';
+%! fill (x, y, c);
+%! title ({'fill() function'; 'cdata = column vector produces FaceColor = "interp"'});
+
--- a/scripts/plot/draw/line.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/draw/line.m	Mon Jan 12 09:17:35 2015 -0800
@@ -49,6 +49,8 @@
 
   if (isempty (hax))
     hax = gca ();
+  else
+    hax = hax(1);
   endif
 
   htmp = __line__ (hax, varargin{:});
@@ -62,6 +64,16 @@
 
 %!demo
 %! clf
+%! line ([0 1], [0.8 0.8], 'linestyle', '-', 'color', 'b');
+%! line ([0 1], [0.6 0.6], 'linestyle', '--', 'color', 'g');
+%! line ([0 1], [0.4 0.4], 'linestyle', ':', 'color', 'r');
+%! line ([0 1], [0.2 0.2], 'linestyle', '-.', 'color', 'k');
+%! ylim ([0 1]);
+%! title ('line() with various linestyles');
+%! legend ('"-"', '"--"', '":"', '"-."', 'location', 'eastoutside');
+
+%!demo
+%! clf
 %! x = 0:0.3:10;
 %! y1 = cos (x);
 %! y2 = sin (x);
--- a/scripts/plot/draw/mesh.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/draw/mesh.m	Mon Jan 12 09:17:35 2015 -0800
@@ -70,10 +70,15 @@
   unwind_protect
     hax = newplot (hax);
 
-    htmp = surface (varargin{:});
+    mesh_props = {"facecolor", "w", "edgecolor", "flat"};
+    chararg = find (cellfun ("isclass", varargin, "char"), 1);
+    if (isempty (chararg))
+      htmp = surface (varargin{:}, mesh_props{:});
+    else
+      htmp = surface (varargin{1:chararg-1}, mesh_props{:},
+                      varargin{chararg:end});
+    endif
 
-    set (htmp, "facecolor", "w");
-    set (htmp, "edgecolor", "flat");
     if (! ishold ())
       set (hax, "view", [-37.5, 30],
                 "xgrid", "on", "ygrid", "on", "zgrid", "on");
@@ -121,7 +126,21 @@
 %! ylabel 'Y-axis';
 %! zlabel 'log scale';
 %! title ({'mesh() with color proportional to Z^2', 'Z-axis is log scale'});
-%! if (strcmp (get (gcf, '__graphics_toolkit__'), 'gnuplot'))
-%!   title ({'Gnuplot: mesh color is wrong', 'This is a Gnuplot bug'});
-%! endif
+%! try
+%!   if (strcmp (get (gcf, '__graphics_toolkit__'), 'gnuplot'))
+%!     title ({'Gnuplot: mesh color is wrong', 'This is a Gnuplot bug'});
+%!   endif
+%! catch
+%! end
 
+%!demo
+%! clf;
+%! x = logspace (0,1,11);
+%! z = x'*x;
+%! mesh (x, x, z, 'facecolor', 'none', 'edgecolor', 'c');
+%! xlabel 'X-axis';
+%! ylabel 'Y-axis';
+%! zlabel 'Z-axis';
+%! title ({'mesh() default properties overriden', ...
+%!         'transparent mesh with cyan color'});
+
--- a/scripts/plot/draw/meshc.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/draw/meshc.m	Mon Jan 12 09:17:35 2015 -0800
@@ -68,13 +68,18 @@
   unwind_protect
     hax = newplot (hax);
 
-    htmp = surface (varargin{:});
+    ## FIXME: gnuplot does not support a filled surface and a
+    ##        non-filled contour.  3D filled patches are also not supported.
+    ##        Thus, the facecolor will be transparent for the gnuplot backend.
+    mesh_props = {"facecolor", "w", "edgecolor", "flat"};
+    chararg = find (cellfun ("isclass", varargin, "char"), 1);
+    if (isempty (chararg))
+      htmp = surface (varargin{:}, mesh_props{:});
+    else
+      htmp = surface (varargin{1:chararg-1}, mesh_props{:},
+                      varargin{chararg:end});
+    endif
 
-    ## FIXME - gnuplot does not support a filled surface and a
-    ## non-filled contour.  3D filled patches are also not supported.
-    ## Thus, the facecolor will be transparent for the gnuplot backend.
-    set (htmp, "facecolor", "w");
-    set (htmp, "edgecolor", "flat");
     if (! ishold ())
       set (hax, "view", [-37.5, 30],
                 "xgrid", "on", "ygrid", "on", "zgrid", "on",
--- a/scripts/plot/draw/meshz.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/draw/meshz.m	Mon Jan 12 09:17:35 2015 -0800
@@ -30,7 +30,7 @@
 ## over a 2-D rectangular region in the x-y plane.  @var{z} determines the
 ## height above the plane of each vertex.  If only a single @var{z} matrix is
 ## given, then it is plotted over the meshgrid
-## @code{@var{x} = 1:columns (@var{z}), @var{y} = 1:rows (@var{z})}.
+## @code{@var{x} = 0:columns (@var{z}) - 1, @var{y} = 0:rows (@var{z}) - 1}.
 ## Thus, columns of @var{z} correspond to different @var{x} values and rows
 ## of @var{z} correspond to different @var{y} values.
 ##
@@ -64,52 +64,65 @@
   ## Find where property/value pairs start
   charidx = find (cellfun ("isclass", varargin, "char"), 1);
 
-  have_c = false;
   if (isempty (charidx))
-    if (nargin == 2 || nargin == 4) 
-      have_c = true;
-      charidx = nargin;   # bundle C matrix back into varargin 
-    else
-      charidx = nargin + 1;
-    endif
+    charidx = nargin + 1;
   endif
 
-  if (charidx == 2)
+  if (nargin == 1)
+    z = varargin{1};
+    [m, n] = size (z);
+    x = 0:(n-1);
+    y = (0:(m-1)).';
+    c = z;
+  elseif (nargin == 2)
     z = varargin{1};
     [m, n] = size (z);
-    x = 1:n;
-    y = (1:m).';
+    x = 0:(n-1);
+    y = (0:(m-1)).';
+    c = varargin{2};
+  elseif (charidx == 4)
+    x = varargin{1};
+    y = varargin{2};
+    z = varargin{3};
+    c = z;
   else
     x = varargin{1};
     y = varargin{2};
     z = varargin{3};
+    c = varargin{4};
   endif
 
+  ## Create a border of one rectangle (2 points) as the curtain around
+  ## the data and draw it with the mean (max + min / 2) color of the data.
+
   if (isvector (x) && isvector (y))
-    x = [x(1), x(:).', x(end)];
-    y = [y(1); y(:); y(end)];
+    x = [x(1), x(1), x(:).', x(end), x(end)];
+    y = [y(1); y(1); y(:); y(end); y(end)];
   else
-    x = [x(1,1), x(1,:), x(1,end);
-         x(:,1), x, x(:,end);
-         x(end,1), x(end,:), x(end,end)];
-    y = [y(1,1), y(1,:), y(1,end);
-         y(:,1), y, y(:,end);
-         y(end,1), y(end,:), y(end,end)];
+    x = [x(1,1), x(1,1), x(1,:), x(1,end), x(1,end);
+         x(1,1), x(1,1), x(1,:), x(1,end), x(1,end);
+         x(:,1), x(:,1), x, x(:,end), x(:,end);
+         x(end,1), x(end,1), x(end,:), x(end,end), x(end,end);
+         x(end,1), x(end,1), x(end,:), x(end,end), x(end,end) ];
+    y = [y(1,1), y(1,1), y(1,:), y(1,end), y(1,end);
+         y(1,1), y(1,1), y(1,:), y(1,end), y(1,end);
+         y(:,1), y(:,1), y, y(:,end), y(:,end);
+         y(end,1), y(end,1), y(end,:), y(end,end), y(end,end);
+         y(end,1), y(end,1), y(end,:), y(end,end), y(end,end) ];
   endif
 
   zref = min (z(isfinite (z)));
-  z = [zref .* ones(1, columns(z) + 2);
-       zref .* ones(rows(z), 1), z, zref .* ones(rows(z), 1);
-       zref .* ones(1, columns(z) + 2)];
+  z = [zref .* ones(1, columns(z) + 4);
+       zref .* ones(1, 2), z(1,:), zref .* ones(1, 2);
+       zref .* ones(rows(z), 1), z(:,1),z, z(:,end), zref .* ones(rows(z), 1);
+       zref .* ones(1, 2), z(end,:), zref .* ones(1, 2);
+       zref .* ones(1, columns(z) + 4)];
 
-  if (have_c)
-    c = varargin{charidx};
-    cref = min (c(isfinite (c)));
-    c = [cref .* ones(1, columns(c) + 2);
-         cref .* ones(rows(c), 1), c, cref .* ones(rows(c), 1);
-         cref .* ones(1, columns(c) + 2)];
-    varargin(charidx) = c;
-  endif
+  cdat = c(isfinite (c(:)));
+  cref = (min (cdat) + max (cdat)) / 2;
+  c = [cref .* ones(2, columns(c) + 4);
+       cref .* ones(rows(c), 2), c, cref .* ones(rows(c), 2);
+       cref .* ones(2, columns(c) + 4)];
     
   oldfig = [];
   if (! isempty (hax))
@@ -117,7 +130,7 @@
   endif
   unwind_protect
     hax = newplot (hax);
-    htmp = mesh (x, y, z, varargin{charidx:end});
+    htmp = mesh (x, y, z, c, varargin{charidx:end});
   unwind_protect_cleanup
     if (! isempty (oldfig))
       set (0, "currentfigure", oldfig);
--- a/scripts/plot/draw/pareto.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/draw/pareto.m	Mon Jan 12 09:17:35 2015 -0800
@@ -104,7 +104,9 @@
   axis (ax(1), [1 - 0.6, idx95 + 0.6, 0, maxcdf]);
   axis (ax(2), [1 - 0.6, idx95 + 0.6, 0, 100]);
   set (ax(2), "ytick", [0, 20, 40, 60, 80, 100],
-              "yticklabel", {"0%", "20%", "40%", "60%", "80%", "100%"});
+              "yticklabel", {"0%", "20%", "40%", "60%", "80%", "100%"},
+              "ycolor", get (ax(1), "ycolor"));
+  set (hline, "color", get (ax(1), "colororder")(1,:));
   set (ax(1:2), "xtick", 1:idx95, "xticklabel", x(1:idx95));
 
   if (nargout > 0)
--- a/scripts/plot/draw/patch.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/draw/patch.m	Mon Jan 12 09:17:35 2015 -0800
@@ -80,6 +80,8 @@
   
   if (isempty (hax))
     hax = gca ();
+  else
+    hax = hax(1);
   endif
   
   [htmp, failed] = __patch__ (hax, varargin{:});
@@ -88,6 +90,15 @@
     print_usage ();
   endif
 
+  ## FIXME: This is a hack to get 'layer' command to work for 2D patches
+  ##        Alternative is much more complicated surgery in graphics.cc.
+  ##        of get_children_limits() for 'z' axis and 'patch' object type.
+  if (! ishold ())
+    if (isempty (get (htmp, "zdata")))
+      set (hax, "zlim", [-1 1]);
+    endif
+  endif
+
   if (nargout > 0)
     h = htmp;
   endif
@@ -141,7 +152,8 @@
 %! y2 = cos (t2);
 %! vert = [x1, y1; x2, y2];
 %! fac = [1:8,NaN(1,8);9:24];
-%! patch ('Faces',fac, 'Vertices',vert, 'FaceVertexCData',[0, 1, 0; 0, 0, 1]);
+%! patch ('Faces',fac, 'Vertices',vert, ...
+%!        'FaceVertexCData',[0, 1, 0; 0, 0, 1], 'FaceColor', 'flat');
 
 %!demo
 %! %% Property change on multiple patches
@@ -223,7 +235,7 @@
 %! colormap (jet (64));
 %! x = [ 0 0; 1 1; 1 0 ];
 %! y = [ 0 0; 0 1; 1 1 ];
-%! p = patch (x, y, 'facecolor', 'b');
+%! p = patch (x, y, 'b');
 %! set (p, 'cdatamapping', 'direct', 'facecolor', 'flat', 'cdata', [1 32]);
 %! title ('Direct mapping of colors: Light-Green UL and Blue LR triangles');
 
--- a/scripts/plot/draw/peaks.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/draw/peaks.m	Mon Jan 12 09:17:35 2015 -0800
@@ -27,7 +27,7 @@
 ## The function has the form
 ##
 ## @tex
-## $$f(x,y) = 3 (1 - x) ^ 2 e ^ {\left(-x^2 - (y+1)^2\right)} - 10 \left({x \over 5} - x^3 - y^5)\right) - {1 \over 3} e^{\left(-(x+1)^2 - y^2\right)}$$
+## $$f(x,y) = 3 (1 - x) ^ 2 e ^ {\left(-x^2 - (y+1)^2\right)} - 10 \left({x \over 5} - x^3 - y^5\right) - {1 \over 3} e^{\left(-(x+1)^2 - y^2\right)}$$
 ## @end tex
 ## @ifnottex
 ## @verbatim
@@ -83,6 +83,9 @@
 
   if (nargout == 0)
     surf (x, y, Z);
+    Z_max = max (Z(:));
+    Z_min = min (Z(:));
+    axis ([-3, 3, -3, 3, Z_min, Z_max]);
   elseif (nargout == 1)
     X_out = Z;
   else
--- a/scripts/plot/draw/pie.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/draw/pie.m	Mon Jan 12 09:17:35 2015 -0800
@@ -30,7 +30,7 @@
 ## @code{pct = @var{x}(i) / sum (@var{x})}. 
 ##
 ## The optional input @var{explode} is a vector of the same length as @var{x}
-## that, if non-zero, "explodes" the slice from the pie chart.
+## that, if nonzero, "explodes" the slice from the pie chart.
 ##
 ## The optional input @var{labels} is a cell array of strings of the same
 ## length as @var{x} specifying the label for each slice.
--- a/scripts/plot/draw/pie3.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/draw/pie3.m	Mon Jan 12 09:17:35 2015 -0800
@@ -31,7 +31,7 @@
 ## @code{pct = @var{x}(i) / sum (@var{x})}. 
 ##
 ## The optional input @var{explode} is a vector of the same length as @var{x}
-## that, if non-zero, "explodes" the slice from the pie chart.
+## that, if nonzero, "explodes" the slice from the pie chart.
 ##
 ## The optional input @var{labels} is a cell array of strings of the same
 ## length as @var{x} specifying the label for each slice.
--- a/scripts/plot/draw/plot3.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/draw/plot3.m	Mon Jan 12 09:17:35 2015 -0800
@@ -377,12 +377,14 @@
 %!demo
 %! clf;
 %! z = [0:0.05:5];
-%! plot3 (cos (2*pi*z), sin (2*pi*z), z, ';helix;');
+%! plot3 (cos (2*pi*z), sin (2*pi*z), z)
+%! legend ('helix');
 %! title ('plot3() of a helix');
 
 %!demo
 %! clf;
 %! z = [0:0.05:5];
-%! plot3 (z, exp (2i*pi*z), ';complex sinusoid;');
+%! plot3 (z, exp (2i*pi*z));
+%! legend ('complex sinusoid');
 %! title ('plot3() with complex input');
 
--- a/scripts/plot/draw/plotyy.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/draw/plotyy.m	Mon Jan 12 09:17:35 2015 -0800
@@ -22,7 +22,7 @@
 ## @deftypefnx {Function File} {} plotyy (@dots{}, @var{fun1}, @var{fun2})
 ## @deftypefnx {Function File} {} plotyy (@var{hax}, @dots{})
 ## @deftypefnx {Function File} {[@var{ax}, @var{h1}, @var{h2}] =} plotyy (@dots{})
-## Plot two sets of data with independent y-axes.
+## Plot two sets of data with independent y-axes and a common x-axis.
 ##
 ## The arguments @var{x1} and @var{y1} define the arguments for the first plot
 ## and @var{x1} and @var{y2} for the second.
@@ -40,7 +40,7 @@
 ## the principal axis in which to plot the @var{x1} and @var{y1} data.
 ##
 ## The return value @var{ax} is a vector with the axis handles of the two
-## y axes.  @var{h1} and @var{h2} are handles to the objects generated by the
+## y-axes.  @var{h1} and @var{h2} are handles to the objects generated by the
 ## plot commands.
 ##
 ## @example
@@ -57,113 +57,66 @@
 ## @seealso{plot}
 ## @end deftypefn
 
-function [Ax, H1, H2] = plotyy (varargin)
+function [ax, h1, h2] = plotyy (varargin)
 
-  ## Don't use __plt_get_axis_arg__ here as ax is a two vector for plotyy
-  if (nargin > 1 && length (varargin{1}) == 2 && ishandle (varargin{1}(1))
-      && ishandle (varargin{1}(2))
-      && all (floor (varargin{1}) != varargin{1}))
-    obj1 = get (varargin{1}(1));
-    obj2 = get (varargin{1}(2));
-    if (strcmp (obj1.type, "axes") || strcmp (obj2.type, "axes"))
-      ax = [obj1, obj2];
-      varargin(1) = [];
-      if (isempty (varargin))
-        varargin = {};
-      endif
-    else
-      error ("plotyy: expecting first argument to be axes handle");
-    endif
-    oldh = gca ();
-  else
-    f = get (0, "currentfigure");
-    if (isempty (f))
-      f = figure ();
-    endif
-    ca = get (f, "currentaxes");
-    if (isempty (ca))
-      ax = [];
-    elseif (ishandle (ca) && isprop (ca, "__plotyy_axes__"))
-      ax = get (ca, "__plotyy_axes__");
-    else
-      ax = ca;
-    endif
-    if (length (ax) > 2)
-      for i = 3 : length (ax)
-        delete (ax (i));
-      endfor
-      ax = ax(1:2);
-    elseif (length (ax) == 1)
-      ax(2) = axes ();
-      set (ax(2), "nextplot", get (ax(1), "nextplot"));
-    elseif (isempty (ax))
-      ax(1) = axes ();
-      ax(2) = axes ();
-      ca = ax(2);
-    endif
-    if (nargin < 2)
-      varargin = {};
-    endif
-    oldh = ca;
-  endif
+  [hax, varargin] = __plt_get_axis_arg__ ("plotyy", varargin{:});
 
-  if (nargin < 4)
+  nargin = numel (varargin);
+  if (nargin < 4 || nargin > 6)
     print_usage ();
   endif
 
+  oldfig = [];
+  if (! isempty (hax))
+    oldfig = get (0, "currentfigure");
+  endif
   unwind_protect
-    [ax, h1, h2] = __plotyy__ (ax, varargin{:});
+    hax = newplot (hax);
+
+    ## FIXME: Second conditional test shouldn't be required.
+    ##        'cla reset' needs to delete user properties like __plotyy_axes__.
+    if (isprop (hax, "__plotyy_axes__")
+        && isaxes (get (hax, "__plotyy_axes__")) == [true true])
+      hax = get (hax, "__plotyy_axes__");
+    else
+      hax(2) = axes ("nextplot", get (hax(1), "nextplot"));
+    endif
+
+    [axtmp, h1tmp, h2tmp] = __plotyy__ (hax, varargin{:});
+
+    set (gcf, "currentaxes", hax(1));
+     
   unwind_protect_cleanup
-    ## Only change back to the old axis if we didn't delete it
-    if (isaxes (oldh))
-      axes (oldh);
+    if (! isempty (oldfig))
+      set (0, "currentfigure", oldfig);
     endif
   end_unwind_protect
 
   if (nargout > 0)
-    Ax = ax;
-    H1 = h1;
-    H2 = h2;
+    ax = axtmp;
+    h1 = h1tmp;
+    h2 = h2tmp;
   endif
 
 endfunction
 
-function [ax, h1, h2] = __plotyy__ (ax, x1, y1, x2, y2, varargin)
-  if (nargin > 5)
-    fun1 = varargin{1};
-  else
-    fun1 = @plot;
-  endif
-  if (nargin > 6)
-    fun2 = varargin{2};
-  else
+function [ax, h1, h2] = __plotyy__ (ax, x1, y1, x2, y2, fun1 = @plot, fun2)
+
+  if (nargin < 7)
     fun2 = fun1;
   endif
 
   xlim = [min([x1(:); x2(:)]), max([x1(:); x2(:)])];
 
-  if (isaxes (ax(1)))
-    axes (ax(1));
-  else
-    ax(1) = axes ();
-  endif
-  newplot ();
+  axes (ax(1));
+
   h1 = feval (fun1, x1, y1);
 
-  set (ax(1), "ycolor", getcolor (h1(1)));
-  set (ax(1), "xlim", xlim);
-  set (ax(1), "color", "none");
-
-  cf = gcf ();
-  set (cf, "nextplot", "add");
+  set (ax(1), "color", "none", "ycolor", getcolor (h1(1)), "xlim", xlim);
 
-  if (isaxes (ax(2)))
-    axes (ax(2));
-  else
-    ax(2) = axes ();
-    set (ax(2), "nextplot", get (ax(1), "nextplot"));
-  endif
-  newplot ();
+  set (gcf (), "nextplot", "add");
+
+  axes (ax(2));
 
   colors = get (ax(1), "colororder");
   set (ax(2), "colororder", [colors(2:end,:); colors(1,:)]);
@@ -174,35 +127,38 @@
     set (ax, "activepositionproperty", "position");
   endif
 
-  ## Kluge, until __plt_get_axis_arg__ and newplot are reworked. 
-  set (ax(2), "nextplot", "replacechildren");
+  ## Don't replace axis which has colororder property already modified
+  if (strcmp (get (ax(1), "nextplot"), "replace"))
+    set (ax(2), "nextplot", "replacechildren");
+  endif
   h2 = feval (fun2, ax(2), x2, y2);
-  set (ax(2), "yaxislocation", "right");
-  set (ax(2), "ycolor", getcolor (h2(1)));
+
+  set (ax(2), "yaxislocation", "right", "color", "none",
+              "ycolor", getcolor (h2(1)), "box", "off", "xlim", xlim);
 
   if (strcmp (get(ax(1), "activepositionproperty"), "position"))
     set (ax(2), "position", get (ax(1), "position"));
   else
-    set (ax(2), "outerposition", get (ax(1), "outerposition"));
-    set (ax(2), "looseinset", get (ax(1), "looseinset"));
+    set (ax(2), {"outerposition", "looseinset"},
+                get (ax(1), {"outerposition", "looseinset"}));
   endif
 
-  set (ax(2), "xlim", xlim);
-  set (ax(2), "color", "none");
-  set (ax(2), "box", "off");
+  ## Restore nextplot value by copying value from axis #1
+  set (ax(2), "nextplot", get (ax(1), "nextplot"));
 
   ## Add invisible text objects that when destroyed,
   ## also remove the other axis
   t1 = text (0, 0, "", "parent", ax(1), "tag", "plotyy",
-             "handlevisibility", "off", "visible", "off",
+             "visible", "off", "handlevisibility", "off",
              "xliminclude", "off", "yliminclude", "off");
   t2 = text (0, 0, "", "parent", ax(2), "tag", "plotyy",
-             "handlevisibility", "off", "visible", "off",
+             "visible", "off", "handlevisibility", "off",
              "xliminclude", "off", "yliminclude", "off");
 
   set (t1, "deletefcn", {@deleteplotyy, ax(2), t2});
   set (t2, "deletefcn", {@deleteplotyy, ax(1), t1});
 
+  ## Add cross-listeners so a change in one axes' attributes updates the other.
   addlistener (ax(1), "position", {@update_position, ax(2)});
   addlistener (ax(2), "position", {@update_position, ax(1)});
   addlistener (ax(1), "outerposition", {@update_position, ax(2)});
@@ -235,6 +191,80 @@
   endif
 endfunction
 
+function deleteplotyy (h, ~, ax2, t2)
+  if (isaxes (ax2)
+      && (isempty (gcbf ()) || strcmp (get (gcbf (), "beingdeleted"), "off"))
+      && strcmp (get (ax2, "beingdeleted"), "off"))
+    set (t2, "deletefcn", []);
+    delete (ax2);
+  endif
+endfunction
+
+function update_nextplot (h, ~, ax2)
+  persistent recursion = false;
+  if (! recursion)
+    unwind_protect
+      recursion = true;
+      set (ax2, "nextplot", get (h, "nextplot"));
+    unwind_protect_cleanup
+      recursion = false;
+    end_unwind_protect
+  endif
+endfunction
+
+function update_position (h, ~, ax2)
+  persistent recursion = false;
+
+  ## Don't allow recursion
+  if (! recursion)
+    unwind_protect
+      recursion = true;
+      view = get (h, "view");
+      oldview = get (ax2, "view");
+      plotboxaspectratio = get (h, "plotboxaspectratio");
+      oldplotboxaspectratio = get (ax2, "plotboxaspectratio");
+      plotboxaspectratiomode = get (h, "plotboxaspectratiomode");
+      oldplotboxaspectratiomode = get (ax2, "plotboxaspectratiomode");
+
+      if (strcmp (get (h, "activepositionproperty"), "position"))
+        position = get (h, "position");
+        oldposition = get (ax2, "position");
+        if (! (isequal (position, oldposition) && isequal (view, oldview)))
+          set (ax2, "position", position, "view", view);
+        endif
+      else
+        outerposition = get (h, "outerposition");
+        oldouterposition = get (ax2, "outerposition");
+        if (! (isequal (outerposition, oldouterposition)
+               && isequal (view, oldview)))
+          set (ax2, "outerposition", outerposition, "view", view);
+        endif
+      endif
+
+      if (! (isequal (plotboxaspectratio, oldplotboxaspectratio)
+             && isequal (plotboxaspectratiomode, oldplotboxaspectratiomode)))
+        set (ax2, "plotboxaspectratio", plotboxaspectratio,
+                  "plotboxaspectratiomode", plotboxaspectratiomode);
+      endif
+    unwind_protect_cleanup
+      recursion = false;
+    end_unwind_protect
+  endif
+endfunction
+
+function color = getcolor (ax)
+  obj = get (ax);
+  if (isfield (obj, "color"))
+    color = obj.color;
+  elseif (isfield (obj, "facecolor") && ! ischar (obj.facecolor))
+    color = obj.facecolor;
+  elseif (isfield (obj, "edgecolor") && ! ischar (obj.edgecolor))
+    color = obj.edgecolor;
+  else
+    color = [0, 0, 0];
+  endif
+endfunction
+
 
 %!demo
 %! clf;
@@ -245,12 +275,11 @@
 %! xlabel ('X');
 %! ylabel (ax(1), 'Axis 1');
 %! ylabel (ax(2), 'Axis 2');
-%! axes (ax(1));
 %! text (0.5, 0.5, 'Left Axis', ...
-%!       'color', [0 0 1], 'horizontalalignment', 'center');
-%! axes (ax(2));
+%!       'color', [0 0 1], 'horizontalalignment', 'center', 'parent', ax(1));
 %! text (4.5, 80, 'Right Axis', ...
-%!       'color', [0 0.5 0], 'horizontalalignment', 'center');
+%!       'color', [0 0.5 0], 'horizontalalignment', 'center', 'parent', ax(2));
+%! title ({'plotyy() example'; 'Left axis uses @plot, Right axis uses @semilogy'});
 
 %!demo
 %! clf;
@@ -267,14 +296,6 @@
 %! axis square;
 
 %!demo
-%! clf;
-%! x = linspace (-1, 1, 201);
-%! hax = plotyy (x, sin (pi*x), x, cos (pi*x));
-%! ylabel (hax(1), 'Blue on the Left');
-%! ylabel (hax(2), 'Green on the Right');
-%! xlabel ('xlabel');
-
-%!demo
 %! clf
 %! hold on
 %! t = (0:0.1:9);
@@ -284,81 +305,7 @@
 %! [~, h3, h4] = plotyy (t+1, x, t+1, y);
 %! set ([h3, h4], 'linestyle', '--');
 %! xlabel (hax(1), 'xlabel');
-%! title (hax(2), 'title');
+%! title (hax(2), 'Two plotyy graphs on same figure using "hold on"');
 %! ylabel (hax(1), 'Left axis is Blue');
 %! ylabel (hax(2), 'Right axis is Green');
 
-function deleteplotyy (h, d, ax2, t2)
-  if (isaxes (ax2)
-      && (isempty (gcbf ()) || strcmp (get (gcbf (), "beingdeleted"),"off"))
-      && strcmp (get (ax2, "beingdeleted"), "off"))
-    set (t2, "deletefcn", []);
-    delete (ax2);
-  endif
-endfunction
-
-function update_nextplot (h, d, ax2)
-  persistent recursion = false;
-  prop = "nextplot";
-  if (! recursion)
-    unwind_protect
-      recursion = true;
-      set (ax2, prop, get (h, prop));
-    unwind_protect_cleanup
-      recursion = false;
-    end_unwind_protect
-  endif
-endfunction
-
-function update_position (h, d, ax2)
-  persistent recursion = false;
-
-  ## Don't allow recursion
-  if (! recursion)
-    unwind_protect
-      recursion = true;
-      view = get (h, "view");
-      oldview = get (ax2, "view");
-      plotboxaspectratio = get (h, "plotboxaspectratio");
-      oldplotboxaspectratio = get (ax2, "plotboxaspectratio");
-      plotboxaspectratiomode = get (h, "plotboxaspectratiomode");
-      oldplotboxaspectratiomode = get (ax2, "plotboxaspectratiomode");
-
-      if (strcmp (get(h, "activepositionproperty"), "position"))
-        position = get (h, "position");
-        oldposition = get (ax2, "position");
-        if (! (isequal (position, oldposition) && isequal (view, oldview)))
-          set (ax2, "position", position, "view", view);
-        endif
-      else
-        outerposition = get (h, "outerposition");
-        oldouterposition = get (ax2, "outerposition");
-        if (! (isequal (outerposition, oldouterposition) && isequal (view, oldview)))
-          set (ax2, "outerposition", outerposition, "view", view);
-        endif
-      endif
-
-      if (! (isequal (plotboxaspectratio, oldplotboxaspectratio)
-             && isequal (plotboxaspectratiomode, oldplotboxaspectratiomode)))
-        set (ax2, "plotboxaspectratio", plotboxaspectratio);
-        set (ax2, "plotboxaspectratiomode", plotboxaspectratiomode);
-      endif
-    unwind_protect_cleanup
-      recursion = false;
-    end_unwind_protect
-  endif
-endfunction
-
-function color = getcolor (ax)
-  obj = get (ax);
-  if (isfield (obj, "color"))
-    color = obj.color;
-  elseif (isfield (obj, "facecolor") && ! ischar (obj.facecolor))
-    color = obj.facecolor;
-  elseif (isfield (obj, "edgecolor") && !  ischar (obj.edgecolor))
-    color = obj.edgecolor;
-  else
-    color = [0, 0, 0];
-  endif
-endfunction
-
--- a/scripts/plot/draw/polar.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/draw/polar.m	Mon Jan 12 09:17:35 2015 -0800
@@ -36,6 +36,14 @@
 ##
 ## The optional return value @var{h} is a graphics handle to the created plot.
 ##
+## Implementation Note: The polar axis is drawn using line and text objects
+## encapsulated in an hggroup.  The hggroup properties are linked to the
+## original axes object such that altering an appearance property, for example
+## @code{fontname}, will update the polar axis.  Two new properties are
+## added to the original axes--@code{rtick}, @code{ttick}--which replace
+## @code{xtick}, @code{ytick}.  The first is a list of tick locations in the
+## radial (rho) direction; The second is a list of tick locations in the
+## angular (theta) direction specified in degrees, i.e., in the range 0--359.
 ## @seealso{rose, compass, plot}
 ## @end deftypefn
 
@@ -87,9 +95,51 @@
       print_usage ();
     endif
 
-    set (hax, "xlim", [-maxr, maxr], "ylim", [-maxr, maxr],
-              "xaxislocation", "zero", "yaxislocation", "zero",
-              "plotboxaspectratio", [1, 1, 1]);
+    if (! ishold (hax))
+      hg = hggroup (hax, "tag", "polar_grid", "handlevisibility", "off");
+
+      set (hax, "visible", "off", "plotboxaspectratio", [1, 1, 1],
+                "zlim", [-1 1]);
+
+      if (! isprop (hax, "rtick"))
+        addproperty ("rtick", hax, "data");
+      endif
+
+      set (hax, "rtick", __calc_rtick__ (hax, maxr));
+
+      ## add t(heta)tick
+      if (! isprop (hax, "ttick"))
+        addproperty ("ttick", hax, "data");
+      endif
+
+      ## theta(angular) ticks in degrees
+      set (hax, "ttick", 0:30:330);
+
+      __update_polar_grid__ (hax, [], hg);
+
+      set (hg, "deletefcn", {@resetaxis, hax});
+
+      addlistener (hax, "rtick", {@__update_polar_grid__, hg});
+      addlistener (hax, "ttick", {@__update_polar_grid__, hg});
+      addlistener (hax, "color", {@__update_patch__, hg});
+      addlistener (hax, "fontangle", {@__update_text__, hg, "fontangle"});
+      addlistener (hax, "fontname", {@__update_text__, hg, "fontname"});
+      addlistener (hax, "fontsize", {@__update_text__, hg, "fontsize"});
+      addlistener (hax, "fontunits", {@__update_text__, hg, "fontunits"});
+      addlistener (hax, "fontweight", {@__update_text__, hg, "fontweight"});
+      addlistener (hax, "interpreter", {@__update_text__, hg, "interpreter"});
+      addlistener (hax, "layer", {@__update_layer__, hg});
+      addlistener (hax, "gridlinestyle",{@__update_lines__,hg,"gridlinestyle"});
+      addlistener (hax, "linewidth", {@__update_lines__, hg, "linewidth"});
+    else
+      hg = findall (hax, "tag", "polar_grid");
+      if (! isempty (hg))
+        oldrtick = max (get (hax, "rtick"));
+        if (maxr > oldrtick)
+          set (hax, "rtick", __calc_rtick__ (hax, maxr));
+        endif
+      endif
+    endif
 
   unwind_protect_cleanup
     if (! isempty (oldfig))
@@ -103,6 +153,19 @@
 
 endfunction
 
+function rtick = __calc_rtick__ (hax, maxr)
+  ## FIXME: workaround: calculate r(ho)tick from xtick
+  savexlim = get (hax, "xlim");
+  saveylim = get (hax, "ylim");
+  set (hax, "xlim", [-maxr maxr], "ylim", [-maxr maxr]);
+  xtick = get (hax, "xtick");
+  rtick = xtick(find (xtick > 0, 1):find (xtick >= maxr, 1));
+  if (isempty (rtick))
+    rtick = [0.5 1];
+  endif
+  set (hax, "xlim", savexlim, "ylim", saveylim);
+endfunction
+
 function retval = __plr1__ (h, theta, fmt)
 
   theta = theta(:);
@@ -193,6 +256,133 @@
 
 endfunction
 
+## Callback functions for listeners
+
+function __update_text__ (hax, ~, hg, prop)
+
+  kids = get (hg, "children");
+  idx = strcmp (get (kids, "type"), "text");
+  set (kids(idx).', prop, get (hax, prop));
+
+endfunction
+
+function __update_lines__ (hax,  ~, hg, prop)
+
+  kids = get (hg, "children");
+  idx = strcmp (get (kids, "type"), "line");
+  lprop = prop;
+  if (strcmp (prop, "gridlinestyle"))
+    lprop = "linestyle";
+  endif
+  set (kids(idx).', lprop, get (hax, prop));
+
+endfunction
+
+function __update_patch__ (hax, ~, hg)
+
+  kids = get (hg, "children");
+  idx = strcmp (get (kids, "type"), "patch");
+  set (kids(idx).', "facecolor", get (hax, "color"));
+
+endfunction
+
+function __update_layer__ (hax,  ~, hg)
+
+  set (hg, "handlevisibility", "on");
+  kids = get (hax, "children");
+  if (strcmp (get (hax, "layer"), "bottom"))
+    set (hax, "children", [kids(kids != hg); hg]); 
+  else
+    set (hax, "children", [hg; kids(kids != hg)]); 
+  endif
+  set (hg, "handlevisibility", "off");
+
+endfunction
+
+function __update_polar_grid__ (hax, ~, hg)
+
+  ## Delete existing polar grid
+  delete (get (hg, "children"));
+
+  rtick = unique (get (hax, "rtick")(:)');
+  rtick = rtick(rtick > 0);
+  if (isempty (rtick))
+    rtick = [0.5 1];
+  endif
+
+  ttick = unique (get (hax, "ttick")(:)');
+  ttick = ttick(ttick >= 0);
+  if (isempty (ttick))
+    ttick = 0:30:330;
+  endif
+
+  lprops = {"linestyle", get(hax, "gridlinestyle"), ...
+            "linewidth", get(hax, "linewidth")};
+  ## "fontunits" should be first because it affects "fontsize" property.
+  tprops(1:2:12) = {"fontunits", "fontangle", "fontname", "fontsize", ...
+                    "fontweight", "interpreter"};
+  tprops(2:2:12) = get (hax, tprops(1:2:12));
+
+  ## The number of points used for a circle
+  circle_points = 50;
+  t = linspace (0, 2*pi, circle_points)';
+  x = kron (cos (t), rtick);
+  y = kron (sin (t), rtick);
+
+  ## Draw colored disk under axes at Z-depth = -1
+  patch (x(:,end), y(:,end), -ones (circle_points, 1),
+         get (hax, "color"), "parent", hg);
+
+  ## Plot dotted circles
+  line (x(:,1:end-1), y(:,1:end-1), lprops{:}, "parent", hg);
+
+  ## Outer circle is drawn solid
+  line (x(:,end), y(:,end), lprops{:}, "linestyle", "-", "parent", hg);
+
+  ## Add radial labels
+  [x, y] = pol2cart (0.42 * pi, rtick);
+  text (x, y, num2cell (rtick), "verticalalignment", "bottom", tprops{:},
+        "parent", hg);
+
+  ## add radial lines
+  s = rtick(end) * sin (ttick * pi / 180);
+  c = rtick(end) * cos (ttick * pi / 180);
+  x = [zeros(1, numel (ttick)); c];
+  y = [zeros(1, numel (ttick)); s];
+  line (x, y, "linestyle", ":", lprops{:}, "parent", hg);
+
+  ## add angular labels
+  tticklabel = num2cell (ttick);
+  ## FIXME: This tm factor does not work as fontsize increases
+  tm = 1.08;
+  text (tm * c, tm * s, tticklabel, "horizontalalignment", "center",
+        tprops{:}, "parent", hg);
+
+  lim = 1.1 * rtick(end);
+  set (hax, "xlim", [-lim, lim], "ylim", [-lim, lim]);
+
+  ## Put polar grid behind or ahead of plot
+  __update_layer__ (hax, [], hg);
+
+endfunction
+
+function resetaxis (~, ~, hax)
+  if (isaxes (hax))
+    dellistener (hax, "rtick");
+    dellistener (hax, "ttick");
+    dellistener (hax, "color");
+    dellistener (hax, "fontangle");
+    dellistener (hax, "fontname");
+    dellistener (hax, "fontsize");
+    dellistener (hax, "fontunits");
+    dellistener (hax, "fontweight");
+    dellistener (hax, "interpreter");
+    dellistener (hax, "layer");
+    dellistener (hax, "gridlinestyle");
+    dellistener (hax, "linewidth");
+  endif
+endfunction
+
 
 %!demo
 %! clf;
@@ -210,8 +400,25 @@
 
 %!demo
 %! clf;
+%! theta = linspace (0,2*pi,1000);
+%! rho = sin (2*theta).*cos (2*theta);
+%! polar (theta, rho, '--r');
+%! set (gca, 'rtick', 0.1:0.1:0.6, 'ttick', 0:20:340);
+%! title ('polar() plot with finer grid');
+
+%!demo
+%! clf;
+%! theta = linspace (0,2*pi,1000);
+%! rho = sin (2*theta).*cos (2*theta);
+%! polar (theta, rho, '--b');
+%! set (gca, 'fontsize', 12, 'linewidth', 2, 'color', [0.8 0.8 0.8]);
+%! title ('polar() plot with modified axis appearance');
+
+%!demo
+%! clf;
 %! theta = linspace (0,8*pi,1000);
 %! rho = sin (5/4*theta);
 %! polar (theta, rho);
+%! set (gca, 'rtick', 0.2:0.2:1);
 %! title ('polar() plot');
 
--- a/scripts/plot/draw/private/__ezplot__.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/draw/private/__ezplot__.m	Mon Jan 12 09:17:35 2015 -0800
@@ -448,8 +448,12 @@
       axis (hax, domain);
     elseif (isplot || ispolar)
       h = feval (pltfunc, hax, X, Z);
-      if (isplot && ! parametric)
-        axis (hax, domain);
+      if (isplot)
+        if (! parametric)
+          axis (hax, domain);
+        else
+          axis ("equal");
+        endif
       endif
     elseif (isplot3)
       if (animate)
--- a/scripts/plot/draw/private/__patch__.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/draw/private/__patch__.m	Mon Jan 12 09:17:35 2015 -0800
@@ -35,8 +35,7 @@
   is_numeric_arg = cellfun (@isnumeric, varargin);
 
   if (isempty (varargin))
-    args = {"xdata", [0; 1; 0], "ydata", [1; 1; 0], "facecolor", [0, 0, 0]};
-    args = setvertexdata (args);
+    args = varargin;
   elseif (isstruct (varargin{1}))
     if (isfield (varargin{1}, "vertices") && isfield (varargin{1}, "faces"))
       args{1} = "faces";
@@ -50,7 +49,6 @@
         args{6} = [];
       endif
       args = [args, varargin(2:end)];
-      args = setdata (args);
     else
       failed = true;
     endif
@@ -58,7 +56,6 @@
     if (nargin < 3 || ! is_numeric_arg(2))
       failed = true;
     else
-
       if (nargin > 4 && all (is_numeric_arg(1:4)))
         x = varargin{1};
         y = varargin{2};
@@ -70,7 +67,7 @@
         y = varargin{2};
         iarg = 4;
         if (rem (nargin - iarg, 2) == 1)
-          c = varargin {iarg};
+          c = varargin{iarg};
           z = varargin{3};
           iarg = 5;
         else
@@ -83,7 +80,7 @@
         z = [];
         iarg = 3;
         if (rem (nargin - iarg, 2) == 1)
-          c = varargin {iarg};
+          c = varargin{iarg};
           iarg++; 
         else
           c = [];
@@ -127,7 +124,7 @@
             args{9} = "cdata";
             args{10} = c;
           else
-            error ("patch: color value not valid");
+            error ("patch: color data C must be numeric");
           endif
         elseif (isvector (c) && numel (c) == 3)
           args{7} = "facecolor";
@@ -150,7 +147,7 @@
             args{9} = "cdata";
             args{10} = c;
           else
-            error ("patch: color value not valid");
+            error ("patch: Invalid TrueColor data C");
           endif
         else
           ## Color Vectors
@@ -159,212 +156,35 @@
             args{8} = "interp";
             args{9} = "cdata";
             args{10} = [];
-          elseif (isequal (size (c), size (x)) && isequal (size (c), size (y)))
+          elseif (size_equal (c, x) && size_equal (c, y))
             args{7} = "facecolor";
             args{8} = "interp";
             args{9} = "cdata";
             args{10} = c;
           else
-            error ("patch: size of x, y, and c must be equal");
+            error ("patch: size of X, Y, and C must be equal");
           endif
         endif
       elseif (ischar (c) && rem (nargin - iarg, 2) == 0)
-        ## Assume that any additional argument over an even number is
-        ## color string.
+        ## Assume any additional argument over an even number is a color string.
         args{7} = "facecolor";
         args{8} =  tolower (c);
         args{9} = "cdata";
         args{10} = [];
       else
         args{7} = "facecolor";
-        args{8} = [0, 1, 0];
+        args{8} = [0, 0, 0];
         args{9} = "cdata";
         args{10} = [];
       endif
 
       args = [args, varargin(iarg:end)];
-      args = setvertexdata (args);
     endif
   else
     args = varargin;
-    if (any (strcmpi (args, "faces") | strcmpi (args, "vertices")))
-      args = setdata (args);
-    else
-      args = setvertexdata (args);
-    endif
   endif
 
   if (!failed)
-    h = __go_patch__ (p, args {:});
-
-    ## Setup listener functions
-    addlistener (h, "xdata", @update_data);
-    addlistener (h, "ydata", @update_data);
-    addlistener (h, "zdata", @update_data);
-    addlistener (h, "cdata", @update_data);
-
-    addlistener (h, "faces", @update_fvc);
-    addlistener (h, "vertices", @update_fvc);
-    addlistener (h, "facevertexcdata", @update_fvc);
+    h = __go_patch__ (p, args{:});
   endif
 endfunction
-
-function args = delfields (args, flds)
-  idx = cellfun ("isclass", args, "char");
-  idx(idx) = ismember (args(idx), flds);
-  if (rows (idx) == 1)
-    idx |= [false, idx(1:end-1)];
-  else
-    idx |= [false; idx(1:end-1)];
-  endif
-  args(idx) = [];
-endfunction
-
-function args = setdata (args)
-  args = delfields (args, {"xdata", "ydata", "zdata", "cdata"});
-  ## Remove the readonly fields as well
-  args = delfields (args, {"type", "uicontextmenu"});
-  nargs = length (args);
-  idx = find (strcmpi (args, "faces"), 1, "last") + 1;
-  if (idx > nargs)
-    faces = [];
-  else
-    faces = args {idx};
-  endif
-  idx = find (strcmpi (args, "vertices"), 1, "last") + 1;
-  if (idx > nargs)
-    vert = [];
-  else
-    vert = args {idx};
-  endif
-  idx = find (strcmpi (args, "facevertexcdata"), 1, "last") + 1;
-  if (isempty (idx) || idx > nargs)
-    fvc = [];
-  else
-    fvc = args {idx};
-  endif
-  idx = find (strcmpi (args, "facecolor"), 1, "last") + 1;
-  if (isempty (idx) || idx > nargs)
-    if (!isempty (fvc))
-      fc = "flat";
-    else
-      fc = [0, 1, 0];
-    endif
-    args = {"facecolor", fc, args{:}};
-  endif
-
-  nc = rows (faces);
-  idx = faces .';
-  t1 = isnan (idx);
-  for i = find (any (t1))
-    first_idx_in_column = find (t1(:,i), 1);
-    idx(first_idx_in_column:end,i) = idx(first_idx_in_column-1,i);
-  endfor
-  x = reshape (vert(:,1)(idx), size (idx));
-  y = reshape (vert(:,2)(idx), size (idx));
-  if (columns (vert) > 2)
-    z = reshape (vert(:,3)(idx), size (idx));
-  else
-    z = [];
-  endif
-
-  if (rows (fvc) == nc || rows (fvc) == 1)
-    c = reshape (fvc, [1, size(fvc)]);
-  else
-    if (columns (fvc) == 3)
-      c = cat (3, reshape (fvc(idx, 1), size (idx)),
-               reshape (fvc(idx, 2), size (idx)),
-               reshape (fvc(idx, 3), size (idx)));
-    elseif (isempty (fvc))
-      c = [];
-    else ## if (columnns (fvc) == 1)
-      c = permute (fvc(faces), [2, 1]);
-    endif
-  endif
-  args = {"xdata", x, "ydata", y, "zdata", z, "cdata", c, args{:}};
-endfunction
-
-function args = setvertexdata (args)
-  args = delfields (args, {"vertices", "faces", "facevertexcdata"});
-  ## Remove the readonly fields as well
-  args = delfields (args, {"type", "uicontextmenu"});
-  nargs = length (args);
-  idx = find (strcmpi (args, "xdata"), 1, "last") + 1;
-  if (idx > nargs)
-    x = [];
-  else
-    x = args {idx};
-  endif
-  idx = find (strcmpi (args, "ydata"), 1, "last") + 1;
-  if (idx > nargs)
-    y = [];
-  else
-    y = args {idx};
-  endif
-  idx = find (strcmpi (args, "zdata"), 1, "last") + 1;
-  if (isempty (idx) || idx > nargs)
-    z = [];
-  else
-    z = args {idx};
-  endif
-  idx = find (strcmpi (args, "cdata"), 1, "last") + 1;
-  if (isempty (idx) || idx > nargs)
-    c = [];
-  else
-    c = args {idx};
-  endif
-  idx = find (strcmpi (args, "facecolor"), 1, "last") + 1;
-  if (isempty (idx) || idx > nargs)
-    if (!isempty (c))
-      fc = "flat";
-    else
-      fc = [0, 1, 0];
-    endif
-    args = {"facecolor", fc, args{:}};
-  endif
-
-  [nr, nc] = size (x);
-  if (nr == 1 && nc > 1)
-    nr = nc;
-    nc = 1;
-  endif
-  if (!isempty (z))
-    vert = [x(:), y(:), z(:)];
-  else
-    vert = [x(:), y(:)];
-  endif
-  faces = reshape (1:numel (x), nr, nc);
-  faces = faces';
-
-  if (ndims (c) == 3)
-    fvc = reshape (c, rows (c) * columns (c), size (c, 3));
-  else
-    fvc = c(:);
-  endif
-
-  args = {"faces", faces, "vertices", vert, "facevertexcdata", fvc, args{:}};
-endfunction
-
-function update_data (h, d)
-  update_handle (h, false);
-endfunction
-
-function update_fvc (h, d)
-  update_handle (h, true);
-endfunction
-
-function update_handle (h, isfv)
-  persistent recursive = false;
-
-  if (! recursive)
-    recursive = true;
-    f = get (h);
-    if (isfv)
-      set (h, setdata ([fieldnames(f), struct2cell(f)].'(:)){:});
-    else
-      set (h, setvertexdata ([fieldnames(f), struct2cell(f)].'(:)){:});
-    endif
-    recursive = false;
-  endif
-endfunction
-
--- a/scripts/plot/draw/private/__quiver__.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/draw/private/__quiver__.m	Mon Jan 12 09:17:35 2015 -0800
@@ -112,8 +112,16 @@
   ## Normalize 0.20 to 1/3 for plotting
   arrowsize /= 0.20 * 3;
 
-  if (autoscale && numel (u) > 1)
-    ## Scale the arrows to fit in the grid
+  ## Scale the arrows to fit in the grid
+  uu = u;
+  vv = v;
+  if (is3d)
+    ww = w;
+    len = max (sqrt (u(:).^2 + v(:).^2 + w(:).^2));
+  else
+    len = max (sqrt (u(:).^2 + v(:).^2));      
+  endif
+  if (len > 0 && autoscale && numel (u) > 1)
     if (isvector (x))
       nx = ny = sqrt (length (x));
     else
@@ -123,29 +131,19 @@
     dy = (max (y(:)) - min (y(:))) / ny;
     if (is3d)
       dz = (max (z(:)) - min (z(:))) / max (nx, ny);
-      len = max (sqrt (u(:).^2 + v(:).^2 + w(:).^2));
     else
       dz = 0;
-      len = max (sqrt (u(:).^2 + v(:).^2));
     endif
-    if (len > 0)
-      sd = sqrt (dx.^2 + dy.^2 + dz.^2) / len;
-      if (sd != 0)
-        s = autoscale * sd;
-      else  # special case of identical points with multiple vectors
-        s = autoscale;
-      endif
-      uu = s * u;
-      vv = s * v;
-      if (is3d)
-        ww = s * w;
-      endif
+    sd = sqrt (dx.^2 + dy.^2 + dz.^2) / len;
+    if (sd != 0)
+      s = autoscale * sd;
+    else  # special case of identical points with multiple vectors
+      s = autoscale;
     endif
-  else
-    uu = u;
-    vv = v;
+    uu = s * u;
+    vv = s * v;
     if (is3d)
-      ww = w;
+      ww = s * w;
     endif
   endif
 
--- a/scripts/plot/draw/private/__scatter__.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/draw/private/__scatter__.m	Mon Jan 12 09:17:35 2015 -0800
@@ -84,6 +84,21 @@
     c = [];
   endif
 
+  ## Validate inputs
+  if (nd == 2 && ! size_equal (x, y)) 
+    error ([fcn ": X and Y must have the same size"]);
+  elseif (nd == 3 && ! size_equal (x, y, z)) 
+    error ([fcn ": X, Y, and Z must have the same size"]);
+  endif
+
+  if (! isscalar (s) && ! size_equal (x, s))
+    error ([fcn ": size of S must match X, Y, and Z"]);
+  endif
+
+  if (rows (c) > 1 && rows (c) != rows (x))
+    error ([fcn ": number of colors in C must match number of points in X"]);
+  endif
+
   newargs = {};
   filled = false;
   have_marker = false;
--- a/scripts/plot/draw/private/__stem__.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/draw/private/__stem__.m	Mon Jan 12 09:17:35 2015 -0800
@@ -48,6 +48,8 @@
 
     h = [];
     nx = rows (x);
+    h_baseline = [];
+    
     for i = 1 : columns (x)
       if (have_z)
         xt = x(:)';
@@ -90,19 +92,19 @@
         __line__ (hax, xt, yt, zt, "color", lc, "linestyle", ls, "parent", hg);
         __line__ (hax, x, y, z, "color", mc, "linestyle", "none",
                        "marker", ms, "markerfacecolor", fc, "parent", hg);
-        h_baseline = [];
       else
         __line__ (hax, xt, yt, "color", lc, "linestyle", ls, "parent", hg);
         __line__ (hax, x(:,i), y(:, i), "color", mc, "linestyle", "none",
                        "marker", ms, "markerfacecolor", fc, "parent", hg);
+        
         x_axis_range = get (hax, "xlim");
-        h_baseline = line (hax, x_axis_range, [0, 0], "color", [0, 0, 0]);
-        set (h_baseline, "handlevisibility", "off", "xliminclude", "off");
-        addlistener (hax, "xlim", @update_xlim);
-        addproperty ("basevalue", h_baseline, "data", 0);
-        addlistener (h_baseline, "basevalue", {@update_baseline, 0});
-        addlistener (h_baseline, "ydata", {@update_baseline, 1});
-        addlistener (h_baseline, "visible", {@update_baseline, 2});
+        if (isempty (h_baseline))
+          h_baseline = line (hax, x_axis_range, [0, 0], "color", [0, 0, 0]);
+          set (h_baseline, "handlevisibility", "off", "xliminclude", "off");
+          addproperty ("basevalue", h_baseline, "data", 0);
+        else
+          set (h_baseline, "xdata", x_axis_range);
+        endif
       endif
 
       ## Setup the hggroup and listeners.
@@ -110,11 +112,6 @@
       addproperty ("baseline", hg, "data", h_baseline);
       addproperty ("basevalue", hg, "data", 0);
 
-      if (! have_z)
-        addlistener (hg, "showbaseline", @show_baseline);
-        addlistener (hg, "basevalue", @move_baseline);
-      endif
-
       addproperty ("color", hg, "linecolor", lc);
       addproperty ("linestyle", hg, "linelinestyle", ls);
       addproperty ("linewidth", hg, "linelinewidth", 0.5);
@@ -131,7 +128,13 @@
       addlistener (hg, "markerfacecolor", @update_props);
       addlistener (hg, "markersize", @update_props);
 
+      if (islogical (x))
+        x = double (x);
+      endif
       addproperty ("xdata", hg, "data", x(:, i));
+      if (islogical (y))
+        y = double (y);
+      endif
       addproperty ("ydata", hg, "data", y(:, i));
       if (have_z)
         addproperty ("zdata", hg, "data", z(:, i));
@@ -146,14 +149,28 @@
       ## Matlab property, although Octave does not implement it.
       addproperty ("hittestarea", hg, "radio", "on|{off}", "off");
 
-      if (! isempty (args))
-        set (hg, args{:});
-      endif
-      if (i == 1 && ! isempty (h_baseline))
-        set (h_baseline, "parent", get (hg, "parent"));
-      endif
     endfor
 
+    ## baseline listeners
+    if (! isempty (h_baseline))
+      addlistener (hax, "xlim", @update_xlim);
+      for hg = h'
+        addlistener (hg, "showbaseline", @show_baseline);
+        addlistener (hg, "visible", {@show_baseline, h});
+        addlistener (hg, "basevalue", @move_baseline);
+      endfor
+      
+      addlistener (h_baseline, "basevalue", {@update_baseline, 0});
+      addlistener (h_baseline, "ydata", {@update_baseline, 1});
+      addlistener (h_baseline, "visible", {@update_baseline, 2});
+      set (h_baseline, "parent", get (hg(1), "parent"));
+    endif
+
+    ## property/value pairs
+    if (! isempty (args))
+        set (h, args{:});
+    endif
+
     if (! strcmp (hold_state, "add") && have_z)
       set (hax, "view", [-37.5 30],
                 "xgrid", "on", "ygrid", "on", "zgrid", "on");
@@ -365,8 +382,16 @@
   endfor
 endfunction
 
-function show_baseline (h, ~)
-  set (get (h, "baseline"), "visible", get (h, "showbaseline"));
+function show_baseline (h, ~, hg = [])
+  if (isempty (hg))
+    set (get (h, "baseline"), "visible", get (h, "showbaseline"));
+  else
+    if (all (strcmp (get (hg, "visible"), "off")))
+      set (get (h, "baseline"), "visible", "off");
+    else
+      set (get (h, "baseline"), "visible", "on");
+    endif
+  endif
 endfunction
 
 function move_baseline (h, ~)
@@ -374,6 +399,7 @@
   bl = get (h, "baseline");
 
   set (bl, "ydata", [b0, b0]);
+  set (bl, "basevalue", b0);
 
   kids = get (h, "children");
   yt = get (h, "ydata")(:)';
--- a/scripts/plot/draw/rose.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/draw/rose.m	Mon Jan 12 09:17:35 2015 -0800
@@ -116,6 +116,11 @@
 
 %!demo
 %! clf;
+%! rose (2*randn (1e5, 1), 8);
+%! title ('rose() angular histogram plot with 8 bins');
+
+%!demo
+%! clf;
 %! rose ([2*randn(1e5, 1), pi + 2*randn(1e5, 1)]);
-%! title ('rose() angular histogram plot');
+%! title ('rose() angular histogram plot with 2 data series');
 
--- a/scripts/plot/draw/shrinkfaces.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/draw/shrinkfaces.m	Mon Jan 12 09:17:35 2015 -0800
@@ -23,24 +23,29 @@
 ## @deftypefnx {Function File} {@var{nfv} =} shrinkfaces (@var{f}, @var{v}, @var{sf})
 ## @deftypefnx {Function File} {[@var{nf}, @var{nv}] =} shrinkfaces (@dots{})
 ##
-## Reduce the faces area for a given patch, structure or explicit faces
-## and points matrices by a scale factor @var{sf}.  The structure
-## @var{fv} must contain the fields @qcode{"faces"} and @qcode{"vertices"}. 
-## If the factor @var{sf} is omitted then a default of 0.3 is used.
+## Reduce the size of faces in a patch by the shrink factor @var{sf}.
+##
+## The patch object can be specified by a graphics handle (@var{p}), a patch
+## structure (@var{fv}) with the fields @qcode{"faces"} and @qcode{"vertices"},
+## or as two separate matrices (@var{f}, @var{v}) of faces and vertices.
 ##
-## Given a patch handle as the first input argument and no output
-## parameters, perform the shrinking of the patch faces in place and
-## redraw the patch.
+## The shrink factor @var{sf} is a positive number specifying the percentage
+## of the original area the new face will occupy.  If no factor is given the
+## default is 0.3 (a reduction to 30% of the original size).  A factor greater
+## than 1.0 will result in the expansion of faces.
+##
+## Given a patch handle as the first input argument and no output parameters,
+## perform the shrinking of the patch faces in place and redraw the patch.
 ##
 ## If called with one output argument, return a structure with fields
 ## @qcode{"faces"}, @qcode{"vertices"}, and @qcode{"facevertexcdata"}
-## containing the data after shrinking which can then directly be used as an
-## input argument for the @code{patch} function.
+## containing the data after shrinking.  This structure can be used directly
+## as an input argument to the @code{patch} function.
 ##
-## Performing the shrinking on faces which are not convex can lead to
-## undesired results.
+## @strong{Caution:}: Performing the shrink operation on faces which are not
+## convex can lead to undesirable results.
 ##
-## For example,
+## Example: a triangulated 3/4 circle and the corresponding shrunken version.
 ##
 ## @example
 ## @group
@@ -56,9 +61,6 @@
 ## @end group
 ## @end example
 ##
-## @noindent
-## draws a triangulated 3/4 circle and the corresponding shrunken
-## version.
 ## @seealso{patch}
 ## @end deftypefn
 
@@ -71,10 +73,11 @@
   endif
   
   sf = 0.3;
+  colors = [];
   p = varargin{1};
-  colors = [];
 
-  if (ishandle (p) && nargin < 3)
+  if (isscalar (p) && ishandle (p) && nargin < 3 &&
+      strcmp (get (p, "type"), "patch"))
     faces = get (p, "Faces");
     vertices = get (p, "Vertices");
     colors = get (p, "FaceVertexCData");
@@ -104,8 +107,8 @@
     error ("shrinkfaces: scale factor must be a positive scalar");
   endif
 
-  n = columns (vertices);
-  if (n < 2 || n > 3)
+  nc = columns (vertices);
+  if (nc < 2 || nc > 3)
     error ("shrinkfaces: only 2-D and 3-D patches are supported");
   endif
 
@@ -120,14 +123,12 @@
   elseif (rows (colors) == rows (vertices))
     c = colors(faces'(:), :);
   else
-    ## Discard inconsistent color data.
-    c = [];
+    c = [];  # Discard inconsistent color data.
   endif
   sv = rows (v);
-  ## we have to deal with a probably very large number of vertices, so
-  ## use sparse we use as midpoint (1/m, ..., 1/m) in generalized
-  ## barycentric coordinates.
-  midpoints = full (kron ( speye (sv / m), ones (m, m) / m) * sparse (v));
+  ## We have to deal with a possibly very large number of vertices, so use
+  ## sparse as midpoint (1/m, ..., 1/m) in generalized barycentric coordinates.
+  midpoints = full (kron (speye (sv / m), ones (m, m) / m) * sparse (v));
   v = sqrt (sf) * (v - midpoints) + midpoints;
   f = reshape (1:sv, m, sv / m)';
   
@@ -216,3 +217,13 @@
 %!assert (size (nfv.vertices), [3 3])
 %!assert (norm (nfv2.vertices - vertices), 0, 2*eps)
 
+%% Test input validation
+%!error shrinkfaces ()
+%!error shrinkfaces (1,2,3,4)
+%!error [a,b,c] = shrinkfaces (1)
+%!error <scale factor must be a positive scalar> shrinkfaces (nfv, ones (2))
+%!error <scale factor must be a positive scalar> shrinkfaces (nfv, 0)
+%!error <only 2-D and 3-D patches are supported> shrinkfaces (faces, ones (3,1))
+%!error <only 2-D and 3-D patches are supported> shrinkfaces (faces, ones (3,4))
+%!error <faces must consist of at least 3 vertices> shrinkfaces (faces(1:2), vertices)
+
--- a/scripts/plot/draw/stem.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/draw/stem.m	Mon Jan 12 09:17:35 2015 -0800
@@ -187,7 +187,7 @@
 %! y = [sin(x), cos(x)];
 %! h = stem (x, y);
 %! set (h(2), 'color', 'g');
-%! set (h(1), 'basevalue', -1);
+%! set (h(1), 'basevalue', -0.75);
 %! title ('stem plots modified through hggroup handle');
 
 %!demo
@@ -213,3 +213,18 @@
 %!error <inconsistent sizes for X and Y> stem (ones (2,2), ones (3,3))
 %!error <No value specified for property "FOO"> stem (1, "FOO")
 
+%!test
+%! ## stemseries share the same baseline and basevalue
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   h = stem ([1 2; 1.5 2.5], [1 1;2 2]);
+%!   assert (get (h(1), "baseline"), get (h(2), "baseline"))
+%!   bv = 0.3;
+%!   set (h(1), "basevalue", bv)
+%!   assert (get (get (h(1), "baseline"), "basevalue"), bv)
+%!   assert (get (h(1), "basevalue"), bv)
+%!   assert (get (h(2), "basevalue"), bv)
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
--- a/scripts/plot/draw/stemleaf.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/draw/stemleaf.m	Mon Jan 12 09:17:35 2015 -0800
@@ -185,7 +185,7 @@
   hl = xs(hlidx);               # lower hinge
   hu = xs(huidx);               # upper hinge
   h_spread = hu - hl;           # h_spread: difference between hinges
-  step = 1.5*h_spread;          # step: 1.5 * h_spread
+  step = fix(1.5*h_spread);     # step: 1.5 * h_spread
   i_fence_l = hl - step;        # inner fences: outside hinges + step
   o_fence_l = hl - 2*step;      # outer fences: outside hinges + 2*step
   i_fence_h = hu + step;
@@ -349,13 +349,13 @@
 %! " "                                  ,
 %! "         Fenced Letter Display"     ,
 %! " "                                  ,
-%! "     #138|___________________"      ,     
-%! "     M 69|          52      |"      ,     
+%! "     #138|___________________"      ,
+%! "     M 69|          52      |"      ,
 %! "     H 35|   30          116|   86" ,
 %! "     1   |  -28          146|"      ,
 %! "               _______"             ,
 %! "         ______|  129|_______"      ,
-%! "        f|  -99          245|"      ,     
+%! "        f|  -99          245|"      ,
 %! "         |    0            0|  out" ,
 %! "        F| -228          374|"      ,
 %! "         |    0            0|  far" ,
@@ -389,13 +389,13 @@
 %! " "                                   ,
 %! "         Fenced Letter Display"      ,
 %! " "                                   ,
-%! "     # 14|___________________"       ,     
-%! "     M  7|          22      |"       ,     
+%! "     # 14|___________________"       ,
+%! "     M  7|          22      |"       ,
 %! "     H  4|   12           42|   30"  ,
 %! "     1   |    5           52|"       ,
 %! "               _______"              ,
 %! "         ______|   45|_______"       ,
-%! "        f|  -33           87|"       ,     
+%! "        f|  -33           87|"       ,
 %! "         |    0            0|  out"  ,
 %! "        F|  -78          132|"       ,
 %! "         |    0            0|  far"  ,
@@ -418,13 +418,13 @@
 %! " "                                   ,
 %! "         Fenced Letter Display"      ,
 %! " "                                   ,
-%! "     # 14|___________________"       ,     
-%! "     M  7|         -28      |"       ,     
+%! "     # 14|___________________"       ,
+%! "     M  7|         -28      |"       ,
 %! "     H  4|  -42          -12|   30"  ,
 %! "     1   |  -52           -5|"       ,
 %! "               _______"              ,
 %! "         ______|   45|_______"       ,
-%! "        f|  -87           33|"       ,     
+%! "        f|  -87           33|"       ,
 %! "         |    0            0|  out"  ,
 %! "        F| -132           78|"       ,
 %! "         |    0            0|  far"  ,
@@ -446,15 +446,15 @@
 %! " "                                  ,
 %! "         Fenced Letter Display"     ,
 %! " "                                  ,
-%! "     # 15|___________________"      ,     
-%! "     M  8|          22      |"      ,     
+%! "     # 15|___________________"      ,
+%! "     M  8|          22      |"      ,
 %! "     H  4|   11           42|   31" ,
 %! "     1   |    0           52|"      ,
 %! "               _______"             ,
 %! "         ______|   46|_______"      ,
-%! "        f|  -35           88|"      ,     
+%! "        f|  -35           88|"      ,
 %! "         |    0            0|  out" ,
-%! "        F|  -82          135|"      ,
+%! "        F|  -81          134|"      ,
 %! "         |    0            0|  far" ,
 %! " "                                  ,
 %! "   0 | 20"                          ,
@@ -475,15 +475,15 @@
 %! " "                                  ,
 %! "         Fenced Letter Display"     ,
 %! " "                                  ,
-%! "     # 15|___________________"      ,     
-%! "     M  8|         -22      |"      ,     
+%! "     # 15|___________________"      ,
+%! "     M  8|         -22      |"      ,
 %! "     H  4|  -42          -11|   31" ,
 %! "     1   |  -52            0|"      ,
 %! "               _______"             ,
 %! "         ______|   46|_______"      ,
-%! "        f|  -88           35|"      ,     
+%! "        f|  -88           35|"      ,
 %! "         |    0            0|  out" ,
-%! "        F| -135           82|"      ,
+%! "        F| -134           81|"      ,
 %! "         |    0            0|  far" ,
 %! " "                                  ,
 %! "  -5 | 2"                           ,
@@ -503,15 +503,15 @@
 %! " "                                  ,
 %! "         Fenced Letter Display"     ,
 %! " "                                  ,
-%! "     #  5|___________________"      ,     
-%! "     M  3|           0      |"      ,     
+%! "     #  5|___________________"      ,
+%! "     M  3|           0      |"      ,
 %! "     H  2|   -7            0|   7"  ,
 %! "     1   |   -9            0|"      ,
 %! "               _______"             ,
 %! "         ______|   10|_______"      ,
-%! "        f|  -17           10|"      ,     
+%! "        f|  -17           10|"      ,
 %! "         |    0            0|  out" ,
-%! "        F|  -28           21|"      ,
+%! "        F|  -27           20|"      ,
 %! "         |    0            0|  far" ,
 %! " "                                  ,
 %! "  -0 | 9700"                        ,
@@ -527,15 +527,15 @@
 %! " "                                    ,
 %! "         Fenced Letter Display"       ,
 %! " "                                    ,
-%! "     #  4|___________________"        ,     
-%! "     M  2|          -7      |"        ,     
+%! "     #  4|___________________"        ,
+%! "     M  2|          -7      |"        ,
 %! "     H  1|   -9            0|   9"    ,
 %! "     1   |   -9            0|"        ,
 %! "               _______"               ,
 %! "         ______|   13|_______"        ,
-%! "        f|  -22           13|"        ,     
+%! "        f|  -22           13|"        ,
 %! "         |    0            0|  out"   ,
-%! "        F|  -36           27|"        ,
+%! "        F|  -35           26|"        ,
 %! "         |    0            0|  far"   ,
 %! " "                                    ,
 %! "  -0 | 970"                           ,
@@ -552,7 +552,7 @@
 %! " "                                      ,
 %! "         Fenced Letter Display"         ,
 %! " "                                      ,
-%! "     # 17|___________________"          ,          
+%! "     # 17|___________________"          ,
 %! "     M  9|         895      |"          ,
 %! "     H  5|  795         1499|   704"    ,
 %! "     1   |  150         1995|"          ,
--- a/scripts/plot/draw/surface.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/draw/surface.m	Mon Jan 12 09:17:35 2015 -0800
@@ -73,109 +73,110 @@
 
   h = 0;
   bad_usage = false;
-  firststring = nargin;
-  for i = 1 : (nargin - 1)
-    if (ischar (varargin{i}))
-      firststring = i;
-      break;
-    endif
-  endfor
+  firststring = find (cellfun ("isclass", varargin, "char"), 1);
+  if (isempty (firststring))
+    firststring = nargin;
+  endif
 
-  if (firststring > 5)
-    bad_usage = true;
-    return;
-  elseif (firststring == 5)
-    x = varargin{1};
-    y = varargin{2};
-    z = varargin{3};
-    c = varargin{4};
+  switch (firststring)
+    case 5
+      x = varargin{1};
+      y = varargin{2};
+      z = varargin{3};
+      c = varargin{4};
 
-    if (iscomplex (x) || iscomplex (y) || iscomplex (z) || iscomplex (c))
-      error ("mesh: X, Y, Z, C arguments must be real");
-    endif
+      if (iscomplex (x) || iscomplex (y) || iscomplex (z) || iscomplex (c))
+        error ("mesh: X, Y, Z, C arguments must be real");
+      endif
+
+      [z_nr, z_nc] = size (z);
+      [c_nr, c_nc, c_np] = size (c);
+      if (! (z_nr == c_nr && z_nc == c_nc && (c_np == 1 || c_np == 3)))
+        error ("surface: Z and C must have the same size");
+      endif
 
-    [z_nr, z_nc] = size (z);
-    [c_nr, c_nc, c_np] = size (c);
-    if (! (z_nr == c_nr && z_nc == c_nc && (c_np == 1 || c_np == 3)))
-      error ("surface: Z and C must have the same size");
-    endif
-
-    if (isvector (x) && isvector (y) && ismatrix (z))
-      if (rows (z) == length (y) && columns (z) == length (x))
-        x = x(:)';
-        y = y(:);
+      if (isvector (x) && isvector (y) && ismatrix (z))
+        if (rows (z) == length (y) && columns (z) == length (x))
+          x = x(:)';
+          y = y(:);
+        else
+          error ("surface: rows (Z) must be the same as length (Y) and columns (Z) must be the same as length (X)");
+        endif
+      elseif (ismatrix (x) && ismatrix (y) && ismatrix (z))
+        if (! size_equal (x, y, z))
+          error ("surface: X, Y, and Z must have the same dimensions");
+        endif
       else
-        error ("surface: rows (Z) must be the same as length (Y) and columns (Z) must be the same as length (X)");
+        error ("surface: X and Y must be vectors and Z must be a matrix");
       endif
-    elseif (ismatrix (x) && ismatrix (y) && ismatrix (z))
-      if (! size_equal (x, y, z))
-        error ("surface: X, Y, and Z must have the same dimensions");
+
+    case 4
+      x = varargin{1};
+      y = varargin{2};
+      z = varargin{3};
+      c = z;
+
+      if (iscomplex (x) || iscomplex (y) || iscomplex (z))
+        error ("mesh: X, Y, Z arguments must be real");
       endif
-    else
-      error ("surface: X and Y must be vectors and Z must be a matrix");
-    endif
-  elseif (firststring == 4)
-    x = varargin{1};
-    y = varargin{2};
-    z = varargin{3};
-    c = z;
-
-    if (iscomplex (x) || iscomplex (y) || iscomplex (z))
-      error ("mesh: X, Y, Z arguments must be real");
-    endif
 
-    if (isvector (x) && isvector (y) && ismatrix (z))
-      if (rows (z) == length (y) && columns (z) == length (x))
-        x = x(:)';
-        y = y(:);
+      if (isvector (x) && isvector (y) && ismatrix (z))
+        if (rows (z) == length (y) && columns (z) == length (x))
+          x = x(:)';
+          y = y(:);
+        else
+          error ("surface: rows (Z) must be the same as length (Y) and columns (Z) must be the same as length (X)");
+        endif
+      elseif (ismatrix (x) && ismatrix (y) && ismatrix (z))
+        if (! size_equal (x, y, z))
+          error ("surface: X, Y, and Z must have the same dimensions");
+        endif
       else
-        error ("surface: rows (Z) must be the same as length (Y) and columns (Z) must be the same as length (X)");
-      endif
-    elseif (ismatrix (x) && ismatrix (y) && ismatrix (z))
-      if (! size_equal (x, y, z))
-        error ("surface: X, Y, and Z must have the same dimensions");
+        error ("surface: X and Y must be vectors and Z must be a matrix");
       endif
-    else
-      error ("surface: X and Y must be vectors and Z must be a matrix");
-    endif
-  elseif (firststring == 3)
-    z = varargin{1};
-    c = varargin{2};
 
-    if (iscomplex (z) || iscomplex (c))
-      error ("mesh: X, C arguments must be real");
-    endif
+    case 3
+      z = varargin{1};
+      c = varargin{2};
+
+      if (iscomplex (z) || iscomplex (c))
+        error ("mesh: X, C arguments must be real");
+      endif
 
-    if (ismatrix (z) && !isvector (z) && !isscalar (z))
-      [nr, nc] = size (z);
-      x = 1:nc;
-      y = (1:nr)';
-    else
-      error ("surface: Z argument must be a matrix");
-    endif
-  elseif (firststring == 2)
-    z = varargin{1};
-    c = z;
+      if (ismatrix (z) && !isvector (z) && !isscalar (z))
+        [nr, nc] = size (z);
+        x = 1:nc;
+        y = (1:nr)';
+      else
+        error ("surface: Z argument must be a matrix");
+      endif
 
-    if (iscomplex (z))
-      error ("mesh: Z argument must be real");
-    endif
+    case 2
+      z = varargin{1};
+      c = z;
+
+      if (iscomplex (z))
+        error ("mesh: Z argument must be real");
+      endif
 
-    if (ismatrix (z) && !isvector (z) && !isscalar (z))
-      [nr, nc] = size (z);
-      x = 1:nc;
-      y = (1:nr)';
-    else
-      error ("surface: Z argument must be a matrix");
-    endif
-  elseif (firststring == 1)
-    x = 1:3;
-    y = x';
-    c = z = eye (3);
-  else
-    bad_usage = true;
-    return;
-  endif
+      if (ismatrix (z) && !isvector (z) && !isscalar (z))
+        [nr, nc] = size (z);
+        x = 1:nc;
+        y = (1:nr)';
+      else
+        error ("surface: Z argument must be a matrix");
+      endif
+
+    case 1
+      x = 1:3;
+      y = x';
+      c = z = eye (3);
+
+    otherwise
+      bad_usage = true;
+      return;
+  
+  endswitch
 
   if (firststring < nargin)
     other_args = varargin(firststring:end);
--- a/scripts/plot/draw/surfc.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/draw/surfc.m	Mon Jan 12 09:17:35 2015 -0800
@@ -71,9 +71,15 @@
   unwind_protect
     hax = newplot (hax);
     
-    htmp = surface (varargin{:});
+    surfc_props = {"facecolor", "flat"};
+    chararg = find (cellfun ("isclass", varargin, "char"), 1);
+    if (isempty (chararg))
+      htmp = surface (varargin{:}, surfc_props{:});
+    else
+      htmp = surface (varargin{1:chararg-1}, surfc_props{:},
+                      varargin{chararg:end});
+    endif
 
-    set (htmp, "facecolor", "flat");
     if (! ishold ())
       set (hax, "view", [-37.5, 30],
                 "xgrid", "on", "ygrid", "on", "zgrid", "on",
--- a/scripts/plot/draw/surfl.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/draw/surfl.m	Mon Jan 12 09:17:35 2015 -0800
@@ -164,7 +164,7 @@
     endif
 
     vn = get (htmp, "vertexnormals");
-    dar = get (hax, "plotboxaspectratio");
+    dar = get (hax, "dataaspectratio");
     vn(:,:,1) *= dar(1);
     vn(:,:,2) *= dar(2);
     vn(:,:,3) *= dar(3);
@@ -206,8 +206,7 @@
 %! clf;
 %! [X,Y,Z] = sombrero ();
 %! colormap (copper (64));
-%! [az, el] = view ();
-%! surfl (X,Y,Z, [az+225,el], [0.2 0.6 0.4 25]);
+%! surfl (X,Y,Z, [62.50,30], [0.2 0.6 0.4 25]);
 %! shading interp;
 %! title ('surfl() with lighting vector and material properties');
 
--- a/scripts/plot/draw/surfnorm.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/draw/surfnorm.m	Mon Jan 12 09:17:35 2015 -0800
@@ -19,49 +19,56 @@
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {} surfnorm (@var{x}, @var{y}, @var{z})
 ## @deftypefnx {Function File} {} surfnorm (@var{z})
+## @deftypefnx {Function File} {} surfnorm (@dots{}, @var{prop}, @var{val}, @dots{})
+## @deftypefnx {Function File} {} surfnorm (@var{hax}, @dots{})
 ## @deftypefnx {Function File} {[@var{nx}, @var{ny}, @var{nz}] =} surfnorm (@dots{})
-## @deftypefnx {Function File} {} surfnorm (@var{h}, @dots{})
-## Find the vectors normal to a meshgridded surface.  The meshed gridded
-## surface is defined by @var{x}, @var{y}, and @var{z}.  If @var{x} and
-## @var{y} are not defined, then it is assumed that they are given by
+## Find the vectors normal to a meshgridded surface.
 ##
-## @example
-## @group
-## [@var{x}, @var{y}] = meshgrid (1:rows (@var{z}),
-##                    1:columns (@var{z}));
-## @end group
-## @end example
+## If @var{x} and @var{y} are vectors, then a typical vertex is
+## (@var{x}(j), @var{y}(i), @var{z}(i,j)).  Thus, columns of @var{z} correspond
+## to different @var{x} values and rows of @var{z} correspond to different
+## @var{y} values.  If only a single input @var{z} is given then @var{x} is
+## taken to be @code{1:rows (@var{z})} and @var{y} is
+## @code{1:columns (@var{z})}.
 ##
 ## If no return arguments are requested, a surface plot with the normal
-## vectors to the surface is plotted.  Otherwise the components of the normal
-## vectors at the mesh gridded points are returned in @var{nx}, @var{ny},
-## and @var{nz}.
+## vectors to the surface is plotted.
 ##
-## The normal vectors are calculated by taking the cross product of the
-## diagonals of each of the quadrilaterals in the meshgrid to find the
-## normal vectors of the centers of these quadrilaterals.  The four nearest
-## normal vectors to the meshgrid points are then averaged to obtain the
-## normal to the surface at the meshgridded points.
+## Any property/value input pairs are assigned to the surface object.
+## 
+## If the first argument @var{hax} is an axes handle, then plot into this axis,
+## rather than the current axes returned by @code{gca}.
+##
+## If output arguments are requested then the components of the normal
+## vectors are returned in @var{nx}, @var{ny}, and @var{nz} and no plot is
+## made.
 ##
 ## An example of the use of @code{surfnorm} is
 ##
 ## @example
 ## surfnorm (peaks (25));
 ## @end example
-## @seealso{surf, quiver3}
+##
+## Algorithm: The normal vectors are calculated by taking the cross product
+## of the diagonals of each of the quadrilaterals in the meshgrid to find the
+## normal vectors of the centers of these quadrilaterals.  The four nearest
+## normal vectors to the meshgrid points are then averaged to obtain the
+## normal to the surface at the meshgridded points.
+##
+## @seealso{isonormals, quiver3, surf, meshgrid}
 ## @end deftypefn
 
 function [Nx, Ny, Nz] = surfnorm (varargin)
 
   [hax, varargin, nargin] = __plt_get_axis_arg__ ("surfnorm", varargin{:});
 
-  if (nargin != 1 && nargin != 3)
+  if (nargin == 0 || nargin == 2)
     print_usage ();
   endif
 
   if (nargin == 1)
     z = varargin{1};
-    [x, y] = meshgrid (1:rows (z), 1:columns (z));
+    [x, y] = meshgrid (1:columns (z), 1:rows (z));
     ioff = 2;
   else
     x = varargin{1};
@@ -70,22 +77,24 @@
     ioff = 4;
   endif
 
-  if (!ismatrix (z) || isvector (z) || isscalar (z))
-    error ("surfnorm: Z argument must be a matrix");
+  if (iscomplex (z) || iscomplex (x) || iscomplex (y))
+    error ("surfnorm: X, Y, and Z must be 2-D real matrices");
   endif
   if (! size_equal (x, y, z))
     error ("surfnorm: X, Y, and Z must have the same dimensions");
   endif
 
-  ## Make life easier, and avoid having to do the extrapolation later, do
-  ## a simpler linear extrapolation here. This is approximative, and works
-  ## badly for closed surfaces like spheres.
-  xx = [2 .* x(:,1) - x(:,2), x, 2 .* x(:,end) - x(:,end-1)];
-  xx = [2 .* xx(1,:) - xx(2,:); xx; 2 .* xx(end,:) - xx(end-1,:)];
-  yy = [2 .* y(:,1) - y(:,2), y, 2 .* y(:,end) - y(:,end-1)];
-  yy = [2 .* yy(1,:) - yy(2,:); yy; 2 .* yy(end,:) - yy(end-1,:)];
-  zz = [2 .* z(:,1) - z(:,2), z, 2 .* z(:,end) - z(:,end-1)];
-  zz = [2 .* zz(1,:) - zz(2,:); zz; 2 .* zz(end,:) - zz(end-1,:)];
+  ## Do a linear extrapolation for mesh points on the boundary so that the mesh
+  ## is increased by 1 on each side.  This allows each original meshgrid point
+  ## to be surrounded by four quadrilaterals and the same calculation can be
+  ## used for interior and boundary points.  The extrapolation works badly for
+  ## closed surfaces like spheres.
+  xx = [2 * x(:,1) - x(:,2), x, 2 * x(:,end) - x(:,end-1)];
+  xx = [2 * xx(1,:) - xx(2,:); xx; 2 * xx(end,:) - xx(end-1,:)];
+  yy = [2 * y(:,1) - y(:,2), y, 2 * y(:,end) - y(:,end-1)];
+  yy = [2 * yy(1,:) - yy(2,:); yy; 2 * yy(end,:) - yy(end-1,:)];
+  zz = [2 * z(:,1) - z(:,2), z, 2 * z(:,end) - z(:,end-1)];
+  zz = [2 * zz(1,:) - zz(2,:); zz; 2 * zz(end,:) - zz(end-1,:)];
 
   u.x = xx(1:end-1,1:end-1) - xx(2:end,2:end);
   u.y = yy(1:end-1,1:end-1) - yy(2:end,2:end);
@@ -101,17 +110,19 @@
 
   ## Create normal vectors as mesh vectices from normals at mesh centers
   nx = (w.x(1:end-1,1:end-1) + w.x(1:end-1,2:end) +
-        w.x(2:end,1:end-1) + w.x(2:end,2:end)) ./ 4;
+        w.x(2:end,1:end-1) + w.x(2:end,2:end)) / 4;
   ny = (w.y(1:end-1,1:end-1) + w.y(1:end-1,2:end) +
-        w.y(2:end,1:end-1) + w.y(2:end,2:end)) ./ 4;
+        w.y(2:end,1:end-1) + w.y(2:end,2:end)) / 4;
   nz = (w.z(1:end-1,1:end-1) + w.z(1:end-1,2:end) +
-        w.z(2:end,1:end-1) + w.z(2:end,2:end)) ./ 4;
+        w.z(2:end,1:end-1) + w.z(2:end,2:end)) / 4;
 
+  ## FIXME: According to Matlab documentation the vertex normals
+  ##        returned are not normalized.
   ## Normalize the normal vectors
   len = sqrt (nx.^2 + ny.^2 + nz.^2);
-  nx = nx ./ len;
-  ny = ny ./ len;
-  nz = nz ./ len;
+  nx ./= len;
+  ny ./= len;
+  nz ./= len;
 
   if (nargout == 0)
     oldfig = [];
@@ -125,10 +136,26 @@
       old_hold_state = get (hax, "nextplot");
       unwind_protect
         set (hax, "nextplot", "add");
-        plot3 ([x(:)'; x(:).' + nx(:).' ; NaN(size(x(:).'))](:),
-               [y(:)'; y(:).' + ny(:).' ; NaN(size(y(:).'))](:),
-               [z(:)'; z(:).' + nz(:).' ; NaN(size(z(:).'))](:),
-               varargin{ioff:end});
+
+        ## FIXME: Scale unit normals by data aspect ratio in order for
+        ##        normals to appear correct.
+        ##daratio = daspect (hax);
+        ##daspect ("manual");
+        ##len = norm (daratio);
+        ## This assumes an even meshgrid which isn't a great assumption
+        ##dx = x(1,2) - x(1,1);  
+        ##dy = y(2,1) - y(1,1);  
+        ##nx *= daratio(1);
+        ##ny *= daratio(2);
+        ##nz *= daratio(3);
+        ##len = sqrt (nx.^2 + ny.^2 + nz.^2);
+        ##nx ./= len;
+        ##ny ./= len;
+        ##nz ./= len;
+        plot3 ([x(:).'; x(:).' + nx(:).' ; NaN(size(x(:).'))](:),
+               [y(:).'; y(:).' + ny(:).' ; NaN(size(y(:).'))](:),
+               [z(:).'; z(:).' + nz(:).' ; NaN(size(z(:).'))](:),
+               "r");
       unwind_protect_cleanup
         set (hax, "nextplot", old_hold_state);
       end_unwind_protect
@@ -150,17 +177,25 @@
 %!demo
 %! clf;
 %! colormap ('default');
-%! [x, y, z] = peaks (10);
-%! surfnorm (x, y, z);
+%! surfnorm (peaks (32));
+%! shading interp;
+%! title ({'surfnorm() shows surface and normals at each vertex', ...
+%!         'peaks() function with 32 faces'});
 
 %!demo
 %! clf;
 %! colormap ('default');
-%! surfnorm (peaks (10));
+%! [x, y, z] = sombrero (10);
+%! surfnorm (x, y, z);
 
-%!demo
-%! clf;
-%! colormap ('default');
-%! surfnorm (peaks (32));
-%! shading interp;
+%% Test input validation
+%!error surfnorm ()
+%!error surfnorm (1,2)
+%!error <X, Y, and Z must be 2-D real matrices> surfnorm (i)
+%!error <X, Y, and Z must be 2-D real matrices> surfnorm (i, 1, 1)
+%!error <X, Y, and Z must be 2-D real matrices> surfnorm (1, i, 1)
+%!error <X, Y, and Z must be 2-D real matrices> surfnorm (1, 1, i)
+%!error <X, Y, and Z must have the same dimensions> surfnorm ([1 2], 1, 1)
+%!error <X, Y, and Z must have the same dimensions> surfnorm (1, [1 2], 1)
+%!error <X, Y, and Z must have the same dimensions> surfnorm (1, 1, [1 2])
 
--- a/scripts/plot/draw/tetramesh.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/draw/tetramesh.m	Mon Jan 12 09:17:35 2015 -0800
@@ -43,7 +43,7 @@
 ## @qcode{"visible"} property @qcode{"on"} or @qcode{"off"}.
 ##
 ## Type @code{demo tetramesh} to see examples on using @code{tetramesh}.
-## @seealso{trimesh, delaunay3, delaunayn, patch}
+## @seealso{trimesh, delaunay, delaunayn, patch}
 ## @end deftypefn
 
 ## Author: Martin Helm <martin@mhelm.de>
@@ -130,7 +130,7 @@
 %! x = [x(:); 0];
 %! y = [y(:); 0];
 %! z = [z(:); 0];
-%! tetra = delaunay3 (x, y, z);
+%! tetra = delaunay (x, y, z);
 %! X = [x(:) y(:) z(:)];
 %! colormap (jet (64));
 %! h = tetramesh (tetra, X);
@@ -147,7 +147,7 @@
 %! x = [x(:); 0];
 %! y = [y(:); 0];
 %! z = [z(:); 0];
-%! tetra = delaunay3 (x, y, z);
+%! tetra = delaunay (x, y, z);
 %! X = [x(:) y(:) z(:)];
 %! colormap (gray (256));
 %! tetramesh (tetra, X, 21:20:241, 'EdgeColor', 'w');
--- a/scripts/plot/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,221 +0,0 @@
-FCN_FILE_DIRS += plot
-
-plot_GEN_FCN_FILES = \
-  plot/gnuplot_binary.m
-
-GEN_FCN_FILES += $(plot_GEN_FCN_FILES)
-
-plot_PRIVATE_FCN_FILES = \
-  plot/private/__actual_axis_position__.m \
-  plot/private/__add_datasource__.m \
-  plot/private/__add_default_menu__.m \
-  plot/private/__axes_limits__.m \
-  plot/private/__axis_label__.m \
-  plot/private/__bar__.m \
-  plot/private/__clabel__.m \
-  plot/private/__contour__.m \
-  plot/private/__default_plot_options__.m \
-  plot/private/__errcomm__.m \
-  plot/private/__errplot__.m \
-  plot/private/__ezplot__.m \
-  plot/private/__file_filter__.m \
-  plot/private/__fltk_file_filter__.m \
-  plot/private/__fltk_ginput__.m \
-  plot/private/__fltk_print__.m \
-  plot/private/__getlegenddata__.m \
-  plot/private/__ghostscript__.m \
-  plot/private/__gnuplot_get_var__.m \
-  plot/private/__gnuplot_ginput__.m \
-  plot/private/__gnuplot_has_feature__.m \
-  plot/private/__gnuplot_has_terminal__.m\
-  plot/private/__gnuplot_open_stream__.m \
-  plot/private/__gnuplot_print__.m \
-  plot/private/__gnuplot_version__.m \
-  plot/private/__go_draw_axes__.m \
-  plot/private/__go_draw_figure__.m \
-  plot/private/__interp_cube__.m \
-  plot/private/__is_function__.m \
-  plot/private/__line__.m \
-  plot/private/__marching_cube__.m \
-  plot/private/__next_line_color__.m \
-  plot/private/__next_line_style__.m \
-  plot/private/__patch__.m \
-  plot/private/__pie__.m \
-  plot/private/__plt__.m \
-  plot/private/__pltopt__.m \
-  plot/private/__print_parse_opts__.m \
-  plot/private/__quiver__.m \
-  plot/private/__scatter__.m \
-  plot/private/__stem__.m \
-  plot/private/__tight_eps_bbox__.m \
-  plot/private/__uigetdir_fltk__.m \
-  plot/private/__uigetfile_fltk__.m \
-  plot/private/__uiputfile_fltk__.m \
-  plot/private/__uiobject_split_args__.m
-
-plot_FCN_FILES = \
-  plot/__gnuplot_drawnow__.m \
-  plot/__plt_get_axis_arg__.m \
-  plot/allchild.m \
-  plot/ancestor.m \
-  plot/area.m \
-  plot/axes.m \
-  plot/axis.m \
-  plot/bar.m \
-  plot/barh.m \
-  plot/box.m \
-  plot/caxis.m \
-  plot/cla.m \
-  plot/clabel.m \
-  plot/clf.m \
-  plot/close.m \
-  plot/closereq.m \
-  plot/colorbar.m \
-  plot/colstyle.m \
-  plot/comet.m \
-  plot/comet3.m \
-  plot/compass.m \
-  plot/contour.m \
-  plot/contour3.m \
-  plot/contourc.m \
-  plot/contourf.m \
-  plot/copyobj.m \
-  plot/cylinder.m \
-  plot/daspect.m \
-  plot/diffuse.m \
-  plot/ellipsoid.m \
-  plot/errorbar.m \
-  plot/ezcontour.m \
-  plot/ezcontourf.m \
-  plot/ezmesh.m \
-  plot/ezmeshc.m \
-  plot/ezplot.m \
-  plot/ezplot3.m \
-  plot/ezpolar.m \
-  plot/ezsurf.m \
-  plot/ezsurfc.m \
-  plot/feather.m \
-  plot/figure.m \
-  plot/fill.m \
-  plot/findall.m \
-  plot/findfigs.m \
-  plot/findobj.m \
-  plot/fplot.m \
-  plot/gca.m \
-  plot/gcbf.m \
-  plot/gcbo.m \
-  plot/gcf.m \
-  plot/gco.m \
-  plot/ginput.m \
-  plot/graphics_toolkit.m \
-  plot/grid.m \
-  plot/gtext.m \
-  plot/guidata.m \
-  plot/guihandles.m \
-  plot/hdl2struct.m \
-  plot/hggroup.m \
-  plot/hidden.m \
-  plot/hist.m \
-  plot/hold.m \
-  plot/isaxes.m \
-  plot/isfigure.m \
-  plot/ishghandle.m \
-  plot/ishold.m \
-  plot/isocolors.m \
-  plot/isonormals.m \
-  plot/isosurface.m \
-  plot/isprop.m \
-  plot/legend.m \
-  plot/line.m \
-  plot/linkprop.m \
-  plot/loglog.m \
-  plot/loglogerr.m \
-  plot/mesh.m \
-  plot/meshc.m \
-  plot/meshgrid.m \
-  plot/meshz.m \
-  plot/ndgrid.m \
-  plot/newplot.m \
-  plot/orient.m \
-  plot/pareto.m \
-  plot/patch.m \
-  plot/pbaspect.m \
-  plot/pcolor.m \
-  plot/peaks.m \
-  plot/pie.m \
-  plot/pie3.m \
-  plot/plot.m \
-  plot/plot3.m \
-  plot/plotmatrix.m \
-  plot/plotyy.m \
-  plot/polar.m \
-  plot/print.m \
-  plot/printd.m \
-  plot/quiver.m \
-  plot/quiver3.m \
-  plot/rectangle.m \
-  plot/refresh.m \
-  plot/refreshdata.m \
-  plot/ribbon.m \
-  plot/rose.m \
-  plot/saveas.m \
-  plot/scatter.m \
-  plot/scatter3.m \
-  plot/semilogx.m \
-  plot/semilogxerr.m \
-  plot/semilogy.m \
-  plot/semilogyerr.m \
-  plot/shading.m \
-  plot/shg.m \
-  plot/shrinkfaces.m \
-  plot/slice.m \
-  plot/sombrero.m \
-  plot/specular.m \
-  plot/sphere.m \
-  plot/stairs.m \
-  plot/stem.m \
-  plot/stem3.m \
-  plot/stemleaf.m \
-  plot/struct2hdl.m \
-  plot/subplot.m \
-  plot/surf.m \
-  plot/surface.m \
-  plot/surfc.m \
-  plot/surfl.m \
-  plot/surfnorm.m \
-  plot/tetramesh.m \
-  plot/text.m \
-  plot/title.m \
-  plot/trimesh.m \
-  plot/triplot.m \
-  plot/trisurf.m \
-  plot/uicontextmenu.m \
-  plot/uicontrol.m \
-  plot/uigetdir.m \
-  plot/uigetfile.m \
-  plot/uimenu.m \
-  plot/uipanel.m \
-  plot/uipushtool.m \
-  plot/uiputfile.m \
-  plot/uiresume.m \
-  plot/uitoggletool.m \
-  plot/uitoolbar.m \
-  plot/uiwait.m \
-  plot/view.m \
-  plot/waitbar.m \
-  plot/waitforbuttonpress.m \
-  plot/waterfall.m \
-  plot/whitebg.m \
-  plot/xlabel.m \
-  plot/xlim.m \
-  plot/ylabel.m \
-  plot/ylim.m \
-  plot/zlabel.m \
-  plot/zlim.m \
-  $(plot_PRIVATE_FCN_FILES)
-
-FCN_FILES += $(plot_FCN_FILES)
-
-PKG_ADD_FILES += plot/PKG_ADD
-
-DIRSTAMP_FILES += plot/$(octave_dirstamp)
--- a/scripts/plot/util/__actual_axis_position__.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/util/__actual_axis_position__.m	Mon Jan 12 09:17:35 2015 -0800
@@ -84,3 +84,6 @@
   endif
 endfunction
 
+
+## No test coverage for internal function.  It is tested through calling fcn.
+%!assert (1)
--- a/scripts/plot/util/__default_plot_options__.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/util/__default_plot_options__.m	Mon Jan 12 09:17:35 2015 -0800
@@ -33,3 +33,13 @@
 
 endfunction
 
+
+%!test
+%! options = __default_plot_options__ ();
+%! assert (isfield (options, "key"));
+%! assert (options.key, "");
+%! assert (options.color, []);
+%! assert (options.linestyle, []);
+%! assert (options.marker, []);
+%! assert (options.errorstyle, []);
+
--- a/scripts/plot/util/__gnuplot_drawnow__.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/util/__gnuplot_drawnow__.m	Mon Jan 12 09:17:35 2015 -0800
@@ -77,7 +77,7 @@
     term = gnuplot_default_term (plot_stream);
     if (strcmp (term, "dumb"))
       ## popen2 eats stdout of gnuplot, use temporary file instead
-      dumb_tmp_file = tmpnam ();
+      dumb_tmp_file = tempname ();
       enhanced = gnuplot_set_term (plot_stream(1), new_stream, h,
                                    term, dumb_tmp_file);
     else
--- a/scripts/plot/util/__next_line_color__.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/util/__next_line_color__.m	Mon Jan 12 09:17:35 2015 -0800
@@ -52,3 +52,22 @@
 
 endfunction
 
+
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   hax = axes ();
+%!   set (hax, "colororder", [1 0 0; 0 1 0; 0 0 1]);
+%!   hold on;
+%!   h = plot (1:5,1:5,'o', 1:4,1:4, "x", 1:3,1:3, "d");
+%!   assert (get (h, "color"), {[1 0 0]; [0 1 0]; [0 0 1]});
+%!   cla (hax);
+%!   hold all;
+%!   h1 = plot (1:5,1:5,'o');
+%!   h2 = plot (1:4,1:4, "x");
+%!   h3 = plot (1:3,1:3, "d");
+%!   assert (get ([h1;h2;h3], "color"), {[1 0 0]; [0 1 0]; [0 0 1]});
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
--- a/scripts/plot/util/__next_line_style__.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/util/__next_line_style__.m	Mon Jan 12 09:17:35 2015 -0800
@@ -56,3 +56,23 @@
 
 endfunction
 
+
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   hax = axes ();
+%!   set (hax, "colororder", [0 0 1]);
+%!   set (hax, "linestyleorder", {"-", ":", "--"});
+%!   hold on;
+%!   h = plot (1:5,1:5, 1:4,1:4, 1:3,1:3);
+%!   assert (get (h, "linestyle"), {"-"; ":"; "--"});
+%!   cla (hax);
+%!   hold all;
+%!   h1 = plot (1:5,1:5);
+%!   h2 = plot (1:4,1:4);
+%!   h3 = plot (1:3,1:3);
+%!   assert (get ([h1;h2;h3], "linestyle"), {"-"; ":"; "--"});
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
--- a/scripts/plot/util/__pltopt__.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/util/__pltopt__.m	Mon Jan 12 09:17:35 2015 -0800
@@ -233,3 +233,39 @@
 
 endfunction
 
+
+## Only cursory testing.  Real testing done by appearance of plots.
+%test
+%! opts = __pltopt__ ("abc", "");
+%! assert (opts.color, []);
+%! assert (opts.linestyle, []);
+%! assert (opts.marker, []);
+%! assert (opts.key, "");
+%!test
+%! opts = __pltopt__ ("abc", "r:x");
+%! assert (opts.color, [1 0 0]);
+%! assert (opts.linestyle, ":");
+%! assert (opts.marker, "x");
+%!test
+%! opts = __pltopt__ ("abc", "2square");
+%! assert (opts.color, [0 1 0]);
+%! assert (opts.linestyle, "none");
+%! assert (opts.marker, "s");
+%!test
+%! opts = __pltopt__ ("abc", ";Title;");
+%! assert (opts.key, "Title");
+%! assert (opts.color, []);
+%! assert (opts.linestyle, []);
+%! assert (opts.marker, []);
+%!test
+%! opts = __pltopt__ ("__errplot__", "~>r");
+%! assert (opts.errorstyle, "~>");
+%! assert (opts.color, [1 0 0 ]);
+%! assert (opts.linestyle, []);
+%! assert (opts.marker, []);
+
+## Test input validation
+%!error <argument must be a character string or cell array> __pltopt__ ("abc", 1)
+%!error <unfinished key label> __pltopt__ ("abc", "rx;my_title", true)
+%!error <unrecognized format character: 'u'> __pltopt__ ("abc", "u", true)
+
--- a/scripts/plot/util/colstyle.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/util/colstyle.m	Mon Jan 12 09:17:35 2015 -0800
@@ -36,10 +36,7 @@
   try
     opt = __pltopt__ ("colstyle", style);
     l = opt.linestyle;
-    c = opt.color;
-    m = opt.marker;
-    msg = [];
-    switch (c)
+    switch (opt.color)
       case [0 0 0]
         c = "k";
       case [1 0 0]
@@ -56,7 +53,11 @@
         c = "c";
       case [0 1 1]
         c = "w";
+      otherwise
+        c = opt.color;
     endswitch
+    m = opt.marker;
+    msg = [];
   catch
     l = c = m = [];
     msg = lasterr ();
@@ -86,5 +87,5 @@
 %% Test input validation
 %!error colstyle ()
 %!error colstyle (1, 2)
-%!error colstyle (1.5)
+%!error <STYLE must be a string> colstyle (1.5)
 
--- a/scripts/plot/util/copyobj.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/util/copyobj.m	Mon Jan 12 09:17:35 2015 -0800
@@ -46,7 +46,7 @@
 
   ## current figure and axes
   cf = gcf ();
-  ca = gca ();
+  ca = get (cf, "currentaxes");
   
   ## compatibility of input handles
   kididx = find (strcmp (alltypes, get (horig).type));
@@ -65,53 +65,67 @@
 
   ## reset current figure (and eventually axes) to original
   set (0, "currentfigure", cf);
-  if (get (hnew, "parent") == cf)
+  if (get (hnew, "parent") == cf && ! isempty (ca))
     set (cf, "currentaxes", ca)
   endif
   
 endfunction
 
 
+## Absurd number of drawnow() function calls in demos is due to problem
+## with FLTK backend which is not respecting the set ('position') call.
+
 %!demo
-%! hdl = figure (1234);
-%! clf;
+%! hobj = figure ('name', 'Original', 'numbertitle', 'off');
 %! hold on;
 %! x = 1:10;
 %! y = x.^2;
 %! dy = 2 * (.2 * x);
 %! y2 = (x - 3).^2;
-%! hg = errorbar (x, y, dy,'#~');
+%! hg = errorbar (x, y, dy);
 %! set (hg, 'marker', '^', 'markerfacecolor', rand (1,3));
 %! plot (x, y2, 'ok-');
 %! legend ('errorbar', 'line');
-%! hnew = copyobj (hdl);
+%! drawnow ();
+%! pos = get (hobj, 'position');
+%! scrn = get (0, 'screensize');
+%! set (hobj, 'position', [scrn(3)/2-pos(3)-10, scrn(4)/2-pos(4)/2, pos(3:4)]);
+%! drawnow ();
+%! hnew = copyobj (hobj);
+%! drawnow ();
+%! set (hnew, 'name', 'Copyobj');
+%! drawnow ();
+%! set (hnew, 'position', [scrn(3)/2, scrn(4)/2-pos(4)/2, pos(3:4)]);
+%! drawnow ();
 
-%!#demo
-%! ## FIXME: This demo fails for an obscure reason.
-%! ## It appears that there is something wrong with Octave code for patches.
-%! ## This demo must remain commented out until patch() has been reworked.
-%! unwind_protect
-%!   hdl = figure (1234);
-%!   clf;
-%!   subplot (2,2,1);
-%!   hold on;
-%!   contourf (rand (10, 10));
-%!   colorbar ();
-%!   subplot (2,2,2);
-%!   quiver (rand (10, 10), rand (10, 10));
-%!   subplot (2,2,3);
-%!   colormap (jet (64));
-%!   hold on;
-%!   sombrero ();
-%!   colorbar ('peer', gca, 'NorthOutside');
-%!   subplot (2,2,4);
-%!   imagesc (rand (30, 30));
-%!   text (15, 15, 'Rotated text', ...
-%!         'HorizontAlalignment', 'Center', 'Rotation', 30);
-%!   hnew = copyobj (hdl);
-%! unwind_protect_cleanup
-%!   close all;
-%! end_unwind_protect
+%!demo
+%! hobj = figure ('name', 'Original', 'numbertitle', 'off');
+%! subplot (2,2,1);
+%! hold on;
+%! contourf (rand (10, 10));
+%! colorbar ();
+%! subplot (2,2,2);
+%! quiver (rand (10, 10), rand (10, 10));
+%! subplot (2,2,3);
+%! colormap (jet (64));
+%! hold on;
+%! sombrero ();
+%! colorbar ('peer', gca, 'NorthOutside');
+%! subplot (2,2,4);
+%! imagesc (rand (30, 30));
+%! text (15, 15, 'Rotated text', ...
+%!       'HorizontAlalignment', 'Center', 'Rotation', 30);
+%! drawnow ();
+%! pos = get (hobj, 'position');
+%! scrn = get (0, 'screensize');
+%! set (hobj, 'position', [scrn(3)/2-pos(3)-10, scrn(4)/2-pos(4)/2, pos(3:4)]);
+%! drawnow ();
+%! hnew = copyobj (hobj);
+%! drawnow ();
+%! set (hnew, 'name', 'Copyobj');
+%! drawnow ();
+%! set (hnew, 'position', [scrn(3)/2, scrn(4)/2-pos(4)/2, pos(3:4)]);
+%! drawnow ();
 
 %!testif HAVE_MAGICK
 %! toolkit = graphics_toolkit ();
@@ -134,8 +148,8 @@
 %!   s1 = hdl2struct (h1);
 %!   h2 = struct2hdl (s1);
 %!   s2 = hdl2struct (h2);
-%!   png1 = strcat (tmpnam (), ".png");
-%!   png2 = strcat (tmpnam (), ".png");
+%!   png1 = [tempname() ".png"];
+%!   png2 = [tempname() ".png"];
 %!   unwind_protect
 %!     print (h1, png1);
 %!     [img1, map1, alpha1] = imread (png1);
@@ -154,3 +168,17 @@
 %!   graphics_toolkit (toolkit);
 %! end_unwind_protect
 
+%!test 
+%! unwind_protect
+%!   tag = "foo";
+%!   hf = figure ("visible", "off");
+%!   hax = axes ("tag", tag);
+%!   hpa = patch ();
+%!   set (hpa, "facecolor", [.5 .5 .5], "tag", tag)
+%!   hax2 = copyobj (hax, hf);
+%!   assert (get (hax2, "tag"), tag)
+%!   hpa2 = get (hax2, "children");
+%!   assert (get (hpa2, "facecolor"), [.5 .5 .5])
+%! unwind_protect_cleanup
+%!   close (hf)
+%! end_unwind_protect
--- a/scripts/plot/util/figure.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/util/figure.m	Mon Jan 12 09:17:35 2015 -0800
@@ -83,16 +83,7 @@
   endif
 
   if (init_new_figure)
-    if (ismac () && strcmp (graphics_toolkit (), "fltk"))
-      ## FIXME: Hack for fltk-aqua to work around bug #31931
-      f = __go_figure__ (f);
-      drawnow ();
-      if (! isempty (varargin))
-        set (f, varargin{:});
-      endif
-    else
-      f = __go_figure__ (f, varargin{:});
-    endif
+    f = __go_figure__ (f, varargin{:});
     __add_default_menu__ (f);
   elseif (nargs > 0)
     set (f, varargin{:});
--- a/scripts/plot/util/findall.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/util/findall.m	Mon Jan 12 09:17:35 2015 -0800
@@ -56,7 +56,7 @@
 %! unwind_protect
 %!   h = findall (hf);
 %!   all_handles(1) = {"figure"};
-%!   all_handles(2:12,1) = {"uimenu"};
+%!   all_handles(2:18,1) = {"uimenu"};
 %!   assert (get (h, "type"), all_handles);
 %! unwind_protect_cleanup
 %!   close (hf);
--- a/scripts/plot/util/findobj.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/util/findobj.m	Mon Jan 12 09:17:35 2015 -0800
@@ -100,9 +100,6 @@
         if (strcmpi (varargin{n1}, "flat"))
           depth = 0;
           n1 = n1 + 1;
-        elseif (strcmpi (varargin{n1}, "-depth"))
-          depth = varargin{n1+1};
-          n1 = n1 + 2;
         endif
       else
         error ("findobj: properties and options must be strings");
@@ -134,7 +131,18 @@
     endif
     logicaloperator{np} = "and";
     if (ischar (args{na}))
-      if (strcmpi (args{na}, "-regexp"))
+      if (strcmpi (args{na}, "-property"))
+        if (na + 1 <= numel (args))
+          na = na + 1;
+          property(np) = 1;
+          pname{np} = args{na};
+          na = na + 1;
+          pvalue{np} = [];
+          np = np + 1;
+        else
+          error ("findobj: inconsistent number of arguments");
+        endif
+      elseif (strcmpi (args{na}, "-regexp"))
         if (na + 2 <= numel (args))
           regularexpression(np) = 1;
           na = na + 1;
@@ -146,14 +154,11 @@
         else
           error ("findobj: inconsistent number of arguments");
         endif
-      elseif (strcmpi (args{na}, "-property"))
+      elseif (strcmpi (args{na}, "-depth"))
         if (na + 1 <= numel (args))
           na = na + 1;
-          property(np) = 1;
-          pname{np} = args{na};
+          depth = args{na};
           na = na + 1;
-          pvalue{np} = [];
-          np = np + 1;
         else
           error ("findobj: inconsistent number of arguments");
         endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/util/frame2im.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,105 @@
+## Copyright (C) 2014 Carnë Draug
+##
+## 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{x}, @var{map}] =} frame2im (@var{f})
+## Convert movie frame to indexed image.
+##
+## A movie frame is simply a struct with the fields @qcode{"cdata"} and
+## @qcode{"colormap"}.
+##
+## Support for N-dimensional images or movies is given when @var{f} is a
+## struct array.  In such cases, @var{x} will be a @nospell{MxNx1xK or MxNx3xK}
+## for indexed and RGB movies respectively, with each frame concatenated on
+## the 4th dimension.
+##
+## @seealso{im2frame}
+## @end deftypefn
+
+## Author: Carnë Draug <carandraug@octave.org>
+
+function [x, map] = frame2im (frame)
+
+  if (nargin != 1)
+    print_usage ();
+  elseif (! all (isfield (frame, {"cdata", "colormap"})))
+    error ("frame2im: F must be a struct with the fields colormap and cdata");
+  endif
+
+  n = numel (frame);
+  if (n == 0)
+    error ("frame2im: FRAME is empty");
+  else
+    x   = [frame.cdata];
+    map = frame(1).colormap;
+  endif
+
+  ## support for N dimensional images if we receive a struct array
+  if (n > 1)
+    x = reshape (x, rows (x), columns (x) / n, n, size (frame(1).cdata, 3));
+    x = permute (x, [1 2 4 3]);
+  endif
+
+endfunction
+
+%!function f = make_rgb_f ()
+%! f = randi ([0 255], 10, 20, 3);
+%!endfunction
+
+%!function f = make_ind_f ()
+%! f = randi ([1 100], 10, 20, 3);
+%!endfunction
+
+%!test
+%! x = make_ind_f ();
+%! cmap = jet (100);
+%! frame = struct ("cdata", x, "colormap", cmap);
+%! [rx, rcmap] = frame2im (frame);
+%! assert (rx, x);
+%! assert (rcmap, cmap);
+
+%!test
+%! rgb = make_rgb_f ();
+%! frame = struct ("cdata", rgb, "colormap", []);
+%! [rrgb, rcmap] = frame2im (frame);
+%! assert (rrgb, rgb);
+%! assert (rcmap, []);
+
+%!test
+%! f1 = make_rgb_f ();
+%! f2 = make_rgb_f ();
+%! f3 = make_rgb_f ();
+%! f4 = make_rgb_f ();
+%! rgb = {f1, f2, f3, f4};
+%! movie = struct ("cdata", rgb, "colormap", []);
+%! [rx, rcmap] = frame2im (movie);
+%! assert (rx, cat (4, f1, f2, f3, f4));
+%! assert (rcmap, []);
+
+%!test
+%! f1 = make_ind_f ();
+%! f2 = make_ind_f ();
+%! f3 = make_ind_f ();
+%! f4 = make_ind_f ();
+%! ind = {f1, f2, f3, f4};
+%! cmap = jet (100);
+%! movie = struct ("cdata", ind, "colormap", cmap);
+%! [rx, rcmap] = frame2im (movie);
+%! assert (rx, cat (4, f1, f2, f3, f4));
+%! assert (rcmap, cmap);
+
--- a/scripts/plot/util/ginput.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/util/ginput.m	Mon Jan 12 09:17:35 2015 -0800
@@ -39,16 +39,15 @@
     print_usage ();
   endif
 
-  f = gcf ();
   a = gca ();  # Create an axis, if necessary
   drawnow ();
-  toolkit = get (f, "__graphics_toolkit__");
+  toolkit = get (gcf, "__graphics_toolkit__");
 
   varargout = cell (1, nargout);
   if (nargin == 0)
-    [varargout{:}] = feval (["__" toolkit "_ginput__"], f);
+    [varargout{:}] = feval (["__" toolkit "_ginput__"]);
   else
-    [varargout{:}] = feval (["__" toolkit "_ginput__"], f, n);
+    [varargout{:}] = feval (["__" toolkit "_ginput__"], n);
   endif
 
 endfunction
--- a/scripts/plot/util/hdl2struct.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/util/hdl2struct.m	Mon Jan 12 09:17:35 2015 -0800
@@ -23,7 +23,7 @@
 ##
 ## The fields of the structure @var{s} are @qcode{"type"}, @qcode{"handle"},
 ## @qcode{"properties"}, @qcode{"children"}, and @qcode{"special"}.
-## @seealso{struct2hdl, findobj}
+## @seealso{struct2hdl, hgsave, findobj}
 ## @end deftypefn
 
 ## Author: pdiribarne <pdiribarne@new-host.home>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/util/hgload.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,69 @@
+## Copyright (C) 2014 Massimiliano Fasi
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {@var{h} =} hgload (@var{filename})
+## Load the graphics object in @var{filename} into the graphics handle @var{h}.
+##
+## If @var{filename} has no extension, Octave will try to find the file with
+## and without the standard extension of @file{.ofig}.
+## @seealso{hgsave, struct2hdl}
+## @end deftypefn
+
+## Author: Massimiliano Fasi
+
+function h = hgload (filename)
+
+  ## Check input arguments
+  if (nargin != 1)
+    print_usage ();
+  endif
+
+  ## Check file existence
+  [~, ~, ext] = fileparts (filename);
+  if (isempty (ext))
+    if (! isempty (file_in_loadpath ([filename ".ofig"])))
+      filename = [filename ".ofig"];
+    elseif (isempty (file_in_loadpath (filename)))
+      error ("hgload: unable to locate file %s", filename);
+    endif
+  else
+    if (isempty (file_in_loadpath (filename)))
+      error ("hgload: unable to locate file %s", filename);
+    endif
+  endif
+    
+  ## Load the handle
+  try
+    stmp = load (filename, "s_oct40");
+  catch
+    error ("hgload: could not load hgsave-formatted object in file %s", filename);
+  end_try_catch
+
+  h = struct2hdl (stmp.s_oct40);
+  
+endfunction
+
+
+## Functional test for hgload/hgsave pair is in hgsave.m
+
+%% Test input validation
+%!error hgload ()
+%!error hgload (1, 2)
+%!error <unable to locate file> hgload ("%%_A_REALLY_UNLIKELY_FILENAME_%%")
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/util/hgsave.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,128 @@
+## Copyright (C) 2014 Massimiliano Fasi
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {Function File} {} hgsave (@var{filename})
+## @deftypefnx {Function File} {} hgsave (@var{h}, @var{filename})
+## @deftypefnx {Function File} {} hgsave (@var{h}, @var{filename}, @var{fmt})
+## Save the graphics handle @var{h} to the file @var{filename} in the format
+## @var{fmt}.
+##
+## If unspecified, @var{h} is the current figure as returned by @code{gcf}. 
+## When @var{filename} does not have an extension the default filename
+## extension @file{.ofig} will be appended.  If present, @var{fmt} should 
+## should be one of the following:
+##
+## @itemize @bullet
+## @item @option{-binary}, @option{-float-binary}
+##
+## @item @option{-hdf5}, @option{-float-hdf5}
+##
+## @item @option{-V7}, @option{-v7}, @code{-7}, @option{-mat7-binary}
+##
+## @item @option{-V6}, @option{-v6}, @code{-6}, @option{-mat6-binary}
+##
+## @item @option{-text}
+##
+## @item @option{-zip}, @option{-z}
+## @end itemize
+##
+## When producing graphics for final publication use @code{print} or
+## @code{saveas}.  When it is important to be able to continue to edit a
+## figure as an Octave object, use @code{hgsave}/@code{hgload}.
+## @seealso{hgload, hdl2struct, saveas, print}
+## @end deftypefn
+
+## Author: Massimiliano Fasi
+
+function hgsave (h, filename, fmt = "-binary")
+
+  if (nargin < 1 || nargin > 3)
+    print_usage ();
+  endif
+
+  ## Check input arguments
+  if (nargin == 1 && ischar (h))
+    filename = h;
+    h = get (0, "currentfigure");
+    if (isempty (h))
+      error ("hgsave: No current figure to save");
+    endif
+  elseif (! (ishandle (h) && ischar (filename)))
+    print_usage ();
+  endif
+
+  ## Check file extension
+  [~, ~, ext] = fileparts (filename);
+  if (isempty (ext))
+    filename = [filename ".ofig"];
+  endif
+
+  s_oct40 = hdl2struct (h);
+  save (fmt, filename, "s_oct40");
+
+endfunction
+
+
+%!testif HAVE_MAGICK
+%! toolkit = graphics_toolkit ();
+%! graphics_toolkit ("gnuplot");
+%! unwind_protect
+%!   h1 = figure ("visible", "off");
+%!   x = 0:0.1:2*pi;
+%!   y1 = sin (x);
+%!   y2 = exp (x - 1);
+%!   ax = plotyy (x,y1, x-1,y2, @plot, @semilogy);
+%!   xlabel ("X");
+%!   ylabel (ax(1), "Axis 1");
+%!   ylabel (ax(2), "Axis 2");
+%!   axes (ax(1));
+%!   text (0.5, 0.5, "Left Axis", ...
+%!         "color", [0 0 1], "horizontalalignment", "center");
+%!   axes (ax(2));
+%!   text (4.5, 80, "Right Axis", ...
+%!         "color", [0 0.5 0], "horizontalalignment", "center");
+%!   ftmp = [tempname() ".ofig"];
+%!   png1 = [tempname() ".png"];
+%!   png2 = [tempname() ".png"];
+%!   unwind_protect
+%!     hgsave (h1, ftmp);
+%!     print (h1, png1);
+%!     [img1, map1, alpha1] = imread (png1);
+%!     h2 = hgload (ftmp);
+%!     print (h2, png2);
+%!     [img2, map2, alpha2] = imread (png2);
+%!   unwind_protect_cleanup
+%!     unlink (ftmp);
+%!     unlink (png1);
+%!     unlink (png2);
+%!   end_unwind_protect
+%!   assert (img1, img2);
+%!   assert (map1, map2);
+%!   assert (alpha1, alpha2);
+%! unwind_protect_cleanup
+%!   close (h1);
+%!   close (h2);
+%!   graphics_toolkit (toolkit);
+%! end_unwind_protect
+
+%% Test input validation
+%!error hgsave ()
+%!error hgsave (1, 2, 3, 4)
+%!error hgsave ("abc", "def")
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/util/im2frame.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,101 @@
+## Copyright (C) 2014 Carnë Draug
+##
+## 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} {} im2frame (@var{rgb})
+## @deftypefnx {Function File} {} im2frame (@var{x}, @var{map})
+## Convert image to movie frame.
+##
+## A movie frame is simply a struct with the fields @qcode{"cdata"} and
+## @qcode{"colormap"}.
+##
+## Support for N-dimensional images is given when each image projection,
+## matrix sizes of @nospell{MxN and MxNx3} for RGB images, is concatenated on
+## the fourth dimension.  In such cases, the returned value is a struct array.
+##
+## @seealso{frame2im}
+## @end deftypefn
+
+## Author: Carnë Draug <carandraug@octave.org>
+
+function [frame] = im2frame (x, map = [])
+
+  if (nargin < 1 || nargin > 2)
+    print_usage ();
+  elseif (ndims (x) > 4)
+    error ("im2frame: X and RGB must be a single image");
+  endif
+
+  ## Matlab documentation is incorrect.  Singleton 3rd dimension will error
+  ## without cmap (no use of default cmap), and cmap is added to the frame
+  ## even when image is RGB.
+
+  nchannels = size (x, 3);
+  if (nchannels == 3)
+    ## RGB image, do nothing
+  elseif (nchannels == 1)
+    if (nargin < 2)
+      error ("im2frame: MAP required for indexed images");
+    endif
+    [x, map] = ind2x ("im2frame", x, map);
+  else
+    error ("im2frame: first argument must be indexed or RGB image");
+  endif
+
+  ## support N dimensional images and return a struct array
+  if (ndims (x) == 4)
+    x = reshape (num2cell (x, [1 2 3]), 1, size (x, 4));
+  endif
+
+  frame = struct ("cdata", x, "colormap", map);
+endfunction
+
+%!function f = make_rgb_f ()
+%! f = randi ([0 255], 10, 20, 3);
+%!endfunction
+
+%!function f = make_ind_f ()
+%! f = randi ([1 100], 10, 20, 3);
+%!endfunction
+
+%!test
+%! rgb = make_rgb_f ();
+%! assert (im2frame (rgb), struct ("cdata", rgb, "colormap", []));
+
+%!test
+%! ind = make_ind_f ();
+%! cmap = bone (100);
+%! assert (im2frame (ind, cmap), struct ("cdata", ind, "colormap", cmap));
+
+%!test
+%! rgb1 = make_rgb_f ();
+%! rgb2 = make_rgb_f ();
+%! rgb3 = make_rgb_f ();
+%! rgb4 = make_rgb_f ();
+%! assert (im2frame (cat (4, rgb1, rgb2, rgb3, rgb4)),
+%!         struct ("cdata", {rgb1, rgb2, rgb3, rgb4}, "colormap", []));
+
+%!test
+%! ind1 = make_ind_f ();
+%! ind2 = make_ind_f ();
+%! ind3 = make_ind_f ();
+%! ind4 = make_ind_f ();
+%! cmap = bone (100);
+%! assert (im2frame (cat (4, ind1, ind2, ind3, ind4), cmap),
+%!         struct ("cdata", {ind1, ind2, ind3, ind4}, "colormap", cmap));
+
--- a/scripts/plot/util/isprop.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/util/isprop.m	Mon Jan 12 09:17:35 2015 -0800
@@ -17,11 +17,14 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {@var{res} =} isprop (@var{h}, "@var{prop}")
-## Return true if @var{prop} is a property of the object with handle @var{h}.
+## @deftypefn {Function File} {@var{res} =} isprop (@var{obj}, "@var{prop}")
+## Return true if @var{prop} is a property of the object @var{obj}.
 ##
-## @var{h} may also be an array of handles in which case @var{res} will be a
+## @var{obj} may also be an array of objects in which case @var{res} will be a
 ## logical array indicating whether each handle has the property @var{prop}.
+## 
+## For plotting, @var{obj} is a handle to a graphics object.  Otherwise,
+## @var{obj} should be an instance of a class.
 ## @seealso{get, set, ismethod, isobject}
 ## @end deftypefn
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/util/linkaxes.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,167 @@
+## Copyright (C) 2014 Willem Atsma
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {Function File} {} linkaxes (@var{hax})
+## @deftypefnx {Function File} {} linkaxes (@var{hax}, @var{optstr})
+## Link the axis limits of 2-D plots such that a change in one is
+## propagated to the others.
+##
+## The axes handles to be linked are passed as the first argument @var{hax}.
+##
+## The optional second argument is a string which defines which axis limits
+## will be linked.  The possible values for @var{optstr} are:
+##
+## @table @asis
+## @item @qcode{"x"}
+## Link x-axes
+##
+## @item @qcode{"y"}
+## Link y-axes
+##
+## @item @qcode{"xy"} (default)
+## Link both axes
+##
+## @item @qcode{"off"}
+## Turn off linking
+## @end table
+##
+## If unspecified the default is to link both X and Y axes.
+##
+## When linking, the limits from the first axes in @var{hax} are applied to the
+## other axes in the list.  Subsequent changes to any one of the axes will be
+## propagated to the others.
+##
+## @seealso{linkprop, addproperty}
+## @end deftypefn
+
+## Author: Willem Atsma willem.atsma at tanglebridge.com
+## Created: 2014-03-18
+
+function linkaxes (hax, optstr = "xy")
+
+  if  (nargin < 1 || nargin > 2)
+    print_usage ();
+  endif
+
+  if (numel (hax) < 2)
+    error ("linkaxes: HAX must contain at least 2 handles");
+  elseif (! all (isaxes (hax(:))))
+    error ("linkaxes: HAX must be a vector of axes handles");
+  endif
+
+  ## Check if axes are linked already and clear if found.
+  ## Otherwise, add the necessary linkaxes_data property.
+  for i = 1:length (hax)
+    if (isprop (hax(i), "linkaxes_data"))
+      hld = get (hax(i), "linkaxes_data");
+      try
+        rmappdata (hld, "linkprop_data");
+      end_try_catch
+    else
+      addproperty ("linkaxes_data", hax(i), "any");
+    endif
+  endfor
+
+  switch  (optstr)
+    case "x"
+      hlink = linkprop (hax, "xlim");
+    case "y"
+      hlink = linkprop (hax, "ylim");
+    case "xy"
+      hlink = linkprop (hax, {"xlim" "ylim"});
+    case "off"
+      ## do nothing - link already deleted
+      hlink = [];
+    otherwise
+      error ("linkaxes: unrecognized OPTSTR '%s'", optstr);
+  endswitch
+
+  if (! isempty (hlink))
+    setappdata (hax(1), "linkprop_data", hlink);
+    set (hax, "linkaxes_data", hax(1));
+  else
+    set (hax, "linkaxes_data", []);
+  endif
+
+endfunction
+
+
+%!demo
+%! clf;
+%! hax1 = subplot (3,1,1);
+%! bar (rand (4, 1), 'facecolor', 'r');
+%! hax2 = subplot (3,1,2);
+%! bar (5*rand (4, 1), 'facecolor', 'g');
+%! hax3 = subplot (3,1,3);
+%! bar (10*rand (4, 1), 'facecolor', 'b');
+%! input ('Type <RETURN> to link axes');
+%! linkaxes ([hax1, hax2, hax3]);
+%! input ('Type <RETURN> to change ylim');
+%! ylim (hax3, [0 10]);
+
+%!test
+%! hf1 = figure ("visible", "off");
+%! hax1 = axes ();
+%! plot (1:10);
+%! hf2 = figure ("visible", "off");
+%! hax2 = axes ();
+%! plot (10:-1:1, "-*g");
+%! hf3 = figure ("visible", "off");
+%! hax3 = axes ();
+%! plot (1:10:100, "-xb");
+%!  unwind_protect
+%!   linkaxes ([hax1, hax2, hax3]);
+%!   ## Test initial values taken from first object in list
+%!   assert (xlim (hax3), [0 10]);
+%!   assert (ylim (hax3), [0 10]);
+%!   ## Test linking
+%!   xlim (hax2, [2 8]);
+%!   assert (xlim (hax1), [2 8]);
+%!   assert (xlim (hax3), [2 8]);
+%!   ylim (hax3, "auto");
+%!   assert (ylim (hax1), [0 100]);
+%!   assert (ylim (hax2), [0 100]);
+%!   ## Test re-linking removes old link
+%!   linkaxes ([hax1, hax2]);
+%!   ylim (hax3, [0 50]);
+%!   assert (ylim (hax1), [0 100]);
+%!   assert (ylim (hax2), [0 100]);
+%!   xlim (hax1, [0 4]);
+%!   assert (xlim (hax2), [0 4]);
+%!   ## Test linking of remaining objects after deletion of one object
+%!   linkaxes ([hax1, hax2, hax3]);
+%!   xlim (hax2, [0 1]);
+%!   assert (xlim (hax1), [0 1]);
+%!   assert (xlim (hax3), [0 1]);
+%!   delete (hax2);
+%!   xlim (hax3, [0 2]);
+%!   assert (xlim (hax1), [0 2]);
+%!   ## Test deletion of link
+%!   linkaxes ([hax1, hax3], "off");
+%!   xlim (hax3, [0 3]);
+%!   assert (xlim (hax1), [0 2]);
+%!  unwind_protect_cleanup
+%!   close ([hf1 hf2 hf3]);
+%!  end_unwind_protect
+
+%% Test input validation
+%!error linkaxes ()
+%!error linkaxes (1,2,3)
+%!error <HAX must be a vector of axes handles> linkaxes ([pi, e])
+
--- a/scripts/plot/util/linkprop.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/util/linkprop.m	Mon Jan 12 09:17:35 2015 -0800
@@ -17,14 +17,24 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {@var{hlink} =} linkprop (@var{h}, @var{prop})
-## @deftypefnx {Function File} {@var{hlink} =} linkprop (@var{h}, @{@var{prop1}, @var{prop2}, @dots{}@})
-## Link graphics object properties, such that a change in one is
-## propagated to the others.
+## @deftypefn  {Function File} {@var{hlink} =} linkprop (@var{h}, "@var{prop}")
+## @deftypefnx {Function File} {@var{hlink} =} linkprop (@var{h}, @{"@var{prop1}", "@var{prop2}", @dots{}@})
+## Link graphic object properties, such that a change in one is propagated to
+## the others.
+##
+## The input @var{h} is a vector of graphic handles to link.
 ##
-## @var{prop} can be a string for a single property, or a cell array of strings
-## for multiple properties.  @var{h} is an array of graphics handles which
-## will have their properties linked.
+## @var{prop} may be a string when linking a single property, or a cell array
+## of strings for multiple properties.  During the linking process all
+## properties in @var{prop} will initially be set to the values that exist on
+## the first object in the list @var{h}.
+##
+## The function returns @var{hlink} which is a special object describing the
+## link.  As long as the reference @var{hlink} exists the link between graphic
+## objects will be active.  This means that @var{hlink} must be preserved in
+## a workspace variable, a global variable, or otherwise stored using a
+## function such as @code{setappdata}, @code{guidata}.  To unlink properties,
+## execute @code{clear @var{hlink}}.
 ##
 ## An example of the use of @code{linkprop} is
 ##
@@ -41,62 +51,122 @@
 ## @end group
 ## @end example
 ##
+## @seealso{linkaxes}
 ## @end deftypefn
 
 function hlink = linkprop (h, prop)
+
+  if (nargin != 2)
+    print_usage ();
+  endif
+
+  if (numel (h) < 2)
+    error ("linkprop: H must contain at least 2 handles");
+  elseif (! all (ishandle (h(:))))
+    error ("linkprop: invalid graphic handle in input H");
+  endif
+
   if (ischar (prop))
     prop = {prop};
-  elseif (!iscellstr (prop))
-    error ("linkprop: properties must be a string or cell string array");
+  elseif (! iscellstr (prop))
+    error ("linkprop: PROP must be a string or cell string array");
   endif
 
+  h = h(:)';  # set() prefers column vectors
+  ## Match all objects to the first one in the list before linking 
+  for j = 1 : numel (prop)
+    set (h(2:end), prop{j}, get (h(1), prop{j})); 
+  endfor
+
+  ## Add listeners to all objects
   for i = 1 : numel (h)
     for j = 1 : numel (prop)
-      addlistener (h(i), prop{j}, {@update_prop, h, prop{j}});
+      addlistener (h(i), prop{j},
+                   {@update_prop, [h(1:i-1),h(i+1:end)], prop{j}});
     endfor
   endfor
 
-  ## This should be an object that when destroyed removes the links
-  ## The below is not quite right. As when you call "clear hlink" the
-  ## hggroup continues to exist.
-  hlink = hggroup ();
-  set (hlink, "deletefcn", {@delete_prop, h, prop});
+  hlink = onCleanup (@() delete_linkprop (h, prop));
+
 endfunction
 
-function update_prop (h, d, hlist, prop)
+function update_prop (h, ~, hlist, prop)
   persistent recursion = false;
 
   ## Don't allow recursion
   if (! recursion)
     unwind_protect
       recursion = true;
-      val = get (h, prop);
-      for hh = hlist(:)'
-        if (hh != h)
-          oldval = get (hh, prop);
-          if (! isequal (val, oldval))
-            set (hh, prop, val);
-          endif
-        endif
-      endfor
+      set (hlist(ishandle (hlist)), prop, get (h, prop));
     unwind_protect_cleanup
       recursion = false;
     end_unwind_protect
   endif
 endfunction
 
-function delete_prop (h, d, hlist, prop)
-  ## FIXME. Actually need to delete the linked properties.
-  ## However, only warn if the graphics objects aren't being deleted.
-  warn = false;
-  for h = hlist(:)'
-    if (ishandle (h) && !strcmpi (get (h, "beingdeleted"), "on"))
-      warn = true;
-      break;
+function delete_linkprop (hlist, prop)
+
+  for i = 1 : numel (hlist)
+    if (ishandle (hlist(i)))
+      for j = 1 : numel (prop)
+        dellistener (hlist(i), prop{j}),
+      endfor
     endif
   endfor
-  if (warn)
-    warning ("linkprop: can not remove linked properties");
-  endif
+
 endfunction
 
+
+%!demo
+%! clf;
+%! x = 0:0.1:10;
+%! subplot (1,2,1);
+%! h1 = plot (x, sin (x), 'r');
+%! subplot (1,2,2);
+%! h2 = plot (x, cos (x), 'b');
+%! input ('Type <RETURN> to link plots');
+%! hlink = linkprop ([h1, h2], {'color', 'linestyle'});
+%! input ('Type <RETURN> to change color');
+%! set (h1, 'color', 'green');
+%! input ('Type <RETURN> to change linestyle');
+%! set (h2, 'linestyle', '--');
+
+%!test
+%! hf1 = figure ("visible", "off");
+%! hl1 = plot (1:10, "or");
+%! hf2 = figure ("visible", "off");
+%! hl2 = plot (1:10, "-*g");
+%! hf3 = figure ("visible", "off");
+%! hl3 = plot (1:10, "-xb");
+%! unwind_protect
+%!   hlink = linkprop ([hl1, hl2, hl3], {"color", "linestyle"});
+%!   ## Test initial values taken from first object in list
+%!   assert (get (hl2, "color"), [1 0 0]);
+%!   assert (get (hl3, "linestyle"), "none");
+%!   ## Test linking
+%!   set (hl2, "color", "b");
+%!   assert (get (hl1, "color"), [0 0 1]);
+%!   assert (get (hl3, "color"), [0 0 1]);
+%!   set (hl3, "linestyle", "--");
+%!   assert (get (hl1, "linestyle"), "--");
+%!   assert (get (hl2, "linestyle"), "--");
+%!   ## Test linking of remaining objects after deletion of one object
+%!   delete (hl2);
+%!   set (hl1, "linestyle", ":");
+%!   assert (get (hl3, "linestyle"), ":");
+%!   ## Test deletion of link
+%!   clear hlink;
+%!   set (hl1, "color", "g");
+%!   assert (get (hl3, "color"), [0 0 1]);
+%! unwind_protect_cleanup
+%!   close ([hf1 hf2 hf3]);
+%! end_unwind_protect
+
+%% Test input validation
+%!error linkprop ()
+%!error linkprop (1)
+%!error linkprop (1,2,3)
+%!error <H must contain at least 2 handles> linkprop (1, "color")
+%!error <invalid graphic handle in input H> linkprop ([pi, e], "color")
+%!error <PROP must be a string or cell string array> linkprop ([0, 0], 1)
+
--- a/scripts/plot/util/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/util/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -38,6 +38,7 @@
   plot/util/findall.m \
   plot/util/findfigs.m \
   plot/util/findobj.m \
+  plot/util/frame2im.m \
   plot/util/gca.m \
   plot/util/gcbf.m \
   plot/util/gcbo.m \
@@ -48,28 +49,36 @@
   plot/util/graphics_toolkit.m \
   plot/util/hdl2struct.m \
   plot/util/hggroup.m \
+  plot/util/hgload.m \
+  plot/util/hgsave.m \
   plot/util/hold.m \
+  plot/util/im2frame.m \
   plot/util/isaxes.m \
   plot/util/isfigure.m \
   plot/util/ishghandle.m \
   plot/util/ishold.m \
   plot/util/isprop.m \
+  plot/util/linkaxes.m \
   plot/util/linkprop.m \
   plot/util/meshgrid.m \
   plot/util/ndgrid.m \
   plot/util/newplot.m \
   plot/util/__next_line_color__.m \
   plot/util/__next_line_style__.m \
+  plot/util/pan.m \
   plot/util/__plt_get_axis_arg__.m \
   plot/util/__pltopt__.m \
   plot/util/printd.m \
   plot/util/print.m \
   plot/util/refreshdata.m \
   plot/util/refresh.m \
+  plot/util/rotate.m \
+  plot/util/rotate3d.m \
   plot/util/saveas.m \
   plot/util/shg.m \
   plot/util/struct2hdl.m \
   plot/util/subplot.m \
+  plot/util/zoom.m \
   $(plot_util_PRIVATE_FCN_FILES)
 
 FCN_FILES += $(plot_util_FCN_FILES)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/util/pan.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,78 @@
+## Copyright (C) 2014 Andreas Weber
+##
+## 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  {Command} {} pan
+## @deftypefnx {Command} {} pan on
+## @deftypefnx {Command} {} pan xon
+## @deftypefnx {Command} {} pan yon
+## @deftypefnx {Command} {} pan off
+## @deftypefnx {Function File} {} pan (@var{hax}, @dots{})
+## Control panning mode of interactive graph in GUI.
+##
+## The function state input may be either @qcode{"on"}, @qcode{"xon"},
+## @qcode{"yon"} or @qcode{"off"}.
+##
+## If it is omitted the current state is toggled (@qcode{"xon"} and
+## @qcode{"yon"} are treated as @qcode{"on"}).
+##
+## @qcode{"xon"} limits panning to the x-axis, @qcode{"yon"} to the
+## y-axis.
+##
+## If the first argument @var{hax} is an axes handle, then operate on
+## this axis rather than the current axes returned by @code{gca}.
+##
+## To query the current mode use the @code{get}
+## function.  For example:
+##
+## @example
+## mode = get (gca, "pan");
+## @end example
+## @seealso{rotate3d, zoom}
+## @end deftypefn
+
+function pan (varargin)
+
+  if (numel (varargin) > 0 && isaxes (varargin{1}))
+    hax = varargin{1};
+    varargin(1) = [];
+  else
+    hax = gca ();
+  endif
+
+  toolkit = get (ancestor (hax, "figure"), "__graphics_toolkit__");
+  if (! strcmp (toolkit, "fltk"))
+    warning ("pan: Only implemented for graphics_toolkit FLTK");
+  endif
+
+  if (numel (varargin) > 1)
+    print_usage ();
+  elseif (numel (varargin) == 0)
+    # toggle
+    m = get (hax, "pan");
+    if (findstr (m, "on") > 0)
+      set (hax, "pan", "off");
+    else
+      set (hax, "pan", "on");
+    endif
+  elseif (numel (varargin) == 1)
+    set (hax, "pan", varargin{1});
+  endif
+
+endfunction
+
--- a/scripts/plot/util/print.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/util/print.m	Mon Jan 12 09:17:35 2015 -0800
@@ -284,7 +284,7 @@
 ## @end group
 ## @end example
 ##
-## @seealso{saveas, orient, figure}
+## @seealso{saveas, hgsave, orient, figure}
 ## @end deftypefn
 
 function print (varargin)
@@ -306,7 +306,7 @@
 
   if (opts.append_to_file)
     [~, ~, ext] = fileparts (opts.ghostscript.output);
-    opts.ghostscript.prepend = strcat (tmpnam (), ext);
+    opts.ghostscript.prepend = [tempname() ext];
     copyfile (opts.ghostscript.output, opts.ghostscript.prepend);
   endif
 
@@ -484,7 +484,7 @@
 
   if (nargin < 2 || strcmp (filein, "-") || isempty (filein))
     pipein = true;
-    filein = strcat (tmpnam (), ".eps");
+    filein = [tempname() ".eps"];
     if (dos_shell)
       cleanup = sprintf ("& del %s ", strrep (filein, '/', '\'));
     else
@@ -496,7 +496,7 @@
   endif
   if (strcmp (fileout, "-"))
     pipeout = true;
-    fileout = strcat (tmpnam (), ".eps");
+    fileout = [tempname() ".eps"];
     if (dos_shell)
       cleanup = horzcat (cleanup, sprintf ("& del %s ", strrep (fileout, '/', '\')));
     else
@@ -619,7 +619,7 @@
   dos_shell = (ispc () && ! isunix ());
   if (! isempty (opts.fig2dev_binary))
     if (dos_shell)
-      ## FIXME - is this the right thing to do for DOS?
+      ## FIXME: Is this the right thing to do for DOS?
       cmd = sprintf ("%s -L %s 2> NUL", opts.fig2dev_binary, devopt);
     else
       cmd = sprintf ("%s -L %s 2> /dev/null", opts.fig2dev_binary, devopt);
@@ -717,7 +717,7 @@
     if (dos_shell)
       cmd = sprintf ("%s -f %s 2> NUL", opts.pstoedit_binary, devopt);
     else
-      ## FIXME - is this the right thing to do for DOS?
+      ## FIXME: Is this the right thing to do for DOS?
       cmd = sprintf ("%s -f %s 2> /dev/null", opts.pstoedit_binary, devopt);
     endif
   elseif (isempty (opts.pstoedit_binary))
--- a/scripts/plot/util/printd.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/util/printd.m	Mon Jan 12 09:17:35 2015 -0800
@@ -44,7 +44,7 @@
     error ("The output filename: %s requires a suffix.\nOptions are: pdf ps eps txt jpg jpeg", filename);
   endif
   opt = substr (filename, sufix+1);
-  [pf, tempf, mag] = mkstemp ("oct-XXXXXX", 1);  # Safe version of tmpnam()
+  [pf, tempf, mag] = mkstemp ("oct-XXXXXX", 1);
   fprintf (pf, "%s", disp (obj));
   frewind (pf);
 
@@ -86,13 +86,13 @@
 
 
 %!demo
-%! r2 = char (
-%! 'stem step: 10, data: unsorted.',
-%! 'Hinges:    lo: 12, hi: 42'     ,
-%! '   1 | 22118'                  ,
-%! '   2 | 28'                     ,
-%! '   3 | 98'                     ,
-%! '   4 | 244'                    ,
+%! r2 = char ( ...
+%! 'stem step: 10, data: unsorted.', ...
+%! 'Hinges:    lo: 12, hi: 42'     , ...
+%! '   1 | 22118'                  , ...
+%! '   2 | 28'                     , ...
+%! '   3 | 98'                     , ...
+%! '   4 | 244'                    , ...
 %! '   5 | 2'                      );
 %! printd (r2, 'test_p.txt');
 %! system ('cat test_p.txt');
--- a/scripts/plot/util/private/__add_default_menu__.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/util/private/__add_default_menu__.m	Mon Jan 12 09:17:35 2015 -0800
@@ -33,12 +33,6 @@
 
   obj = findall (fig, "-depth", 1, "tag", "__default_menu__", "label", "&File");
   if (isempty (obj))
-    ## FIXME: uimenu() will cause menubar to be displayed, even though property
-    ##        menubar remains set at "none".  So, forcibly turn menubar status
-    ##        on and then off to force figure to hide menubar.
-    menubar_state = get (fig, "menubar");
-    set (fig, "menubar", "figure");
-
     __f = uimenu (fig, "label", "&File", "handlevisibility", "off",
                        "tag", "__default_menu__");
       uimenu (__f, "label", "Save &As", "callback", @save_cb);
@@ -47,19 +41,19 @@
 
     __e = uimenu (fig, "label", "&Edit", "handlevisibility", "off",
                        "tag", "__default_menu__");
-      uimenu (__e, "label", "&Grid", "callback", @grid_cb);
-      uimenu (__e, "label", "Auto&scale", "callback", @autoscale_cb);
-      gm = uimenu (__e, "label", "GUI &Mode");
-        uimenu (gm, "label", "Pan+Zoom", "callback", @guimode_cb);
-        uimenu (gm, "label", "Rotate+Zoom", "callback", @guimode_cb);
-        uimenu (gm, "label", "None+Zoom", "callback", @guimode_cb);
+      uimenu (__e, "label", "Toggle &grid on all axes", "tag", "toggle", "callback", @grid_cb);
+      uimenu (__e, "label", "Show grid on all axes", "tag", "on", "callback", @grid_cb);
+      uimenu (__e, "label", "Hide grid on all axes", "tag", "off", "callback", @grid_cb);
+      uimenu (__e, "label", "Auto&scale all axes", "callback", @autoscale_cb);
+      gm = uimenu (__e, "label", "GUI &Mode (on all axes)");
+        uimenu (gm, "label", "Pan x and y", "tag", "pan_on", "callback", @guimode_cb);
+        uimenu (gm, "label", "Pan x only", "tag", "pan_xon", "callback", @guimode_cb);
+        uimenu (gm, "label", "Pan y only", "tag", "pan_yon", "callback", @guimode_cb);
+        uimenu (gm, "label", "Disable pan and rotate", "tag", "no_pan_rotate", "callback", @guimode_cb);
+        uimenu (gm, "label", "Rotate on", "tag", "rotate3d", "callback", @guimode_cb);
+        uimenu (gm, "label", "Enable mousezoom", "tag", "zoom_on", "callback", @guimode_cb);
+        uimenu (gm, "label", "Disable mousezoom", "tag", "zoom_off", "callback", @guimode_cb);
 
-    ## FIXME: This drawnow () must occur after at least one menu item has
-    ##        been defined to avoid sizing issues in new figures.
-    ##        This may lead to flicker.  The real fix must be in the C++ code. 
-    drawnow ();
-
-    set (fig, "menubar", menubar_state);
   endif
 
 endfunction
@@ -93,23 +87,51 @@
   endif
 endfunction
 
+
+function hax = __get_axes__ (h)
+  ## Get parent figure
+  fig = ancestor (h, "figure");
+
+  ## Find all axes which aren't legends
+  hax = findobj (fig, "type", "axes", "-not", "tag", "legend");
+endfunction
+
 function grid_cb (h, e)
-  grid;
+  hax = __get_axes__ (h);
+  id = get (h, "tag");
+  switch (id)
+    case "toggle"
+      arrayfun (@grid, hax);
+    otherwise
+      arrayfun (@(h) grid(h, id), hax);
+  endswitch
+  drawnow ();
 endfunction
 
 function autoscale_cb (h, e)
-  axis ("auto");
+  hax = __get_axes__ (h);
+  arrayfun (@(h) axis (h, "auto"), hax)
+  drawnow ();
 endfunction
 
 function guimode_cb (h, e)
-  lbl = get (h, "label");
-  switch (lbl)
-    case "Pan+Zoom"
-      gui_mode ("2D");
-    case "Rotate+Zoom"
-      gui_mode ("3D");
-    case "None"
-      gui_mode ("None");
+  hax = __get_axes__ (h);
+  id = get (h, "tag");
+  switch (id)
+    case "pan_on"
+      arrayfun (@(h) pan (h, "on"), hax)
+    case "pan_xon"
+      arrayfun (@(h) pan (h, "xon"), hax)
+    case "pan_yon"
+      arrayfun (@(h) pan (h, "yon"), hax)
+    case "rotate3d"
+      arrayfun (@(h) rotate3d (h, "on"), hax)
+    case "no_pan_rotate"
+      arrayfun (@(h) pan (h, "off"), hax)
+      arrayfun (@(h) rotate3d (h, "off"), hax)
+    case "zoom_on"
+      arrayfun (@(h) set (h, "mouse_wheel_zoom", 0.05), hax);
+    case "zoom_off"
+      arrayfun (@(h) set (h, "mouse_wheel_zoom", 0.0), hax);
   endswitch
 endfunction
-
--- a/scripts/plot/util/private/__fltk_ginput__.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/util/private/__fltk_ginput__.m	Mon Jan 12 09:17:35 2015 -0800
@@ -17,15 +17,15 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {[@var{x}, @var{y}, @var{buttons}] =} __fltk_ginput__ (@var{f}, @var{n})
+## @deftypefn {Function File} {[@var{x}, @var{y}, @var{buttons}] =} __fltk_ginput__ (@var{n})
 ## Undocumented internal function.
 ## @end deftypefn
 
 ## This is ginput.m implementation for fltk.
 
-function [x, y, button] = __fltk_ginput__ (f, n = -1)
+function [x, y, button] = __fltk_ginput__ (n = -1)
 
-  if (isempty (get (f, "currentaxes")))
+  if (isempty (gca))
     error ("ginput: must have at least one axes");
   endif
 
@@ -34,14 +34,14 @@
 
   unwind_protect
 
-    orig_windowbuttondownfcn = get (f, "windowbuttondownfcn");
-    set (f, "windowbuttondownfcn", @ginput_windowbuttondownfcn);
+    orig_buttondownfcn = get (gca, "buttondownfcn");
+    set (gca, "buttondownfcn", @ginput_buttondownfcn);
 
-    orig_ginput_keypressfcn = get (f, "keypressfcn");
-    set (f, "keypressfcn", @ginput_keypressfcn);
+    orig_ginput_keypressfcn = get (gcf, "keypressfcn");
+    set (gcf, "keypressfcn", @ginput_keypressfcn);
 
     do
-      __fltk_redraw__ ();
+      __fltk_check__ ();
 
       ## Release CPU.
       sleep (0.01);
@@ -57,8 +57,8 @@
     endif
 
   unwind_protect_cleanup
-    set (f, "windowbuttondownfcn", orig_windowbuttondownfcn);
-    set (f, "keypressfcn", orig_ginput_keypressfcn);
+    set (gca, "buttondownfcn", orig_buttondownfcn);
+    set (gcf, "keypressfcn", orig_ginput_keypressfcn);
   end_unwind_protect
 
 endfunction
@@ -83,20 +83,19 @@
 
 endfunction
 
-function ginput_windowbuttondownfcn (src, data)
-  point = get (get (src,"currentaxes"), "currentpoint");
-  button = data;
-  ginput_accumulator (1, point(1,1), point(2,1), button);
+function ginput_buttondownfcn (src, button)
+  point = get (src, "currentpoint");
+  ginput_accumulator (1, point(1,1), point(1,2), button);
 endfunction
 
 function ginput_keypressfcn (src, evt)
-  point = get (get (src, "currentaxes"), "currentpoint");
+  point = get (gca, "currentpoint");
   key = evt.Key;
-  if (key == 10)
+  if (key == "return")
     ## Enter key stops ginput.
     ginput_accumulator (2, NaN, NaN, NaN);
   else
-    ginput_accumulator (1, point(1,1), point(2,1), key);
+    ginput_accumulator (1, point(1,1), point(1,2), uint8 (key(1)));
   endif
 endfunction
 
--- a/scripts/plot/util/private/__fltk_print__.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/util/private/__fltk_print__.m	Mon Jan 12 09:17:35 2015 -0800
@@ -27,7 +27,6 @@
 
   set (0, "currentfigure", opts.figure);
   drawnow ("expose");
-  __fltk_redraw__ ();
 
   if (! isempty (opts.fig2dev_binary))
     ## fig2dev is prefered for conversion to emf
--- a/scripts/plot/util/private/__ghostscript__.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/util/private/__ghostscript__.m	Mon Jan 12 09:17:35 2015 -0800
@@ -112,7 +112,7 @@
       offsetfile = opts.offsetfile;
       cleanup_cmd = "";
     else
-      offsetfile = strcat (tmpnam (), ".ps");
+      offsetfile = [tempname() ".ps"];
       cleanup_cmd = sprintf ("rm %s", offsetfile);
     endif
     unwind_protect
@@ -143,9 +143,9 @@
   endif
   if (! isempty (opts.prepend)
       && any (strcmpi (opts.device, {"pswrite", "ps2write", "pdfwrite"})))
-    ## FIXME - Fonts get may be mangled when appending ps/ps2.
-    ##         See "How to concatenate several PS files" at the link,
-    ##         http://en.wikibooks.org/wiki/PostScript_FAQ
+    ## FIXME: Fonts get may be mangled when appending ps/ps2.
+    ##        See "How to concatenate several PS files" at the link,
+    ##        http://en.wikibooks.org/wiki/PostScript_FAQ
     cmd = sprintf ("%s %s", cmd, opts.prepend);
     if (isempty (cleanup_cmd))
       cleanup_cmd = sprintf ("rm %s", opts.prepend);
--- a/scripts/plot/util/private/__gnuplot_get_var__.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/util/private/__gnuplot_get_var__.m	Mon Jan 12 09:17:35 2015 -0800
@@ -50,7 +50,7 @@
   endif
 
   if (use_mkfifo)
-    gpin_name = tmpnam ();
+    gpin_name = tempname ();
 
     ## Mode: 0600 == 6*8*8
     [err, msg] = mkfifo (gpin_name, 6*8*8);
--- a/scripts/plot/util/private/__gnuplot_ginput__.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/util/private/__gnuplot_ginput__.m	Mon Jan 12 09:17:35 2015 -0800
@@ -61,7 +61,7 @@
   endif
 
   if (use_mkfifo)
-    gpin_name = tmpnam ();
+    gpin_name = tempname ();
 
     ##Mode: 6*8*8 ==  0600
     [err, msg] = mkfifo (gpin_name, 6*8*8);
--- a/scripts/plot/util/private/__gnuplot_print__.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/util/private/__gnuplot_print__.m	Mon Jan 12 09:17:35 2015 -0800
@@ -54,7 +54,7 @@
         gp_opts = [gp_opts " level1"];
       endif
       if (opts.tight_flag || ! isempty (opts.preview))
-        tmp_file = strcat (tmpnam (), ".eps");
+        tmp_file = [tempname() ".eps"];
         eps_drawnow (opts, tmp_file, gp_opts);
         if (dos_shell)
           cleanup = [" & del " strrep(tmp_file, '/', '\')];
@@ -119,7 +119,7 @@
     case opts.ghostscript.device
       gp_opts = font_spec (opts, "devopt", "eps");
       opts.ghostscript.output = opts.name;
-      opts.ghostscript.source = strcat (tmpnam (), ".eps");
+      opts.ghostscript.source = [tempname() ".eps"];
       eps_drawnow (opts, opts.ghostscript.source, gp_opts);
       [cmd_gs, cmd_cleanup] = __ghostscript__ (opts.ghostscript);
       if (opts.send_to_printer || isempty (opts.name))
--- a/scripts/plot/util/private/__go_draw_axes__.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/util/private/__go_draw_axes__.m	Mon Jan 12 09:17:35 2015 -0800
@@ -63,7 +63,7 @@
       && strcmp (axis_obj.xlimmode, "manual")
       && strcmp (axis_obj.ylimmode, "manual")
       && (nd == 2 || all (mod (axis_obj.view, 90) == 0)))
-    ## FIXME - adjust plotboxaspectratio to respect other
+    ## FIXME: adjust plotboxaspectratio to respect other
     fpos = get (axis_obj.parent, "position");
     apos = axis_obj.position;
   endif
@@ -75,7 +75,7 @@
     if (nd == 2 || all (mod (axis_obj.view, 90) == 0))
       dr = dr(1) / dr(2);
     else
-      ## FIXME - need to properly implement 3D
+      ## FIXME: need to properly implement 3D
       dr = mean (dr(1:2)) / dr(3);
     endif
   else
@@ -106,7 +106,7 @@
       fprintf (plot_stream, "set rmargin 0;\n");
 
       if (nd == 3 && all (axis_obj.view == [0, 90]))
-        ## FIXME -- Kludge to allow colorbar to be added to a pcolor() plot
+        ## FIXME: Kludge to allow colorbar to be added to a pcolor() plot
         pos(3:4) = pos(3:4) * 1.4;
         pos(1:2) = pos(1:2) - pos(3:4) * 0.125;
       endif
@@ -139,8 +139,8 @@
   endif
 
   ## Reset all labels, axis-labels, tick-labels, and title
-  ## FIXME - We should have an function to initialize the axis.
-  ##         Presently, this is dispersed in this function.
+  ## FIXME: We should have an function to initialize the axis.
+  ##        Presently, this is dispersed in this function.
   fputs (plot_stream, "unset label;\n");
   fputs (plot_stream, "unset xtics;\n");
   fputs (plot_stream, "unset ytics;\n");
@@ -153,10 +153,11 @@
     if (isempty (t.string))
       fputs (plot_stream, "unset title;\n");
     else
+      colorspec = get_text_colorspec (t.color, mono);
       [tt, f, s] = __maybe_munge_text__ (enhanced, t, "string");
       fontspec = create_fontspec (f, s, gnuplot_term);
-      fprintf (plot_stream, "set title \"%s\" %s %s;\n",
-               undo_string_escapes (tt), fontspec,
+      fprintf (plot_stream, "set title \"%s\" %s %s %s;\n",
+               undo_string_escapes (tt), fontspec, colorspec,
                __do_enhanced_option__ (enhanced, t));
     endif
   endif
@@ -164,7 +165,7 @@
   if (! isempty (axis_obj.xlabel))
     t = get (axis_obj.xlabel);
     angle = t.rotation;
-    colorspec = get_text_colorspec (axis_obj.xcolor, mono);
+    colorspec = get_text_colorspec (t.color, mono);
     if (isempty (t.string))
       fprintf (plot_stream, "unset xlabel;\n");
       fprintf (plot_stream, "unset x2label;\n");
@@ -192,7 +193,7 @@
   if (! isempty (axis_obj.ylabel))
     t = get (axis_obj.ylabel);
     angle = t.rotation;
-    colorspec = get_text_colorspec (axis_obj.ycolor, mono);
+    colorspec = get_text_colorspec (t.color, mono);
     if (isempty (t.string))
       fprintf (plot_stream, "unset ylabel;\n");
       fprintf (plot_stream, "unset y2label;\n");
@@ -220,7 +221,7 @@
   if (! isempty (axis_obj.zlabel))
     t = get (axis_obj.zlabel);
     angle = t.rotation;
-    colorspec = get_text_colorspec (axis_obj.zcolor, mono);
+    colorspec = get_text_colorspec (t.color, mono);
     if (isempty (t.string))
       fputs (plot_stream, "unset zlabel;\n");
     else
@@ -323,9 +324,9 @@
     fputs (plot_stream, "set border front;\n");
   else
     fputs (plot_stream, "set grid layerdefault;\n");
-    ## FIXME -- the gnuplot help says that "layerdefault" should work
-    ## for set border too, but it fails for me with gnuplot 4.2.5.  So
-    ## use "back" instead.
+    ## FIXME: The gnuplot help says that "layerdefault" should work
+    ##        for set border too, but it fails for me with gnuplot 4.2.5.
+    ##        So, use "back" instead.
     fputs (plot_stream, "set border back;\n");
   endif
 
@@ -512,6 +513,9 @@
           img_ydata = img_ydata(1) + [0, rows(img_data)-1];
         endif
 
+        x_origin = min (img_xdata);
+        y_origin = min (img_ydata);
+
         [y_dim, x_dim] = size (img_data(:,:,1));
         if (x_dim > 1)
           dx = abs (img_xdata(2)-img_xdata(1))/(x_dim-1);
@@ -519,6 +523,11 @@
           x_dim = 2;
           img_data = [img_data, img_data];
           dx = abs (img_xdata(2)-img_xdata(1));
+          if (dx < 1)
+            ## Correct gnuplot string for 1-D images
+            dx       = 0.5;
+            x_origin = 0.75;
+          endif
         endif
         if (y_dim > 1)
           dy = abs (img_ydata(2)-img_ydata(1))/(y_dim-1);
@@ -526,11 +535,13 @@
           y_dim = 2;
           img_data = [img_data; img_data];
           dy = abs (img_ydata(2)-img_ydata(1));
+          if (dy < 1)
+            ## Correct gnuplot string for 1-D images
+            dy       = 0.5;
+            y_origin = 0.75;
+          endif
         endif
 
-        x_origin = min (img_xdata);
-        y_origin = min (img_ydata);
-
         if (ndims (img_data) == 3)
           data{data_idx} = permute (img_data, [3, 1, 2])(:);
           format = "1:2:3";
@@ -561,7 +572,9 @@
         if (isempty (obj.displayname))
           titlespec{data_idx} = "title \"\"";
         else
-          tmp = undo_string_escapes (__maybe_munge_text__ (enhanced, obj, "displayname"));
+          tmp = undo_string_escapes (
+                  __maybe_munge_text__ (enhanced, obj, "displayname")
+                );
           titlespec{data_idx} = ['title "' tmp '"'];
         endif
         usingclause{data_idx} = sprintf ("record=%d", numel (obj.xdata));
@@ -575,14 +588,17 @@
             zdat = zeros (size (xdat));
           endif
           data{data_idx} = [xdat, ydat, zdat]';
-          usingclause{data_idx} = sprintf ("record=%d using ($1):($2):($3)", numel (xdat));
+          usingclause{data_idx} = sprintf ("record=%d using ($1):($2):($3)",
+                                           numel (xdat));
+          hidden_removal = false;
           ## fputs (plot_stream, "set parametric;\n");
         else
           xdat = obj.xdata(:);
           ydat = obj.ydata(:);
           data{data_idx} = [xdat, ydat]';
-          usingclause{data_idx} = sprintf ("record=%d using ($1):($2) axes %s%s",
-                                          rows (xdat), xaxisloc_using, yaxisloc_using);
+          usingclause{data_idx} = ...
+            sprintf ("record=%d using ($1):($2) axes %s%s",
+                     rows (xdat), xaxisloc_using, yaxisloc_using);
         endif
 
         style = do_linestyle_command (obj, obj.color, data_idx, mono,
@@ -680,7 +696,9 @@
              if (i > 1 || isempty (obj.displayname))
                titlespec{local_idx} = "title \"\"";
              else
-               tmp = undo_string_escapes (__maybe_munge_text__ (enhanced, obj, "displayname"));
+               tmp = undo_string_escapes (
+                       __maybe_munge_text__ (enhanced, obj, "displayname")
+                     );
                titlespec{local_idx} = ['title "' tmp '"'];
              endif
              if (isfield (obj, "facecolor"))
@@ -756,6 +774,8 @@
                if (isnan (ccdat))
                  ccdat = (rows (cmap) + rows (addedcmap) + 1) * ones(3, 1);
                  addedcmap = [addedcmap; reshape(color, 1, 3)];
+               elseif (numel (ccdat) <= 1)
+                 ccdat = zcol;  
                endif
                data{data_3d_idx} = [data{data_3d_idx}, ...
                                     [[xcol; xcol(end)], [ycol; ycol(end)], ...
@@ -766,7 +786,7 @@
                elseif (__gnuplot_has_feature__ ("transparent_patches")
                        && isscalar (obj.facealpha))
                  colorspec = sprintf ("lc rgb \"#%02x%02x%02x\" fillstyle transparent solid %f",
-                                    round (255*color), obj.facealpha);
+                                      round (255*color), obj.facealpha);
                else
                  colorspec = sprintf ("lc rgb \"#%02x%02x%02x\"",
                                       round (255*color));
@@ -800,12 +820,11 @@
            endif
 
            if (isfield (obj, "edgecolor"))
-             ## FIXME
-             ## This is the wrong thing to do as edgecolor, markeredgecolor
-             ## and markerfacecolor can have different values and we should
-             ## treat them seperately. However, the below allow the scatter
-             ## functions to work as expected, where only one of these values
-             ## is set
+             ## FIXME: This is the wrong thing to do as edgecolor,
+             ## markeredgecolor and markerfacecolor can have different values
+             ## and we should treat them seperately. However, the code below
+             ## allows the scatter functions to work as expected, where only
+             ## one of these values is set.
              if (strcmp (obj.edgecolor, "none"))
                if (strcmp (obj.markeredgecolor, "none"))
                  ec = obj.markerfacecolor;
@@ -1116,7 +1135,9 @@
           if (isempty (obj.displayname))
             titlespec{data_idx} = "title \"\"";
           else
-            tmp = undo_string_escapes (__maybe_munge_text__ (enhanced, obj, "displayname"));
+            tmp = undo_string_escapes (
+                    __maybe_munge_text__ (enhanced, obj, "displayname")
+                  );
             titlespec{data_idx} = ['title "' tmp '"'];
           endif
           withclause{data_idx} = sprintf ("with pm3d linestyle %d",
@@ -1212,7 +1233,8 @@
           endif
 
           if (flat_interp_face && strcmp (obj.edgecolor, "flat"))
-            fprintf (plot_stream, "set pm3d explicit at s %s %s corners2color c3;\n",
+            fprintf (plot_stream,
+                     "set pm3d explicit at s %s %s corners2color c3;\n",
                      interp_str, dord);
           elseif (!facecolor_none_or_white)
             if (strcmp (obj.edgecolor, "none"))
@@ -1222,10 +1244,12 @@
                          "set style fill transparent solid %f;\n",
                          obj.facealpha);
               endif
-              fprintf (plot_stream, "set pm3d explicit at s %s corners2color c3;\n",
+              fprintf (plot_stream,
+                       "set pm3d explicit at s %s corners2color c3;\n",
                        interp_str, dord);
             else
-              fprintf (plot_stream, "set pm3d explicit at s hidden3d %d %s %s corners2color c3;\n",
+              fprintf (plot_stream,
+                       "set pm3d explicit at s hidden3d %d %s %s corners2color c3;\n",
                        data_idx, interp_str, dord);
 
               if (__gnuplot_has_feature__ ("transparent_surface")
@@ -1444,8 +1468,8 @@
             data{i}(end,:) = clim(2) * (data{i}(end, :) - 0.5) / cmap_sz;
            endif
         endfor
-        fprintf (plot_stream, "set cbrange [%.15e:%.15e];\n", clim(1), clim(2) *
-                 (cmap_sz + rows (addedcmap)) / cmap_sz);
+        fprintf (plot_stream, "set cbrange [%.15e:%.15e];\n",
+                 clim(1), clim(2) * (cmap_sz + rows (addedcmap)) / cmap_sz);
       else
         fprintf (plot_stream, "set cbrange [%.15e:%.15e];\n", clim);
       endif
@@ -1469,12 +1493,10 @@
         fprintf (plot_stream, "unset ytics; set y2tics %s nomirror\n",
                  axis_obj.tickdir);
         if (strcmpi (axis_obj.xaxislocation, "top"))
-          fprintf (plot_stream, "unset xtics; set x2tics %s nomirror\n",
-                   axis_obj.tickdir);
+          maybe_do_x2tick_mirror (plot_stream, axis_obj)
           fputs (plot_stream, "set border 12;\n");
         elseif (strcmpi (axis_obj.xaxislocation, "bottom"))
-          fprintf (plot_stream, "unset x2tics; set xtics %s nomirror\n",
-                   axis_obj.tickdir);
+          maybe_do_xtick_mirror (plot_stream, axis_obj)
           fputs (plot_stream, "set border 9;\n");
         else # xaxislocation == zero
           fprintf (plot_stream, "unset x2tics; set xtics %s nomirror\n",
@@ -1487,16 +1509,13 @@
         fprintf (plot_stream, "unset y2tics; set ytics %s nomirror\n",
                  axis_obj.tickdir);
         if (strcmpi (axis_obj.xaxislocation, "top"))
-          fprintf (plot_stream, "unset xtics; set x2tics %s nomirror\n",
-                   axis_obj.tickdir);
+          maybe_do_x2tick_mirror (plot_stream, axis_obj)
           fputs (plot_stream, "set border 6;\n");
         elseif (strcmpi (axis_obj.xaxislocation, "bottom"))
-          fprintf (plot_stream, "unset x2tics; set xtics %s nomirror\n",
-                   axis_obj.tickdir);
+          maybe_do_xtick_mirror (plot_stream, axis_obj)
           fputs (plot_stream, "set border 3;\n");
         else # xaxislocation == zero
-          fprintf (plot_stream, "unset x2tics; set xtics %s nomirror\n",
-                   axis_obj.tickdir);
+          maybe_do_xtick_mirror (plot_stream, axis_obj)
           fputs (plot_stream, "set border 2;\n");
           fprintf (plot_stream, "set xzeroaxis lt -1 lw %f;\n",
                    axis_obj.linewidth);
@@ -1505,18 +1524,15 @@
         fprintf (plot_stream, "unset y2tics; set ytics %s nomirror\n",
                  axis_obj.tickdir);
         if (strcmpi (axis_obj.xaxislocation, "top"))
-          fprintf (plot_stream, "unset xtics; set x2tics %s nomirror\n",
-                   axis_obj.tickdir);
+          maybe_do_x2tick_mirror (plot_stream, axis_obj)
           fputs (plot_stream, "set border 4;\n");
         elseif (strcmpi (axis_obj.xaxislocation, "bottom"))
-          fprintf (plot_stream, "unset x2tics; set xtics %s nomirror\n",
-                   axis_obj.tickdir);
+          maybe_do_xtick_mirror (plot_stream, axis_obj)
           fputs (plot_stream, "set border 1;\n");
         else # xaxislocation == zero
+          maybe_do_xtick_mirror (plot_stream, axis_obj)
           fprintf (plot_stream, "unset y2tics; set ytics %s nomirror\n",
                    axis_obj.tickdir);
-          fprintf (plot_stream, "unset x2tics; set xtics %s nomirror\n",
-                   axis_obj.tickdir);
           fputs (plot_stream, "unset border;\n");
           fprintf (plot_stream, "set xzeroaxis lt -1 lw %f;\n",
                    axis_obj.linewidth);
@@ -1587,9 +1603,10 @@
     endswitch
     if (__gnuplot_has_feature__ ("key_has_font_properties"))
       [fontname, fontsize] = get_fontname_and_size (hlgnd);
-      fontspec = create_fontspec (fontname, fontsize, gnuplot_term);
+      fontspacespec = [ create_spacingspec(fontname, fontsize, gnuplot_term),...
+                        create_fontspec(fontname, fontsize, gnuplot_term) ];
     else
-      fontspec = "";
+      fontspacespec = "";
     endif
     textcolors = get (findobj (hlgnd.children, "type", "text"), "color");
     if (iscell (textcolors))
@@ -1605,7 +1622,7 @@
       colorspec = get_text_colorspec (textcolors, mono);
     endif
     fprintf (plot_stream, "set key %s %s;\nset key %s %s %s %s %s %s;\n",
-             inout, pos, box, reverse, horzvert, fontspec, colorspec,
+             inout, pos, box, reverse, horzvert, fontspacespec, colorspec,
              __do_enhanced_option__ (enhanced, hlgnd));
   else
     fputs (plot_stream, "unset key;\n");
@@ -1659,8 +1676,8 @@
       fprintf (plot_stream, "%s \"-\" %s %s %s \\\n", plot_cmd,
                usingclause{1}, titlespec{1}, withclause{1});
     else
-      fprintf (plot_stream, "%s \"-\" binary format='%%float64' %s %s %s \\\n", plot_cmd,
-               usingclause{1}, titlespec{1}, withclause{1});
+      fprintf (plot_stream, "%s \"-\" binary format='%%float64' %s %s %s \\\n",
+               plot_cmd, usingclause{1}, titlespec{1}, withclause{1});
     endif
     for i = 2:data_idx
       if (have_3d_patch (i))
@@ -1700,8 +1717,8 @@
           fputs (plot_stream, "unset obj 2; \\\n");
           fg_is_set = false;
         endif
-        fprintf (plot_stream, "%s \"-\" binary format='%%float64' %s %s %s \\\n", plot_cmd,
-                 usingclause{i}, titlespec{i}, withclause{i});
+        fprintf (plot_stream,"%s \"-\" binary format='%%float64' %s %s %s \\\n",
+                 plot_cmd, usingclause{i}, titlespec{i}, withclause{i});
       else
         fprintf (plot_stream, ", \"-\" binary format='%%float64' %s %s %s \\\n",
                  usingclause{i}, titlespec{i}, withclause{i});
@@ -1718,7 +1735,7 @@
             fputs (plot_stream, "\n\n");
           endif
           fprintf (plot_stream, "%.15g %.15g %.15g %.15g\n", data{i}(:,j).');
-          fprintf (plot_stream, "%.15g %.15g %.15g %.15g\n\n", data{i}(:,j+1).');
+          fprintf (plot_stream, "%.15g %.15g %.15g %.15g\n\n",data{i}(:,j+1).');
           fprintf (plot_stream, "%.15g %.15g %.15g %.15g\n", data{i}(:,j+2).');
           fprintf (plot_stream, "%.15g %.15g %.15g %.15g\n", data{i}(:,j+3).');
         endfor
@@ -1758,6 +1775,18 @@
   endif
 endfunction
 
+function spacing_spec = create_spacingspec (f, s, gp_term)
+  # The gnuplot default font size is 10, and default spacing is 1.25.
+  # gnuplot has a concept of a figure global font, and sizes everything
+  # appropriate to that, including the legend spacing.
+  #
+  # This means that if an alternative size is used, gnuplot will use an
+  # inappropriate spacing in the legend by default.
+  spc = s / 10 * 1.25;
+  spacing_spec = sprintf ("spacing %d", spc);
+
+endfunction
+
 function fontspec = create_fontspec (f, s, gp_term)
   if (strcmp (f, "*") || strcmp (gp_term, "tikz"))
     fontspec = sprintf ("font \",%d\"", s);
@@ -1969,19 +1998,19 @@
         pt = "10";
         pt2 = "11";
       case ">"
-        ## FIXME: should be triangle pointing right, use triangle pointing up
+        ## FIXME: Should be triangle pointing right, use triangle pointing up
         pt = "8";
         pt2 = "9";
       case "<"
-        ## FIXME: should be triangle pointing left, use triangle pointing down
+        ## FIXME: Should be triangle pointing left, use triangle pointing down
         pt = "10";
         pt2 = "11";
       case {"pentagram", "p"}
-        ## FIXME: should be pentagram, using pentagon
+        ## FIXME: Should be pentagram, using pentagon
         pt = "14";
         pt2 = "15";
       case {"hexagram", "h"}
-        ## FIXME: should be 6 pt start, using "*" instead
+        ## FIXME: Should be 6 pt start, using "*" instead
         pt = pt2 = "3";
       case "none"
         pt = pt2 = "";
@@ -1997,7 +2026,7 @@
 
   ## DATA is already transposed.
 
-  ## FIXME -- this may need to be converted to C++ for speed.
+  ## FIXME: this may need to be converted to C++ for speed.
 
   ## Convert NA elements to normal NaN values because fprintf writes
   ## "NA" and that confuses gnuplot.
@@ -2115,6 +2144,13 @@
                     plot_stream, mirror, mono, axispos, tickdir, ticklength,
                     fontname, fontspec, interpreter, scale, sgn, gnuplot_term)
   persistent warned_latex = false;
+
+  ## Avoid emitting anything if the tics are empty, because this undoes the
+  ## effect of the previous unset xtics and thereby adds back in the tics.
+  if (isempty (tics))
+    return;
+  endif
+
   if (mirror)
     mirror = "mirror";
   else
@@ -2145,54 +2181,38 @@
     num_mtics = 5;
   endif
   colorspec = get_text_colorspec (color, mono);
-  if (strcmpi (ticmode, "manual") || strcmpi (labelmode, "manual"))
+  fprintf (plot_stream, "set format %s \"%s\";\n", ax, fmt);
+  if (strcmpi (ticmode, "manual"))
     if (isempty (tics))
       fprintf (plot_stream, "unset %stics;\nunset m%stics;\n", ax, ax);
       return
     endif
-    if (strcmpi (ticmode, "manual"))
-      fprintf (plot_stream, "set format %s \"%s\";\n", ax, fmt);
-      fprintf (plot_stream, "set %stics %s %s %s %s (", ax, tickdir,
-               ticklength, axispos, mirror);
-      fprintf (plot_stream, " %.15g,", tics(1:end-1));
-      fprintf (plot_stream, " %.15g) %s;\n", tics(end), fontspec);
-    endif
-    if (strcmpi (labelmode, "manual"))
-      if (ischar (labels))
-        labels = cellstr (labels);
-      endif
-      if (isnumeric (labels))
-        labels = num2str (real (labels(:)));
-      endif
-      if (ischar (labels))
-        labels = permute (cellstr (labels), [2, 1]);
-      endif
-      if (iscellstr (labels))
-        k = 1;
-        ntics = numel (tics);
-        nlabels = numel (labels);
-        fprintf (plot_stream, "set %stics add %s %s %s %s (", ax,
-                 tickdir, ticklength, axispos, mirror);
-        labels = strrep (labels, "%", "%%");
-        for i = 1:ntics
-          fprintf (plot_stream, " \"%s\" %.15g", labels{k++}, tics(i));
-          if (i < ntics)
-            fputs (plot_stream, ", ");
-          endif
-          if (k > nlabels)
-            k = 1;
-          endif
-        endfor
-        fprintf (plot_stream, ") %s %s;\n", colorspec, fontspec);
-      else
-        error ("__go_draw_axes__: unsupported type of ticklabel");
-      endif
-    endif
+    fprintf (plot_stream, "set %stics %s %s %s %s (", ax, tickdir,
+             ticklength, axispos, mirror);
+    fprintf (plot_stream, " %.15e,", tics(1:end-1));
+    fprintf (plot_stream, " %.15e) %s;\n", tics(end), fontspec);
   else
-    fprintf (plot_stream, "set format %s \"%s\";\n", ax, fmt);
     fprintf (plot_stream, "set %stics %s %s %s %s %s %s;\n", ax,
              tickdir, ticklength, axispos, mirror, colorspec, fontspec);
   endif
+  if (strcmpi (labelmode, "manual"))
+    k = 1;
+    ntics = numel (tics);
+    nlabels = numel (labels);
+    fprintf (plot_stream, "set %stics add %s %s %s %s (", ax,
+             tickdir, ticklength, axispos, mirror);
+    labels = strrep (labels, "%", "%%");
+    for i = 1:ntics
+      fprintf (plot_stream, " \"%s\" %.15g", labels{k++}, tics(i));
+      if (i < ntics)
+        fputs (plot_stream, ", ");
+      endif
+      if (k > nlabels)
+        k = 1;
+      endif
+    endfor
+    fprintf (plot_stream, ") %s %s;\n", colorspec, fontspec);
+  endif
   if (strcmp (mtics, "on"))
     fprintf (plot_stream, "set m%stics %d;\n", ax, num_mtics);
   else
@@ -2201,20 +2221,12 @@
 endfunction
 
 function ticklabel = ticklabel_to_cell (ticklabel)
-  if (isnumeric (ticklabel))
-    ## Use upto 5 significant digits
-    ticklabel = num2str (ticklabel(:), 5);
-  endif
   if (ischar (ticklabel))
-    if (rows (ticklabel) == 1 && any (ticklabel == "|"))
-      ticklabel = ostrsplit (ticklabel, "|");
-    else
-      ticklabel = cellstr (ticklabel);
-    endif
-  elseif (isempty (ticklabel))
-    ticklabel = {""};
+    ticklabel = cellstr (ticklabel);
+  elseif (iscellstr (ticklabel))
+    ticklabel = ticklabel;
   else
-    ticklabel = ticklabel;
+    error ("__go_draw_axes__: unsupported type of ticklabel");
   endif
 endfunction
 
@@ -2274,7 +2286,7 @@
     bld = false;
   endif
 
-  ## The text object maybe multiline, and may be of any class
+  ## The text object may be multiline, and may be of any class
   str = getfield (obj, fld);
   if (ischar (str) && rows (str) > 1)
     str = cellstr (str);
@@ -2291,6 +2303,10 @@
   endif
 
   if (enhanced)
+    str = regexprep (str, '(?<!\\)@', '\@');
+  endif
+
+  if (enhanced)
     if (strcmpi (obj.interpreter, "tex"))
       if (iscellstr (str))
         for n = 1:numel (str)
@@ -2315,14 +2331,14 @@
   [s, e, m] = regexp (str, "\\\\([a-zA-Z]+|0)", "start", "end", "matches");
 
   for i = length (s) : -1 : 1
-    ## special case for "\0"  and replace with "{/Symbol \306}'
+    ## special case for "\0"  and replace with empty set "{/Symbol \306}'
     if (strncmp (m{i}, '\0', 2))
       str = [str(1:s(i) - 1) '{/Symbol \306}' str(s(i) + 2:end)];
     else
       f = m{i}(2:end);
       if (isfield (sym, f))
         g = getfield (sym, f);
-        ## FIXME The symbol font doesn't seem to support bold or italic
+        ## FIXME: The symbol font doesn't seem to support bold or italic
         ##if (bld)
         ##  if (it)
         ##    g = regexprep (g, '/Symbol', '/Symbol-bolditalic');
@@ -2352,7 +2368,7 @@
           str = [str(1:s(i) - 1) '/' fnt '-bold ' str(s(i) + 3:end)];
         endif
       elseif (strcmpi (f, "color"))
-        ## FIXME Ignore \color but remove trailing {} block as well
+        ## FIXME: Ignore \color but remove trailing {} block as well
         d = strfind (str(e(i) + 1:end),'}');
         if (isempty (d))
           warning ('syntax error in \color argument');
@@ -2383,7 +2399,7 @@
         for j = 1 : length (flds)
           if (strncmp (flds{j}, f, length (flds{j})))
             g = getfield (sym, flds{j});
-            ## FIXME The symbol font doesn't seem to support bold or italic
+            ## FIXME: The symbol font doesn't seem to support bold or italic
             ##if (bld)
             ##  if (it)
             ##    g = regexprep (g, '/Symbol', '/Symbol-bolditalic');
@@ -2407,7 +2423,7 @@
   ## shortest.. Don't have to worry about things like ^\theta as they
   ## are already converted to ^{/Symbol q}.
 
-  ## FIXME -- This is a mess... Is it worth it just for a "@" character?
+  ## FIXME: This is a mess... Is it worth it just for a "@" character?
 
   [s, m] = regexp (str,'[_\^]','start','matches');
   i = 1;
@@ -2519,7 +2535,7 @@
   sym.gamma = '{/Symbol g}';
   sym.eta = '{/Symbol h}';
   sym.iota = '{/Symbol i}';
-  sym.varphi = '{/Symbol j}';
+  sym.varphi = '{/Symbol j}';              # Not in OpenGL
   sym.kappa = '{/Symbol k}';
   sym.lambda = '{/Symbol l}';
   sym.mu = '{/Symbol m}';
@@ -2550,7 +2566,9 @@
   sym.uparrow = '{/Symbol \255}';
   sym.rightarrow = '{/Symbol \256}';
   sym.downarrow = '{/Symbol \257}';
-  sym.circ = '{/Symbol \260}';
+  sym.circ = '{/Symbol \260}';         # degree symbol, not circ as in FLTK
+  sym.deg = '{/Symbol \260}';
+  sym.ast = '{/Symbol *}';
   sym.pm = '{/Symbol \261}';
   sym.geq = '{/Symbol \263}';
   sym.times = '{/Symbol \264}';
@@ -2569,6 +2587,7 @@
   sym.wp = '{/Symbol \303}';
   sym.otimes = '{/Symbol \304}';
   sym.oplus = '{/Symbol \305}';
+  ## empty set, not circled slash division operator as in FLTK.
   sym.oslash = '{/Symbol \306}';
   sym.cap = '{/Symbol \307}';
   sym.cup = '{/Symbol \310}';
@@ -2577,24 +2596,24 @@
   sym.subset = '{/Symbol \314}';
   sym.subseteq = '{/Symbol \315}';
   sym.in = '{/Symbol \316}';
-  sym.notin = '{/Symbol \317}';
+  sym.notin = '{/Symbol \317}';            # Not in OpenGL
   sym.angle = '{/Symbol \320}';
-  sym.bigtriangledown = '{/Symbol \321}';
+  sym.bigtriangledown = '{/Symbol \321}';  # Not in OpenGL
   sym.langle = '{/Symbol \341}';
   sym.rangle = '{/Symbol \361}';
   sym.nabla = '{/Symbol \321}';
-  sym.prod = '{/Symbol \325}';
+  sym.prod = '{/Symbol \325}';             # Not in OpenGL
   sym.surd = '{/Symbol \326}';
   sym.cdot = '{/Symbol \327}';
   sym.neg = '{/Symbol \330}';
   sym.wedge = '{/Symbol \331}';
   sym.vee = '{/Symbol \332}';
-  sym.Leftrightarrow = '{/Symbol \333}';
+  sym.Leftrightarrow = '{/Symbol \333}';   # Not in OpenGL
   sym.Leftarrow = '{/Symbol \334}';
-  sym.Uparrow = '{/Symbol \335}';
+  sym.Uparrow = '{/Symbol \335}';          # Not in OpenGL
   sym.Rightarrow = '{/Symbol \336}';
-  sym.Downarrow = '{/Symbol \337}';
-  sym.diamond = '{/Symbol \340}';
+  sym.Downarrow = '{/Symbol \337}';        # Not in OpenGL
+  sym.diamond = '{/Symbol \340}';          # Not in OpenGL
   sym.copyright = '{/Symbol \343}';
   sym.lfloor = '{/Symbol \353}';
   sym.lceil  = '{/Symbol \351}';
@@ -2614,3 +2633,16 @@
   endif
 endfunction
 
+function maybe_do_xtick_mirror (plot_stream, axis_obj)
+  if (! isempty(axis_obj.xtick))
+    fprintf (plot_stream, "unset x2tics; set xtics %s nomirror\n",
+                          axis_obj.tickdir);
+  endif
+endfunction
+
+function maybe_do_x2tick_mirror (plot_stream, axis_obj)
+  if (! isempty(axis_obj.xtick))
+    fprintf (plot_stream, "unset xtics; set x2tics %s nomirror\n",
+                          axis_obj.tickdir);
+  endif
+endfunction
--- a/scripts/plot/util/private/__print_parse_opts__.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/util/private/__print_parse_opts__.m	Mon Jan 12 09:17:35 2015 -0800
@@ -327,10 +327,9 @@
     else
       error ("print: a file name may not specified when spooling to a printer")
     endif
-    if (! any (strcmp (arg_st.devopt, gs_device_list))
-      || ! any (strcmp (arg_st.devopt, {"pswrite", "ps2write"})))
-      ## Only postscript and supported ghostscript devices
-      error ("print: invalid format for spooling to a printer")
+    if (! any (strcmp (arg_st.devopt, gs_device_list)))
+      ## Only supported ghostscript devices
+      error ("print: format must be a valid Ghostscript format for spooling to a printer")
     endif
   elseif (isempty (arg_st.name))
     error ("print: an output file name must be specified")
@@ -574,8 +573,8 @@
     paperposition = convert2points (paperposition, paperunits);
   endif
 
-  ## FIXME - This will be obsoleted by listeners for paper properties.
-  ##         Papersize is tall when portrait,and wide when landscape.
+  ## FIXME: This will be obsoleted by listeners for paper properties.
+  ##        Papersize is tall when portrait,and wide when landscape.
   if ((papersize(1) > papersize(2) && strcmpi (paperorientation, "portrait"))
       || (papersize(1) < papersize(2) && strcmpi (paperorientation, "landscape")))
     papersize = papersize([2,1]);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/util/rotate.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,188 @@
+## Copyright (C) 2014 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  {Function File} {} rotate (@var{h}, @var{dir}, @var{alpha})
+## @deftypefnx {Function File} {} rotate (@dots{}, @var{origin})
+## Rotate the plot object @var{h} through @var{alpha} degrees around
+## the line with direction @var{dir} and origin @var{origin}.
+##
+## The default value of @var{origin} is the center of the axes
+## object that is the parent of @var{h}.
+##
+## If @var{h} is a vector of handles, they must all have the same
+## parent axes object.
+##
+## Graphics objects that may be rotated are lines, surfaces, patches,
+## and images.
+## @end deftypefn
+
+function rotate (h, direction, alpha, origin)
+
+  ## Note in doc string about compatibility issues with calculation of
+  ## default origin due to possible differences in the auto-scaling
+  ## algorithm between Octave and Matlab.
+
+  if (nargin < 3 || nargin > 4)
+    print_usage ();
+  endif
+
+  is_h = ishandle (h);
+  if (is_h)
+    ax_list = get (h, "parent");
+    if (iscell (ax_list))
+      ax_list = cell2mat (ax_list);
+    endif
+    if (ax_list == ax_list(1))
+      ax = ax_list(1);
+    else
+       error ("rotate: all handles must be children of the same axes object");
+    endif
+  else
+    error ("rotate: H must be an array of one or more graphics handles");
+  endif
+
+  if (! (isnumeric (direction) && numel (direction) == 3))
+    error ("rotate: invalid direction");
+  endif
+
+  if (! (isnumeric (alpha) && isscalar (alpha)))
+    error ("rotate: invalid rotation angle");
+  endif
+
+  t = get (h, "type");
+
+  is_image = strcmp (t, "image");
+  is_line = strcmp (t, "line");
+  is_patch = strcmp (t, "patch");
+  is_surface = strcmp (t, "surface");
+
+  if (! all (is_image | is_line | is_patch | is_surface))
+    error ("rotate: expecting image, line, patch, or surface objects");
+  endif
+
+  if (nargin == 4)
+    if (! (isnumeric (origin) && numel (origin) == 3))
+       error ("rotate: invalid origin");
+    endif
+  else
+    ## Should Z limit be considered when computing origin?
+
+    use_zlim = any (is_patch | is_surface);
+
+    if (! use_zlim && any (is_line))
+      idx = find (is_line)';
+      for i = idx
+        if (! isempty (get (h(i), "zdata")))
+          use_zlim = true;
+          break;
+        endif
+      endfor
+    endif
+
+    xlim = get (ax, "xlim");
+    ylim = get (ax, "ylim");
+
+    a = (xlim(1) + xlim(2)) / 2;
+    b = (ylim(1) + ylim(2)) / 2;
+
+    if (use_zlim)
+      zlim = get (ax, "zlim");
+      c = (zlim(1) + zlim(2)) / 2;
+    else
+      c = 0;
+    endif
+
+    origin = [a, b, c];
+  endif
+
+  direction = direction / norm (direction);
+
+  u = direction(1);
+  v = direction(2);
+  w = direction(3);
+
+  a = origin(1);
+  b = origin(2);
+  c = origin(3);
+
+  sa = sind (alpha);
+  ca = cosd (alpha);
+
+  for i = 1:numel (h)
+    x = get (h(i), "xdata");
+    y = get (h(i), "ydata");
+
+    if (is_image(i))
+      z = zeros (size (x));
+    else
+      z = get (h(i), "zdata");
+      if (isempty (z))
+        z = zeros (size (x));
+      elseif (isvector (x) && isvector (y) && ! isvector (z))
+        [x, y] = meshgrid (x, y);
+      endif
+    endif
+
+    if (a == 0 && b == 0 && c == 0)
+      tmp = (u*x + v*y + w*z) * (1 - ca);
+
+      xr = u*tmp + x*ca + (-w*y + v*z)*sa;
+      yr = v*tmp + y*ca + (w*x - u*z)*sa;
+      zr = w*tmp + z*ca + (-v*x + u*y)*sa;
+    else
+      one_m_ca = 1 - ca;
+      tmp = u*x + v*y + w*z;
+
+      xr = ((a*(v**2 + w**2) - u*(b*v + c*w - tmp))*one_m_ca
+            + x*ca + (-c*v + b*w - w*y + v*z)*sa);
+      yr = ((b*(u**2 + w**2) - v*(a*u + c*w - tmp))*one_m_ca
+            + y*ca + (c*u - a*w + w*x - u*z)*sa);
+      zr = ((c*(u**2 + v**2) - w*(a*u + b*v - tmp))*one_m_ca
+            + z*ca + (-b*u + a*v - v*x + u*y)*sa);
+    endif
+
+    set (h(i), "xdata", xr, "ydata", yr);
+
+    if (! is_image(i))
+      set (h(i), "zdata", zr);
+    endif
+  endfor
+
+endfunction
+
+%% Test input validation
+%!shared h1, h2, o1, o2, o3
+%! h1 = figure ("visible", "off");
+%! o1 = line ();
+%! h2 = figure ("visible", "off");
+%! o2 = line ();
+%! o3 = text (0, 0, "foobar");
+%!error rotate ()
+%!error rotate (o1)
+%!error rotate (o1, [0,0,0]);
+%!error <all handles must be children of the same axes object> rotate ([o1, o2], [0,0,0], 90);
+%!error <invalid direction> rotate (o1, "foo", 90);
+%!error <invalid rotation angle> rotate (o1, [0,0,0], "foo");
+%!error <invalid origin> rotate (o1, [0,0,0], 90, "foo");
+%!error rotate (o1, [0,0,0], 90, [0,0,0], 1);
+%!error <H must be an array of one or more graphics handles> rotate (NaN, [0,0,0], 90);
+%!error <expecting image, line, patch, or surface objects> rotate (o3, [0,0,0], 90);
+%!test
+%! close (h1);
+%! close (h2);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/util/rotate3d.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,74 @@
+## Copyright (C) 2014 Andreas Weber
+##
+## 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  {Command} {} rotate3d
+## @deftypefnx {Command} {} rotate3d on
+## @deftypefnx {Command} {} rotate3d off
+## @deftypefnx {Function File} {} rotate3d (@var{hax}, @dots{})
+## Control 3-D rotation mode of interactive graph in GUI.
+##
+## The function state input may be either @qcode{"on"} or @qcode{"off"}
+## and can only be set for 3-D plots.
+##
+## If the first argument @var{hax} is an axes handle, then operate on
+## this axis rather than the current axes returned by @code{gca}.
+##
+## To query the current mode use the @code{get} function.  For example:
+##
+## @example
+## mode = get (gca, "rotate3d");
+## @end example
+## @seealso{pan, zoom}
+## @end deftypefn
+
+function rotate3d (varargin)
+
+  if (numel (varargin) > 0 && isaxes (varargin{1}))
+    hax = varargin{1};
+    varargin(1) = [];
+  else
+    hax = gca ();
+  endif
+
+  toolkit = get (ancestor (hax, "figure"), "__graphics_toolkit__");
+  if (! strcmp (toolkit, "fltk"))
+    warning ("rotate3d: Only implemented for graphics_toolkit FLTK");
+  endif
+
+  ndims = __calc_dimensions__ (hax);
+  if (ndims == 2)
+    warning ("rotate3d: Only available for 3D plots");
+  else
+    if (numel (varargin) > 1)
+      print_usage ();
+    elseif (numel (varargin) == 0)
+      # toggle
+      m = get (hax, "pan");
+      if (strcmp (get (hax, "rotate3d"), "on"))
+        set (hax, "rotate3d", "off");
+      else
+        set (hax, "rotate3d", "on");
+      endif
+    elseif (numel (varargin) == 1)
+      set (hax, "rotate3d", varargin{1});
+    endif
+  endif
+
+endfunction
+
--- a/scripts/plot/util/saveas.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/util/saveas.m	Mon Jan 12 09:17:35 2015 -0800
@@ -56,7 +56,7 @@
 ## @end group
 ## @end example
 ##
-## @seealso{print, orient}
+## @seealso{print, hgsave, orient}
 ## @end deftypefn
 
 ## Author: Kai Habel
--- a/scripts/plot/util/struct2hdl.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/plot/util/struct2hdl.m	Mon Jan 12 09:17:35 2015 -0800
@@ -32,7 +32,7 @@
 ## A third boolean argument @var{hilev} can be passed to specify whether
 ## the function should preserve listeners/callbacks, e.g., for legends or
 ## hggroups.  The default is false.
-## @seealso{hdl2struct, findobj}
+## @seealso{hdl2struct, hgload, findobj}
 ## @end deftypefn
 
 ## Author: pdiribarne <pdiribarne@new-host.home>
@@ -177,7 +177,7 @@
 
 function [h, sout] = createaxes (s, p, par)
   ## regular axes
-  if (strcmp (s.properties.tag, ""))
+  if (! any (strcmpi (s.properties.tag, {"colorbar", "legend"})))
     propval = {"position", s.properties.position};
     hid = {"autopos_tag", "looseinset"};
     for ii = 1:numel (hid)
@@ -297,7 +297,11 @@
   h = patch (prp);
   set (h, "parent", par);
   s.properties = rmfield (s.properties,
-                            {"faces", "vertices", "facevertexcdata"});
+                          {"faces", "vertices", "facevertexcdata"});
+  ## Also remove derived properties.  Otherwise there is a possibility for
+  ## a segfault when 'set (h, properties)' is used to restore properties
+  ## which do not match in size the ones created with from the call to patch().
+  s.properties = rmfield (s.properties, {"xdata", "ydata", "zdata", "cdata"});
   addmissingprops (h, s.properties);
   sout = s;
 endfunction
@@ -447,7 +451,7 @@
 
   elseif (isfield (fields, "bargroup"))
     ## bar plot
-    ## FIXME - here we don't have access to brothers so we first create all
+    ## FIXME: Here we don't have access to brothers so we first create all
     ## the barseries of the bargroup (but the last), then retrieve information,
     ## and rebuild the whole bargroup.
     ## The duplicate are deleted after calling "setprops"
@@ -547,8 +551,7 @@
 endfunction
 
 function setprops (s, h, p, hilev)
-  more off;
-  if (strcmpi (s.properties.tag, ""))
+  if (! any (strcmpi (s.properties.tag, {"colorbar", "legend"})))
     specs = s.children(s.special);
     if (isempty (specs))
       hdls = [];
@@ -613,8 +616,7 @@
       endif
     endif
 
-  elseif (strcmpi (s.properties.tag, "legend")
-          || strcmpi (s.properties.tag, "colorbar"))
+  else
     set (h, s.properties);
   endif
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/util/zoom.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,164 @@
+## Copyright (C) 2014 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  {Command} {} zoom (@var{factor})
+## @deftypefnx {Command} {} zoom out
+## @deftypefnx {Command} {} zoom reset
+## Zoom the current axes object.
+##
+## Given a numeric argument greater than zero, zoom by the given factor.
+## If the zoom factor is greater than one, zoom in on the plot.  If the
+## factor is less than one, zoom out.  If the zoom factor is a two- or
+## three-element vector, then the elements specify the zoom factors for
+## the x, y, and z axes respectively.
+##
+## Given the option @qcode{"out"}, zoom to the initial zoom setting.
+##
+## Given the option @qcode{"reset"}, store the current zoom setting so
+## that @code{zoom out} will return to this zoom level.
+##
+## @seealso{pan, rotate3d}
+## @end deftypefn
+
+## Eventually we need to also support these features:
+## @deftypefn {Command} {} zoom
+## @deftypefnx {Command} {} zoom on
+## @deftypefnx {Command} {} zoom off
+## @deftypefnx {Command} {} zoom xon
+## @deftypefnx {Command} {} zoom yon
+## @deftypefnx {Command} {} zoom (@var{hfig}, @var{option})
+## @deftypefnx {Command} {zoom_object_handle =} zoom (@var{hfig})
+
+function zoom (varargin)
+
+  hfig = NaN;
+
+  nargs = nargin;
+
+  if (nargs > 2)
+    print_usage ();
+  endif
+
+  if (nargin == 1 && nargout > 0 && isfigure (varargin{1}))
+    error ("zoom_object_handle = zoom (hfig): not implemented");
+  endif
+
+  if (nargs == 2)
+    hfig = varargin{1};
+    if (isfigure (hfig))
+      varargin(1) = [];
+      nargs--;
+    else
+      error ("zoom: expecting figure handle as first argument");
+    endif
+  endif
+
+  if (isnan (hfig))
+    hfig = gcf ();
+  endif
+
+  if (nargs == 0)
+    error ("zoom: toggling zoom mode is not implemented");
+  elseif (nargs == 1)
+    arg = varargin{1};
+    if (isnumeric (arg))
+      factor = arg;
+      switch (numel (factor))
+        case 3
+          xfactor = factor(1);
+          yfactor = factor(2);
+          zfactor = factor(3);
+        case 2
+          xfactor = factor(1);
+          yfactor = factor(2);
+          zfactor = 1;
+        case 1
+          xfactor = yfactor = zfactor = factor;
+        otherwise
+          error ("zoom: invalid factor");
+      endswitch
+      if (xfactor < 0 || yfactor < 0 || zfactor < 0)
+        error ("zoom: factor must be greater than 1");
+      elseif (xfactor == 1 && yfactor == 1 && zfactor == 1)
+        return;
+      endif
+      cax = get (hfig, "currentaxes");
+      if (! isempty (cax))
+        limits = axis ();
+        initial_zoom = getappdata (cax, "initial_zoom");
+        if (isempty (initial_zoom))
+          setappdata (cax, "__initial_zoom__", limits);
+        endif
+        limits(1:2) /= xfactor;
+        limits(3:4) /= yfactor;
+        if (numel (limits) > 4)
+          limits(5:6) /= zfactor;
+        endif
+        axis (cax, limits);
+      endif
+    elseif (ischar (arg))
+      switch (arg)
+        case {"on", "off", "xon", "yon"}
+          error ("zoom %s: not implemented", arg);
+
+        case "out"
+          cax = get (hfig, "currentaxes");
+          if (! isempty (cax))
+            initial_zoom = getappdata (cax, "__initial_zoom__");
+            if (! isempty (initial_zoom))
+              axis (cax, initial_zoom);
+            endif
+          endif
+
+        case "reset"
+          cax = get (hfig, "currentaxes");
+          if (! isempty (cax))
+            setappdata (cax, "__initial_zoom__", axis ());
+          endif
+
+        otherwise
+          error ("zoom: unrecognized option '%s'", arg);
+      endswitch
+    else
+      error ("zoom: wrong type argument '%s'", class (arg));
+    endif
+  endif
+
+endfunction
+
+%!demo
+%! clf;
+%! sombrero ();
+%! pause (1);
+%! %% zoom in by a factor of 2
+%! zoom (2);
+%! pause (1);
+%! %% return to original zoom level
+%! zoom out;
+%! pause (1);
+%! %% zoom in by a factor of 2
+%! zoom (2);
+%! pause (1);
+%! %% set this zoom level as the "initial zoom level"
+%! %% and zoom in some more
+%! zoom reset;
+%! zoom (2);
+%! pause (1);
+%! %% return to zoom level set by last call to "zoom reset"
+%! zoom out;
--- a/scripts/polynomial/polygcd.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/polynomial/polygcd.m	Mon Jan 12 09:17:35 2015 -0800
@@ -91,10 +91,12 @@
 %!assert (deconv (poly (1:8), polygcd (poly (1:8), poly (3:12))), poly (1:2), sqrt (eps))
 
 %!test
-%! for ii=1:10
-%!   p  = (unique (randn (10, 1)) * 10).';
+%! for ii=1:100
+%!   ## Exhibits numerical problems for multipliers of ~4 and greater.
+%!   p  = (unique (randn (10, 1)) * 3).';
 %!   p1 = p(3:end);
 %!   p2 = p(1:end-2);
-%!   assert (polygcd (poly (-p1), poly (-p2)), poly (- intersect (p1, p2)), sqrt (eps));
+%!   assert (polygcd (poly (-p1), poly (-p2)),
+%!           poly (- intersect (p1, p2)), sqrt (eps));
 %! endfor
 
--- a/scripts/polynomial/private/__splinefit__.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/polynomial/private/__splinefit__.m	Mon Jan 12 09:17:35 2015 -0800
@@ -111,7 +111,7 @@
 %   2011-07-01  Robust fitting parameter added.
 
 % Check number of arguments
-error(nargchk(3,7,nargin));
+narginchk(3,7);
 
 % Check arguments
 [x,y,dim,breaks,n,periodic,beta,constr] = arguments(varargin{:});
--- a/scripts/set/intersect.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/set/intersect.m	Mon Jan 12 09:17:35 2015 -0800
@@ -18,19 +18,25 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} intersect (@var{a}, @var{b})
-## @deftypefnx {Function File} {[@var{c}, @var{ia}, @var{ib}] =} intersect (@var{a}, @var{b})
+## @deftypefn  {Function File} {@var{c} =} intersect (@var{a}, @var{b})
+## @deftypefnx {Function File} {@var{c} =} intersect (@var{a}, @var{b}, "rows")
+## @deftypefnx {Function File} {[@var{c}, @var{ia}, @var{ib}] =} intersect (@dots{})
+##
+## Return the elements common to both @var{a} and @var{b} sorted in ascending
+## order.
 ##
-## Return the elements in both @var{a} and @var{b}, sorted in ascending
-## order.  If @var{a} and @var{b} are both column vectors return a column
-## vector, otherwise return a row vector.
-## @var{a}, @var{b} may be cell arrays of string(s).
+## If @var{a} and @var{b} are both column vectors then return a column vector;
+## Otherwise, return a row vector.  The inputs may also be cell arrays of
+## strings.
 ##
-## Return index vectors @var{ia} and @var{ib} such that @code{a(ia)==c} and
-## @code{b(ib)==c}.
+## If the optional input @qcode{"rows"} is given then return the common rows of
+## @var{a} and @var{b}.  The inputs must be 2-D matrices to use this option.
+##
+## If requested, return index vectors @var{ia} and @var{ib} such that
+## @code{@var{c} = @var{a}(@var{ia})} and @code{@var{c} = @var{b}(@var{ib})}.
 ##
 ## @end deftypefn
-## @seealso{unique, union, setxor, setdiff, ismember}
+## @seealso{unique, union, setdiff, setxor, ismember}
 
 function [c, ia, ib] = intersect (a, b, varargin)
 
@@ -38,12 +44,15 @@
     print_usage ();
   endif
 
-  [a, b] = validargs ("intersect", a, b, varargin{:});
+  [a, b] = validsetargs ("intersect", a, b, varargin{:});
 
   if (isempty (a) || isempty (b))
     c = ia = ib = [];
   else
-    ## form a and b into sets
+    by_rows = nargin == 3;
+    iscol = isvector (a) && isvector (b) && iscolumn (a) && iscolumn (b);
+
+    ## Form A and B into sets
     if (nargout > 1)
       [a, ja] = unique (a, varargin{:});
       [b, jb] = unique (b, varargin{:});
@@ -52,7 +61,7 @@
       b = unique (b, varargin{:});
     endif
 
-    if (nargin > 2)
+    if (by_rows)
       c = [a; b];
       [c, ic] = sortrows (c);
       ii = find (all (c(1:end-1,:) == c(2:end,:), 2));
@@ -60,7 +69,7 @@
       len_a = rows (a);
     else
       c = [a(:); b(:)];
-      [c, ic] = sort (c);               # [a(:);b(:)](ic) == c
+      [c, ic] = sort (c);         # [a(:);b(:)](ic) == c
       if (iscellstr (c))
         ii = find (strcmp (c(1:end-1), c(2:end)));
       else
@@ -71,11 +80,12 @@
     endif
 
     if (nargout > 1)
-      ia = ja(ic(ii));                  # a(ia) == c
-      ib = jb(ic(ii+1) - len_a);        # b(ib) == c
+      ia = ja(ic(ii));            # a(ia) == c
+      ib = jb(ic(ii+1) - len_a);  # b(ib) == c
     endif
 
-    if (nargin == 2 && (rows (b) == 1 || rows (a) == 1))
+    ## Adjust output orientation for Matlab compatibility
+    if (! by_rows && ! iscol)
       c = c.';
     endif
   endif
@@ -83,7 +93,24 @@
 endfunction
 
 
-%!# Test the routine for index vectors ia and ib
+## Test orientation of output
+%!shared a,b
+%! a = 1:4;
+%! b = 2:5;
+
+%!assert (size (intersect (a, b)), [1 3])
+%!assert (size (intersect (a', b)), [1 3])
+%!assert (size (intersect (a, b')), [1 3])
+%!assert (size (intersect (a', b')), [3 1])
+
+## Test multi-dimensional arrays
+%!test
+%! a = rand (3,3,3);
+%! b = a;
+%! b(1,1,1) = 2;
+%! assert (intersect (a, b), sort (a(2:end)));
+
+## Test the routine for index vectors ia and ib
 %!test
 %! a = [3 2 4 5 7 6 5 1 0 13 13];
 %! b = [3 5 12 1 1 7];
--- a/scripts/set/ismember.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/set/ismember.m	Mon Jan 12 09:17:35 2015 -0800
@@ -18,13 +18,16 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {@var{tf} =} ismember (@var{A}, @var{s})
-## @deftypefnx {Function File} {[@var{tf}, @var{S_idx}] =} ismember (@var{A}, @var{s})
-## @deftypefnx {Function File} {[@var{tf}, @var{S_idx}] =} ismember (@var{A}, @var{s}, "rows")
-## Return a logical matrix @var{tf} with the same shape as @var{A} which is
-## true (1) if @code{A(i,j)} is in @var{s} and false (0) if it is not.  If a
-## second output argument is requested, the index into @var{s} of each of the
-## matching elements is also returned.
+## @deftypefn  {Function File} {@var{tf} =} ismember (@var{a}, @var{s})
+## @deftypefnx {Function File} {@var{tf} =} ismember (@var{a}, @var{s}, "rows")
+## @deftypefnx {Function File} {[@var{tf}, @var{s_idx}] =} ismember (@dots{})
+##
+## Return a logical matrix @var{tf} with the same shape as @var{a} which is
+## true (1) if the element in @var{a} is found in @var{s} and false (0) if it
+## is not.
+##
+## If a second output argument is requested then the index into @var{s} of each
+## matching element is also returned.
 ##
 ## @example
 ## @group
@@ -36,7 +39,7 @@
 ## @end group
 ## @end example
 ##
-## The inputs, @var{A} and @var{s}, may also be cell arrays.
+## The inputs @var{a} and @var{s} may also be cell arrays.
 ##
 ## @example
 ## @group
@@ -48,9 +51,9 @@
 ## @end group
 ## @end example
 ##
-## With the optional third argument @qcode{"rows"}, and matrices
-## @var{A} and @var{s} with the same number of columns, compare rows in
-## @var{A} with the rows in @var{s}.
+## If the optional third argument @qcode{"rows"} is given then compare rows
+## in @var{a} with rows in @var{s}.  The inputs must be 2-D matrices with the
+## same number of columns to use this option.
 ##
 ## @example
 ## @group
@@ -62,7 +65,7 @@
 ## @end group
 ## @end example
 ##
-## @seealso{unique, union, intersect, setxor, setdiff}
+## @seealso{lookup, unique, union, intersect, setdiff, setxor}
 ## @end deftypefn
 
 ## Author: Paul Kienzle <pkienzle@users.sf.net>
@@ -71,63 +74,67 @@
 ## Adapted-by: jwe
 ## Reimplemented using lookup & unique: Jaroslav Hajek <highegg@gmail.com>
 
-function [tf, a_idx] = ismember (A, s, varargin)
+function [tf, s_idx] = ismember (a, s, varargin)
 
   if (nargin < 2 || nargin > 3)
     print_usage ();
   endif
 
   ## lookup() does not handle logical values
-  if (islogical (A))
-    A = uint8 (A);
+  if (islogical (a))
+    a = uint8 (a);
   endif
   if (islogical (s))
     s = uint8 (s);
   endif
 
-  [A, s] = validargs ("ismember", A, s, varargin{:});
+  [a, s] = validsetargs ("ismember", a, s, varargin{:});
+
+  by_rows = nargin == 3;
 
-  if (nargin == 2)
+  if (! by_rows)
     s = s(:);
-    ## We do it this way, because we expect the array to be often sorted.
+    ## Check sort status, because we expect the array will often be sorted.
     if (issorted (s))
       is = [];
     else
       [s, is] = sort (s);
     endif
 
-    ## sort out NaNs in table
+    ## Remove NaNs from table because lookup can't handle them
     if (isreal (s) && ! isempty (s) && isnan (s(end)))
-        s = s(1:end - sum (isnan (s)));
+      s = s(1:end - sum (isnan (s)));
     endif
 
     if (nargout > 1)
-      a_idx = lookup (s, A, "m");
-      tf = logical (a_idx);
+      s_idx = lookup (s, a, "m");
+      tf = logical (s_idx);
       if (! isempty (is))
-        a_idx(tf) = is (a_idx(tf));
+        s_idx(tf) = is(s_idx(tf));
       endif
     else
-      tf = lookup (s, A, "b");
+      tf = lookup (s, a, "b");
     endif
 
-  else
-
-    if (isempty (A) || isempty (s))
-      tf = false (rows (A), 1);
-      a_idx = zeros (rows (A), 1);
+  else  # "rows" argument
+    if (isempty (a) || isempty (s))
+      tf = false (rows (a), 1);
+      s_idx = zeros (rows (a), 1);
     else
+      if (rows (s) == 1)
+        tf = all (bsxfun (@eq, a, s), 2);
+        s_idx = double (tf);
+      else
+        ## FIXME: lookup does not support "rows", so we just use unique.
+        [~, ii, jj] = unique ([a; s], "rows", "last");
+        na = rows (a);
+        jj = ii(jj(1:na));
+        tf = jj > na;
 
-      ## FIXME: lookup does not support "rows", so we just use unique.
-      [xx, ii, jj] = unique ([A; s], "rows", "last");
-      na = rows (A);
-      jj = ii(jj(1:na));
-      tf = jj > na;
-
-      if (nargout > 1)
-        a_idx = max (0, jj - na);
+        if (nargout > 1)
+          s_idx = max (0, jj - na);
+        endif
       endif
-
     endif
   endif
 
@@ -155,62 +162,67 @@
 %!assert (ismember ("1", "0123456789."), true)
 
 %!test
-%! [result, a_idx] = ismember ([1, 2], []);
+%! [result, s_idx] = ismember ([1, 2], []);
 %! assert (result, [false false])
-%! assert (a_idx, [0, 0]);
+%! assert (s_idx, [0, 0]);
 
 %!test
-%! [result, a_idx] = ismember ([], [1, 2]);
+%! [result, s_idx] = ismember ([], [1, 2]);
 %! assert (result, logical ([]))
-%! assert (a_idx, []);
+%! assert (s_idx, []);
 
 %!test
-%! [result, a_idx] = ismember ({"a", "b"}, "");
+%! [result, s_idx] = ismember ({"a", "b"}, "");
 %! assert (result, [false false])
-%! assert (a_idx, [0, 0]);
+%! assert (s_idx, [0, 0]);
 
 %!test
-%! [result, a_idx] = ismember ({"a", "b"}, {});
+%! [result, s_idx] = ismember ({"a", "b"}, {});
 %! assert (result, [false false])
-%! assert (a_idx, [0, 0]);
+%! assert (s_idx, [0, 0]);
 
 %!test
-%! [result, a_idx] = ismember ("", {"a", "b"});
+%! [result, s_idx] = ismember ("", {"a", "b"});
 %! assert (result, false)
-%! assert (a_idx, 0);
+%! assert (s_idx, 0);
 
 %!test
-%! [result, a_idx] = ismember ({}, {"a", "b"});
+%! [result, s_idx] = ismember ({}, {"a", "b"});
 %! assert (result, logical ([]))
-%! assert (a_idx, []);
+%! assert (s_idx, []);
 
 %!test
-%! [result, a_idx] = ismember ([1 2 3 4 5], [3]);
+%! [result, s_idx] = ismember ([1 2 3 4 5], [3]);
 %! assert (result, logical ([0 0 1 0 0]))
-%! assert (a_idx , [0 0 1 0 0]);
+%! assert (s_idx , [0 0 1 0 0]);
 
 %!test
-%! [result, a_idx] = ismember ([1 6], [1 2 3 4 5 1 6 1]);
+%! [result, s_idx] = ismember ([1 6], [1 2 3 4 5 1 6 1]);
 %! assert (result, [true true]);
-%! assert (a_idx(2), 7);
+%! assert (s_idx(2), 7);
 
 %!test
-%! [result, a_idx] = ismember ([3,10,1], [0,1,2,3,4,5,6,7,8,9]);
+%! [result, s_idx] = ismember ([3,10,1], [0,1,2,3,4,5,6,7,8,9]);
 %! assert (result, [true false true]);
-%! assert (a_idx, [4, 0, 2]);
+%! assert (s_idx, [4, 0, 2]);
 
 %!test
-%! [result, a_idx] = ismember ("1.1", "0123456789.1");
+%! [result, s_idx] = ismember ("1.1", "0123456789.1");
 %! assert (result, [true true true]);
-%! assert (a_idx, [12, 11, 12]);
+%! assert (s_idx, [12, 11, 12]);
+
+%!test
+%! [result, s_idx] = ismember ([1:3; 5:7; 4:6], [0:2; 1:3; 2:4; 3:5; 4:6], "rows");
+%! assert (result, [true; false; true]);
+%! assert (s_idx, [2; 0; 5]);
 
 %!test
-%! [result, a_idx] = ismember ([1:3; 5:7; 4:6], [0:2; 1:3; 2:4; 3:5; 4:6], "rows");
+%! [result, s_idx] = ismember ([1.1,1.2,1.3; 2.1,2.2,2.3; 10,11,12], [1.1,1.2,1.3; 10,11,12; 2.12,2.22,2.32], "rows");
 %! assert (result, [true; false; true]);
-%! assert (a_idx, [2; 0; 5]);
+%! assert (s_idx, [1; 0; 2]);
 
 %!test
-%! [result, a_idx] = ismember ([1.1,1.2,1.3; 2.1,2.2,2.3; 10,11,12], [1.1,1.2,1.3; 10,11,12; 2.12,2.22,2.32], "rows");
-%! assert (result, [true; false; true]);
-%! assert (a_idx, [1; 0; 2]);
+%! [result, s_idx] = ismember ([1:3; 5:7; 4:6; 0:2; 1:3; 2:4], [1:3], "rows");
+%! assert (result, logical ([1 0 0 0 1 0]'));
+%! assert (s_idx, [1 0 0 0 1 0]');
 
--- a/scripts/set/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/set/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -8,7 +8,7 @@
   set/setxor.m \
   set/union.m \
   set/unique.m \
-  set/private/validargs.m
+  set/private/validsetargs.m
 
 FCN_FILES += $(set_FCN_FILES)
 
--- a/scripts/set/powerset.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/set/powerset.m	Mon Jan 12 09:17:35 2015 -0800
@@ -25,33 +25,35 @@
 ## output will always be a cell array of either vectors or strings.
 ##
 ## With the optional second argument @qcode{"rows"}, each row of the set @var{a}
-## is considered one element of the set.  As a result, @var{a} must then be a
-## numerical 2-D matrix.
+## is considered one element of the set.  The input must be a 2-D numeric
+## matrix to use this argument.
 ##
-## @seealso{unique, union, setxor, setdiff, ismember}
+## @seealso{unique, union, intersect, setdiff, setxor, ismember}
 ## @end deftypefn
 
 function p = powerset (a, byrows_arg)
 
+  if (nargin < 1 || nargin > 2)
+    print_usage ();
+  endif
+
   byrows = false;
-
   if (nargin == 2)
     if (! strcmpi (byrows_arg, "rows"))
       error ('powerset: expecting second argument to be "rows"');
     elseif (iscell (a))
-      warning ('powerset: "rows" not valid for cell arrays');
+      error ('powerset: "rows" not valid for cell arrays');
     else
       byrows = true;
     endif
-  elseif (nargin != 1)
-    print_usage ();
   endif
+
   if (iscell (a) && ! iscellstr (a))
-    error ("powerset: cell arrays can only used for character strings");
+    error ("powerset: cell arrays can only be used for character strings");
   endif
 
   if (byrows)
-    a = unique (a, byrows_arg);
+    a = unique (a, "rows");
     n = rows (a);
   else
     a = unique (a);
@@ -86,12 +88,23 @@
 endfunction
 
 
-%!shared c, p
-%! c = sort (cellstr ({ [], [1], [2], [3], [1, 2], [1, 3], [2, 3], [1, 2, 3]}));
+%!test
+%! c = sort (cellstr ({[], [1], [2], [3], [1, 2], [1, 3], [2, 3], [1, 2, 3]}));
 %! p = sort (cellstr (powerset ([1, 2, 3])));
-%!assert (p, c);
+%! assert (p, c);
+
+%!test
 %! c = sort (cellstr ({ [], [1:3], [2:4], [3:5], [1:3; 2:4], [1:3; 3:5], [2:4; 3:5], [1:3; 2:4; 3:5]}));
 %! p = sort (cellstr (powerset ([1:3;2:4;3:5], "rows")));
-%!assert (p,c);
+%! assert (p,c);
+
 %!assert (powerset([]), {});  # always return a cell array
 
+%% Test input validation
+%!error powerset ()
+%!error powerset (1,2,3)
+%!error <expecting second argument to be "rows"> powerset (1, "cols")
+%!error <"rows" not valid for cell arrays> powerset ({1}, "rows")
+%!error <cell arrays can only be used for character> powerset ({1})
+%!error <not implemented for more than 32 elements> powerset (1:33)
+
--- a/scripts/set/private/validargs.m	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-## Copyright (C) 2000-2013 Paul Kienzle
-## Copyright (C) 2009-2010 Jaroslav Hajek
-##
-## 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/>.
-
-## Validate arguments for binary set operation.
-function [x, y] = validargs (caller, x, y, byrows_arg)
-
-  if (nargin == 3)
-    icx = iscellstr (x);
-    icy = iscellstr (y);
-    if (icx || icy)
-      if (icx && ischar (y))
-        y = cellstr (y);
-      elseif (icy && ischar (x))
-        x = cellstr (x);
-      elseif (! (icx && icy))
-        error ("%s: cell array of strings cannot be combined with a nonstring value", caller);
-      endif
-    elseif (! (ismatrix (x) && ismatrix (y)))
-      error ("%s: input arguments must be arrays or cell arrays of strings", caller);
-    endif
-  elseif (nargin == 4)
-    if (strcmpi (byrows_arg, "rows"))
-      if (iscell (x) || iscell (y))
-        error ('%s: cells not supported with "rows"', caller);
-      elseif (! (ismatrix (x) && ismatrix (y)))
-        error ("%s: input arguments must be arrays or cell arrays of strings", caller);
-      else
-        if (ndims (x) > 2 || ndims (y) > 2)
-          error ('%s: need 2-dimensional matrices for "rows"', caller);
-        elseif (columns (x) != columns (y) && ! (isempty (x) || isempty (y)))
-          error ("%s: number of columns must match", caller);
-        endif
-      endif
-    else
-      error ("%s: invalid option: %s", caller, byrows_arg);
-    endif
-  else
-    print_usage (caller);
-  endif
-
-endfunction
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/set/private/validsetargs.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,59 @@
+## Copyright (C) 2000-2013 Paul Kienzle
+## Copyright (C) 2009-2010 Jaroslav Hajek
+##
+## 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/>.
+
+## Validate arguments for binary set operation.
+
+function [x, y] = validsetargs (caller, x, y, byrows_arg)
+
+  if (nargin == 3)
+    icx = iscellstr (x);
+    icy = iscellstr (y);
+    if (icx || icy)
+      if (icx && ischar (y))
+        y = cellstr (y);
+      elseif (icy && ischar (x))
+        x = cellstr (x);
+      elseif (! (icx && icy))
+        error ("%s: cell array of strings cannot be combined with a nonstring value", caller);
+      endif
+    elseif (! (ismatrix (x) && ismatrix (y)))
+      error ("%s: A and B must be arrays or cell arrays of strings", caller);
+    endif
+  elseif (nargin == 4)
+    if (! strcmpi (byrows_arg, "rows"))
+      error ("%s: invalid option: %s", caller, byrows_arg);
+    endif
+
+    if (iscell (x) || iscell (y))
+      error ('%s: cells not supported with "rows"', caller);
+    elseif (! (ismatrix (x) && ismatrix (y)))
+      error ("%s: A and B must be arrays or cell arrays of strings", caller);
+    else
+      if (ndims (x) > 2 || ndims (y) > 2)
+        error ('%s: A and B must be 2-dimensional matrices for "rows"', caller);
+      elseif (columns (x) != columns (y) && ! (isempty (x) || isempty (y)))
+        error ("%s: number of columns in A and B must match", caller);
+      endif
+    endif
+  endif
+
+endfunction
+
+
+## %!tests for function are in union.m
--- a/scripts/set/setdiff.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/set/setdiff.m	Mon Jan 12 09:17:35 2015 -0800
@@ -18,72 +18,81 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} setdiff (@var{a}, @var{b})
-## @deftypefnx {Function File} {} setdiff (@var{a}, @var{b}, "rows")
-## @deftypefnx {Function File} {[@var{c}, @var{i}] =} setdiff (@var{a}, @var{b})
-## Return the elements in @var{a} that are not in @var{b}, sorted in
-## ascending order.  If @var{a} and @var{b} are both column vectors
-## return a column vector, otherwise return a row vector.
-## @var{a}, @var{b} may be cell arrays of string(s).
+## @deftypefn  {Function File} {@var{c} =} setdiff (@var{a}, @var{b})
+## @deftypefnx {Function File} {@var{c} =} setdiff (@var{a}, @var{b}, "rows")
+## @deftypefnx {Function File} {[@var{c}, @var{ia}] =} setdiff (@dots{})
+## Return the elements in @var{a} that are not in @var{b} sorted in
+## ascending order.
 ##
-## Given the optional third argument @qcode{"rows"}, return the rows in
-## @var{a} that are not in @var{b}, sorted in ascending order by rows.
+## If @var{a} and @var{b} are both column vectors return a column vector;
+## Otherwise, return a row vector.  The inputs may also be cell arrays of
+## strings.
 ##
-## If requested, return @var{i} such that @code{c = a(i)}.
+## If the optional input @qcode{"rows"} is given then return the rows in 
+## @var{a} that are not in @var{b}.  The inputs must be 2-D matrices to use
+## this option.
+##
+## If requested, return the index vector @var{ia} such that
+## @code{@var{c} = @var{a}(@var{ia})}.
 ## @seealso{unique, union, intersect, setxor, ismember}
 ## @end deftypefn
 
 ## Author: Paul Kienzle
 ## Adapted-by: jwe
 
-function [c, i] = setdiff (a, b, varargin)
+function [c, ia] = setdiff (a, b, varargin)
 
   if (nargin < 2 || nargin > 3)
     print_usage ();
   endif
 
-  [a, b] = validargs ("setdiff", a, b, varargin{:});
+  [a, b] = validsetargs ("setdiff", a, b, varargin{:});
 
-  if (nargin > 2)
+  by_rows = nargin == 3;
+  iscol = isvector (a) && isvector (b) && iscolumn (a) && iscolumn (b);
+
+  if (by_rows)
     if (nargout > 1)
-      [c, i] = unique (a, "rows");
+      [c, ia] = unique (a, "rows");
     else
       c = unique (a, "rows");
     endif
     if (! isempty (c) && ! isempty (b))
-      ## Form a and b into combined set.
+      ## Form A and B into combined set.
       b = unique (b, "rows");
-      [dummy, idx] = sortrows ([c; b]);
-      ## Eliminate those elements of a that are the same as in b.
-      dups = find (all (dummy(1:end-1,:) == dummy(2:end,:), 2));
+      [tmp, idx] = sortrows ([c; b]);
+      ## Eliminate those elements of A that are the same as in B.
+      dups = find (all (tmp(1:end-1,:) == tmp(2:end,:), 2));
       c(idx(dups),:) = [];
       if (nargout > 1)
-        i(idx(dups),:) = [];
+        ia(idx(dups),:) = [];
       endif
     endif
   else
     if (nargout > 1)
-      [c, i] = unique (a);
+      [c, ia] = unique (a);
     else
       c = unique (a);
     endif
     if (! isempty (c) && ! isempty (b))
       ## Form a and b into combined set.
       b = unique (b);
-      [dummy, idx] = sort ([c(:); b(:)]);
+      [tmp, idx] = sort ([c(:); b(:)]);
       ## Eliminate those elements of a that are the same as in b.
-      if (iscellstr (dummy))
-        dups = find (strcmp (dummy(1:end-1), dummy(2:end)));
+      if (iscellstr (tmp))
+        dups = find (strcmp (tmp(1:end-1), tmp(2:end)));
       else
-        dups = find (dummy(1:end-1) == dummy(2:end));
+        dups = find (tmp(1:end-1) == tmp(2:end));
       endif
       c(idx(dups)) = [];
       if (nargout > 1)
-        i(idx(dups)) = [];
+        ia(idx(dups)) = [];
       endif
-      ## Reshape if necessary.
-      if (rows (c) != 1 && rows (b) == 1)
-        c = c.';
+      ## Reshape if necessary for Matlab compatibility.
+      if (iscol)
+        c = c(:);
+      else
+        c = c(:).';
       endif
     endif
   endif
@@ -100,8 +109,22 @@
 %!assert (setdiff ({"one","two";"three","four"}, {"one","two";"three","six"}), {"four"})
 
 %!test
-%! a = [3, 1, 4, 1, 5];  b = [1, 2, 3, 4];
-%! [y, i] = setdiff (a, b.');
-%! assert (y, [5]);
-%! assert (y, a(i));
+%! a = [3, 1, 4, 1, 5];
+%! b = [1, 2, 3, 4];
+%! [c, ia] = setdiff (a, b');
+%! assert (c, [5]);
+%! assert (c, a(ia));
 
+%% Test output orientation compatibility (bug #42577)
+%!assert (setdiff ([1:5], 2), [1,3,4,5])
+%!assert (setdiff ([1:5]', 2), [1;3;4;5])
+%!assert (setdiff ([1:5], [2:3]), [1,4,5])
+%!assert (setdiff ([1:5], [2:3]'), [1,4,5])
+%!assert (setdiff ([1:5]', [2:3]), [1,4,5])
+%!assert (setdiff ([1:5]', [2:3]'), [1;4;5])
+
+%!test
+%! a = rand (3,3,3);
+%! b = a(1);
+%! assert (setdiff (a, b), sort (a(2:end)));
+
--- a/scripts/set/setxor.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/set/setxor.m	Mon Jan 12 09:17:35 2015 -0800
@@ -1,3 +1,4 @@
+## Copyright (C) 2014 Julien Bect
 ## Copyright (C) 2008-2013 Jaroslav Hajek
 ## Copyright (C) 2000, 2006-2007 Paul Kienzle
 ##
@@ -18,18 +19,24 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} setxor (@var{a}, @var{b})
-## @deftypefnx {Function File} {} setxor (@var{a}, @var{b}, "rows")
-## @deftypefnx {Function File} {[@var{c}, @var{ia}, @var{ib}] =} setxor (@var{a}, @var{b})
+## @deftypefn  {Function File} {@var{c} =} setxor (@var{a}, @var{b})
+## @deftypefnx {Function File} {@var{c} =} setxor (@var{a}, @var{b}, "rows")
+## @deftypefnx {Function File} {[@var{c}, @var{ia}, @var{ib}] =} setxor (@dots{})
+##
+## Return the elements exclusive to sets @var{a} or @var{b} sorted in
+## ascending order.
 ##
-## Return the elements exclusive to @var{a} or @var{b}, sorted in ascending
-## order.  If @var{a} and @var{b} are both column vectors return a column
-## vector, otherwise return a row vector.
-## @var{a}, @var{b} may be cell arrays of string(s).
+## If @var{a} and @var{b} are both column vectors return a column vector;
+## Otherwise, return a row vector.  The inputs may also be cell arrays of
+## strings.
 ##
-## With three output arguments, return index vectors @var{ia} and @var{ib}
-## such that @code{a(ia)} and @code{b(ib)} are disjoint sets whose union
-## is @var{c}.
+## If the optional input @qcode{"rows"} is given then return the rows exclusive
+## to sets @var{a} and @var{b}.  The inputs must be 2-D matrices to use this
+## option.
+##
+## If requested, return index vectors @var{ia} and @var{ib} such that
+## @code{@var{a}(@var{ia})} and @code{@var{b}(@var{ib})} are disjoint sets
+## whose union is @var{c}.
 ##
 ## @seealso{unique, union, intersect, setdiff, ismember}
 ## @end deftypefn
@@ -40,7 +47,10 @@
     print_usage ();
   endif
 
-  [a, b] = validargs ("setxor", a, b, varargin{:});
+  [a, b] = validsetargs ("setxor", a, b, varargin{:});
+
+  by_rows = nargin == 3;
+  iscol = isvector (a) && isvector (b) && iscolumn (a) && iscolumn (b);
 
   ## Form A and B into sets.
   if (nargout > 1)
@@ -57,8 +67,8 @@
     c = a;
   else
     ## Reject duplicates.
-    if (nargin > 2)
-      na = rows (a); nb = rows (b);
+    if (by_rows)
+      na = rows (a);  nb = rows (b);
       [c, i] = sortrows ([a; b]);
       n = rows (c);
       idx = find (all (c(1:n-1, :) == c(2:n, :), 2));
@@ -67,7 +77,7 @@
         i([idx, idx+1],:) = [];
       endif
     else
-      na = numel (a); nb = numel (b);
+      na = numel (a);  nb = numel (b);
       [c, i] = sort ([a(:); b(:)]);
       n = length (c);
       if (iscell (c))
@@ -79,31 +89,81 @@
         c([idx, idx+1]) = [];
         i([idx, idx+1]) = [];
       endif
-      if (rows (a) == 1 || rows (b) == 1)
+
+      ## Adjust output orientation for Matlab compatibility
+      if (! iscol)
         c = c.';
       endif
     endif
-  endif
-  if (nargout > 1)
-    ia = ia(i(i <= na));
-    ib = ib(i(i > na) - na);
+
+    if (nargout > 1)
+      ia = ia(i(i <= na));
+      ib = ib(i(i > na) - na);
+    endif
   endif
 
 endfunction
 
 
-%!assert (setxor ([1,2,3],[2,3,4]),[1,4])
+%!assert (setxor ([1,2,3], [2,3,4]), [1,4])
 %!assert (setxor ({'a'}, {'a', 'b'}), {'b'})
 
 %!test
-%! a = [3, 1, 4, 1, 5];  b = [1, 2, 3, 4];
+%! a = [3, 1, 4, 1, 5];
+%! b = [1, 2, 3, 4];
 %! [c, ia, ib] = setxor (a, b.');
 %! assert (c, [2, 5]);
 %! assert (c, sort ([a(ia), b(ib)]));
 
 %!test
-%! a = [1 2; 4 5; 1 3];  b = [1 1; 1 2; 4 5; 2 10];
+%! a = [1 2; 4 5; 1 3];
+%! b = [1 1; 1 2; 4 5; 2 10];
 %! [c, ia, ib] = setxor (a, b, "rows");
 %! assert (c, [1 1; 1 3; 2 10]);
 %! assert (c, sortrows ([a(ia,:); b(ib,:)]));
 
+%!assert (setxor (1, []), 1)
+%!assert (setxor ([], 1), 1)
+
+%!test
+%! [c, ia, ib] = setxor (1, []);
+%! assert (c, 1);
+%! assert (ia, 1);
+%! assert (isempty (ib));
+
+%!test
+%! [c, ia, ib] = setxor ([], 1);
+%! assert (c, 1);
+%! assert (isempty (ia));
+%! assert (ib, 1);
+
+%!test
+%! a = [2 1; 4 3];  b = [];
+%! [c, ia, ib] = setxor (a, b);
+%! assert (c, [1; 2; 3; 4]);
+%! assert (ia, [3; 1; 4; 2]);
+%! assert (isempty (ib));
+
+%!test
+%! a = [];  b = [2 1; 4 3];
+%! [c, ia, ib] = setxor (a, b);
+%! assert (c, [1; 2; 3; 4]);
+%! assert (isempty (ia));
+%! assert (ib, [3; 1; 4; 2]);
+## Test orientation of output
+%!shared x,y
+%! x = 1:3;
+%! y = 2:5;
+
+%!assert (size (setxor (x, y)), [1 3])
+%!assert (size (setxor (x', y)), [1 3])
+%!assert (size (setxor (x, y')), [1 3])
+%!assert (size (setxor (x', y')), [3 1])
+
+## Test multi-dimensional arrays
+%!test
+%! a = rand (3,3,3);
+%! b = a;
+%! b(1,1,1) = 2;
+%! assert (intersect (a, b), sort (a(2:end)));
+
--- a/scripts/set/union.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/set/union.m	Mon Jan 12 09:17:35 2015 -0800
@@ -18,38 +18,26 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} union (@var{a}, @var{b})
-## @deftypefnx {Function File} {} union (@var{a}, @var{b}, "rows")
-## @deftypefnx {Function File} {[@var{c}, @var{ia}, @var{ib}] =} union (@var{a}, @var{b})
+## @deftypefn  {Function File} {@var{c} =} union (@var{a}, @var{b})
+## @deftypefnx {Function File} {@var{c} =} union (@var{a}, @var{b}, "rows")
+## @deftypefnx {Function File} {[@var{c}, @var{ia}, @var{ib}] =} union (@dots{})
 ##
-## Return the set of elements that are in either of the sets @var{a} and
-## @var{b}.  @var{a}, @var{b} may be cell arrays of strings.
-## For example:
-##
-## @example
-## @group
-## union ([1, 2, 4], [2, 3, 5])
-##     @result{} [1, 2, 3, 4, 5]
-## @end group
-## @end example
+## Return the elements that are in either @var{a} or @var{b} sorted in
+## ascending order with duplicates removed.
 ##
-## If the optional third input argument is the string @qcode{"rows"} then
-## each row of the matrices @var{a} and @var{b} will be considered as a
-## single set element.  For example:
+## If @var{a} and @var{b} are both column vectors return a column vector;
+## Otherwise, return a row vector.  The inputs may also be cell arrays of
+## strings.
 ##
-## @example
-## @group
-## union ([1, 2; 2, 3], [1, 2; 3, 4], "rows")
-##    @result{}  1   2
-##        2   3
-##        3   4
-## @end group
-## @end example
+## If the optional input @qcode{"rows"} is given then return rows that are in
+## either @var{a} or @var{b}.  The inputs must be 2-D matrices to use this
+## option.
+## 
+## The optional outputs @var{ia} and @var{ib} are index vectors such that
+## @code{@var{a}(@var{ia})} and @code{@var{b}(@var{ib})} are disjoint sets
+## whose union is @var{c}.
 ##
-## The optional outputs @var{ia} and @var{ib} are index vectors such that
-## @code{a(ia)} and @code{b(ib)} are disjoint sets whose union is @var{c}.
-##
-## @seealso{intersect, setdiff, unique}
+## @seealso{unique, intersect, setdiff, setxor, ismember}
 ## @end deftypefn
 
 ## Author: jwe
@@ -60,40 +48,59 @@
     print_usage ();
   endif
 
-  [a, b] = validargs ("union", a, b, varargin{:});
+  [a, b] = validsetargs ("union", a, b, varargin{:});
+
+  by_rows = nargin == 3;
+  iscol = isvector (a) && isvector (b) && iscolumn (a) && iscolumn (b);
 
-  if (nargin == 2)
+  if (by_rows)
+    y = [a; b];
+  else
     y = [a(:); b(:)];
-    na = numel (a); nb = numel (b);
-    if (rows (a) == 1 || rows (b) == 1)
+    ## Adjust output orientation for Matlab compatibility
+    if (! iscol)
       y = y.';
     endif
-  else
-    y = [a; b];
-    na = rows (a); nb = rows (b);
   endif
 
-  if (nargout == 1)
+  if (nargout <= 1)
     y = unique (y, varargin{:});
   else
-    [y, i] = unique (y, varargin{:});
-    ia = i(i <= na);
-    ib = i(i > na) - na;
+    [y, idx] = unique (y, varargin{:});
+    na = numel (a);
+    ia = idx(idx <= na);
+    ib = idx(idx > na) - na;
   endif
 
 endfunction
 
 
-%!assert (union ([1, 2, 4], [2, 3, 5]), [1, 2, 3, 4, 5]);
-%!assert (union ([1; 2; 4], [2, 3, 5]), [1, 2, 3, 4, 5]);
-%!assert (union ([1, 2, 3], [5; 7; 9]), [1, 2, 3, 5, 7, 9]);
+%!assert (union ([1, 2, 4], [2, 3, 5]), [1, 2, 3, 4, 5])
+%!assert (union ([1; 2; 4], [2, 3, 5]), [1, 2, 3, 4, 5])
+%!assert (union ([1; 2; 4], [2; 3; 5]), [1; 2; 3; 4; 5])
+%!assert (union ([1, 2, 3], [5; 7; 9]), [1, 2, 3, 5, 7, 9])
+
+## Test multi-dimensional arrays
+%!test
+%! a = rand (3,3,3);
+%! b = a;
+%! b(1,1,1) = 2;
+%! assert (union (a, b), sort ([a(1:end), 2]));
 
 %!test
-%! a = [3, 1, 4, 1, 5];  b = [1, 2, 3, 4];
+%! a = [3, 1, 4, 1, 5]; 
+%! b = [1, 2, 3, 4];
 %! [y, ia, ib] = union (a, b.');
 %! assert (y, [1, 2, 3, 4, 5]);
 %! assert (y, sort ([a(ia), b(ib)]));
 
-%!error union (1)
-%!error union (1, 2, 3)
 
+%% Test common input validation for set routines contained in validsetargs
+%!error <cell array of strings cannot be combined> union ({"a"}, 1)
+%!error <A and B must be arrays or cell arrays> union (@sin, 1)
+%!error <invalid option: columns> union (1, 2, "columns")
+%!error <cells not supported with "rows"> union ({"a"}, {"b"}, "rows")
+%!error <A and B must be arrays or cell arrays> union (@sin, 1, "rows")
+%!error <A and B must be 2-dimensional matrices> union (rand(2,2,2), 1, "rows")
+%!error <number of columns in A and B must match> union ([1 2], 1, "rows")
+
--- a/scripts/set/unique.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/set/unique.m	Mon Jan 12 09:17:35 2015 -0800
@@ -20,20 +20,20 @@
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {} unique (@var{x})
 ## @deftypefnx {Function File} {} unique (@var{x}, "rows")
-## @deftypefnx {Function File} {} unique (@dots{}, "first")
-## @deftypefnx {Function File} {} unique (@dots{}, "last")
 ## @deftypefnx {Function File} {[@var{y}, @var{i}, @var{j}] =} unique (@dots{})
-## Return the unique elements of @var{x}, sorted in ascending order.
-## If the input @var{x} is a vector then the output is also a vector with the
-## same orientation (row or column) as the input.  For a matrix input the
-## output is always a column vector.  @var{x} may also be a cell array of
-## strings.
+## @deftypefnx {Function File} {[@var{y}, @var{i}, @var{j}] =} unique (@dots{}, "first")
+## @deftypefnx {Function File} {[@var{y}, @var{i}, @var{j}] =} unique (@dots{}, "last")
+## Return the unique elements of @var{x} sorted in ascending order.
 ##
-## If the optional argument @qcode{"rows"} is supplied, return the unique
-## rows of @var{x}, sorted in ascending order.
+## If the input @var{x} is a column vector then return a column vector;
+## Otherwise, return a row vector.  @var{x} may also be a cell array of strings.
+##
+## If the optional argument @qcode{"rows"} is given then return the unique
+## rows of @var{x} sorted in ascending order.  The input must be a 2-D matrix
+## to use this option.
 ##
 ## If requested, return index vectors @var{i} and @var{j} such that
-## @code{x(i)==y} and @code{y(j)==x}.
+## @code{@var{y} = @var{x}(@var{i})} and @code{@var{x} = @var{y}(@var{j})}.
 ##
 ## Additionally, if @var{i} is a requested output then one of @qcode{"first"} or
 ## @qcode{"last"} may be given as an input.  If @qcode{"last"} is specified,
@@ -46,37 +46,35 @@
 
   if (nargin < 1)
     print_usage ();
+  elseif (! (ismatrix (x) || iscellstr (x)))
+    error ("unique: X must be a matrix or cell array of strings");
   endif
 
   if (nargin > 1)
     ## parse options
-    if (iscellstr (varargin))
-      optfirst = strcmp ("first", varargin);
-      optlast  = strcmp ("last", varargin);
-      optrows  = strcmp ("rows", varargin);
-      if (! all (optfirst | optlast | optrows))
-        error ("unique: invalid option");
-      endif
-      optfirst = any (optfirst);
-      optlast  = any (optlast);
-      optrows  = any (optrows);
-      if (optfirst && optlast)
-        error ('unique: cannot specify both "last" and "first"');
-      endif
-    else
+    if (! iscellstr (varargin))
       error ("unique: options must be strings");
     endif
 
-    if (optrows && iscell (x))
+    optrows  = any (strcmp ("rows", varargin));
+    optfirst = any (strcmp ("first", varargin));
+    optlast  = any (strcmp ("last", varargin));
+    if (optfirst && optlast)
+      error ('unique: cannot specify both "first" and "last"');
+    elseif (optfirst + optlast + optrows != nargin-1)
+      error ("unique: invalid option");
+    endif
+
+    if (optrows && iscellstr (x))
       warning ('unique: "rows" is ignored for cell arrays');
       optrows = false;
     endif
   else
+    optrows = false;
     optfirst = false;
-    optrows = false;
   endif
 
-  ## FIXME -- the operations
+  ## FIXME: The operations
   ##
   ##   match = (y(1:n-1) == y(2:n));
   ##   y(idx) = [];
@@ -87,7 +85,7 @@
 
   if (issparse (x) && ! optrows && nargout <= 1)
     if (nnz (x) < numel (x))
-      y = unique ([0; (full (nonzeros (x)))], varargin{:});
+      y = unique ([0; nonzeros(x)], varargin{:});
     else
       ## Corner case where sparse matrix is actually full
       y = unique (full (x), varargin{:});
@@ -107,7 +105,7 @@
   ## Special cases 0 and 1
   if (n == 0)
     if (! optrows && isempty (x) && any (size (x)))
-      if (iscell (y))
+      if (iscellstr (y))
         y = cell (0, 1);
       else
         y = zeros (0, 1, class (y));
@@ -127,8 +125,7 @@
       y = sortrows (y);
     endif
     match = all (y(1:n-1,:) == y(2:n,:), 2);
-    idx = find (match);
-    y(idx,:) = [];
+    y(match,:) = [];
   else
     if (! isvector (y))
       y = y(:);
@@ -138,13 +135,12 @@
     else
       y = sort (y);
     endif
-    if (iscell (y))
+    if (iscellstr (y))
       match = strcmp (y(1:n-1), y(2:n));
     else
       match = (y(1:n-1) == y(2:n));
     endif
-    idx = find (match);
-    y(idx) = [];
+    y(match) = [];
   endif
 
   if (isargout (3))
@@ -157,25 +153,25 @@
   endif
 
   if (isargout (2))
+    idx = find (match);
     if (optfirst)
-      i(idx+1) = [];
-    else
-      i(idx) = [];
+      idx += 1;   # in-place is faster than other forms of increment
     endif
+    i(idx) = [];
   endif
 
 endfunction
 
 
-%!assert (unique ([1 1 2; 1 2 1; 1 1 2]),[1;2])
-%!assert (unique ([1 1 2; 1 0 1; 1 1 2],"rows"),[1 0 1; 1 1 2])
-%!assert (unique ([]),[])
-%!assert (unique ([1]),[1])
-%!assert (unique ([1 2]),[1 2])
-%!assert (unique ([1;2]),[1;2])
-%!assert (unique ([1,NaN,Inf,NaN,Inf]),[1,Inf,NaN,NaN])
-%!assert (unique ({"Foo","Bar","Foo"}),{"Bar","Foo"})
-%!assert (unique ({"Foo","Bar","FooBar"}'),{"Bar","Foo","FooBar"}')
+%!assert (unique ([1 1 2; 1 2 1; 1 1 2]), [1;2])
+%!assert (unique ([1 1 2; 1 0 1; 1 1 2],"rows"), [1 0 1; 1 1 2])
+%!assert (unique ([]), [])
+%!assert (unique ([1]), [1])
+%!assert (unique ([1 2]), [1 2])
+%!assert (unique ([1;2]), [1;2])
+%!assert (unique ([1,NaN,Inf,NaN,Inf]), [1,Inf,NaN,NaN])
+%!assert (unique ({"Foo","Bar","Foo"}), {"Bar","Foo"})
+%!assert (unique ({"Foo","Bar","FooBar"}'), {"Bar","Foo","FooBar"}')
 %!assert (unique (zeros (1,0)), zeros (0,1))
 %!assert (unique (zeros (1,0), "rows"), zeros (1,0))
 %!assert (unique (cell (1,0)), cell (0,1))
@@ -192,6 +188,7 @@
 %!assert (unique (uint8 ([1,2,2,3,2,4]), "rows"), uint8 ([1,2,2,3,2,4]))
 %!assert (unique (uint8 ([1,2,2,3,2,4])), uint8 ([1,2,3,4]))
 %!assert (unique (uint8 ([1,2,2,3,2,4]'), "rows"), uint8 ([1,2,3,4]'))
+
 %!test
 %! [a,i,j] = unique ([1,1,2,3,3,3,4]);
 %! assert (a, [1,2,3,4]);
@@ -217,8 +214,15 @@
 %! assert (A(i,:), a);
 %! assert (a(j,:), A);
 
-%!error unique({"a", "b", "c"}, "UnknownOption")
-%!error unique({"a", "b", "c"}, "UnknownOption1", "UnknownOption2")
-%!error unique({"a", "b", "c"}, "rows", "UnknownOption2")
-%!error unique({"a", "b", "c"}, "UnknownOption1", "last")
+%% Test input validation
+%!error unique ()
+%!error <X must be a matrix or cell array of strings> unique ({1})
+%!error <options must be strings> unique (1, 2)
+%!error <cannot specify both "first" and "last"> unique (1, "first", "last")
+%!error <invalid option> unique (1, "middle")
+%!error <invalid option> unique ({"a", "b", "c"}, "UnknownOption")
+%!error <invalid option> unique ({"a", "b", "c"}, "UnknownOption1", "UnknownOption2")
+%!error <invalid option> unique ({"a", "b", "c"}, "rows", "UnknownOption2")
+%!error <invalid option> unique ({"a", "b", "c"}, "UnknownOption1", "last")
+%!warning <"rows" is ignored for cell arrays> unique ({"1"}, "rows");
 
--- a/scripts/signal/arch_fit.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/signal/arch_fit.m	Mon Jan 12 09:17:35 2015 -0800
@@ -19,7 +19,7 @@
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {[@var{a}, @var{b}] =} arch_fit (@var{y}, @var{x}, @var{p}, @var{iter}, @var{gamma}, @var{a0}, @var{b0})
 ## Fit an ARCH regression model to the time series @var{y} using the
-## scoring algorithm in Engle's original ARCH paper.  The model is
+## scoring algorithm in @nospell{Engle's} original ARCH paper.  The model is
 ##
 ## @example
 ## @group
--- a/scripts/signal/bartlett.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/signal/bartlett.m	Mon Jan 12 09:17:35 2015 -0800
@@ -21,8 +21,9 @@
 ## Return the filter coefficients of a Bartlett (triangular) window of
 ## length @var{m}.
 ##
-## For a definition of the Bartlett window, see e.g., A. V. Oppenheim &
-## R. W. Schafer, @cite{Discrete-Time Signal Processing}.
+## For a definition of the Bartlett window, see e.g.,
+## @nospell{A.V. Oppenheim & R. W. Schafer},
+## @cite{Discrete-Time Signal Processing}.
 ## @end deftypefn
 
 ## Author: AW <Andreas.Weingessel@ci.tuwien.ac.at>
--- a/scripts/signal/blackman.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/signal/blackman.m	Mon Jan 12 09:17:35 2015 -0800
@@ -20,8 +20,9 @@
 ## @deftypefn {Function File} {} blackman (@var{m})
 ## Return the filter coefficients of a Blackman window of length @var{m}.
 ##
-## For a definition of the Blackman window, see e.g., A. V. Oppenheim &
-## R. W. Schafer, @cite{Discrete-Time Signal Processing}.
+## For a definition of the Blackman window, see e.g.,
+## @nospell{A.V. Oppenheim & R. W. Schafer},
+## @cite{Discrete-Time Signal Processing}.
 ## @end deftypefn
 
 ## Author: AW <Andreas.Weingessel@ci.tuwien.ac.at>
--- a/scripts/signal/diffpara.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/signal/diffpara.m	Mon Jan 12 09:17:35 2015 -0800
@@ -32,7 +32,7 @@
 ## described above is returned in @var{dd}.  The value of @var{d} is
 ## simply the mean of @var{dd}.
 ##
-## Reference: P.J. Brockwell & R.A. Davis. @cite{Time Series:
+## Reference: @nospell{P.J. Brockwell & R.A. Davis}. @cite{Time Series:
 ## Theory and Methods}. Springer 1987.
 ## @end deftypefn
 
--- a/scripts/signal/durbinlevinson.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/signal/durbinlevinson.m	Mon Jan 12 09:17:35 2015 -0800
@@ -18,7 +18,7 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} durbinlevinson (@var{c}, @var{oldphi}, @var{oldv})
-## Perform one step of the Durbin-Levinson algorithm.
+## Perform one step of the @nospell{Durbin-Levinson} algorithm.
 ##
 ## The vector @var{c} specifies the autocovariances @code{[gamma_0, @dots{},
 ## gamma_t]} from lag 0 to @var{t}, @var{oldphi} specifies the
--- a/scripts/signal/hamming.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/signal/hamming.m	Mon Jan 12 09:17:35 2015 -0800
@@ -20,8 +20,9 @@
 ## @deftypefn {Function File} {} hamming (@var{m})
 ## Return the filter coefficients of a Hamming window of length @var{m}.
 ##
-## For a definition of the Hamming window, see e.g., A. V. Oppenheim &
-## R. W. Schafer, @cite{Discrete-Time Signal Processing}.
+## For a definition of the Hamming window, see e.g.,
+## @nospell{A.V. Oppenheim & R. W. Schafer},
+## @cite{Discrete-Time Signal Processing}.
 ## @end deftypefn
 
 ## Author: AW <Andreas.Weingessel@ci.tuwien.ac.at>
--- a/scripts/signal/hanning.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/signal/hanning.m	Mon Jan 12 09:17:35 2015 -0800
@@ -20,8 +20,9 @@
 ## @deftypefn {Function File} {} hanning (@var{m})
 ## Return the filter coefficients of a Hanning window of length @var{m}.
 ##
-## For a definition of this window type, see e.g., A. V. Oppenheim &
-## R. W. Schafer, @cite{Discrete-Time Signal Processing}.
+## For a definition of the Hanning window, see e.g.,
+## @nospell{A.V. Oppenheim & R. W. Schafer},
+## @cite{Discrete-Time Signal Processing}.
 ## @end deftypefn
 
 ## Author: AW <Andreas.Weingessel@ci.tuwien.ac.at>
--- a/scripts/signal/periodogram.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/signal/periodogram.m	Mon Jan 12 09:17:35 2015 -0800
@@ -1,5 +1,6 @@
 ## Copyright (C) 1995-2013 Friedrich Leisch
 ## Copyright (C) 2010 Alois Schloegl
+## Copyright (C) 2014 Drew Abbot
 ##
 ## This file is part of Octave.
 ##
@@ -18,43 +19,60 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {[Pxx, @var{w}] =} periodogram (@var{x})
-## For a data matrix @var{x} from a sample of size @var{n}, return the
-## periodogram.  The angular frequency is returned in @var{w}.
+## @deftypefn  {Function File} {[@var{Pxx}, @var{w}] =} periodogram (@var{x})
+## @deftypefnx {Function File} {[@var{Pxx}, @var{w}] =} periodogram (@var{x}, @var{win})
+## @deftypefnx {Function File} {[@var{Pxx}, @var{w}] =} periodogram (@var{x}, @var{win}, @var{nfft})
+## @deftypefnx {Function File} {[@var{Pxx}, @var{f}] =} periodogram (@var{x}, @var{win}, @var{nfft}, @var{Fs})
+## @deftypefnx {Function File} {[@var{Pxx}, @var{f}] =} periodogram (@dots{}, "@var{range}")
+## @deftypefnx {Function File} {} periodogram (@dots{})
 ##
-## [Pxx,w] = periodogram (@var{x}).
+## Return the periodogram (Power Spectral Density) of @var{x}.
 ##
-## [Pxx,w] = periodogram (@var{x},win).
+## The possible inputs are:
 ##
-## [Pxx,w] = periodogram (@var{x},win,nfft).
-##
-## [Pxx,f] = periodogram (@var{x},win,nfft,Fs).
+## @table @var
+## @item x
 ##
-## [Pxx,f] = periodogram (@var{x},win,nfft,Fs,"range").
+## data vector.  If @var{x} is real-valued a one-sided spectrum is estimated.
+## If @var{x} is complex-valued, or @qcode{"@var{range}"} specifies
+## @qcode{"@nospell{twosided}"}, the full spectrum is estimated.
 ##
-## @itemize
-## @item x: data; if real-valued a one-sided spectrum is estimated,
-## if complex-valued or range indicates @qcode{"@nospell{twosided}"}, the full
-## spectrum is estimated.
+## @item win
+## window weight data.  If window is empty or unspecified a default rectangular
+## window is used.  Otherwise, the window is applied to the signal
+## (@code{@var{x} .* @var{win}}) before computing the periodogram.  The window
+## data must be a vector of the same length as @var{x}.
 ##
-## @item win: weight data with window, x.*win is used for further computation,
-## if window is empty, a rectangular window is used.
+## @item nfft
+## number of frequency bins.  The default is 256 or the next higher power of 
+## 2 greater than the length of @var{x}
+## (@code{max (256, 2.^nextpow2 (length (x)))}).  If @var{nfft} is greater
+## than the length of the input then @var{x} will be zero-padded to the length
+## of @var{nfft}.
 ##
-## @item nfft: number of frequency bins, default max (256, 2.^ceil (log2 (length (x)))).
-##
-## @item Fs: sampling rate, default 1.
+## @item Fs
+## sampling rate.  The default is 1.
 ##
-## @item range: @qcode{"@nospell{onesided}"} computes spectrum from [0..nfft/2+1].
-## @qcode{"@nospell{twosided}"} computes spectrum from [0..nfft-1].  These
-## strings can appear at any position in the list input arguments after
-## window.
+## @item range
+## range of spectrum.  @qcode{"@nospell{onesided}"} computes spectrum from
+## [0..nfft/2+1].  @qcode{"@nospell{twosided}"} computes spectrum from
+## [0..nfft-1].
+## @end table
 ##
-## @item @nospell{Pxx}: one-, or two-sided power spectrum.
+## The optional second output @var{w} are the normalized angular frequencies.
+## For a one-sided calculation @var{w} is in the range [0, pi] if @var{nfft}
+## is even and [0, pi) if @var{nfft} is odd.  Similarly, for a two-sided
+## calculation @var{w} is in the range [0, 2*pi] or [0, 2*pi) depending on
+## @var{nfft}.
 ##
-## @item w: angular frequency [0..2*pi) (two-sided) or [0..pi] one-sided.
-##
-## @item f: frequency [0..Fs) (two-sided) or [0..Fs/2] one-sided.
-## @end itemize
+## If a sampling frequency is specified, @var{Fs}, then the output frequencies
+## @var{f} will be in the range [0, @var{Fs}/2] or [0, @var{Fs}/2) for
+## one-sided calculations.  For two-sided calculations the range will be
+## [0, @var{Fs}).
+## 
+## When called with no outputs the periodogram is immediately plotted in the
+## current figure window.
+## @seealso{fft}
 ## @end deftypefn
 
 ## Author: FL <Friedrich.Leisch@ci.tuwien.ac.at>
@@ -63,117 +81,113 @@
 function [pxx, f] = periodogram (x, varargin)
 
   ## check input arguments
-
   if (nargin < 1 || nargin > 5)
     print_usage ();
   endif
 
-  nfft = []; fs = []; range = []; window = [];
-  j = 1;
+  nfft = fs = range = window = [];
+  j = 2;
   for k = 1:length (varargin)
     if (ischar (varargin{k}))
       range = varargin{k};
     else
       switch (j)
-        case 1
+        case 2
           window = varargin{k};
-        case 2
+        case 3
           nfft   = varargin{k};
-        case 3
+        case 4
           fs     = varargin{k};
-        case 4
-          range  = varargin{k};
       endswitch
       j++;
     endif
   endfor
 
-  [r, c] = size (x);
-  if (r == 1)
-    r = c;
+  if (! isvector (x))
+    error ("periodogram: X must be a real or complex vector");
+  endif
+  x = x(:);  # Use column vectors from now on
+  
+  n = rows (x);
+
+  if (! isempty (window))
+    if (! isvector (window) || length (window) != n)
+      error ("periodogram: WIN must be a vector of the same length as X");
+    endif
+    window = window(:);
+    x .*= window;
   endif
 
-  if (ischar (window))
-    range = window;
-    window = [];
-  endif;
-  if (ischar (nfft))
-    range = nfft;
-    nfft = [];
-  endif;
-  if (ischar (fs))
-    range = fs;
-    fs = [];
-  endif;
-
-  if (!  isempty (window))
-    if (all (size (x) == size (window)))
-      x .*= window;
-    elseif (rows (x) == rows (window) && columns (window) == 1)
-      x .*= window (:,ones (1,c));
-    endif;
+  if (isempty (nfft))
+    nfft = max (256, 2.^nextpow2 (n));
+  elseif (! isscalar (nfft))
+    error ("periodogram: NFFT must be a scalar");
   endif
 
-  if (numel (nfft)>1)
-    error ("nfft must be scalar");
-  endif
-  if (isempty (nfft))
-    nfft = max (256, 2.^ceil (log2 (r)));
+  use_w_freq = isempty (fs);
+  if (! use_w_freq && ! isscalar (fs))
+    error ("periodogram: FS must be a scalar");
   endif
 
-  if (strcmp (range, "onesided"))
+  if (strcmpi (range, "onesided"))
     range = 1;
-  elseif (strcmp (range, "twosided"))
+  elseif (strcmpi (range, "twosided"))
     range = 2;
+  elseif (strcmpi (range, "centered"))
+    error ('periodogram: "centered" range type is not implemented');
   else
     range = 2-isreal (x);
   endif
 
   ## compute periodogram
 
-  if (r>nfft)
+  if (n > nfft)
     Pxx = 0;
     rr = rem (length (x), nfft);
     if (rr)
-      x = [x(:); (zeros (nfft-rr, 1))];
+      x = [x(:); zeros(nfft-rr, 1)];
     endif
     x = sum (reshape (x, nfft, []), 2);
   endif
 
-  if (isempty (window))
-    n = r;
-  else
+  if (! isempty (window))
     n = sumsq (window);
-  end;
-  Pxx = (abs (fft (x, nfft))) .^ 2 / n ;
+  endif;
+  Pxx = (abs (fft (x, nfft))) .^ 2 / n;
 
-  if (nargin<4)
+  if (use_w_freq)
     Pxx /= 2*pi;
-  elseif (! isempty (fs))
+  else
     Pxx /= fs;
   endif
 
   ## generate output arguments
 
   if (range == 1)  # onesided
-    Pxx = Pxx(1:nfft/2+1) + [0; Pxx(end:-1:(nfft/2+2)); 0];
+    if (! rem (nfft,2))  # nfft is even
+      psd_len = nfft/2+1;
+      Pxx = Pxx(1:psd_len) + [0; Pxx(nfft:-1:psd_len+1); 0];
+    else                 # nfft is odd
+      psd_len = (nfft+1)/2;
+      Pxx = Pxx(1:psd_len) + [0; Pxx(nfft:-1:psd_len+1)];
+    endif
   endif
 
   if (nargout != 1)
     if (range == 1)
-      f = (0:nfft/2)'/nfft;
+      f = (0:nfft/2)' / nfft;
     elseif (range == 2)
-      f = (0:nfft-1)'/nfft;
+      f = (0:nfft-1)' / nfft;
     endif
-    if (nargin<4)
-      f *= 2*pi; # generate w=2*pi*f
-    elseif (! isempty (fs))
+    if (use_w_freq)
+      f *= 2*pi;  # generate w=2*pi*f
+    else
       f *= fs;
     endif
   endif
 
   if (nargout == 0)
-    if (nargin<4)
+    if (use_w_freq)
       plot (f/(2*pi), 10*log10 (Pxx));
       xlabel ("normalized frequency [x pi rad]");
       ylabel ("Power density [dB/rad/sample]");
@@ -190,3 +204,17 @@
 
 endfunction
 
+
+## FIXME: Need some functional tests
+
+
+%% Test input validation
+%!error periodogram ()
+%!error periodogram (1,2,3,4,5,6)
+%!error <X must be a real or complex vector> periodogram (ones (2,2))
+%!error <WIN must be a vector.*same length> periodogram (1:5, ones (2,2))
+%!error <WIN must be a vector.*same length> periodogram (1:5, 1:6)
+%!error <NFFT must be a scalar> periodogram (1:5, 1:5, 1:5)
+%!error <FS must be a scalar> periodogram (1:5, [], [], 1:5)
+%!error <"centered" range type is not implemented> periodogram (1:5, "centered")
+
--- a/scripts/sparse/colperm.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/sparse/colperm.m	Mon Jan 12 09:17:35 2015 -0800
@@ -20,9 +20,9 @@
 ## @deftypefn {Function File} {@var{p} =} colperm (@var{s})
 ## Return the column permutations such that the columns of
 ## @code{@var{s} (:, @var{p})} are ordered in terms of increase number
-## of non-zero elements.  If @var{s} is symmetric, then @var{p} is chosen
+## of nonzero elements.  If @var{s} is symmetric, then @var{p} is chosen
 ## such that @code{@var{s} (@var{p}, @var{p})} orders the rows and
-## columns with increasing number of non zeros elements.
+## columns with increasing number of nonzeros elements.
 ## @end deftypefn
 
 function p = colperm (s)
--- a/scripts/sparse/eigs.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/sparse/eigs.m	Mon Jan 12 09:17:35 2015 -0800
@@ -183,9 +183,9 @@
 ## of the convergence.  If @var{flag} is 0 then all eigenvalues have converged.
 ## Any other value indicates a failure to converge.
 ## 
-## This function is based on the @sc{arpack} package, written by R. Lehoucq,
-## K. Maschhoff, D. Sorensen, and C. Yang.  For more information see
-## @url{http://www.caam.rice.edu/software/ARPACK/}.
+## This function is based on the @sc{arpack} package, written by
+## @nospell{R. Lehoucq, K. Maschhoff, D. Sorensen, and C. Yang}.  For more
+## information see @url{http://www.caam.rice.edu/software/ARPACK/}.
 ## 
 ## @seealso{eig, svds}
 ## @end deftypefn
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/sparse/ichol.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,470 @@
+## Copyright (C) 2014 Eduardo Ramos Fernández <eduradical951@gmail.com>
+## Copyright (C) 2013 Kai T. Ohlhus <k.ohlhus@gmail.com>
+##
+## 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{L} =} ichol (@var{A})
+## @deftypefnx {Function File} {@var{L} =} ichol (@var{A}, @var{opts})
+##
+## Compute the incomplete Cholesky factorization of the sparse square matrix
+## @var{A}.
+##
+## By default, @code{ichol} uses only the lower triangle of @var{A} and
+## produces a lower triangular factor @var{L} such that @tcode{L*L'}
+## approximates @var{A}.
+##
+## The factor given by this routine may be useful as a preconditioner for a
+## system of linear equations being solved by iterative methods such as
+## PCG (Preconditioned Conjugate Gradient).
+##
+## The factorization may be modified by passing options in a structure
+## @var{opts}.  The option name is a field of the structure and the setting
+## is the value of field.  Names and specifiers are case sensitive.
+##
+## @table @asis
+## @item type
+## Type of factorization.
+##
+## @table @asis
+## @item @qcode{"nofill"} (default)
+## Incomplete Cholesky factorization with no fill-in (@nospell{IC(0)}).
+##
+## @item @qcode{"ict"}
+## Incomplete Cholesky factorization with threshold dropping (@nospell{ICT}).
+## @end table
+##
+## @item diagcomp
+## A non-negative scalar @var{alpha} for incomplete Cholesky factorization of
+## @code{@var{A} + @var{alpha} * diag (diag (@var{A}))} instead of @var{A}.
+## This can be useful when @var{A} is not positive definite.  The default value
+## is 0.
+##
+## @item droptol
+## A non-negative scalar specifying the drop tolerance for factorization if
+## performing @nospell{ICT}@.  The default value is 0 which produces the
+## complete Cholesky factorization.
+##
+## Non-diagonal entries of @var{L} are set to 0 unless
+##
+## @code{abs (@var{L}(i,j)) >= droptol * norm (@var{A}(j:end, j), 1)}.
+##
+## @item michol
+## Modified incomplete Cholesky factorization:
+##
+## @table @asis
+## @item @qcode{"off"} (default)
+## Row and column sums are not necessarily preserved.
+##
+## @item @qcode{"on"}
+## The diagonal of @var{L} is modified so that row (and column) sums are
+## preserved even when elements have been dropped during the factorization.
+## The relationship preserved is: @code{@var{A} * e = @var{L} * @var{L}' * e},
+## where e is a vector of ones.
+## @end table
+##
+## @item shape
+##
+## @table @asis
+## @item @qcode{"lower"} (default)
+## Use only the lower triangle of @var{A} and return a lower triangular
+## factor @var{L} such that @tcode{L*L'} approximates @var{A}.
+##
+## @item @qcode{"upper"}
+## Use only the upper triangle of @var{A} and return an upper triangular
+## factor @var{U} such that @code{U'*U} approximates @var{A}.
+## @end table
+## @end table
+##
+## EXAMPLES
+##
+## The following problem demonstrates how to factorize a sample symmetric
+## positive definite matrix with the full Cholesky decomposition and with the
+## incomplete one.
+##
+## @example
+## @group
+## A = [ 0.37, -0.05,  -0.05,  -0.07;
+##      -0.05,  0.116,  0.0,   -0.05;
+##      -0.05,  0.0,    0.116, -0.05;
+##      -0.07, -0.05,  -0.05,   0.202];
+## A = sparse (A);
+## nnz (tril (A))
+## ans =  9
+## L = chol (A, "lower");
+## nnz (L)
+## ans =  10
+## norm (A - L * L', "fro") / norm (A, "fro")
+## ans =  1.1993e-16
+## opts.type = "nofill";
+## L = ichol (A, opts);
+## nnz (L)
+## ans =  9
+## norm (A - L * L', "fro") / norm (A, "fro")
+## ans =  0.019736
+## @end group
+## @end example
+##
+## Another example for decomposition is a finite difference matrix used to
+## solve a boundary value problem on the unit square.
+##
+## @example
+## @group
+## nx = 400; ny = 200;
+## hx = 1 / (nx + 1); hy = 1 / (ny + 1);
+## Dxx = spdiags ([ones(nx, 1), -2*ones(nx, 1), ones(nx, 1)],
+##                [-1 0 1 ], nx, nx) / (hx ^ 2);
+## Dyy = spdiags ([ones(ny, 1), -2*ones(ny, 1), ones(ny, 1)],
+##                [-1 0 1 ], ny, ny) / (hy ^ 2);
+## A = -kron (Dxx, speye (ny)) - kron (speye (nx), Dyy);
+## nnz (tril (A))
+## ans =  239400
+## opts.type = "nofill";
+## L = ichol (A, opts);
+## nnz (tril (A))
+## ans =  239400
+## norm (A - L * L', "fro") / norm (A, "fro")
+## ans =  0.062327
+## @end group
+## @end example
+##
+## References for implemented algorithms:
+##
+## [1] @nospell{Y. Saad}. "Preconditioning Techniques." @cite{Iterative
+## Methods for Sparse Linear Systems}, @nospell{PWS} Publishing Company, 1996.
+##
+## [2] @nospell{M. Jones, P. Plassmann}: @cite{An Improved Incomplete
+## Cholesky Factorization}, 1992.
+## @seealso{chol, ilu, pcg}
+## @end deftypefn
+
+function L = ichol (A, opts = struct ())
+
+  if (nargin < 1 || nargin > 2 || nargout > 1)
+    print_usage ();
+  endif
+
+  if (! (issparse (A) && issquare (A)))
+    error ("ichol: A must be a sparse square matrix");
+  endif
+
+  if (! isstruct (opts))
+    error ("ichol: OPTS must be a structure.");
+  endif
+
+  ## If A is empty then return empty L for Matlab compatibility
+  if (isempty (A))
+    L = A;
+    return;
+  endif
+
+  ## Parse input options
+  if (! isfield (opts, "type"))
+    opts.type = "nofill";  # set default
+  else
+    type = tolower (getfield (opts, "type"));
+    if (! strcmp (type, "nofill") && ! strcmp (type, "ict"))
+      error ('ichol: TYPE must be "nofill" or "ict"');
+    endif
+    opts.type = type;
+  endif
+
+  if (! isfield (opts, "droptol"))
+    opts.droptol = 0;      # set default
+  else
+    if (! (isreal (opts.droptol) && isscalar (opts.droptol)
+           && opts.droptol >= 0))
+      error ("ichol: DROPTOL must be a non-negative real scalar");
+    endif
+  endif
+
+  michol = "";
+  if (! isfield (opts, "michol"))
+    opts.michol = "off";   # set default
+  else
+    michol = tolower (getfield (opts, "michol"));
+    if (! strcmp (michol, "off") && ! strcmp (michol, "on"))
+      error ('ichol: MICHOL must be "on" or "off"');
+    endif
+    opts.michol = michol;
+  endif
+
+  if (! isfield (opts, "diagcomp"))
+    opts.diagcomp = 0;     # set default
+  else
+    if (! (isreal (opts.diagcomp) && isscalar (opts.diagcomp)
+           && opts.diagcomp >= 0))
+      error ("ichol: DIAGCOMP must be a non-negative real scalar");
+    endif
+  endif
+
+  if (! isfield (opts, "shape"))
+    opts.shape = "lower";  # set default
+  else
+    shape = tolower (getfield (opts, "shape"));
+    if (! strcmp (shape, "lower") && ! strcmp (shape, "upper"))
+      error ('ichol: SHAPE must be "lower" or "upper"');
+    endif
+    opts.shape = shape;
+  endif
+
+  ## Prepare input for specialized ICHOL
+  A_in = [];
+  if (opts.diagcomp > 0)
+    A += opts.diagcomp * diag (diag (A));
+  endif
+  if (strcmp (opts.shape, "upper"))
+    A_in = triu (A);
+    A_in = A_in';
+  else
+    A_in = tril (A);
+  endif
+
+  ## Delegate to specialized ICHOL
+  switch (opts.type)
+    case "nofill"
+      L  = __ichol0__ (A_in, opts.michol);
+    case "ict"
+      L = __icholt__ (A_in, opts.droptol, opts.michol);
+  endswitch
+
+  if (strcmp (opts.shape, "upper"))
+    L = L';
+  endif
+
+endfunction
+
+
+%!shared A1, A2, A3, A4, A5, A6, A7
+%! A1 = [ 0.37, -0.05,  -0.05,  -0.07;
+%!       -0.05,  0.116,  0.0,   -0.05;
+%!       -0.05,  0.0,    0.116, -0.05;
+%!       -0.07, -0.05,  -0.05,   0.202];
+%! A1 = sparse (A1);
+%! A2 = gallery ("poisson", 30);
+%! A3 = gallery ("tridiag", 50);
+%! nx = 400; ny = 200;
+%! hx = 1 / (nx + 1); hy = 1 / (ny + 1);
+%! Dxx = spdiags ([ones(nx, 1), -2*ones(nx, 1), ones(nx, 1)],
+%!                [-1 0 1 ], nx, nx) / (hx ^ 2);
+%! Dyy = spdiags ([ones(ny, 1), -2*ones(ny, 1), ones(ny, 1)],
+%!                [-1 0 1 ], ny, ny) / (hy ^ 2);
+%! A4 = -kron (Dxx, speye (ny)) - kron (speye (nx), Dyy);
+%! A5 = [ 0.37, -0.05,         -0.05,  -0.07;
+%!       -0.05,  0.116,         0.0,   -0.05 + 0.05i;
+%!       -0.05,  0.0,           0.116, -0.05;
+%!       -0.07, -0.05 - 0.05i, -0.05,   0.202];
+%! A5 = sparse (A5);
+%! A6 = [ 0.37,     -0.05 - i, -0.05,  -0.07;
+%!       -0.05 + i,  0.116,     0.0,   -0.05;
+%!       -0.05,      0.0,       0.116, -0.05;
+%!       -0.07,     -0.05,     -0.05,   0.202];
+%! A6 = sparse (A6);
+%! A7 = A5;
+%! A7(1) = 2i;
+
+## ICHOL0 tests
+
+%!test
+%! opts.type = "nofill";
+%! opts.michol = "off";
+%! assert (nnz (tril (A1)), nnz (ichol (A1, opts)));
+%! assert (nnz (tril (A2)), nnz (ichol (A2, opts)));
+%! assert (nnz (tril (A3)), nnz (ichol (A3, opts)));
+%! assert (nnz (tril (A4)), nnz (ichol (A4, opts)));
+%! assert (nnz (tril (A5)), nnz (ichol (A5, opts)));
+%!
+%!test
+%! opts.type = "nofill";
+%! opts.michol = "off";
+%! L = ichol (A1, opts);
+%! assert (norm (A1 - L * L', "fro") / norm (A1, "fro"), 0.0197, 1e-4);
+%! opts.shape = "upper";
+%! U = ichol (A1, opts);
+%! assert (norm (A1 - U' * U, "fro") / norm (A1, "fro"), 0.0197, 1e-4);
+%! opts.shape = "lower";
+%! L = ichol (A1, opts);
+%! assert (norm (A1 - L * L', "fro") / norm (A1, "fro"), 0.0197, 1e-4);
+%!
+%!test
+%! opts.michol = "on";
+%! opts.shape = "lower";
+%! opts.type = "nofill";
+%! L = ichol (A1, opts);
+%! assert (norm (A1 - L * L', "fro") / norm (A1, "fro"), 0.0279, 1e-4);
+%! opts.shape = "upper";
+%! U = ichol (A1, opts);
+%! assert (norm (A1 - U' * U, "fro") / norm (A1, "fro"), 0.0279, 1e-4);
+%! opts.shape = "lower";
+%! opts.diagcomp = 3e-3;
+%! L = ichol (A1, opts);
+%! assert (norm (A1 - L * L', "fro") / norm (A1, "fro"), 0.0272, 1e-4);
+%!
+%!test
+%! opts.type = "nofill";
+%! opts.michol = "off";
+%! L = ichol (A2, opts);
+%! assert (norm (A2 - L*L', "fro") / norm (A2, "fro"), 0.0893, 1e-4)
+%! opts.michol = "on";
+%! L = ichol (A2, opts);
+%! assert (norm (A2 - L*L', "fro") / norm (A2, "fro"), 0.2377, 1e-4)
+%!
+%!test
+%! opts.type = "nofill";
+%! opts.michol = "off";
+%! L = ichol (A3, opts);
+%! assert (norm (A3 - L*L', "fro") / norm (A3, "fro"), eps, eps);
+%! opts.michol = "on";
+%! L = ichol (A3, opts);
+%! assert (norm (A3 - L*L', "fro") / norm (A3, "fro"), eps, eps);
+%!
+%!test
+%! opts.type = "nofill";
+%! opts.michol = "off";
+%! L = ichol (A4, opts);
+%! assert (norm (A4 - L*L', "fro") / norm (A4, "fro"), 0.0623, 1e-4);
+%! opts.michol = "on";
+%! L = ichol (A4, opts);
+%! assert (norm (A4 - L*L', "fro") / norm (A4, "fro"), 0.1664, 1e-4);
+%!
+%!test
+%! opts.type = "nofill";
+%! opts.michol = "off";
+%! L = ichol (A5, opts);
+%! assert (norm (A5 - L*L', "fro") / norm (A5, "fro"), 0.0195, 1e-4);
+%! opts.michol = "on";
+%! L = ichol (A5, opts);
+%! assert (norm (A5 - L*L', "fro") / norm (A5, "fro"), 0.0276, 1e-4);
+
+## Negative pivot
+%!error <negative pivot> ichol (A6)
+%!error ichol (A6)
+## Complex entry in the diagonal
+%!error <non-real pivot> ichol (A7)
+
+## ICHOLT tests
+
+%%!test
+%! opts.type = "ict";
+%! opts.droptol = 1e-1;
+%! opts.michol = "off";
+%! L = ichol (A1, opts);
+%! assert (norm (A1 - L * L', "fro") / norm (A1, "fro"), 0.2065, 1e-4);
+%! opts.shape = "upper";
+%! U = ichol (A1, opts);
+%! assert (norm (A1 - U' * U, "fro") / norm (A1, "fro"), 0.2065, 1e-4);
+%! opts.shape = "lower";
+%! L = ichol (A1, opts);
+%! assert (norm (A1 - L * L', "fro") / norm (A1, "fro"), 0.2065, 1e-4);
+%!
+%%!test
+%! opts.type = "ict";
+%! opts.droptol = 1e-1;
+%! opts.michol = "on";
+%! L = ichol (A1, opts);
+%! assert (norm (A1 - L * L', "fro") / norm (A1, "fro"), 0.3266, 1e-4);
+%! opts.shape = "upper";
+%! U = ichol (A1, opts);
+%! assert (norm (A1 - U' * U, "fro") / norm (A1, "fro"), 0.3266, 1e-4);
+%! opts.shape = "lower";
+%! opts.diagcomp = 3e-3;
+%! L = ichol (A1, opts);
+%! assert (norm (A1 - L * L', "fro") / norm (A1, "fro"), 0.3266, 1e-4);
+%!
+%!test
+%! opts.type = "ict";
+%! opts.droptol = 1e-1;
+%! opts.michol = "off";
+%! L = ichol (A2, opts);
+%! assert (norm (A2 - L*L', "fro") / norm (A2, "fro"),  0.0893, 1e-4)
+%! opts.michol = "on";
+%! L = ichol (A2, opts);
+%! assert (norm (A2 - L*L', "fro") / norm (A2, "fro"), 0.2377, 1e-4)
+%!
+%!test
+%! opts.type = "ict";
+%! opts.droptol = 1e-1;
+%! opts.michol = "off";
+%! L = ichol (A3, opts);
+%! assert (norm (A3 - L*L', "fro") / norm (A3, "fro"), eps, eps);
+%! opts.michol = "on";
+%! L = ichol (A3, opts);
+%! assert (norm (A3 - L*L', "fro") / norm (A3, "fro"), eps, eps);
+%!
+%!test
+%! opts.type = "ict";
+%! opts.droptol = 1e-1;
+%! opts.michol = "off";
+%! L = ichol (A4, opts);
+%! assert (norm (A4 - L*L', "fro") / norm (A4, "fro"), 0.1224, 1e-4);
+%! opts.michol = "on";
+%! L = ichol (A4, opts);
+%! assert (norm (A4 - L*L', "fro") / norm (A4, "fro"), 0.2118, 1e-4);
+%!
+%!test
+%! opts.type = "ict";
+%! opts.droptol = 1e-1;
+%! opts.michol = "off";
+%! L = ichol (A5, opts);
+%! assert (norm (A5 - L*L', "fro") / norm (A5, "fro"), 0.2044, 1e-4);
+%! opts.michol = "on";
+%! L = ichol (A5, opts);
+%! assert (norm (A5 - L*L', "fro") / norm (A5, "fro"), 0.3231, 1e-4);
+
+%% Input validation tests
+
+%!error <A must be a sparse square matrix> ichol ([])
+%!error <A must be a sparse square matrix> ichol (0)
+%!error <pivot equal to 0> ichol (sparse (0))
+%!error <pivot equal to 0> ichol (sparse (-0))
+%!error <negative pivot> ichol (sparse (-1))
+%!test
+%! opts.type = "foo";
+%! fail ("ichol (A1, opts)", 'TYPE must be "nofill"');
+%! opts.type = 1;
+%! fail ("ichol (A1, opts)", 'TYPE must be "nofill"');
+%! opts.type = [];
+%! fail ("ichol (A1, opts)", 'TYPE must be "nofill"');
+%!test
+%! opts.droptol = -1;
+%! fail ("ichol (A1, opts)", "DROPTOL must be a non-negative real scalar");
+%! opts.droptol = 0.5i;
+%! fail ("ichol (A1, opts)", "DROPTOL must be a non-negative real scalar");
+%! opts.droptol = [];
+%! fail ("ichol (A1, opts)", "DROPTOL must be a non-negative real scalar");
+%!test
+%! opts.michol = "foo";
+%! fail ("ichol (A1, opts)", 'MICHOL must be "on"');
+%! opts.michol = 1;
+%! fail ("ichol (A1, opts)", 'MICHOL must be "on"');
+%! opts.michol = [];
+%! fail ("ichol (A1, opts)", 'MICHOL must be "on"');
+%!test
+%! opts.diagcomp = -1;
+%! fail ("ichol (A1, opts)", "DIAGCOMP must be a non-negative real scalar");
+%! opts.diagcomp = 0.5i;
+%! fail ("ichol (A1, opts)", "DIAGCOMP must be a non-negative real scalar");
+%! opts.diagcomp = [];
+%! fail ("ichol (A1, opts)", "DIAGCOMP must be a non-negative real scalar");
+%!test
+%! opts.shape = "foo";
+%! fail ("ichol (A1, opts)", 'SHAPE must be "lower"');
+%! opts.shape = 1;
+%! fail ("ichol (A1, opts)", 'SHAPE must be "lower"');
+%! opts.shape = [];
+%! fail ("ichol (A1, opts)", 'SHAPE must be "lower"');
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/sparse/ilu.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,536 @@
+## Copyright (C) 2014 Eduardo Ramos Fernández <eduradical951@gmail.com>
+## Copyright (C) 2013 Kai T. Ohlhus <k.ohlhus@gmail.com>
+## 
+## 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} {} ilu (@var{A})
+## @deftypefnx {Function File} {} ilu (@var{A}, @var{opts})
+## @deftypefnx {Function File} {[@var{L}, @var{U}] =} ilu (@dots{})
+## @deftypefnx {Function File} {[@var{L}, @var{U}, @var{P}] =} ilu (@dots{})
+##
+## Compute the incomplete LU factorization of the sparse square matrix @var{A}.
+##
+## @code{ilu} returns a unit lower triangular matrix @var{L}, an upper
+## triangular matrix @var{U}, and optionally a permutation matrix @var{P}, such
+## that @code{@var{L}*@var{U}} approximates @code{@var{P}*@var{A}}. 
+##
+## The factors given by this routine may be useful as preconditioners for a
+## system of linear equations being solved by iterative methods such as BICG
+## (BiConjugate Gradients) or GMRES (Generalized Minimum Residual Method).
+##
+## The factorization may be modified by passing options in a structure
+## @var{opts}.  The option name is a field of the structure and the setting
+## is the value of field.  Names and specifiers are case sensitive.
+##
+## @table @code
+## @item type
+## Type of factorization.
+##
+## @table @asis
+## @item @qcode{"nofill"}
+## ILU factorization with no fill-in (ILU(0)).
+##
+## Additional supported options: @code{milu}.
+##
+## @item @qcode{"crout"}
+## Crout version of ILU factorization (@nospell{ILUC}).
+##
+## Additional supported options: @code{milu}, @code{droptol}.
+##
+## @item @qcode{"ilutp"} (default)
+## ILU factorization with threshold and pivoting.
+##
+## Additional supported options: @code{milu}, @code{droptol}, @code{udiag},
+## @code{thresh}.
+## @end table
+##
+## @item droptol
+## A non-negative scalar specifying the drop tolerance for factorization.  The
+## default value is 0 which produces the complete LU factorization.
+##
+## Non-diagonal entries of @var{U} are set to 0 unless
+##
+## @code{abs (@var{U}(i,j)) >= droptol * norm (@var{A}(:,j))}.
+##
+## Non-diagonal entries of @var{L} are set to 0 unless
+##
+## @code{abs (@var{L}(i,j)) >= droptol * norm (@var{A}(:,j))/@var{U}(j,j)}.
+##
+## @item milu
+## Modified incomplete LU factorization:
+##
+## @table @asis
+## @item @qcode{"row"}
+## Row-sum modified incomplete LU factorization. 
+## The factorization preserves row sums:
+## @code{@var{A} * e = @var{L} * @var{U} * e}, where e is a vector of ones.
+##
+## @item @qcode{"col"}
+## Column-sum modified incomplete LU factorization. 
+## The factorization preserves column sums:
+## @code{e' * @var{A} = e' * @var{L} * @var{U}}.
+##
+## @item @qcode{"off"} (default)
+## Row and column sums are not necessarily preserved.
+## @end table
+##
+## @item udiag
+## If true, any zeros on the diagonal of the upper triangular factor are
+## replaced by the local drop tolerance
+## @code{droptol * norm (@var{A}(:,j))/@var{U}(j,j)}.  The default is false.
+##
+## @item thresh
+## Pivot threshold for factorization.  It can range between 0 (diagonal
+## pivoting) and 1 (default), where the maximum magnitude entry in the column
+## is chosen to be the pivot.
+## @end table
+##
+## If @code{ilu} is called with just one output, the returned matrix is 
+## @code{@var{L} + @var{U} - speye (size (@var{A}))}, where @var{L} is unit
+## lower triangular and @var{U} is upper triangular.
+##
+## With two outputs, @code{ilu} returns a unit lower triangular matrix @var{L}
+## and an upper triangular matrix @var{U}.  For @var{opts}.type ==
+## @qcode{"ilutp"}, one of the factors is permuted based on the value of
+## @var{opts}.milu.  When @var{opts}.milu == @qcode{"row"}, @var{U} is a
+## column permuted upper triangular factor.  Otherwise, @var{L} is a
+## row-permuted unit lower triangular factor.
+##
+## If there are three named outputs and @var{opts}.milu != @qcode{"row"},
+## @var{P} is returned such that @var{L} and @var{U} are incomplete factors
+## of @code{@var{P}*@var{A}}.  When @var{opts}.milu == @qcode{"row"}, @var{P}
+## is returned such that @var{L} and @var{U} are incomplete factors of
+## @code{@var{A}*@var{P}}.
+##
+## EXAMPLES
+##
+## @example
+## @group
+## A = gallery ("neumann", 1600) + speye (1600);
+## opts.type = "nofill";
+## nnz (A)
+## ans = 7840
+##
+## nnz (lu (A))
+## ans = 126478
+##
+## nnz (ilu (A, opts))
+## ans = 7840
+## @end group
+## @end example
+##
+## This shows that @var{A} has 7,840 nonzeros, the complete LU factorization has
+## 126,478 nonzeros, and the incomplete LU factorization, with 0 level of
+## fill-in, has 7,840 nonzeros, the same amount as @var{A}.  Taken from:
+## http://www.mathworks.com/help/matlab/ref/ilu.html
+##
+## @example
+## @group
+## A = gallery ("wathen", 10, 10);
+## b = sum (A, 2); 
+## tol = 1e-8; 
+## maxit = 50;
+## opts.type = "crout";
+## opts.droptol = 1e-4;
+## [L, U] = ilu (A, opts);
+## x = bicg (A, b, tol, maxit, L, U);
+## norm (A * x - b, inf)
+## @end group
+## @end example
+##
+## This example uses ILU as preconditioner for a random FEM-Matrix, which has a
+## large condition number.  Without @var{L} and @var{U} BICG would not converge.
+##
+## @seealso{lu, ichol, bicg, gmres}
+## @end deftypefn
+
+function [L, U, P] = ilu (A, opts = struct ())
+
+  if (nargin < 1 || nargin > 2 || (nargout > 3))
+    print_usage ();
+  endif
+
+  if (! (issparse (A) && issquare (A)))
+    error ("ichol: A must be a sparse square matrix");
+  endif
+
+  if (! isstruct (opts))
+    error ("ichol: OPTS must be a structure.");
+  endif
+
+  ## If A is empty then return empty L, U and P for Matlab compatibility
+  if (isempty (A)) 
+    L = U = P = A;
+    return;
+  endif
+
+  ## Parse input options
+  if (! isfield (opts, "type"))
+    opts.type = "nofill";  # set default
+  else
+    type = tolower (getfield (opts, "type"));
+    if (! any (strcmp (type, {"nofill", "crout", "ilutp"})))
+      error ("ilu: invalid TYPE specified");
+    endif
+    opts.type = type;
+  endif
+
+  if (! isfield (opts, "droptol"))
+    opts.droptol = 0;      # set default
+  else
+    if (! (isreal (opts.droptol) && isscalar (opts.droptol)
+           && opts.droptol >= 0))
+      error ("ilu: DROPTOL must be a non-negative real scalar");
+    endif
+  endif
+
+  if (! isfield (opts, "milu"))
+    opts.milu = "off";     # set default
+  else
+    milu = tolower (getfield (opts, "milu"));
+    if (! any (strcmp (milu, {"off", "col", "row"})))
+      error ('ilu: MILU must be one of "off", "col", or "row"');
+    endif
+    opts.milu = milu;
+  endif
+
+  if (! isfield (opts, "udiag"))
+    opts.udiag = 0;        # set default
+  else
+    if (! isscalar (opts.udiag) || (opts.udiag != 0 && opts.udiag != 1))
+      error ("ilu: UDIAG must be 0 or 1");
+    endif
+  endif
+
+  if (! isfield (opts, "thresh"))
+    opts.thresh = 1;       # set default
+  else
+    if (! (isreal (opts.thresh) && isscalar (opts.thresh))
+        || opts.thresh < 0 || opts.thresh > 1)
+      error ("ilu: THRESH must be a scalar in the range [0, 1]");
+    endif
+  endif
+
+  n = length (A);
+
+  ## Delegate to specialized ILU
+  switch (opts.type)
+    case "nofill"
+        [L, U] = __ilu0__ (A, opts.milu);
+        if (nargout == 3)
+          P = speye (length (A));
+        endif
+    case "crout"
+        [L, U] = __iluc__ (A, opts.droptol, opts.milu);
+        if (nargout == 3)
+          P = speye (length (A));
+        endif
+    case "ilutp"
+        if (nargout == 2)
+          [L, U]  = __ilutp__ (A, opts.droptol, opts.thresh,
+                                  opts.milu, opts.udiag);
+        elseif (nargout == 3)
+          [L, U, P]  = __ilutp__ (A, opts.droptol, opts.thresh,
+                                     opts.milu, opts.udiag);
+        endif
+  endswitch
+
+  if (nargout == 1)
+    L = L + U - speye (n);
+  endif
+
+endfunction
+
+
+%!shared n, dtol, A
+%! n = 1600;
+%! dtol = 0.1;
+%! A = gallery ("neumann", n) + speye (n);
+%!test
+%! opts.type = "nofill";
+%! assert (nnz (ilu (A, opts)), 7840);
+## This test has been verified in both Matlab and Octave.
+%!test
+%! opts.type = "crout";
+%! opts.milu = "row";
+%! opts.droptol = dtol;
+%! [L, U] = ilu (A, opts);
+%! e = ones (size (A, 2),1);
+%! assert (norm (A*e - L*U*e), 1e-14, 1e-14);
+%!test
+%! opts.type = "crout";
+%! opts.droptol = dtol;
+%! [L, U] = ilu (A, opts);
+%! assert (norm (A - L * U, "fro") / norm (A, "fro"), 0.05, 1e-2);
+
+## Check if the elements in U satisfy the non-dropping condition.
+%!test
+%! opts.type = "crout";
+%! opts.droptol = dtol;
+%! [L, U] = ilu (A, opts);
+%! for j = 1:n
+%!   cmp_value = dtol * norm (A(:, j));
+%!   non_zeros = nonzeros (U(:, j));
+%!   assert (abs (non_zeros) >= cmp_value);
+%! endfor
+%!test
+%! opts.type = "ilutp";
+%! opts.droptol = dtol;
+%! [L, U] = ilu (A, opts);
+%! for j = 1:n
+%!   cmp_value = dtol * norm (A(:, j));
+%!   non_zeros = nonzeros (U(:, j));
+%!   assert (abs (non_zeros) >= cmp_value);
+%! endfor
+
+## Check that the complete LU factorisation with crout and ilutp algorithms
+## produce the same result.
+%!test
+%! opts.type = "crout";
+%! opts.droptol = 0;
+%! [L1, U1] = ilu (A, opts);
+%! opts.type = "ilutp";
+%! opts.thresh = 0;
+%! [L2, U2] = ilu (A, opts);
+%! assert (norm (L1 - L2, "fro") / norm (L1, "fro"), 0, eps);
+%! assert (norm (U1 - U2, "fro") / norm (U1, "fro"), 0, eps);
+
+## Tests for real matrices of different sizes for ilu0, iluc and ilutp.
+## The difference A - L*U should be not greater than eps because with droptol
+## equaling 0, the LU complete factorization is performed.
+%!shared n_tiny, n_small, n_medium, n_large, A_tiny, A_small, A_medium, A_large
+%! n_tiny = 5;
+%! n_small = 40;
+%! n_medium = 600;
+%! n_large = 10000;
+%! A_tiny = spconvert ([1 4 2 3 3 4 2 5; 1 1 2 3 4 4 5 5; 1 2 3 4 5 6 7 8]');
+%! A_small = sprand (n_small, n_small, 1/n_small) + speye (n_small);
+%! A_medium = sprand (n_medium, n_medium, 1/n_medium) + speye (n_medium);
+%! A_large = sprand (n_large, n_large, 1/n_large/10) + speye (n_large);
+%!
+%!test 
+%! opts.type = "nofill";
+%! [L, U] = ilu (A_tiny);
+%! assert (norm (A_tiny - L*U, "fro") / norm (A_tiny, "fro"), 0, n_tiny * eps);
+%!test 
+%! opts.type = "nofill";
+%! [L, U] = ilu (A_small);
+%! assert (norm (A_small - L*U, "fro") / norm (A_small, "fro"), 0, 1);
+%!test 
+%! opts.type = "nofill";
+%! [L, U] = ilu (A_medium);
+%! assert (norm (A_medium - L*U, "fro") / norm (A_medium, "fro"), 0, 1);
+%!test 
+%! opts.type = "nofill";
+%! [L, U] = ilu (A_large);
+%! assert (norm (A_large - L*U, "fro") / norm (A_large, "fro"), 0, 1);
+%!
+%!test 
+%! opts.type = "crout";
+%! [L, U] = ilu (A_tiny, opts);
+%! assert (norm (A_tiny - L*U, "fro") / norm (A_tiny, "fro"), eps, eps);
+%!test 
+%! opts.type = "crout";
+%! [L, U] = ilu (A_small, opts);
+%! assert (norm (A_small - L*U, "fro") / norm (A_small, "fro"), eps, eps);
+%!test 
+%! opts.type = "crout";
+%! [L, U] = ilu (A_medium, opts);
+%! assert (norm (A_medium - L*U, "fro") / norm (A_medium, "fro"), eps, eps);
+%!test 
+%! opts.type = "crout";
+%! [L, U] = ilu (A_large, opts);
+%! assert (norm (A_large - L*U, "fro") / norm (A_large, "fro"), eps, eps);
+%!
+%!test 
+%! opts.type = "ilutp";
+%! opts.droptol = 0;
+%! opts.thresh = 0;
+%! [L, U] = ilu (A_tiny, opts);
+%! assert (norm (A_tiny - L*U, "fro") / norm (A_tiny, "fro"), eps, eps);
+%!test 
+%! opts.type = "ilutp";
+%! opts.droptol = 0;
+%! opts.thresh = 0;
+%! [L, U] = ilu (A_small, opts);
+%! assert (norm (A_small - L*U, "fro") / norm (A_small, "fro"), eps, eps);
+%!test 
+%! opts.type = "ilutp";
+%! opts.droptol = 0;
+%! opts.thresh = 0;
+%! [L, U] = ilu (A_medium, opts);
+%! assert (norm (A_medium - L*U, "fro") / norm (A_medium, "fro"), eps, eps);
+%!test 
+%! opts.type = "ilutp";
+%! opts.droptol = 0;
+%! opts.thresh = 0;
+%! [L, U] = ilu (A_large, opts);
+%! assert (norm (A_large - L*U, "fro") / norm (A_large, "fro"), eps, eps);
+
+## Tests for complex matrices of different sizes for ilu0, iluc and ilutp.
+%!shared n_tiny, n_small, n_medium, n_large, A_tiny, A_small, A_medium, A_large
+%! n_tiny = 5;
+%! n_small = 40;
+%! n_medium = 600;
+%! n_large = 10000;
+%! A_tiny = spconvert ([1 4 2 3 3 4 2 5; 1 1 2 3 4 4 5 5; 1 2 3 4 5 6 7 8]');
+%! A_tiny(1,1) += 1i;
+%! A_small = sprand (n_small, n_small, 1/n_small) + ...
+%!   i * sprand (n_small, n_small, 1/n_small) + speye (n_small);
+%! A_medium = sprand (n_medium, n_medium, 1/n_medium) + ...
+%!   i * sprand (n_medium, n_medium, 1/n_medium) + speye (n_medium);
+%! A_large = sprand (n_large, n_large, 1/n_large/10) + ...
+%!   i * sprand (n_large, n_large, 1/n_large/10) + speye (n_large);
+%!
+%!test 
+%! opts.type = "nofill";
+%! [L, U] = ilu (A_tiny);
+%! assert (norm (A_tiny - L*U, "fro") / norm (A_tiny, "fro"), 0, n_tiny * eps);
+%!test 
+%! opts.type = "nofill";
+%! [L, U] = ilu (A_small);
+%! assert (norm (A_small - L*U, "fro") / norm (A_small, "fro"), 0, 1);
+%!test 
+%! opts.type = "nofill";
+%! [L, U] = ilu (A_medium);
+%! assert (norm (A_medium - L*U, "fro") / norm (A_medium, "fro"), 0, 1);
+%!test 
+%! opts.type = "nofill";
+%! [L, U] = ilu (A_large);
+%! assert (norm (A_large - L*U, "fro") / norm (A_large, "fro"), 0, 1);
+%!
+%!test 
+%! opts.type = "crout";
+%! [L, U] = ilu (A_tiny, opts);
+%! assert (norm (A_tiny - L*U, "fro") / norm (A_tiny, "fro"), eps, eps);
+%!test 
+%! opts.type = "crout";
+%! [L, U] = ilu (A_small, opts);
+%! assert (norm (A_small - L*U, "fro") / norm (A_small, "fro"), eps, eps);
+%!test 
+%! opts.type = "crout";
+%! [L, U] = ilu (A_medium, opts);
+%! assert (norm (A_medium - L*U, "fro") / norm (A_medium, "fro"), eps, eps);
+%!test 
+%! opts.type = "crout";
+%! [L, U] = ilu (A_large, opts);
+%! assert (norm (A_large - L*U, "fro") / norm (A_large, "fro"), eps, eps);
+%!
+%!test 
+%! opts.type = "ilutp";
+%! opts.droptol = 0;
+%! opts.thresh = 0;
+%! [L, U] = ilu (A_tiny, opts);
+%! assert (norm (A_tiny - L*U, "fro") / norm (A_tiny, "fro"), eps, eps);
+%!test 
+%! opts.type = "ilutp";
+%! opts.droptol = 0;
+%! opts.thresh = 0;
+%! [L, U] = ilu (A_small, opts);
+%! assert (norm (A_small - L*U, "fro") / norm (A_small, "fro"), eps, eps);
+%!test 
+%! opts.type = "ilutp";
+%! opts.droptol = 0;
+%! opts.thresh = 0;
+%! [L, U] = ilu (A_medium, opts);
+%! assert (norm (A_medium - L*U, "fro") / norm (A_medium, "fro"), eps, eps);
+%!test 
+%! opts.type = "ilutp";
+%! opts.droptol = 0;
+%! opts.thresh = 0;
+%! [L, U] = ilu (A_large, opts);
+%! assert (norm (A_large - L*U, "fro") / norm (A_large, "fro"), eps, eps);
+
+## Specific tests for ilutp
+
+%!shared a1, a2
+%! a1 = sparse ([0 0 4 3 1; 5 1 2.3 2 4.5; 0 0 0 2 1;0 0 8 0 2.2; 0 0 9 9 1 ]);
+%! a2 = sparse ([3 1 0 0 4; 3 1 0 0 -2;0 0 8 0 0; 0 4 0 4 -4.5; 0 -1 0 0 1]);
+%!test
+%! opts.udiag = 1;
+%! opts.type = "ilutp";
+%! opts.droptol = 0.2;
+%! [L, U, P] = ilu (a1, opts);
+%! assert (norm (U, "fro"), 17.4577, 1e-4);
+%! assert (norm (L, "fro"), 2.4192, 1e-4);
+%! opts.udiag = 0;
+%! #fail ("ilu (a1, opts)");
+%!
+%!test
+%! opts.type = "ilutp";
+%! opts.droptol = 0;
+%! opts.thresh = 0;
+%! opts.milu = "row";
+%! #fail ("ilu (a2, opts)");
+
+%% Tests for input validation
+%!shared A_tiny
+%! A_tiny = spconvert ([1 4 2 3 3 4 2 5; 1 1 2 3 4 4 5 5; 1 2 3 4 5 6 7 8]');
+
+%!test
+%! [L, U] = ilu (sparse ([]));
+%! assert (isempty (L));
+%! assert (isempty (U));
+%! opts.type = "crout";
+%! [L, U] = ilu (sparse ([]), opts);
+%! assert (isempty (L));
+%! assert (isempty (U));
+%! opts.type = "ilutp";
+%! [L, U] = ilu (sparse ([]), opts);
+%! assert (isempty (L));
+%! assert (isempty (U));
+%!error <A must be a sparse square matrix> ilu (0)
+%!error <A must be a sparse square matrix> ilu ([])
+%!error <zero on the diagonal> ilu (sparse (0))
+
+%!test
+%! opts.type = "foo";
+%! fail ("ilu (A_tiny, opts)", "invalid TYPE specified");
+%! opts.type = 1;
+%! fail ("ilu (A_tiny, opts)", "invalid TYPE specified");
+%! opts.type = [];
+%! fail ("ilu (A_tiny, opts)", "invalid TYPE specified");
+%!test
+%! opts.droptol = -1;
+%! fail ("ilu (A_tiny, opts)", "DROPTOL must be a non-negative real scalar");
+%! opts.droptol = 0.5i;
+%! fail ("ilu (A_tiny, opts)", "DROPTOL must be a non-negative real scalar");
+%! opts.droptol = [];
+%! fail ("ilu (A_tiny, opts)", "DROPTOL must be a non-negative real scalar");
+%!test
+%! opts.milu = "foo";
+%! fail ("ilu (A_tiny, opts)", 'MILU must be one of "off"');
+%! opts.milu = 1;
+%! fail ("ilu (A_tiny, opts)", 'MILU must be one of "off"');
+%! opts.milu = [];
+%! fail ("ilu (A_tiny, opts)", 'MILU must be one of "off"');
+%!test
+%! opts.udiag = -1;
+%! fail ("ilu (A_tiny, opts)", "UDIAG must be 0 or 1");
+%! opts.udiag = 0.5i;
+%! fail ("ilu (A_tiny, opts)", "UDIAG must be 0 or 1");
+%! opts.udiag = [];
+%! fail ("ilu (A_tiny, opts)", "UDIAG must be 0 or 1");
+%!test
+%! opts.thresh = -1;
+%! fail ("ilu (A_tiny, opts)", "THRESH must be a scalar");
+%! opts.thresh = 0.5i;
+%! fail ("ilu (A_tiny, opts)", "THRESH must be a scalar");
+%! opts.thresh = [];
+%! fail ("ilu (A_tiny, opts)", "THRESH must be a scalar");
+
--- a/scripts/sparse/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/sparse/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -12,9 +12,12 @@
   sparse/etreeplot.m \
   sparse/gmres.m \
   sparse/gplot.m \
+  sparse/ichol.m \
+  sparse/ilu.m \
   sparse/nonzeros.m \
   sparse/pcg.m \
   sparse/pcr.m \
+  sparse/qmr.m \
   sparse/spaugment.m \
   sparse/spconvert.m \
   sparse/spdiags.m \
--- a/scripts/sparse/nonzeros.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/sparse/nonzeros.m	Mon Jan 12 09:17:35 2015 -0800
@@ -18,7 +18,7 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} nonzeros (@var{s})
-## Return a vector of the non-zero values of the sparse matrix @var{s}.
+## Return a vector of the nonzero values of the sparse matrix @var{s}.
 ## @seealso{find, nnz}
 ## @end deftypefn
 
--- a/scripts/sparse/pcg.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/sparse/pcg.m	Mon Jan 12 09:17:35 2015 -0800
@@ -124,7 +124,7 @@
 ## n = 10;
 ## A = diag (sparse (1:n));
 ## b = rand (n, 1);
-## [l, u, p, q] = luinc (A, 1.e-3);
+## [l, u, p] = ilu (A, struct ("droptol", 1.e-3));
 ## @end group
 ## @end example
 ##
@@ -203,7 +203,7 @@
 ## SIAM, 1995. (the base PCG algorithm)
 ##
 ## @item
-## Y. Saad, @cite{Iterative Methods for Sparse Linear Systems}, 
+## @nospell{Y. Saad}, @cite{Iterative Methods for Sparse Linear Systems}, 
 ## @nospell{PWS} 1996. (condition number estimate from PCG)
 ## Revised version of this book is available online at
 ## @url{http://www-users.cs.umn.edu/~saad/books.html}
--- a/scripts/sparse/pcr.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/sparse/pcr.m	Mon Jan 12 09:17:35 2015 -0800
@@ -162,8 +162,8 @@
 ##
 ## References:
 ##
-##      [1] W. Hackbusch, @cite{Iterative Solution of Large Sparse Systems of
-##      Equations}, section 9.5.4; Springer, 1994
+## [1] @nospell{W. Hackbusch}, @cite{Iterative Solution of Large Sparse
+## Systems of Equations}, section 9.5.4; Springer, 1994
 ##
 ## @seealso{sparse, pcg}
 ## @end deftypefn
--- a/scripts/sparse/private/__sprand_impl__.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/sparse/private/__sprand_impl__.m	Mon Jan 12 09:17:35 2015 -0800
@@ -22,7 +22,8 @@
 
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {} __sprand_impl__ (@var{s}, @var{randfun})
-## @deftypefnx {Function File} {} __sprand_impl__ (@var{m}, @var{n}, @var{d}, @var{funname}, @var{randfun})
+## @deftypefnx {Function File} {} __sprand_impl__ (@var{m}, @var{n}, @var{d}, @var{fcnname}, @var{randfun})
+## @deftypefnx {Function File} {} __sprand_impl__ (@var{m}, @var{n}, @var{d}, @var{rc}, @var{fcnname}, @var{randfun})
 ## Undocumented internal function.
 ## @end deftypefn
 
@@ -31,52 +32,114 @@
 function S = __sprand_impl__ (varargin)
 
   if (nargin == 2)
-    m = varargin{1};
-    randfun = varargin{2};
+    [m, randfun] = deal (varargin{1:2});
     [i, j] = find (m);
     [nr, nc] = size (m);
     S = sparse (i, j, randfun (size (i)), nr, nc);
-    return;
-  endif
+  else
+    if (nargin == 5)
+      [m, n, d, fcnname, randfun] = deal (varargin{:});
+    else
+      [m, n, d, rc, fcnname, randfun] = deal (varargin{:});
+    endif
 
-  [m, n, d, funname, randfun] = deal (varargin{:});
+    if (! (isscalar (m) && m == fix (m) && m > 0))
+      error ("%s: M must be an integer greater than 0", fcnname);
+    endif
+    if (! (isscalar (n) && n == fix (n) && n > 0))
+      error ("%s: N must be an integer greater than 0", fcnname);
+    endif
+    if (d < 0 || d > 1)
+      error ("%s: density D must be between 0 and 1", fcnname);
+    endif
+
+    if (nargin == 5)
+      mn = m*n;
+      k = round (d*mn);
+      if (mn > sizemax ())
+        ## randperm will overflow, so use alternative methods
 
-  if (!(isscalar (m) && m == fix (m) && m > 0))
-    error ("%s: M must be an integer greater than 0", funname);
-  endif
+        idx = unique (fix (rand (1.01*k, 1) * mn)) + 1;
+
+        ## idx contains random numbers in [1,mn]
+        ## Generate 1% more random values than necessary in order to reduce the
+        ## probability that there are less than k distinct values; maybe a
+        ## better strategy could be used but I don't think it's worth the price.
 
-  if (!(isscalar (n) && n == fix (n) && n > 0))
-    error ("%s: N must be an integer greater than 0", funname);
-  endif
+        ## actual number of entries in S
+        k = min (length (idx), k);
+        j = floor ((idx(1:k) - 1) / m);
+        i = idx(1:k) - j * m;
+        j++;
+      else
+        idx = randperm (mn, k);
+        [i, j] = ind2sub ([m, n], idx);
+      endif
 
-  if (d < 0 || d > 1)
-    error ("%s: density D must be between 0 and 1", funname);
-  endif
+      S = sparse (i, j, randfun (k, 1), m, n);
+
+    elseif (nargin == 6)
+      ## Create a matrix with specified reciprocal condition number.
+
+      if (! isscalar (rc) && ! isvector (rc))
+        error ("%s: RC must be a scalar or vector", fcnname);
+      endif
 
-  mn = m*n;
-  k = round (d*mn);
-  if (mn > sizemax ())
-    ## randperm will overflow, so use alternative methods
+      ## We want to reverse singular valued decomposition A=U*S*V'.
+      ## First, first S is constructed and then U = U1*U2*..Un and
+      ## V' = V1*V2*..Vn are seen as Jacobi rotation matrices with angles and
+      ## planes of rotation randomized.  Repeatedly apply rotations until the
+      ## required density for A is achieved.
 
-    idx = unique (fix (rand (min (k*1.01, k+10), 1) * mn)) + 1;
+      if (isscalar (rc))
+        if (rc < 0 || rc > 1)
+          error ("%s: reciprocal condition number RC must be between 0 and 1", fcnname);
+        endif
+        ## Reciprocal condition number is ratio of smallest SV to largest SV
+        ## Generate singular values randomly and sort them to build S
+        ## Random singular values in range [rc, 1].
+        v = rand (1, min (m,n)) * (1 - rc) + rc;
+        v(1) = 1;
+        v(end) = rc;
+        v = sort (v, "descend");
+        S = sparse (diag (v, m, n));
+      else
+        ## Only the min (m, n) greater singular values from rc vector are used.
+        if (length (rc) > min (m,n))
+          rc = rc(1:min(m, n));
+        endif
+        S = sparse (diag (sort (rc, "descend"), m, n));
+      endif
 
-    ## idx contains random numbers in [1,mn]
-    ## generate 1% or 10 more random values than necessary in order to
-    ## reduce the probability that there are less than k distinct
-    ## values; maybe a better strategy could be used but I don't think
-    ## it's worth the price
-    
-    ## actual number of entries in S
-    k = min (length (idx), k);
-    j = floor ((idx(1:k) - 1) / m);
-    i = idx(1:k) - j * m;
-    j++;
-  else
-    idx = randperm (mn, k);
-    [i, j] = ind2sub ([m, n], idx);
+      Uinit = speye (m);
+      Vinit = speye (n);
+      k = round (d*m*n);
+      while (nnz (S) < k)
+        if (m > 1)
+          ## Construct U randomized rotation matrix
+          rot_angleu = 2 * pi * rand ();
+          cu = cos (rot_angleu); su = sin (rot_angleu);
+          rndtmp = randperm (m, 2);
+          i = rndtmp(1); j = rndtmp(2);
+          U = Uinit;
+          U(i, i) = cu; U(i, j) = -su;
+          U(j, i) = su; U(j, j) = cu;
+          S = U * S;
+        endif
+        if (n > 1)
+          ## Construct V' randomized rotation matrix
+          rot_anglev = 2 * pi * rand ();
+          cv = cos (rot_anglev); sv = sin (rot_anglev);
+          rndtmp = randperm (n, 2);
+          i = rndtmp(1); j = rndtmp(2);
+          V = Vinit;
+          V(i, i) = cv;  V(i, j) = sv;
+          V(j, i) = -sv; V(j, j) = cv;
+          S = S * V;
+        endif
+      endwhile
+    endif
   endif
 
-  S = sparse (i, j, randfun (k, 1), m, n);
-
 endfunction
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/sparse/qmr.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,324 @@
+## Copyright (C) 2014 Nathan Podlich
+##
+## 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; If not, see <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {Function File} {@var{x} =} qmr (@var{A}, @var{b}, @var{rtol}, @var{maxit}, @var{M1}, @var{M2}, @var{x0})
+## @deftypefnx {Function File} {@var{x} =} qmr (@var{A}, @var{b}, @var{rtol}, @var{maxit}, @var{P})
+## @deftypefnx {Function File} {[@var{x}, @var{flag}, @var{relres}, @var{iter}, @var{resvec}] =} qmr (@var{A}, @var{b}, @dots{})
+## Solve @code{A x = b} using the Quasi-Minimal Residual iterative
+## method (without look-ahead).
+##
+## @itemize @minus
+## @item @var{rtol} is the relative tolerance, if not given
+## or set to [] the default value 1e-6 is used.
+##
+## @item @var{maxit} the maximum number of outer iterations,
+## if not given or set to [] the default value
+## @code{min (20, numel (b))} is used.
+##
+## @item @var{x0} the initial guess, if not given or set to []
+## the default value @code{zeros (size (b))} is used.
+## @end itemize
+##
+## @var{A} can be passed as a matrix or as a function handle or
+## inline function @code{f} such that @code{f(x, "notransp") = A*x}
+## and @code{f(x, "transp") = A'*x}.
+##
+## The preconditioner @var{P} is given as @code{P = M1 * M2}.
+## Both @var{M1} and @var{M2} can be passed as a matrix or as
+## a function handle or inline function @code{g} such that
+## @code{g(x, "notransp") = M1 \ x} or @code{g(x, "notransp") = M2 \ x} and
+## @code{g(x, "transp") = M1' \ x} or @code{g(x, "transp") = M2' \ x}.
+##
+## If called with more than one output parameter
+##
+## @itemize @minus
+## @item @var{flag} indicates the exit status:
+##
+## @itemize @minus
+## @item 0: iteration converged to the within the chosen tolerance
+##
+## @item 1: the maximum number of iterations was reached before convergence
+##
+## @item 3: the algorithm reached stagnation
+## @end itemize
+##
+## (the value 2 is unused but skipped for compatibility).
+##
+## @item @var{relres} is the final value of the relative residual.
+##
+## @item @var{iter} is the number of iterations performed.
+##
+## @item @var{resvec} is a vector containing the residual norms at each
+##       iteration.
+## @end itemize
+##
+## References:
+##
+## @enumerate
+## @item
+## R. Freund and N. Nachtigal, @cite{QMR: a quasi-minimal residual
+## method for non-Hermitian linear systems}, Numerische Mathematik,
+## 1991, 60, pp. 315-339.
+##
+## @item
+## R. Barrett, M. Berry, T. Chan, J. Demmel, J. Donato, J. Dongarra,
+## V. Eijkhour, R. Pozo, C. Romine, and H. van der Vorst,
+## @cite{Templates for the solution of linear systems: Building blocks
+## for iterative methods}, SIAM, 2nd ed., 1994.
+## @end enumerate
+##
+## @seealso{bicg, bicgstab, cgs, gmres}
+## @end deftypefn
+
+## Author: Nathan Podlich <nathan.podlich@gmail.com>
+
+function [x, flag, relres, iter, resvec] = qmr (A, b, tol, maxit, M1, M2, x0)
+
+  if (nargin >= 2 && isvector (full (b)))
+
+    if (ischar (A))
+      fun = str2func (A);
+      Ax  = @(x) feval (fun, x, "notransp");
+      Atx = @(x) feval (fun, x, "transp");
+    elseif (isa (A, "function_handle"))
+      Ax  = @(x) feval (A, x, "notransp");
+      Atx = @(x) feval (A, x, "transp");
+    elseif (ismatrix (A))
+      Ax  = @(x) A  * x;
+      Atx = @(x) A' * x;
+    else
+      error (["qmr: first argument is expected to " ...
+                "be a function or a square matrix"]);
+    endif
+
+    if (nargin < 3 || isempty (tol))
+      tol = 1e-6;
+    endif
+
+    if (nargin < 4 || isempty (maxit))
+      maxit = min (rows (b), 20);
+    endif
+
+    if (nargin < 5 || isempty (M1))
+      M1m1x = @(x, ignore) x;
+      M1tm1x = M1m1x;
+    elseif (ischar (M1))
+      fun = str2func (M1);
+      M1m1x  = @(x) feval (fun, x, "notransp");
+      M1tm1x = @(x) feval (fun, x, "transp");
+    elseif (isa (M1, "function_handle"))
+      M1m1x  = @(x) feval (M1, x, "notransp");
+      M1tm1x = @(x) feval (M1, x, "transp");
+    elseif (ismatrix (M1))
+      M1m1x  = @(x) M1  \ x;
+      M1tm1x = @(x) M1' \ x;
+    else
+      error (["qmr: preconditioner is expected to " ...
+                "be a function or matrix"]);
+    endif
+
+    if (nargin < 6 || isempty (M2))
+      M2m1x = @(x, ignore) x;
+      M2tm1x = M2m1x;
+    elseif (ischar (M2))
+      fun = str2func (M2);
+      M2m1x  = @(x) feval (fun, x, "notransp");
+      M2tm1x = @(x) feval (fun, x, "transp");
+    elseif (isa (M2, "function_handle"))
+      M2m1x  = @(x) feval (M2, x, "notransp");
+      M2tm1x = @(x) feval (M2, x, "transp");
+    elseif (ismatrix (M2))
+      M2m1x  = @(x) M2  \ x;
+      M2tm1x = @(x) M2' \ x;
+    else
+      error (["qmr: preconditioner is expected to " ...
+                "be a function or matrix"]);
+    endif
+
+
+    if (nargin < 7 || isempty (x0))
+      x = zeros (size (b));
+    else
+      x = x0;
+    endif
+
+    r = b - Ax (x);
+    
+    bnorm = norm (b);
+    res0 = norm (r);
+    if (nargout > 4)
+      resvec(1) = res0;
+    endif
+    vt = r;
+
+    y = M1m1x (vt);
+
+    rho0 = norm (y);
+    wt = r;
+
+    z = M2tm1x (wt);
+
+    xi1 = norm (z);
+    gamma0 = 1;
+    eta0 = -1;
+    flag = 1;
+    for iter=1:1:maxit
+      ## If rho0 == 0 or xi1 == 0, method fails.
+      v = vt / rho0;
+      y = y / rho0;
+      w = wt / xi1;
+      z = z / xi1;
+
+      delta1 = z' * y; ## If delta1 == 0, method fails.
+
+      yt = M2m1x (y);
+      zt = M1tm1x (z);
+
+      if (iter == 1)
+        p = yt;
+        q = zt;
+      else
+        p = yt - (xi1*delta1/eps0) * p;
+        q = zt - (rho0*delta1/eps0) * q;
+      endif
+      pt = Ax (p);
+
+      eps0 = q' * pt; ## If eps0 == 0, method fails.
+      beta1 = eps0 / delta1; ## If beta1 == 0, method fails.
+      vt = pt - beta1 * v;
+
+      y = M1m1x (vt);
+      rho1 = norm(y);
+      wt = Atx (q) - beta1 * w;
+      z = M2tm1x (wt);
+
+      xi1 = norm(z);
+      theta1 = rho1 / (gamma0 * abs(beta1));
+      gamma1 = 1 / sqrt(1 + theta1^2); ## If gamma1 == 0, method fails.
+      eta1 = -eta0 * rho0 * gamma1^2 / (beta1 * gamma0^2);
+
+      if (iter == 1)
+        d = eta1 * p;
+        s = eta1 * pt;
+      else
+        d = eta1 * p + (theta0*gamma1)^2 * d;
+        s = eta1 * pt + (theta0 * gamma1)^2 * s;
+      endif
+      x += d;
+      r -= s;
+
+      res1 = norm (r) / bnorm;
+      if (nargout > 4)
+        resvec(iter + 1, 1) = norm (r);
+      end
+      
+      if (res1 < tol)
+        ## Convergence achieved.
+        flag = 0;
+        break;
+      elseif (res0 <= res1)
+        ## Stagnation encountered.
+        flag = 3;
+        break;
+      endif
+      theta0 = theta1;
+      eta0 = eta1;
+      gamma0 = gamma1;
+      rho0 = rho1;
+    endfor
+
+    relres = res1;
+    if (flag == 1)
+      if (nargout < 2)
+        printf ("qmr stopped at iteration %i ", iter);
+        printf ("without converging to the desired tolerance %e\n", tol);
+        printf ("because the maximum number of iterations was reached. ");
+        printf ("The iterate returned (number %i) has ", maxit);
+        printf ("relative residual %e\n", res1);
+      endif
+    elseif (flag == 3)
+      if (nargout < 2)
+        printf ("qmr stopped at iteration %i ", iter);
+        printf (" without converging to the desired tolerance %e\n", tol);
+        printf ("because the method stagnated.\n");
+        printf ("The iterate returned (number %i) ", iter);
+        printf ("has relative residual %e\n", res1);
+      endif
+    elseif (nargout < 2)
+      printf ("qmr converged at iteration %i ", iter);
+      printf ("to a solution with relative residual %e\n", res1);
+    endif
+  else
+    print usage();
+  endif
+endfunction
+
+
+%!demo
+%! % Solve system of A*x=b
+%! A = [5 -1 3;-1 2 -2;3 -2 3];
+%! b = [7;-1;4];
+%! [x, flag, relres, iter, resvec] = qmr (A, b)
+
+%!test
+%! n = 100;
+%! A = spdiags ([-2*ones(n,1) 4*ones(n,1) -ones(n,1)], -1:1, n, n);
+%! b = sum (A, 2);
+%! tol = 1e-8;
+%! maxit = 15;
+%! M1 = spdiags ([ones(n,1)/(-2) ones(n,1)],-1:0, n, n);
+%! M2 = spdiags ([4*ones(n,1) -ones(n,1)], 0:1, n, n);
+%! [x, flag, relres, iter, resvec] = qmr (A, b, tol, maxit, M1, M2);
+%! assert (x, ones (size (b)), 1e-7);
+
+%!function y = afun (x, t, a)
+%!  switch (t)
+%!    case "notransp"
+%!      y = a * x;
+%!    case "transp"
+%!      y = a' * x;
+%!  endswitch
+%!endfunction
+%!
+%!test
+%! n = 100;
+%! A = spdiags ([-2*ones(n,1) 4*ones(n,1) -ones(n,1)], -1:1, n, n);
+%! b = sum (A, 2);
+%! tol = 1e-8;
+%! maxit = 15;
+%! M1 = spdiags ([ones(n,1)/(-2) ones(n,1)],-1:0, n, n);
+%! M2 = spdiags ([4*ones(n,1) -ones(n,1)], 0:1, n, n);
+%!
+%! [x, flag, relres, iter, resvec] = qmr (@(x, t) afun (x, t, A),
+%!                                         b, tol, maxit, M1, M2);
+%! assert (x, ones (size (b)), 1e-7);
+
+%!test
+%! n = 100;
+%! tol = 1e-8;
+%! a = sprand (n, n, .1);
+%! A = a' * a + 100 * eye (n);
+%! b = sum (A, 2);
+%! [x, flag, relres, iter, resvec] = qmr (A, b, tol, [], diag (diag (A)));
+%! assert (x, ones (size (b)), 1e-7);
+
+%!test
+%! A = [1 + 1i, 1 + 1i; 2 - 1i, 2 + 1i];
+%! b = A * [1; 1];
+%! [x, flag, relres, iter, resvec] = qmr (A, b);
+%! assert (x, [1; 1], 1e-6);
--- a/scripts/sparse/spdiags.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/sparse/spdiags.m	Mon Jan 12 09:17:35 2015 -0800
@@ -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 nonzero 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:
@@ -50,45 +51,125 @@
 ## @end group
 ## @end example
 ##
+## @seealso{diag}
 ## @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);
+      ## Put sub/super-diagonals in the right place based on matrix size (MxN)
+      if (nr >= nc)
+        if (dn > 0)
+          offset = Brows - len + 1;
+          B(offset:Brows, k) = dv;
+        else
+          B(1:len, k) = dv;
+        endif
+      else
+        if (dn < 0)
+          offset = Brows - len + 1;
+          B(offset:Brows, k) = dv;
+        else
+          B(1:len, k) = dv;
+        endif
+      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);
+    if (m >= n)
+      offset = max (min (d(:), n-m), 0);
+    else
+      offset = d(:);
+    endif
     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, [4 3 8 0 0
+%!             0 9 5 1 0
+%!             0 0 2 7 6]);
+%! B = spdiags (magic (3), [-2 1]);
+%! assert (B, [4 0; 0 1; 0 7]);
+
+## Test zero filling for supra- and super-diagonals
+%!test
+%! ## Case 1: M = N
+%! A = sparse (zeros (3,3));
+%! A(1,3) = 13;
+%! A(3,1) = 31;
+%! [B, d] = spdiags (A);
+%! assert (d, [-2 2]');
+%! assert (B, [31 0; 0 0; 0 13]);
+%! assert (spdiags (B, d, 3,3), A)
+
+%!test
+%! ## Case 1: M > N
+%! A = sparse (zeros (4,3));
+%! A(1,3) = 13;
+%! A(3,1) = 31;
+%! [B, d] = spdiags (A);
+%! assert (d, [-2 2]');
+%! assert (B, [31 0; 0 0; 0 13]);
+%! assert (spdiags (B, d, 4,3), A)
+
+%!test
+%! ## Case 1: M < N
+%! A = sparse (zeros (3,4));
+%! 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 (B, d, 3,4), A)
+
 %!assert (spdiags (zeros (1,0),1,1,1), sparse (0))
 %!assert (spdiags (zeros (0,1),1,1,1), sparse (0))
-%!assert (spdiags ([0.5 -1 0.5], 0:2, 1, 1), sparse(0.5))
+%!assert (spdiags ([0.5 -1 0.5], 0:2, 1, 1), sparse (0.5))
 
+%% Test input validation
+%!error spdiags ()
+%!error spdiags (1,2,3,4,5)
+
--- a/scripts/sparse/spfun.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/sparse/spfun.m	Mon Jan 12 09:17:35 2015 -0800
@@ -18,7 +18,7 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {@var{y} =} spfun (@var{f}, @var{S})
-## Compute @code{f(@var{S})} for the non-zero values of @var{S}.
+## Compute @code{f(@var{S})} for the nonzero values of @var{S}.
 ## This results in a sparse matrix with the same structure as
 ## @var{S}.  The function @var{f} can be passed as a string, a
 ## function handle, or an inline function.
--- a/scripts/sparse/spones.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/sparse/spones.m	Mon Jan 12 09:17:35 2015 -0800
@@ -18,7 +18,7 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {@var{r} =} spones (@var{S})
-## Replace the non-zero entries of @var{S} with ones.  This creates a
+## Replace the nonzero entries of @var{S} with ones.  This creates a
 ## sparse matrix with the same structure as @var{S}.
 ## @seealso{sparse, sprand, sprandn, sprandsym, spfun, spy}
 ## @end deftypefn
--- a/scripts/sparse/sprand.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/sparse/sprand.m	Mon Jan 12 09:17:35 2015 -0800
@@ -21,15 +21,23 @@
 
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {} sprand (@var{m}, @var{n}, @var{d})
+## @deftypefnx {Function File} {} sprand (@var{m}, @var{n}, @var{d}, @var{rc})
 ## @deftypefnx {Function File} {} sprand (@var{s})
-## Generate a random sparse matrix.  The size of the matrix will be
-## @var{m}x@var{n}, with a density of values given by @var{d}.  @var{d} must
-## be between 0 and 1 inclusive.  Values will be uniformly distributed between
-## 0 and 1.
+## Generate a sparse matrix with uniformly distributed random values.
+##
+## The size of the matrix is @var{m}x@var{n} with a density of values @var{d}.
+## @var{d} must be between 0 and 1.  Values will be uniformly distributed on
+## the interval (0, 1).
 ##
-## If called with a single matrix argument, a random sparse matrix is
-## generated wherever the matrix @var{S} is non-zero.
-## @seealso{sprandn, sprandsym, spones, sparse}
+## If called with a single matrix argument, a sparse matrix is generated with
+## random values wherever the matrix @var{s} is nonzero.
+##
+## If called with a scalar fourth argument @var{rc}, a random sparse matrix
+## with reciprocal condition number @var{rc} is generated.  If @var{rc} is
+## a vector, then it specifies the first singular values of the generated
+## matrix (@code{length (@var{rc}) <= min (@var{m}, @var{n})}).
+##
+## @seealso{sprandn, sprandsym, rand}
 ## @end deftypefn
 
 ## Author: Paul Kienzle <pkienzle@users.sf.net>
@@ -42,12 +50,14 @@
 ## David Bateman
 ##      2004-10-20      Texinfo help and copyright message
 
-function S = sprand (m, n, d)
+function s = sprand (m, n, d, rc)
 
   if (nargin == 1 )
-    S = __sprand_impl__ (m, @rand);
+    s = __sprand_impl__ (m, @rand);
   elseif ( nargin == 3)
-    S = __sprand_impl__ (m, n, d, "sprand", @rand);
+    s = __sprand_impl__ (m, n, d, "sprand", @rand);
+  elseif (nargin == 4)
+    s = __sprand_impl__ (m, n, d, rc, "sprand", @rand);
   else
     print_usage ();
   endif
@@ -55,11 +65,25 @@
 endfunction
 
 
+%% Test 3-input calling form
 %!test
 %! s = sprand (4, 10, 0.1);
 %! assert (size (s), [4, 10]);
 %! assert (nnz (s) / numel (s), 0.1);
 
+%% Test 4-input calling form
+%!test
+%! d = rand ();
+%! s1 = sprand (100, 100, d, 0.4);
+%! rc = [5, 4, 3, 2, 1, 0.1];
+%! s2 = sprand (100, 100, d, rc);
+%! s3 = sprand (6, 4, d, rc);
+%! assert (svd (s2)'(1:length (rc)), rc, sqrt (eps)); 
+%! assert (1/cond (s1), 0.4, sqrt (eps));
+%! assert (nnz (s1) / (100*100), d, 0.02);
+%! assert (nnz (s2) / (100*100), d, 0.02); 
+%! assert (svd (s3)', [5 4 3 2], sqrt (eps));
+
 %% Test 1-input calling form
 %!test
 %! s = sprand (sparse ([1 2 3], [3 2 3], [2 2 2]));
@@ -72,16 +96,19 @@
 %!error sprand ()
 %!error sprand (1, 2)
 %!error sprand (1, 2, 3, 4)
-%!error sprand (ones (3), 3, 0.5)
-%!error sprand (3.5, 3, 0.5)
-%!error sprand (0, 3, 0.5)
-%!error sprand (3, ones (3), 0.5)
-%!error sprand (3, 3.5, 0.5)
-%!error sprand (3, 0, 0.5)
-%!error sprand (3, 3, -1)
-%!error sprand (3, 3, 2)
+%!error <M must be an integer greater than 0> sprand (ones (3), 3, 0.5)
+%!error <M must be an integer greater than 0> sprand (3.5, 3, 0.5)
+%!error <M must be an integer greater than 0> sprand (0, 3, 0.5)
+%!error <N must be an integer greater than 0> sprand (3, ones (3), 0.5)
+%!error <N must be an integer greater than 0> sprand (3, 3.5, 0.5)
+%!error <N must be an integer greater than 0> sprand (3, 0, 0.5)
+%!error <D must be between 0 and 1> sprand (3, 3, -1)
+%!error <D must be between 0 and 1> sprand (3, 3, 2)
+%!error <RC must be a scalar or vector> sprand (2, 2, 0.2, ones (3,3))
+%!error <RC must be between 0 and 1> sprand (2, 2, 0.2, -1)
+%!error <RC must be between 0 and 1> sprand (2, 2, 0.2, 2)
 
 %% Test very large, very low density matrix doesn't fail 
 %!test
-%! s = sprand(1e6,1e6,1e-7);
+%! s = sprand (1e6, 1e6, 1e-7);
 
--- a/scripts/sparse/sprandn.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/sparse/sprandn.m	Mon Jan 12 09:17:35 2015 -0800
@@ -21,25 +21,35 @@
 
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {} sprandn (@var{m}, @var{n}, @var{d})
+## @deftypefnx {Function File} {} sprandn (@var{m}, @var{n}, @var{d}, @var{rc})
 ## @deftypefnx {Function File} {} sprandn (@var{s})
-## Generate a random sparse matrix.  The size of the matrix will be
-## @var{m}x@var{n}, with a density of values given by @var{d}.  @var{d} must be
-## between 0 and 1 inclusive.  Values will be normally distributed with a mean
-## of zero and a variance of 1.
+## Generate a sparse matrix with normally distributed random values.
+##
+## The size of the matrix is @var{m}x@var{n} with a density of values @var{d}.
+## @var{d} must be between 0 and 1.  Values will be normally distributed with a
+## mean of 0 and a variance of 1.
 ##
-## If called with a single matrix argument, a random sparse matrix is
-## generated wherever the matrix @var{S} is non-zero.
-## @seealso{sprand, sprandsym, spones, sparse}
+## If called with a single matrix argument, a sparse matrix is generated with
+## random values wherever the matrix @var{s} is nonzero.
+##
+## If called with a scalar fourth argument @var{rc}, a random sparse matrix
+## with reciprocal condition number @var{rc} is generated.  If @var{rc} is
+## a vector, then it specifies the first singular values of the generated
+## matrix (@code{length (@var{rc}) <= min (@var{m}, @var{n})}).
+## 
+## @seealso{sprand, sprandsym, randn}
 ## @end deftypefn
 
 ## Author: Paul Kienzle <pkienzle@users.sf.net>
 
-function S = sprandn (m, n, d)
+function s = sprandn (m, n, d, rc)
 
   if (nargin == 1 )
-    S = __sprand_impl__ (m, @randn);
+    s = __sprand_impl__ (m, @randn);
   elseif ( nargin == 3)
-    S = __sprand_impl__ (m, n, d, "sprandn", @randn);
+    s = __sprand_impl__ (m, n, d, "sprandn", @randn);
+  elseif (nargin == 4)
+    s = __sprand_impl__ (m, n, d, rc, "sprandn", @randn);
   else
     print_usage ();
   endif
@@ -47,11 +57,25 @@
 endfunction
 
 
+%% Test 3-input calling form
 %!test
 %! s = sprandn (4, 10, 0.1);
 %! assert (size (s), [4, 10]);
 %! assert (nnz (s) / numel (s), 0.1);
 
+%% Test 4-input calling form
+%!test
+%! d = rand ();
+%! s1 = sprandn (100, 100, d, 0.4);
+%! rc = [5, 4, 3, 2, 1, 0.1];
+%! s2 = sprandn (100, 100, d, rc);
+%! s3 = sprandn (6, 4, d, rc);
+%! assert (svd (s2)'(1:length (rc)), rc, sqrt (eps)); 
+%! assert (1/cond (s1), 0.4, sqrt (eps));
+%! assert (nnz (s1) / (100*100), d, 0.02); 
+%! assert (nnz (s2) / (100*100), d, 0.02); 
+%! assert (svd (s3)', [5 4 3 2], sqrt (eps));
+
 %% Test 1-input calling form
 %!test
 %! s = sprandn (sparse ([1 2 3], [3 2 3], [2 2 2]));
@@ -63,16 +87,19 @@
 %!error sprandn ()
 %!error sprandn (1, 2)
 %!error sprandn (1, 2, 3, 4)
-%!error sprandn (ones (3), 3, 0.5)
-%!error sprandn (3.5, 3, 0.5)
-%!error sprandn (0, 3, 0.5)
-%!error sprandn (3, ones (3), 0.5)
-%!error sprandn (3, 3.5, 0.5)
-%!error sprandn (3, 0, 0.5)
-%!error sprandn (3, 3, -1)
-%!error sprandn (3, 3, 2)
+%!error <M must be an integer greater than 0> sprandn (ones (3), 3, 0.5)
+%!error <M must be an integer greater than 0> sprandn (3.5, 3, 0.5)
+%!error <M must be an integer greater than 0> sprandn (0, 3, 0.5)
+%!error <N must be an integer greater than 0> sprandn (3, ones (3), 0.5)
+%!error <N must be an integer greater than 0> sprandn (3, 3.5, 0.5)
+%!error <N must be an integer greater than 0> sprandn (3, 0, 0.5)
+%!error <D must be between 0 and 1> sprandn (3, 3, -1)
+%!error <D must be between 0 and 1> sprandn (3, 3, 2)
+%!error <RC must be a scalar or vector> sprandn (2, 2, 0.2, ones (3,3))
+%!error <RC must be between 0 and 1> sprandn (2, 2, 0.2, -1)
+%!error <RC must be between 0 and 1> sprandn (2, 2, 0.2, 2)
 
 %% Test very large, very low density matrix doesn't fail 
 %!test
-%! s = sprandn(1e6,1e6,1e-7);
+%! s = sprandn (1e6,1e6,1e-7);
 
--- a/scripts/sparse/sprandsym.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/sparse/sprandsym.m	Mon Jan 12 09:17:35 2015 -0800
@@ -27,7 +27,7 @@
 ## be normally distributed with a mean of zero and a variance of 1.
 ##
 ## If called with a single matrix argument, a random sparse matrix is generated
-## wherever the matrix @var{S} is non-zero in its lower triangular part.
+## wherever the matrix @var{S} is nonzero in its lower triangular part.
 ## @seealso{sprand, sprandn, spones, sparse}
 ## @end deftypefn
 
--- a/scripts/sparse/spstats.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/sparse/spstats.m	Mon Jan 12 09:17:35 2015 -0800
@@ -19,10 +19,10 @@
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {[@var{count}, @var{mean}, @var{var}] =} spstats (@var{S})
 ## @deftypefnx {Function File} {[@var{count}, @var{mean}, @var{var}] =} spstats (@var{S}, @var{j})
-## Return the stats for the non-zero elements of the sparse matrix @var{S}.
-## @var{count} is the number of non-zeros in each column, @var{mean}
-## is the mean of the non-zeros in each column, and @var{var} is the
-## variance of the non-zeros in each column.
+## Return the stats for the nonzero elements of the sparse matrix @var{S}.
+## @var{count} is the number of nonzeros in each column, @var{mean}
+## is the mean of the nonzeros in each column, and @var{var} is the
+## variance of the nonzeros in each column.
 ##
 ## Called with two input arguments, if @var{S} is the data and @var{j}
 ## is the bin number for the data, compute the stats for each bin.  In
@@ -50,7 +50,7 @@
     mean = sum (S) ./ count;
   endif
   if (nargout > 2)
-    ## FIXME Variance with count = 0 or 1?
+    ## FIXME: Variance with count = 0 or 1?
     diff = S - sparse (i, j, mean (j), n, m);
     var = sum (diff .* diff) ./ (count - 1);
   endif
--- a/scripts/sparse/svds.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/sparse/svds.m	Mon Jan 12 09:17:35 2015 -0800
@@ -169,7 +169,7 @@
       ## The eigenvalues returns by eigs for sigma=0 are symmetric about 0.
       ## As we are only interested in the positive eigenvalues, we have to
       ## double k and then throw out the k negative eigenvalues.
-      ## Separately, if sigma is non-zero, but smaller than the smallest
+      ## Separately, if sigma is nonzero, but smaller than the smallest
       ## singular value, ARPACK may not return k eigenvalues. However, as
       ## computation scales with k we'd like to avoid doubling k for all
       ## scalar values of sigma.
--- a/scripts/sparse/treeplot.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/sparse/treeplot.m	Mon Jan 12 09:17:35 2015 -0800
@@ -156,9 +156,9 @@
   ## of most left and most right descendants).
   x_coordinate = (x_coordinate_l + x_coordinate_r) / 2;
 
-  ## FIXME -- we should probably stuff all the arguments into a cell
-  ## array and make a single call to plot here so we can avoid
-  ## setting the hold state...
+  ## FIXME: We should probably stuff all the arguments into a cell
+  ##        array and make a single call to plot here so we can avoid
+  ##        setting the hold state...
 
   hold_is_on = ishold ();
   unwind_protect
--- a/scripts/specfun/bessel.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/specfun/bessel.m	Mon Jan 12 09:17:35 2015 -0800
@@ -31,24 +31,21 @@
 ##
 ## @item bessely
 ## Bessel functions of the second kind.  If the argument @var{opt} is supplied,
-## the result is multiplied by @code{exp (-abs (imag (x)))}.
+## the result is multiplied by @w{@code{exp (-abs (imag (x)))}}.
 ##
 ## @item besseli
 ## Modified Bessel functions of the first kind.  If the argument @var{opt} is
-## supplied,
-## the result is multiplied by @code{exp (-abs (real (x)))}.
+## supplied, the result is multiplied by @w{@code{exp (-abs (real (x)))}}.
 ##
 ## @item besselk
 ## Modified Bessel functions of the second kind.  If the argument @var{opt} is
-## supplied,
-## the result is multiplied by @code{exp (x)}.
+## supplied, the result is multiplied by @w{@code{exp (x)}}.
 ##
 ## @item besselh
-## Compute Hankel functions of the first (@var{k} = 1) or second (@var{k}
-## = 2) kind.  If the argument @var{opt} is supplied, the result is multiplied
-## by
-## @code{exp (-I*@var{x})} for @var{k} = 1 or @code{exp (I*@var{x})} for
-## @var{k} = 2.
+## Compute Hankel functions of the first (@var{k} = 1) or second (@var{k} = 2)
+## kind.  If the argument @var{opt} is supplied, the result is multiplied by
+## @w{@code{exp (-I*@var{x})}} for @var{k} = 1 or @w{@code{exp (I*@var{x})}}
+## for @var{k} = 2.
 ## @end table
 ##
 ## If @var{alpha} is a scalar, the result is the same size as @var{x}.
@@ -58,11 +55,10 @@
 ## @code{length (@var{alpha})} columns.  Otherwise, @var{alpha} and
 ## @var{x} must conform and the result will be the same size.
 ##
-## The value of @var{alpha} must be real.  The value of @var{x} may be
-## complex.
+## The value of @var{alpha} must be real.  The value of @var{x} may be complex.
 ##
-## If requested, @var{ierr} contains the following status information
-## and is the same size as the result.
+## If requested, @var{ierr} contains the following status information and is
+## the same size as the result.
 ##
 ## @enumerate 0
 ## @item
@@ -75,8 +71,8 @@
 ## Overflow, return @code{Inf}.
 ##
 ## @item
-## Loss of significance by argument reduction results in less than
-## half of machine accuracy.
+## Loss of significance by argument reduction results in less than half of
+## machine accuracy.
 ##
 ## @item
 ## Complete loss of significance by argument reduction, return @code{NaN}.
@@ -88,7 +84,7 @@
 ## @end deftypefn
 
 function bessel ()
-  error ("bessel: you must use besselj, bessely, besseli, or besselk");
+  error ("bessel: you must use besselj, bessely, besseli, besselk, or besselh");
 endfunction
 
 
--- a/scripts/specfun/beta.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/specfun/beta.m	Mon Jan 12 09:17:35 2015 -0800
@@ -18,7 +18,9 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Mapping Function} {} beta (@var{a}, @var{b})
-## For real inputs, return the Beta function,
+## Compute the Beta function for real inputs @var{a} and @var{b}. 
+##
+## The Beta function definition is
 ## @tex
 ## $$
 ##  B (a, b) = {\Gamma (a) \Gamma (b) \over \Gamma (a + b)}.
@@ -31,7 +33,12 @@
 ## @end example
 ##
 ## @end ifnottex
-## @seealso{betaln, betainc}
+##
+## The Beta function can grow quite large and it is often more useful to work
+## with the logarithm of the output rather than the function directly.
+## @xref{XREFbetaln,,betaln}, for computing the logarithm of the Beta function
+## in an efficient manner.
+## @seealso{betaln, betainc, betaincinv}
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
@@ -44,12 +51,10 @@
     print_usage ();
   endif
 
-  if (any (size (a) != size (b)) && numel (a) != 1 && numel (b) != 1)
-    error ("beta: inputs A and B have inconsistent sizes");
-  endif
-
   if (! isreal (a) || ! isreal (b))
-    error ("beta: inputs A and B must be real");
+    error ("beta: A and B must be real");
+  elseif (! size_equal (a, b) && numel (a) != 1 && numel (b) != 1)
+    error ("beta: A and B must have consistent sizes");
   endif
 
   retval = real (exp (gammaln (a) + gammaln (b) - gammaln (a+b)));
@@ -60,8 +65,8 @@
 %!test
 %! a = [1, 1.5, 2, 3];
 %! b = [4, 3, 2, 1];
-%! v1 = beta (a,b);
-%! v2 = beta (b,a);
+%! v1 = beta (a, b);
+%! v2 = beta (b, a);
 %! v3 = gamma (a).*gamma (b) ./ gamma (a+b);
 %! assert (v1, v2, sqrt (eps));
 %! assert (v2, v3, sqrt (eps));
@@ -82,4 +87,10 @@
 
 %!error beta ()
 %!error beta (1)
+%!error beta (1,2,3)
+%!error <A and B must be real> beta (1i, 2)
+%!error <A and B must be real> beta (2, 1i)
+%!error <A and B must have consistent sizes> beta ([1 2], [1 2 3])
+%!error <A and B must have consistent sizes> beta ([1 2 3], [1 2])
+%!error <A and B must have consistent sizes> beta ([1 2 3], [1 2 3]')
 
--- a/scripts/specfun/betaln.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/specfun/betaln.m	Mon Jan 12 09:17:35 2015 -0800
@@ -18,7 +18,10 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Mapping Function} {} betaln (@var{a}, @var{b})
-## Return the natural logarithm of the Beta function,
+## Compute the natural logarithm of the Beta function for real inputs @var{a}
+## and @var{b}.
+##
+## @code{betaln} is defined as
 ## @tex
 ## $$
 ##  {\rm betaln} (a, b) = \ln (B (a,b)) \equiv \ln ({\Gamma (a) \Gamma (b) \over \Gamma (a + b)}).
@@ -31,8 +34,11 @@
 ## @end example
 ##
 ## @end ifnottex
-## calculated in a way to reduce the occurrence of underflow.
-## @seealso{beta, betainc, gammaln}
+## and is calculated in a way to reduce the occurrence of underflow.
+##
+## The Beta function can grow quite large and it is often more useful to work
+## with the logarithm of the output rather than the function directly.
+## @seealso{beta, betainc, betaincinv, gammaln}
 ## @end deftypefn
 
 ## Author:   Nicol N. Schraudolph <nic@idsia.ch>
@@ -45,6 +51,12 @@
     print_usage ();
   endif
 
+  if (! isreal (a) || ! isreal (b))
+    error ("betaln: A and B must be real");
+  elseif (! size_equal (a, b) && numel (a) != 1 && numel (b) != 1)
+    error ("betaln: A and B must have consistent sizes");
+  endif
+
   retval = gammaln (a) + gammaln (b) - gammaln (a + b);
 
 endfunction
@@ -53,6 +65,12 @@
 %!assert (betaln (3,4), log (beta (3,4)), eps)
 
 %% Test input validation
-%!error (betaln (1))
-%!error (betaln (1,2,3))
+%!error betaln ()
+%!error betaln (1)
+%!error betaln (1,2,3)
+%!error <A and B must be real> betaln (1i, 2)
+%!error <A and B must be real> betaln (2, 1i)
+%!error <A and B must have consistent sizes> betaln ([1 2], [1 2 3])
+%!error <A and B must have consistent sizes> betaln ([1 2 3], [1 2])
+%!error <A and B must have consistent sizes> betaln ([1 2 3], [1 2 3]')
 
--- a/scripts/specfun/ellipke.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/specfun/ellipke.m	Mon Jan 12 09:17:35 2015 -0800
@@ -27,13 +27,58 @@
 ##
 ## @var{m} must be a scalar or real array with -Inf @leq{} @var{m} @leq{} 1.
 ##
-## The optional input @var{tol} is currently ignored (@sc{matlab} uses this
-## to allow a faster, less accurate approximation).
+## The optional input @var{tol} controls the stopping tolerance of the
+## algorithm and defaults to @code{eps (class (@var{m}))}.  The tolerance can
+## be increased to compute a faster, less accurate approximation.
 ##
-## Called with only one output, elliptic integrals of the first kind are
+## When called with one output only elliptic integrals of the first kind are
 ## returned.
 ##
-## Reference: Milton Abramowitz and Irene A. Stegun,
+## Mathematical Note:
+##
+## Elliptic integrals of the first kind are defined as
+##
+## @tex
+## $$
+## {\rm K} (m) = \int_0^1 {dt \over \sqrt{(1 - t^2) (1 - m^2 t^2)}}
+## $$
+## @end tex
+## @ifnottex
+##
+## @example
+## @group
+##          1
+##         /               dt
+## K (m) = | ------------------------------
+##         / sqrt ((1 - t^2)*(1 - m^2*t^2))
+##        0
+## @end group
+## @end example
+##
+## @end ifnottex
+##
+## Elliptic integrals of the second kind are defined as
+##
+## @tex
+## $$
+## {\rm E} (m) = \int_0^1 {\sqrt{1 - m^2 t^2} \over \sqrt{1 - t^2}} dt
+## $$
+## @end tex
+## @ifnottex
+##
+## @example
+## @group
+##          1
+##         /  sqrt (1 - m^2*t^2)
+## E (m) = |  ------------------ dt
+##         /  sqrt (1 - t^2)
+##        0
+## @end group
+## @end example
+##
+## @end ifnottex
+##
+## Reference: Milton @nospell{Abramowitz} and Irene A. @nospell{Stegun},
 ## @cite{Handbook of Mathematical Functions}, Chapter 17, Dover, 1965.
 ## @seealso{ellipj}
 ## @end deftypefn
@@ -42,20 +87,27 @@
 ## Author: Paul Kienzle <pkienzle@users.sf.net>
 ## Author: Jaakko Ruohio
 
-function [k, e] = ellipke (m)
+function [k, e] = ellipke (m, tol = [])
 
   if (nargin < 1 || nargin > 2)
     print_usage ();
   endif
 
+  sz = size (m);
   m = m(:);
   if (! isreal (m))
     error ("ellipke: M must be real");
   elseif (any (m > 1))
     error ("ellipke: M must be <= 1");
   endif
+ 
+  if (isempty (tol))
+    tol = eps (class (m));
+  elseif (! (isreal (tol) && isscalar (tol) && tol > 0))
+    error ("ellipke: TOL must be a real scalar > 0")
+  endif
 
-  k = e = zeros (size (m));
+  k = e = zeros (sz);
 
   ## Handle extreme values
   idx_1 = (m == 1);
@@ -84,11 +136,11 @@
     do
       t = (a + b)/2;
       c = (a - b)/2;
-      b = sqrt (a.*b);
+      b = sqrt (a .* b);
       a = t;
       f *= 2;
       sum += f*c.^2;
-    until (all (c./a < eps) || (++n > Nmax))
+    until (all (c./a < tol) || (++n > Nmax))
     if (n >= Nmax)
       error ("ellipke: algorithm did not converge in %d iterations", Nmax);
     endif
@@ -104,23 +156,17 @@
 ## Test complete elliptic functions of first and second kind
 ## against "exact" solution from Mathematica 3.0
 %!test
-%! m = [0.0; 0.01; 0.1; 0.5; 0.9; 0.99; 1.0];
+%! m = [0.0, 0.01; 0.1, 0.5; 0.9, 0.99; 1.0, 0.0];
 %! [k,e] = ellipke (m);
 %!
-%! k_exp = [1.5707963267948966192;
-%!          1.5747455615173559527;
-%!          1.6124413487202193982;
-%!          1.8540746773013719184;
-%!          2.5780921133481731882;
-%!          3.6956373629898746778;
-%!          Inf ];
-%! e_exp = [1.5707963267948966192;
-%!          1.5668619420216682912;
-%!          1.5307576368977632025;
-%!          1.3506438810476755025;
-%!          1.1047747327040733261;
-%!          1.0159935450252239356;
-%!          1.0 ];
+%! k_exp = [1.5707963267948966192, 1.5747455615173559527
+%!          1.6124413487202193982, 1.8540746773013719184
+%!          2.5780921133481731882, 3.6956373629898746778
+%!          Inf                  , 1.5707963267948966192 ];
+%! e_exp = [1.5707963267948966192, 1.5668619420216682912
+%!          1.5307576368977632025, 1.3506438810476755025
+%!          1.1047747327040733261, 1.0159935450252239356
+%!          1.0                  , 1.5707963267948966192 ];
 %! assert (k, k_exp, 8*eps);
 %! assert (e, e_exp, 8*eps);
 
@@ -175,4 +221,9 @@
 ## Test input validation
 %!error ellipke ()
 %!error ellipke (1,2,3)
+%!error <M must be real> ellipke (1i)
+%!error <M must be .= 1> ellipke (2)
+%!error <TOL must be a real scalar . 0> ellipke (1, i)
+%!error <TOL must be a real scalar . 0> ellipke (1, [1 1])
+%!error <TOL must be a real scalar . 0> ellipke (1, -1)
 
--- a/scripts/specfun/factor.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/specfun/factor.m	Mon Jan 12 09:17:35 2015 -0800
@@ -17,20 +17,20 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {@var{p} =} factor (@var{q})
-## @deftypefnx {Function File} {[@var{p}, @var{n}] =} factor (@var{q})
-##
-## Return the prime factorization of @var{q}.  That is,
-## @code{prod (@var{p}) == @var{q}} and every element of @var{p} is a prime
-## number.  If @code{@var{q} == 1}, return 1.
+## @deftypefn  {Function File} {@var{pf} =} factor (@var{q})
+## @deftypefnx {Function File} {[@var{pf}, @var{n}] =} factor (@var{q})
+## Return the prime factorization of @var{q}.
 ##
-## With two output arguments, return the unique primes @var{p} and
-## their multiplicities.  That is, @code{prod (@var{p} .^ @var{n}) ==
-## @var{q}}.
+## The prime factorization is defined as @code{prod (@var{pf}) == @var{q}}
+## where every element of @var{pf} is a prime number.  If @code{@var{q} == 1},
+## return 1.
+##
+## With two output arguments, return the unique prime factors @var{pf} and
+## their multiplicities.  That is, @code{prod (@var{pf} .^ @var{n}) == @var{q}}.
 ## 
-## Implementation Note: The input @var{q} must not be greater than
+## Implementation Note: The input @var{q} must be less than
 ## @code{bitmax} (9.0072e+15) in order to factor correctly.
-## @seealso{gcd, lcm, isprime}
+## @seealso{gcd, lcm, isprime, primes}
 ## @end deftypefn
 
 ## Author: Paul Kienzle
@@ -40,29 +40,29 @@
 ## * return multiplicity as suggested by Dirk Laurie
 ## * add error handling
 
-function [x, n] = factor (q)
+function [pf, n] = factor (q)
 
-  if (nargin < 1)
+  if (nargin != 1)
     print_usage ();
   endif
 
-  if (! isscalar (q) || q != fix (q))
-    error ("factor: Q must be a scalar integer");
+  if (! isreal (q) || ! isscalar (q) || q != fix (q))
+    error ("factor: Q must be a real integer");
   endif
 
   ## Special case of no primes less than sqrt(q).
   if (q < 4)
-    x = q;
+    pf = q;
     n = 1;
     return;
   endif
 
   q = double (q);  # For the time being, calcs rely on double precision var.
   qorig = q;
-  x = [];
+  pf = [];
   ## There is at most one prime greater than sqrt(q), and if it exists,
   ## it has multiplicity 1, so no need to consider any factors greater
-  ## than sqrt(q) directly. [If there were two factors p1, p2 > sqrt(q),
+  ## than sqrt(q) directly.  [If there were two factors p1, p2 > sqrt(q),
   ## then q >= p1*p2 > sqrt(q)*sqrt(q) == q. Contradiction.]
   p = primes (sqrt (q));
   while (q > 1)
@@ -72,24 +72,24 @@
       ## Can't be reduced further, so q must itself be a prime.
       p = q;
     endif
-    x = [x, p];
+    pf = [pf, p];
     ## Reduce q.
     q /= prod (p);
   endwhile
-  x = sort (x);
+  pf = sort (pf);
 
   ## Verify algorithm was succesful
-  q = prod (x);
+  q = prod (pf);
   if (q != qorig)
-    error ("factor: Input Q too large to factor");
+    error ("factor: Q too large to factor");
   elseif (q > bitmax)
-    warning ("factor: Input Q too large.  Answer is unreliable");
+    warning ("factor: Q too large.  Answer is unreliable");
   endif
 
   ## Determine muliplicity.
   if (nargout > 1)
-    idx = find ([0, x] != [x, 0]);
-    x = x(idx(1:length (idx)-1));
+    idx = find ([0, pf] != [pf, 0]);
+    pf = pf(idx(1:length (idx)-1));
     n = diff (idx);
   endif
 
@@ -99,16 +99,18 @@
 %!assert (factor (1), 1)
 %!test
 %! for i = 2:20
-%!   p = factor (i);
-%!   assert (prod (p), i);
-%!   assert (all (isprime (p)));
-%!   [p,n] = factor (i);
-%!   assert (prod (p.^n), i);
-%!   assert (all ([0,p] != [p,0]));
+%!   pf = factor (i);
+%!   assert (prod (pf), i);
+%!   assert (all (isprime (pf)));
+%!   [pf, n] = factor (i);
+%!   assert (prod (pf.^n), i);
+%!   assert (all ([0,pf] != [pf,0]));
 %! endfor
 
 %% Test input validation
 %!error factor ()
-%!error <Q must be a scalar integer> factor ([1,2])
-%!error <Q must be a scalar integer> factor (1.5)
+%!error factor (1,2)
+%!error <Q must be a real integer> factor (6i)
+%!error <Q must be a real integer> factor ([1,2])
+%!error <Q must be a real integer> factor (1.5)
 
--- a/scripts/specfun/factorial.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/specfun/factorial.m	Mon Jan 12 09:17:35 2015 -0800
@@ -18,28 +18,48 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} factorial (@var{n})
-## Return the factorial of @var{n} where @var{n} is a positive integer.  If
-## @var{n} is a scalar, this is equivalent to @code{prod (1:@var{n})}.  For
+## Return the factorial of @var{n} where @var{n} is a real non-negative integer.
+##
+## If @var{n} is a scalar, this is equivalent to @code{prod (1:@var{n})}.  For
 ## vector or matrix arguments, return the factorial of each element in the
-## array.  For non-integers see the generalized factorial function
-## @code{gamma}.
-## @seealso{prod, gamma}
+## array.
+##
+## For non-integers see the generalized factorial function @code{gamma}.
+## Note that the factorial function grows large quite quickly, and even
+## with double precision values overflow will occur if @var{n} > 171.  For
+## such cases consider @code{gammaln}.
+## @seealso{prod, gamma, gammaln}
 ## @end deftypefn
 
 function x = factorial (n)
+
   if (nargin != 1)
     print_usage ();
-  elseif (any (n(:) < 0 | n(:) != fix (n(:))))
-    error ("factorial: N must all be non-negative integers");
+  elseif (! isreal (n) || any (n(:) < 0 | n(:) != fix (n(:))))
+    error ("factorial: all N must be real non-negative integers");
   endif
+
   x = round (gamma (n+1));
+
+  ## FIXME: Matlab returns an output of the same type as the input.
+  ## This doesn't seem particularly worth copying--for example uint8 would
+  ## saturate for n > 5.  If desired, however, the following code could be
+  ## uncommented.
+  # if (! isfloat (x))
+  #   x = cast (x, class (n));
+  # endif
+
 endfunction
 
 
 %!assert (factorial (5), prod (1:5))
 %!assert (factorial ([1,2;3,4]), [1,2;6,24])
 %!assert (factorial (70), exp (sum (log (1:70))), -128*eps)
+%!assert (factorial (0), 1)
 
-%!fail ("factorial (5.5)", "must all be non-negative integers")
-%!fail ("factorial (-3)", "must all be non-negative integers")
+%!error factorial ()
+%!error factorial (1,2)
+%!error <must be real non-negative integers> factorial (2i)
+%!error <must be real non-negative integers> factorial (-3)
+%!error <must be real non-negative integers> factorial (5.5)
 
--- a/scripts/specfun/isprime.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/specfun/isprime.m	Mon Jan 12 09:17:35 2015 -0800
@@ -22,8 +22,21 @@
 ## Return a logical array which is true where the elements of @var{x} are
 ## prime numbers and false where they are not.
 ##
-## If the maximum value in @var{x} is very large, then you should be using
-## special purpose factorization code.
+## A prime number is conventionally defined as a positive integer greater than
+## 1 (e.g., 2, 3, @dots{}) which is divisible only by itself and 1.  Octave
+## extends this definition to include both negative integers and complex
+## values.  A negative integer is prime if its positive counterpart is prime.
+## This is equivalent to @code{isprime (abs (x))}.
+## 
+## If @code{class (@var{x})} is complex, then primality is tested in the domain
+## of Gaussian integers (@url{http://en.wikipedia.org/wiki/Gaussian_integer}).
+## Some non-complex integers are prime in the ordinary sense, but not in the
+## domain of Gaussian integers.  For example, @math{5 = (1+2i)*(1-2i)} shows
+## that 5 is not prime because it has a factor other than itself and 1.
+## Exercise caution when testing complex and real values together in the same
+## matrix.
+##
+## Examples:
 ##
 ## @example
 ## @group
@@ -31,59 +44,129 @@
 ##     @result{} [0, 1, 1, 0, 1, 0]
 ## @end group
 ## @end example
+##
+## @example
+## @group
+## isprime ([i, 2, 3, 5])
+##     @result{} [0, 0, 1, 0]
+## @end group
+## @end example
+##
+## Programming Note: @code{isprime} is appropriate if the maximum value in
+## @var{x} is not too large (< 1e15).  For larger values special purpose
+## factorization code should be used.
+##
+## Compatibility Note: @var{matlab} does not extend the definition of prime
+## numbers and will produce an error if given negative or complex inputs.
 ## @seealso{primes, factor, gcd, lcm}
 ## @end deftypefn
 
 function t = isprime (x)
 
-  if (nargin == 1)
-    if (any ((x != floor (x) | x < 0)(:)))
-      error ("isprime: needs positive integers");
-    endif
-    maxn = max (x(:));
-    ## generate prime table of suitable length.
-    maxp = min (maxn, max (sqrt (maxn), 1e7)); # FIXME: threshold not optimized.
-    pr = primes (maxp);
-    ## quick search for table matches.
-    t = lookup (pr, x, "b");
-    ## take the rest.
-    m = x(x > maxp);
-    if (! isempty (m))
-      ## there are still possible primes. filter them out by division.
-      if (maxn <= intmax ("uint32"))
-        m = uint32 (m);
-      elseif (maxn <= intmax ("uint64"))
-        m = uint64 (m);
-      else
-        warning ("isprime: too large integers being tested");
-      endif
-      pr = cast (pr(pr <= sqrt (maxn)), class (m));
-      for p = pr
-        m = m(rem (m, p) != 0);
-        if (length (m) < length (pr) / 10)
-          break;
-        endif
-      endfor
-      pr = pr(pr > p);
-      mm = arrayfun (@(x) all (rem (x, pr)), m);
-      m = m(mm);
-      if (! isempty (m))
-        m = cast (sort (m), class (x));
-        t |= lookup (m, x, "b");
-      endif
+  if (nargin != 1)
+    print_usage ();
+  elseif (any (fix (x) != x))
+    error ("isprime: X contains non-integer entries");
+  endif
+
+  if (isempty (x))
+    t = x;
+    return;
+  endif
+
+  if (iscomplex (x))
+    t = isgaussianprime (x);
+    return;
+  endif
+
+  ## Code strategy is to build a table with the list of possible primes
+  ## and then quickly compare entries in x with the table of primes using
+  ## lookup().  The table size is limited to save memory and computation
+  ## time during its creation.  All entries larger than the maximum in the
+  ## table are checked by straightforward division.
+
+  x = abs (x);              # handle negative entries
+  maxn = max (x(:));
+  ## generate prime table of suitable length.
+  ## 1e7 threshold requires ~0.15 seconds of computation, 1e8 requires 1.8.
+  maxp = min (maxn, max (sqrt (maxn), 1e7));
+  pr = primes (maxp);
+  t = lookup (pr, x, "b");  # quick search for table matches.
+
+  ## process any remaining large entries
+  m = x(x > maxp);
+  if (! isempty (m))
+    if (maxn <= intmax ("uint32"))
+      m = uint32 (m);
+    elseif (maxn <= intmax ("uint64"))
+      m = uint64 (m);
+    else
+      warning ("isprime: X contains integers too large to be tested");
     endif
 
-  else
-    print_usage ();
+    ## Start by dividing through by the small primes until the remaining
+    ## list of entries is small (and most likely prime themselves).
+    pr = cast (pr(pr <= sqrt (maxn)), class (m));
+    for p = pr
+      m = m(rem (m, p) != 0);
+      if (numel (m) < numel (pr) / 10)
+        break;
+      endif
+    endfor
+
+    ## Check the remaining list of possible primes against the
+    ## remaining prime factors which were not tested in the for loop.
+    ## This is just an optimization to use arrayfun over for loo
+    pr = pr(pr > p);
+    mm = arrayfun (@(x) all (rem (x, pr)), m);
+    m = m(mm);
+
+    ## Add any remaining entries, which are truly prime, to the results.
+    if (! isempty (m))
+      m = cast (sort (m), class (x));
+      t |= lookup (m, x, "b");
+    endif
   endif
 
 endfunction
 
+function t = isgaussianprime (z)
+  ## Assume prime unless proven otherwise
+  t = true (size (z));
+
+  x = real (z);
+  y = imag (z);
+
+  ## If purely real or purely imaginary, ordinary prime test for
+  ## that complex part if that part is 3 mod 4.
+  xidx = y==0 & mod (x, 4) == 3;
+  yidx = x==0 & mod (y, 4) == 3;
+
+  t(xidx) &= isprime (x(xidx));
+  t(yidx) &= isprime (y(yidx));
+
+  ## Otherwise, prime if x^2 + y^2 is prime
+  zidx = ! (xidx | yidx);          # Skip entries that were already evaluated
+  zabs = x(zidx).^2 + y(zidx).^2;
+  t(zidx) &= isprime (zabs);
+endfunction
+
 
 %!assert (isprime (3), true)
 %!assert (isprime (4), false)
+%!assert (isprime (5i), false)
+%!assert (isprime (7i), true)
+%!assert (isprime ([1+2i, (2+3i)*(-1+2i)]), [true, false])
+%!assert (isprime (-2), true)
+%!assert (isprime (complex (-2)), false)
+%!assert (isprime (2i), false)
+%!assert (isprime ([i, 2, 3, 5]), [false, false, true, false])
+%!assert (isprime (0), false)
 %!assert (isprime (magic (3)), logical ([0, 0, 0; 1, 1, 1; 0, 0, 1]))
 
+%% Test input validation
 %!error isprime ()
 %!error isprime (1, 2)
+%!error <X contains non-integer entries> isprime (0.5i)
+%!error <X contains non-integer entries> isprime (0.5)
 
--- a/scripts/specfun/lcm.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/specfun/lcm.m	Mon Jan 12 09:17:35 2015 -0800
@@ -19,10 +19,11 @@
 ## -*- texinfo -*-
 ## @deftypefn  {Mapping Function} {} lcm (@var{x}, @var{y})
 ## @deftypefnx {Mapping Function} {} lcm (@var{x}, @var{y}, @dots{})
-## Compute the least common multiple of @var{x} and @var{y},
-## or of the list of all arguments.  All elements must be the same size or
-## scalar.
-## @seealso{factor, gcd}
+## Compute the least common multiple of @var{x} and @var{y}, or of the list of
+## all arguments.
+##
+## All elements must be numeric and of the same size or scalar.
+## @seealso{factor, gcd, isprime}
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
@@ -31,31 +32,31 @@
 
 function l = lcm (varargin)
 
-  if (nargin > 1)
-    if (common_size (varargin{:}) != 0)
-      error ("lcm: all args must be of the same size or scalar");
-    elseif (! all (cellfun ("isnumeric", varargin)))
-      error ("lcm: all arguments must be numeric");
-    endif
-
-    l = varargin{1};
-    for i = 2:nargin
-      x = varargin{i};
-      msk = l == 0 & x == 0;
-      l .*= x ./ gcd (l, x);
-      l(msk) = 0;
-    endfor
-  else
+  if (nargin < 2)
     print_usage ();
   endif
 
+  if (common_size (varargin{:}) != 0)
+    error ("lcm: all args must be the same size or scalar");
+  elseif (! all (cellfun ("isnumeric", varargin)))
+    error ("lcm: all arguments must be numeric");
+  endif
+
+  l = varargin{1};
+  for i = 2:nargin
+    x = varargin{i};
+    msk = (l == 0 & x == 0);
+    l .*= x ./ gcd (l, x);
+    l(msk) = 0;
+  endfor
+
 endfunction
 
 
 %!assert (lcm (3, 5, 7, 15), 105)
 
-%!error lcm ();
-%!test
-%! s.a = 1;
-%! fail ("lcm (s)");
+%!error lcm ()
+%!error lcm (1)
+%!error <same size or scalar> lcm ([1 2], [1 2 3])
+%!error <arguments must be numeric> lcm ([1 2], {1 2})
 
--- a/scripts/specfun/legendre.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/specfun/legendre.m	Mon Jan 12 09:17:35 2015 -0800
@@ -21,15 +21,19 @@
 ## @deftypefn  {Function File} {@var{l} =} legendre (@var{n}, @var{x})
 ## @deftypefnx {Function File} {@var{l} =} legendre (@var{n}, @var{x}, @var{normalization})
 ## Compute the Legendre function of degree @var{n} and order
-## @var{m} = 0 @dots{} N@.  The optional argument, @var{normalization},
-## may be one of @qcode{"unnorm"}, @qcode{"sch"}, or @qcode{"norm"}.
-## The default is @qcode{"unnorm"}.  The value of @var{n} must be a
-## non-negative scalar integer.
+## @var{m} = 0 @dots{} @var{n}.
+##
+## The value @var{n} must be a real non-negative integer.  @var{x} is a
+## vector with real-valued elements in the range [-1, 1].
 ##
-## If the optional argument @var{normalization} is missing or is
-## @qcode{"unnorm"}, compute the Legendre function of degree @var{n} and
-## order @var{m} and return all values for @var{m} = 0 @dots{} @var{n}.
-## The return value has one dimension more than @var{x}.
+## The optional argument @var{normalization} may be one of @qcode{"unnorm"},
+## @qcode{"sch"}, or @qcode{"norm"}.  The default if no normalization is given
+## is @qcode{"unnorm"}.
+##
+## When the optional argument @var{normalization} is @qcode{"unnorm"}, compute
+## the Legendre function of degree @var{n} and order @var{m} and return all
+## values for @var{m} = 0 @dots{} @var{n}.  The return value has one dimension
+## more than @var{x}.
 ##
 ## The Legendre Function of degree @var{n} and order @var{m}:
 ##
@@ -42,7 +46,7 @@
 ##
 ## @example
 ## @group
-##  m        m       2  m/2   d^m
+##  m         m      2  m/2   d^m
 ## P(x) = (-1) * (1-x  )    * ----  P(x)
 ##  n                         dx^m   n
 ## @end group
@@ -84,12 +88,12 @@
 ## @end group
 ## @end example
 ##
-## If the optional argument @code{normalization} is @qcode{"sch"},
+## When the optional argument @code{normalization} is @qcode{"sch"},
 ## compute the Schmidt semi-normalized associated Legendre function.
 ## The Schmidt semi-normalized associated Legendre function is related
 ## to the unnormalized Legendre functions by the following:
 ##
-## For Legendre functions of degree n and order 0:
+## For Legendre functions of degree @var{n} and order 0:
 ##
 ## @tex
 ## $$
@@ -127,7 +131,7 @@
 ##
 ## @end ifnottex
 ##
-## If the optional argument @var{normalization} is @qcode{"norm"},
+## When the optional argument @var{normalization} is @qcode{"norm"},
 ## compute the fully normalized associated Legendre function.
 ## The fully normalized associated Legendre function is related
 ## to the unnormalized Legendre functions by the following:
@@ -162,11 +166,9 @@
     print_usage ();
   endif
 
-  if (!isscalar (n) || n < 0 || n != fix (n))
-    error ("legendre: N must be a non-negative scalar integer");
-  endif
-
-  if (!isreal (x) || any (x(:) < -1 | x(:) > 1))
+  if (! isreal (n) || ! isscalar (n) || n < 0 || n != fix (n))
+    error ("legendre: N must be a real non-negative integer");
+  elseif (! isreal (x) || any (x(:) < -1 | x(:) > 1))
     error ("legendre: X must be real-valued vector in the range -1 <= X <= 1");
   endif
 
@@ -176,15 +178,17 @@
     normalization = "unnorm";
   endif
 
+  unnorm = false;
   switch (normalization)
+    case "unnorm"
+      scale = 1;
+      unnorm = true;
     case "norm"
       scale = sqrt (n+0.5);
     case "sch"
       scale = sqrt (2);
-    case "unnorm"
-      scale = 1;
     otherwise
-      error ('legendre: expecting NORMALIZATION option to be "norm", "sch", or "unnorm"');
+      error ('legendre: NORMALIZATION option must be "unnorm", "norm", or "sch"');
   endswitch
 
   scale = scale * ones (size (x));
@@ -204,11 +208,11 @@
     for k = m+1:n
       lpm3a = (2*k-1) .* x .* lpm2;
       lpm3b = (k+m-2) .* lpm1;
-      lpm3 = (lpm3a - lpm3b)/(k-m+1);
+      lpm3 = (lpm3a - lpm3b) / (k-m+1);
       lpm1 = lpm2;
       lpm2 = lpm3;
       if (! warned_overflow)
-        if (any (abs (lpm3a) > realmax)
+        if (   any (abs (lpm3a) > realmax)
             || any (abs (lpm3b) > realmax)
             || any (abs (lpm3)  > realmax))
           overflow = true;
@@ -216,24 +220,23 @@
       endif
     endfor
     retval(m,:) = lpm3(:);
-    if (strcmp (normalization, "unnorm"))
-      scale = -scale * (2*m-1);
-    else
-      ## normalization == "sch" or normalization == "norm"
-      scale = scale / sqrt ((n-m+1)*(n+m))*(2*m-1);
+    if (unnorm)
+      scale *= -(2*m-1);
+    else  # normalization = "sch" or "norm"
+      scale *= (2*m-1) / sqrt ((n-m+1)*(n+m));
     endif
-    scale = scale .* sqrt (1-x.^2);
+    scale .*= sqrt (1-x.^2);
   endfor
 
   retval(n+1,:) = scale(:);
 
   if (isvector (x))
-  ## vector case is special
+    ## vector case is special
     retval = reshape (retval, n + 1, length (x));
   endif
 
   if (strcmp (normalization, "sch"))
-    retval(1,:) = retval(1,:) / sqrt (2);
+    retval(1,:) ./= sqrt (2);
   endif
 
   if (overflow && ! warned_overflow)
@@ -289,8 +292,8 @@
 %! assert (result, full (ones (1,11)));
 
 %!test
+%! ## Test matrix input
 %! result = legendre (3, [-1,0,1;1,0,-1]);
-%! ## Test matrix input
 %! expected(:,:,1) = [-1,1;0,0;0,0;0,0];
 %! expected(:,:,2) = [0,0;1.5,1.5;0,0;-15,-15];
 %! expected(:,:,3) = [1,-1;0,0;0,0;0,0];
@@ -306,11 +309,12 @@
 %!error legendre ()
 %!error legendre (1)
 %!error legendre (1,2,3,4)
-%!error legendre ([1, 2], [-1, 0, 1])
-%!error legendre (-1, [-1, 0, 1])
-%!error legendre (1.1, [-1, 0, 1])
-%!error legendre (1, [-1+i, 0, 1])
-%!error legendre (1, [-2, 0, 1])
-%!error legendre (1, [-1, 0, 2])
-%!error legendre (1, [-1, 0, 1], "badnorm")
+%!error <must be a real non-negative integer> legendre (i, [-1, 0, 1])
+%!error <must be a real non-negative integer> legendre ([1, 2], [-1, 0, 1])
+%!error <must be a real non-negative integer> legendre (-1, [-1, 0, 1])
+%!error <must be a real non-negative integer> legendre (1.1, [-1, 0, 1])
+%!error <must be real-valued vector> legendre (1, [-1+i, 0, 1])
+%!error <in the range -1 .= X .= 1> legendre (1, [-2, 0, 1])
+%!error <in the range -1 .= X .= 1> legendre (1, [-1, 0, 2])
+%!error <NORMALIZATION option must be> legendre (1, [-1, 0, 1], "badnorm")
 
--- a/scripts/specfun/nchoosek.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/specfun/nchoosek.m	Mon Jan 12 09:17:35 2015 -0800
@@ -21,7 +21,8 @@
 ## @deftypefn  {Function File} {@var{c} =} nchoosek (@var{n}, @var{k})
 ## @deftypefnx {Function File} {@var{c} =} nchoosek (@var{set}, @var{k})
 ##
-## Compute the binomial coefficient or all combinations of a set of items.
+## Compute the binomial coefficient of @var{n} or list all possible
+## combinations of a @var{set} of items.
 ##
 ## If @var{n} is a scalar then calculate the binomial coefficient
 ## of @var{n} and @var{k} which is defined as
@@ -75,10 +76,10 @@
 ## @end group
 ## @end example
 ##
-## @code{nchoosek} works only for non-negative, integer arguments.  Use
-## @code{bincoeff} for non-integer and negative scalar arguments, or for
-## computing many binomial coefficients at once with vector inputs
-## for @var{n} or @var{k}.
+## Programming Note: When calculating the binomial coefficient @code{nchoosek}
+## works only for non-negative, integer arguments.  Use @code{bincoeff} for
+## non-integer and negative scalar arguments, or for computing many binomial
+## coefficients at once with vector inputs for @var{n} or @var{k}.
 ##
 ## @seealso{bincoeff, perms}
 ## @end deftypefn
@@ -87,16 +88,17 @@
 ## Author: Paul Kienzle <pkienzle@users.sf.net>
 ## Author: Jaroslav Hajek
 
-function A = nchoosek (v, k)
+function C = nchoosek (v, k)
 
   if (nargin != 2
-      || !isnumeric (k) || !isnumeric (v)
-      || !isscalar (k) || ! (isscalar (v) || isvector (v)))
+      || ! (isreal (k) && isscalar (k))
+      || ! (isnumeric (v) && isvector (v)))
     print_usage ();
   endif
-  if (k < 0 || k != fix (k)
-      || (isscalar (v) && (v < k || v < 0 || v != fix (v))))
-    error ("nchoosek: args are non-negative integers with V not less than K");
+  if (k < 0 || k != fix (k))
+    error ("nchoosek: K must be an integer >= 0");
+  elseif (isscalar (v) && (iscomplex (v) || v < k || v < 0 || v != fix (v)))
+    error ("nchoosek: N must be a non-negative integer >= K");
   endif
 
   n = length (v);
@@ -104,54 +106,60 @@
   if (n == 1)
     ## Improve precision at next step.
     k = min (k, v-k);
-    A = round (prod ((v-k+1:v)./(1:k)));
-    if (A*2*k*eps >= 0.5)
-      warning ("nchoosek", "nchoosek: possible loss of precision");
+    C = round (prod ((v-k+1:v)./(1:k)));
+    if (C*2*k*eps >= 0.5)
+      warning ("nchoosek: possible loss of precision");
     endif
   elseif (k == 0)
-    A = [];
+    C = zeros (1,0);
   elseif (k == 1)
-    A = v(:);
+    C = v(:);
   elseif (k == n)
-    A = v(:).';
+    C = v(:).';
   elseif (k > n)
-    A = zeros (0, k, class (v));
+    C = zeros (0, k, class (v));
   elseif (k == 2)
     ## Can do it without transpose.
     x = repelems (v(1:n-1), [1:n-1; n-1:-1:1]).';
     y = cat (1, cellslices (v(:), 2:n, n*ones (1, n-1)){:});
-    A = [x, y];
+    C = [x, y];
   elseif (k < n)
     v = v(:).';
-    A = v(k:n);
+    C = v(k:n);
     l = 1:n-k+1;
     for j = 2:k
-      c = columns (A);
-      cA = cellslices (A, l, c*ones (1, n-k+1), 2);
+      c = columns (C);
+      cA = cellslices (C, l, c*ones (1, n-k+1), 2);
       l = c-l+1;
       b = repelems (v(k-j+1:n-j+1), [1:n-k+1; l]);
-      A = [b; cA{:}];
+      C = [b; cA{:}];
       l = cumsum (l);
       l = [1, 1 + l(1:n-k)];
     endfor
-    clear cA b;
-    A = A.';
+    C = C.';
   endif
+
 endfunction
 
 
 %!assert (nchoosek (80,10), bincoeff (80,10))
 %!assert (nchoosek (1:5,3), [1:3;1,2,4;1,2,5;1,3,4;1,3,5;1,4,5;2:4;2,3,5;2,4,5;3:5])
+%!assert (size (nchoosek (1:5,0)), [1 0])
 
 %% Test input validation
-%!warning nchoosek (100,45);
+%!error nchoosek ()
+%!error nchoosek (1)
+%!error nchoosek (1,2,3)
+
+%!error nchoosek (100, 2i)
+%!error nchoosek (100, [2 3])
 %!error nchoosek ("100", 45)
-%!error nchoosek (100, "45")
-%!error nchoosek (100, ones (2,2))
-%!error nchoosek (repmat (100, [2 2]), 45)
-%!error nchoosek (100, -45)
-%!error nchoosek (100, 45.5)
-%!error nchoosek (100, 145)
-%!error nchoosek (-100, 45)
-%!error nchoosek (100.5, 45)
+%!error nchoosek (100*ones (2, 2), 45)
+%!error <K must be an integer .= 0> nchoosek (100, -45)
+%!error <K must be an integer .= 0> nchoosek (100, 45.5)
+%!error <N must be a non-negative integer .= K> nchoosek (100i, 2)
+%!error <N must be a non-negative integer .= K> nchoosek (100, 145)
+%!error <N must be a non-negative integer .= K> nchoosek (-100, 45)
+%!error <N must be a non-negative integer .= K> nchoosek (100.5, 45)
+%!warning <possible loss of precision> nchoosek (100, 45);
 
--- a/scripts/specfun/nthroot.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/specfun/nthroot.m	Mon Jan 12 09:17:35 2015 -0800
@@ -23,8 +23,13 @@
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} nthroot (@var{x}, @var{n})
 ##
-## Compute the n-th root of @var{x}, returning real results for real
-## components of @var{x}.  For example:
+## Compute the real (non-complex) @var{n}-th root of @var{x}.
+##
+## @var{x} must have all real entries and @var{n} must be a scalar.
+## If @var{n} is an even integer and @var{x} has negative entries then
+## @code{nthroot} aborts and issues an error.
+##
+## Example:
 ##
 ## @example
 ## @group
@@ -34,10 +39,6 @@
 ## @result{} 0.50000 - 0.86603i
 ## @end group
 ## @end example
-##
-## @var{x} must have all real entries.  @var{n} must be a scalar.
-## If @var{n} is an even integer and @var{X} has negative entries, an
-## error is produced.
 ## @seealso{realsqrt, sqrt, cbrt}
 ## @end deftypefn
 
@@ -47,12 +48,12 @@
     print_usage ();
   endif
 
-  if (any (iscomplex (x(:))))
+  if (iscomplex (x))
     error ("nthroot: X must not contain complex values");
   endif
 
-  if (! isscalar (n) || n == 0)
-    error ("nthroot: N must be a nonzero scalar");
+  if (! isreal (n) || ! isscalar (n) || n == 0)
+    error ("nthroot: N must be a real nonzero scalar");
   endif
 
   if (n == 3)
@@ -63,37 +64,48 @@
     y = 1 ./ nthroot (x, -n);
   else
     ## Compute using power.
-    if (n == fix (n) && mod (n, 2) == 1)
+    integer_n = n == fix (n);
+    if (integer_n && mod (n, 2) == 1)
       y = abs (x) .^ (1/n) .* sign (x);
     elseif (any (x(:) < 0))
-      error ("nthroot: if X contains negative values, N must be an odd integer");
+      error ("nthroot: N must be an odd integer if X contains negative values");
     else
       y = x .^ (1/n);
     endif
 
-    if (finite (n) && n > 0 && n == fix (n))
-      ## Correction.
-      y = ((n-1)*y + x ./ (y.^(n-1))) / n;
-      y = merge (finite (y), y, x);
+    if (integer_n && n > 0 && isfinite (n))
+      if (isscalar (y) && y == 0)
+        ## Don't apply correction which leads to division by zero (bug #43492)
+      else
+        ## FIXME: What is this correction for?
+        y = ((n-1)*y + x ./ (y.^(n-1))) / n;
+        y = merge (isfinite (y), y, x);
+      endif
     endif
-
   endif
 
 endfunction
 
 
-%!assert (nthroot (-32,5), -2);
-%!assert (nthroot (81,4), 3);
-%!assert (nthroot (Inf,4), Inf);
-%!assert (nthroot (-Inf,7), -Inf);
-%!assert (nthroot (-Inf,-7), 0);
+%!assert (nthroot (-32, 5), -2)
+%!assert (nthroot (81, 4), 3)
+%!assert (nthroot (Inf, 4), Inf)
+%!assert (nthroot (-Inf, 7), -Inf)
+%!assert (nthroot (-Inf, -7), 0)
+
+## Bug #43492.  This should not generate a division by zero warning
+%!test
+%! warnmsg = lastwarn ();
+%! assert (nthroot (0, 2), 0);
+%! assert (lastwarn (), warnmsg);
 
 %% Test input validation
-%!error (nthroot ())
-%!error (nthroot (1))
-%!error (nthroot (1,2,3))
-%!error (nthroot (1+j,2))
-%!error (nthroot (1,[1 2]))
-%!error (nthroot (1,0))
-%!error (nthroot (-1,2))
+%!error nthroot ()
+%!error nthroot (1)
+%!error nthroot (1,2,3)
+%!error <X must not contain complex values> nthroot (1+j, 2)
+%!error <N must be a real nonzero scalar> nthroot (1, i)
+%!error <N must be a real nonzero scalar> nthroot (1, [1 2])
+%!error <N must be a real nonzero scalar> nthroot (1, 0)
+%!error <N must be an odd integer> nthroot (-1, 2)
 
--- a/scripts/specfun/perms.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/specfun/perms.m	Mon Jan 12 09:17:35 2015 -0800
@@ -19,15 +19,17 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} perms (@var{v})
+## Generate all permutations of @var{v} with one row per permutation.
 ##
-## Generate all permutations of @var{v}, one row per permutation.  The
-## result has size @code{factorial (@var{n}) * @var{n}}, where @var{n}
+## The result has size @code{factorial (@var{n}) * @var{n}}, where @var{n}
 ## is the length of @var{v}.
 ##
-## As an example, @code{perms ([1, 2, 3])} returns the matrix
+## Example
 ##
 ## @example
 ## @group
+## perms ([1, 2, 3])
+## @result{}
 ##   1   2   3
 ##   2   1   3
 ##   1   3   2
@@ -36,12 +38,18 @@
 ##   3   2   1
 ## @end group
 ## @end example
+##
+## Programming Note: The maximum length of @var{v} should be less than or
+## equal to 10 to limit memory consumption.
+## @seealso{permute, randperm, nchoosek}
 ## @end deftypefn
 
 function A = perms (v)
+
   if (nargin != 1)
     print_usage ();
   endif
+
   vidx = uint8 ([1:length(v)]');
   n = length (vidx);
 
@@ -62,7 +70,9 @@
       endfor
     endfor
   endif
+
   A = v(p);
+
 endfunction
 
 
--- a/scripts/specfun/pow2.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/specfun/pow2.m	Mon Jan 12 09:17:35 2015 -0800
@@ -17,9 +17,9 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Mapping Function} {} pow2 (@var{x})
-## @deftypefnx {Mapping Function} {} pow2 (@var{f}, @var{e})
-## With one argument, computes
+## @deftypefn  {Function File} {} pow2 (@var{x})
+## @deftypefnx {Function File} {} pow2 (@var{f}, @var{e})
+## With one input argument, compute
 ## @tex
 ## $2^x$
 ## @end tex
@@ -28,14 +28,14 @@
 ## @end ifnottex
 ## for each element of @var{x}.
 ##
-## With two arguments, returns
+## With two input arguments, return
 ## @tex
 ## $f \cdot 2^e$.
 ## @end tex
 ## @ifnottex
 ## f .* (2 .^ e).
 ## @end ifnottex
-## @seealso{log2, nextpow2}
+## @seealso{log2, nextpow2, power}
 ## @end deftypefn
 
 ## Author: AW <Andreas.Weingessel@ci.tuwien.ac.at>
@@ -67,4 +67,5 @@
 %! assert (pow2 (x,y), z, sqrt (eps));
 
 %!error pow2 ()
+%!error pow2 (1,2,3)
 
--- a/scripts/specfun/primes.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/specfun/primes.m	Mon Jan 12 09:17:35 2015 -0800
@@ -18,12 +18,13 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} primes (@var{n})
-##
 ## Return all primes up to @var{n}.
 ##
-## The algorithm used is the Sieve of Eratosthenes.
+## The output data class (double, single, uint32, etc.) is the same as
+## the input class of @var{n}.  The algorithm used is the Sieve of
+## Eratosthenes.
 ##
-## Note that if you need a specific number of primes you can use the
+## Notes: If you need a specific number of primes you can use the
 ## fact that the distance from one prime to the next is, on average,
 ## proportional to the logarithm of the prime.  Integrating, one finds
 ## that there are about @math{k} primes less than
@@ -33,6 +34,9 @@
 ## @ifnottex
 ## k*log (5*k).
 ## @end ifnottex
+##
+## See also @code{list_primes} if you need a specific number @var{n} of
+## primes.
 ## @seealso{list_primes, isprime}
 ## @end deftypefn
 
@@ -40,7 +44,7 @@
 ## Author: Francesco Potortì
 ## Author: Dirk Laurie
 
-function x = primes (n)
+function p = primes (n)
 
   if (nargin != 1)
     print_usage ();
@@ -50,9 +54,9 @@
     error ("primes: N must be a scalar");
   endif
 
-  if (n > 100000)
+  if (n > 100e3)
     ## Optimization: 1/6 less memory, and much faster (asymptotically)
-    ## 100000 happens to be the cross-over point for Paul's machine;
+    ## 100K happens to be the cross-over point for Paul's machine;
     ## below this the more direct code below is faster.  At the limit
     ## of memory in Paul's machine, this saves .7 seconds out of 7 for
     ## n = 3e6.  Hardly worthwhile, but Dirk reports better numbers.
@@ -71,8 +75,8 @@
         sievem(5*i+1:6*i+1:lenm) = false;
       endif
     endfor
-    x = sort ([2, 3, 6*find(sievem)-1, 6*find(sievep)+1]);
-  elseif (n > 352)                # nothing magical about 352; must be >2
+    p = sort ([2, 3, 6*find(sievem)-1, 6*find(sievep)+1]);
+  elseif (n > 352)                # nothing magical about 352; must be > 2
     len = floor ((n-1)/2);        # length of the sieve
     sieve = true (1, len);        # assume every odd number is prime
     for i = 1:(sqrt (n)-1)/2      # check up to sqrt (n)
@@ -80,7 +84,7 @@
         sieve(3*i+1:2*i+1:len) = false; # do it
       endif
     endfor
-    x = [2, 1+2*find(sieve)];     # primes remaining after sieve
+    p = [2, 1+2*find(sieve)];     # primes remaining after sieve
   else
     a = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, ...
          53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, ...
@@ -88,7 +92,11 @@
          173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, ...
          233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, ...
          293, 307, 311, 313, 317, 331, 337, 347, 349];
-    x = a(a <= n);
+    p = a(a <= n);
+  endif
+
+  if (! isa (n, "double"))
+    cast (p, class (n));
   endif
 
 endfunction
@@ -99,4 +107,5 @@
 
 %!error primes ()
 %!error primes (1, 2)
+%!error <N must be a scalar> primes (ones (2,2))
 
--- a/scripts/specfun/reallog.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/specfun/reallog.m	Mon Jan 12 09:17:35 2015 -0800
@@ -18,12 +18,15 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} reallog (@var{x})
-## Return the real-valued natural logarithm of each element of @var{x}.  Report
-## an error if any element results in a complex return value.
+## Return the real-valued natural logarithm of each element of @var{x}.
+##
+## If any element results in a complex return value @code{reallog} aborts
+## and issues an error.
 ## @seealso{log, realpow, realsqrt}
 ## @end deftypefn
 
 function y = reallog (x)
+
   if (nargin != 1)
     print_usage ();
   elseif (iscomplex (x) || any (x(:) < 0))
@@ -31,13 +34,17 @@
   else
     y = log (x);
   endif
+
 endfunction
 
 
-%!assert (log (1:5), reallog (1:5))
+%!assert (reallog (1:5), log (1:5))
 %!test
-%! x = rand (10,10);
-%! assert (log (x),reallog (x));
+%! x = rand (10, 10);
+%! assert (reallog (x), log (x));
 
+%!error reallog ()
+%!error reallog (1,2)
+%!error <produced complex result> reallog (2i)
 %!error <produced complex result> reallog (-1)
 
--- a/scripts/specfun/realpow.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/specfun/realpow.m	Mon Jan 12 09:17:35 2015 -0800
@@ -18,31 +18,37 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} realpow (@var{x}, @var{y})
-## Compute the real-valued, element-by-element power operator.  This is
-## equivalent to @w{@code{@var{x} .^ @var{y}}}, except that @code{realpow}
-## reports an error if any return value is complex.
-## @seealso{reallog, realsqrt}
+## Compute the real-valued, element-by-element power operator.
+##
+## This is equivalent to @w{@code{@var{x} .^ @var{y}}}, except that
+## @code{realpow} reports an error if any return value is complex.
+## @seealso{power, reallog, realsqrt}
 ## @end deftypefn
 
 function z = realpow (x, y)
+
   if (nargin != 2)
     print_usage ();
-  else
-    z = x .^ y;
-    if (iscomplex (z))
-      error ("realpow: produced complex result");
-    endif
   endif
+
+  z = x .^ y;
+  if (iscomplex (z))
+    error ("realpow: produced complex result");
+  endif
+
 endfunction
 
 
-%!assert (power (1:10, 0.5:0.5:5), realpow (1:10, 0.5:0.5:5))
-%!assert ([1:10] .^ [0.5:0.5:5], realpow (1:10, 0.5:0.5:5))
+%!assert (realpow (1:10, 0.5:0.5:5), power (1:10, 0.5:0.5:5))
+%!assert (realpow (1:10, 0.5:0.5:5), [1:10] .^ [0.5:0.5:5])
 %!test
-%! x = rand (10,10);
-%! y = randn (10,10);
+%! x = rand (10, 10);
+%! y = randn (10, 10);
 %! assert (x.^y, realpow (x,y));
 %!assert (realpow (1i,2), -1)
 
+%!error realpow ()
+%!error realpow (1)
+%!error realpow (1,2,3)
 %!error <produced complex result> realpow (-1, 1/2)
 
--- a/scripts/specfun/realsqrt.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/specfun/realsqrt.m	Mon Jan 12 09:17:35 2015 -0800
@@ -18,12 +18,15 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} realsqrt (@var{x})
-## Return the real-valued square root of each element of @var{x}.  Report an
-## error if any element results in a complex return value.
+## Return the real-valued square root of each element of @var{x}.
+##
+## If any element results in a complex return value @code{realsqrt} aborts
+## and issues an error.
 ## @seealso{sqrt, realpow, reallog}
 ## @end deftypefn
 
 function y = realsqrt (x)
+
   if (nargin != 1)
     print_usage ();
   elseif (iscomplex (x) || any (x(:) < 0))
@@ -31,13 +34,16 @@
   else
     y = sqrt (x);
   endif
+
 endfunction
 
 
-%!assert (sqrt (1:5), realsqrt (1:5))
+%!assert (realsqrt (1:5), sqrt (1:5))
 %!test
-%! x = rand (10,10);
-%! assert (sqrt (x), realsqrt (x));
+%! x = rand (10, 10);
+%! assert (realsqrt (x), sqrt (x));
 
+%!error realsqrt ()
+%!error realsqrt (1,2)
 %!error <produced complex result> realsqrt (-1)
 
--- a/scripts/special-matrix/gallery.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/special-matrix/gallery.m	Mon Jan 12 09:17:35 2015 -0800
@@ -83,7 +83,7 @@
 ## @deftypefn  {Function File} {[@var{c}, @var{d}, @var{e}] =} gallery ("dorr", @var{n})
 ## @deftypefnx {Function File} {[@var{c}, @var{d}, @var{e}] =} gallery ("dorr", @var{n}, @var{theta})
 ## @deftypefnx {Function File} {@var{a} =} gallery ("dorr", @dots{})
-## Create a diagonally dominant, ill conditioned, tridiagonal matrix.
+## Create a diagonally dominant, ill-conditioned, tridiagonal matrix.
 ##
 ## @end deftypefn
 ##
@@ -94,20 +94,20 @@
 ## @end deftypefn
 ##
 ## @deftypefn {Function File} {@var{a} =} gallery ("fiedler", @var{c})
-## Create a symmetric Fiedler matrix.
+## Create a symmetric @nospell{Fiedler} matrix.
 ##
 ## @end deftypefn
 ##
 ## @deftypefn  {Function File} {@var{a} =} gallery ("forsythe", @var{n})
 ## @deftypefnx {Function File} {@var{a} =} gallery ("forsythe", @var{n}, @var{alpha})
 ## @deftypefnx {Function File} {@var{a} =} gallery ("forsythe", @var{n}, @var{alpha}, @var{lambda})
-## Create a Forsythe matrix (a perturbed Jordan block).
+## Create a @nospell{Forsythe} matrix (a perturbed Jordan block).
 ##
 ## @end deftypefn
 ##
 ## @deftypefn  {Function File} {@var{f} =} gallery ("frank", @var{n})
 ## @deftypefnx {Function File} {@var{f} =} gallery ("frank", @var{n}, @var{k})
-## Create a Frank matrix (ill conditioned eigenvalues).
+## Create a Frank matrix (ill-conditioned eigenvalues).
 ##
 ## @end deftypefn
 ##
@@ -194,13 +194,13 @@
 ## @deftypefn  {Function File} {@var{u} =} gallery ("kahan", @var{n})
 ## @deftypefnx {Function File} {@var{u} =} gallery ("kahan", @var{n}, @var{theta})
 ## @deftypefnx {Function File} {@var{u} =} gallery ("kahan", @var{n}, @var{theta}, @var{pert})
-## Create a Kahan matrix (upper trapezoidal).
+## Create a @nospell{Kahan} matrix (upper trapezoidal).
 ##
 ## @end deftypefn
 ##
 ## @deftypefn  {Function File} {@var{a} =} gallery ("kms", @var{n})
 ## @deftypefnx {Function File} {@var{a} =} gallery ("kms", @var{n}, @var{rho})
-## Create a Kac-Murdock-Szego Toeplitz matrix.
+## Create a @nospell{Kac-Murdock-Szego} Toeplitz matrix.
 ##
 ## @end deftypefn
 ##
@@ -213,12 +213,12 @@
 ##
 ## @deftypefn  {Function File} {@var{a} =} gallery ("lauchli", @var{n})
 ## @deftypefnx {Function File} {@var{a} =} gallery ("lauchli", @var{n}, @var{mu})
-## Create a Lauchli matrix (rectangular).
+## Create a @nospell{Lauchli} matrix (rectangular).
 ##
 ## @end deftypefn
 ##
 ## @deftypefn {Function File} {@var{a} =} gallery ("lehmer", @var{n})
-## Create a Lehmer matrix (symmetric positive definite).
+## Create a @nospell{Lehmer} matrix (symmetric positive definite).
 ##
 ## @end deftypefn
 ##
@@ -228,7 +228,7 @@
 ## @end deftypefn
 ##
 ## @deftypefn {Function File} {@var{a} =} gallery ("lotkin", @var{n})
-## Create a Lotkin matrix.
+## Create a @nospell{Lotkin} matrix.
 ##
 ## @end deftypefn
 ##
@@ -239,7 +239,7 @@
 ##
 ## @deftypefn  {Function File} {@var{a} =} gallery ("moler", @var{n})
 ## @deftypefnx {Function File} {@var{a} =} gallery ("moler", @var{n}, @var{alpha})
-## Create a Moler matrix (symmetric positive definite).
+## Create a @nospell{Moler} matrix (symmetric positive definite).
 ##
 ## @end deftypefn
 ##
@@ -274,7 +274,8 @@
 ## @end deftypefn
 ##
 ## @deftypefn {Function File} {@var{a} =} gallery ("parter", @var{n})
-## Create a Parter matrix (a Toeplitz matrix with singular values near pi).
+## Create a @nospell{Parter} matrix (a Toeplitz matrix with singular values
+## near pi).
 ##
 ## @end deftypefn
 ##
@@ -316,8 +317,8 @@
 ## @end deftypefn
 ##
 ## @deftypefn {Function File} {@var{a} =} gallery ("redheff", @var{n})
-## Create a zero and ones matrix of Redheffer associated with the Riemann
-## hypothesis.
+## Create a zero and ones matrix of @nospell{Redheffer} associated with the
+## Riemann hypothesis.
 ##
 ## @end deftypefn
 ##
@@ -365,7 +366,8 @@
 ## @deftypefn  {Function File} {@var{t} =} gallery ("triw", @var{n})
 ## @deftypefnx {Function File} {@var{t} =} gallery ("triw", @var{n}, @var{alpha})
 ## @deftypefnx {Function File} {@var{t} =} gallery ("triw", @var{n}, @var{alpha}, @var{k})
-## Create an upper triangular matrix discussed by Kahan, Golub and Wilkinson.
+## Create an upper triangular matrix discussed by
+## @nospell{Kahan, Golub, and Wilkinson}.
 ##
 ## @end deftypefn
 ##
@@ -390,7 +392,7 @@
 ##
 ## @deftypefn  {Function File} {@var{a} =} gallery ("wathen", @var{nx}, @var{ny})
 ## @deftypefnx {Function File} {@var{a} =} gallery ("wathen", @var{nx}, @var{ny}, @var{k})
-## Create the Wathen matrix.
+## Create the @nospell{Wathen} matrix.
 ##
 ## @end deftypefn
 ##
@@ -1214,9 +1216,9 @@
   elseif (! isnumeric (n) || ! isscalar (n) || fix (n) != n)
     error ("gallery: N must be an integer for gearmat matrix.");
   elseif (! isnumeric (i) || ! isscalar (i) || i == 0 || abs (i) <= n)
-    error ("gallery: I must be a non-zero scalar, and abs (I) <= N for gearmat matrix.");
+    error ("gallery: I must be a nonzero scalar, and abs (I) <= N for gearmat matrix.");
   elseif (! isnumeric (j) || ! isscalar (j) || i == 0 || abs (j) <= n)
-    error ("gallery: J must be a non-zero scalar, and abs (J) <= N for gearmat matrix.");
+    error ("gallery: J must be a nonzero scalar, and abs (J) <= N for gearmat matrix.");
   endif
 
   A = diag (ones (n-1, 1), -1) + diag (ones (n-1, 1), 1);
@@ -2520,7 +2522,7 @@
   T = spdiags ([[x;0] y [0;z]], -1:1, n, n);
 endfunction
 
-function t = triw (n, alpha = -1, k = -1)
+function t = triw (n, alpha = -1, k = n(end) - 1)
   ## TRIW   Upper triangular matrix discussed by Wilkinson and others.
   ##        TRIW(N, ALPHA, K) is the upper triangular matrix with ones on
   ##        the diagonal and ALPHAs on the first K >= 0 superdiagonals.
@@ -2556,8 +2558,8 @@
     error ("gallery: N must be a 1 or 2 elements vector for triw matrix.");
   elseif (! isscalar (alpha))
     error ("gallery: ALPHA must be a scalar for triw matrix.");
-  elseif (! isscalar (k) || ! isnumeric (k) || fix (k) != k)
-    error ("gallery: K must be a numeric integer for triw matrix.");
+  elseif (! isscalar (k) || ! isnumeric (k) || fix (k) != k || k < 0)
+    error ("gallery: K must be a numeric integer >= 0 for triw matrix.");
   endif
 
   m = n(1);              # Parameter n specifies dimension: m-by-n.
@@ -2853,3 +2855,15 @@
   endif
 endfunction
 
+
+## BIST testing for just a few functions to verify that the main gallery
+## dispatch function works.
+%assert (gallery ("clement", 3), [0 1 0; 2 0 2; 0 1 0])
+%assert (gallery ("invhess", 2), [1 -1; 1 2])
+
+## Test input validation of main dispatch function only
+%!error gallery ()
+%!error <NAME must be a string> gallery (123)
+%!error <matrix binomial not implemented> gallery ("binomial")
+%!error <unknown matrix with NAME foobar> gallery ("foobar")
+
--- a/scripts/special-matrix/invhilb.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/special-matrix/invhilb.m	Mon Jan 12 09:17:35 2015 -0800
@@ -63,7 +63,7 @@
 ## The validity of this formula can easily be checked by expanding
 ## the binomial coefficients in both formulas as factorials.  It can
 ## be derived more directly via the theory of Cauchy matrices.
-## See J. W. Demmel, @cite{Applied Numerical Linear Algebra}, p. 92.
+## See @nospell{J. W. Demmel}, @cite{Applied Numerical Linear Algebra}, p. 92.
 ##
 ## Compare this with the numerical calculation of @code{inverse (hilb (n))},
 ## which suffers from the ill-conditioning of the Hilbert matrix, and the
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/statistics/base/lscov.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,188 @@
+## Copyright (C) 2014 Nir Krakauer
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program 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 this program; If not, see <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {Function File} {@var{x} =} lscov (@var{A}, @var{b})
+## @deftypefnx {Function File} {@var{x} =} lscov (@var{A}, @var{b}, @var{V})
+## @deftypefnx {Function File} {@var{x} =} lscov (@var{A}, @var{b}, @var{V}, @var{alg})
+## @deftypefnx {Function File} {[@var{x}, @var{stdx}, @var{mse}, @var{S}] =} lscov (@dots{})
+##
+## Compute a generalized linear least squares fit.
+## Estimate @var{x} under the model @var{b} = @var{A}@var{x} + @var{w}, 
+## where the noise @var{w} is assumed to follow a normal distribution 
+## with covariance matrix @math{{\sigma^2} V}.
+##
+## If the size of the coefficient matrix @var{A} is n-by-p, the
+## size of the vector/array of constant terms @var{b} must be n-by-k.
+##
+## The optional input argument @var{V} may be a n-by-1 vector of positive
+## weights (inverse variances), or a n-by-n symmetric positive
+## semidefinite matrix representing the covariance of @var{b}.  If
+## @var{V} is not supplied, the ordinary least squares solution is
+## returned.
+##
+## The @var{alg} input argument, a guidance on solution method to use,
+## is currently ignored.
+##
+## Besides the least-squares estimate matrix @var{x} (p-by-k), the
+## function also returns @var{stdx} (p-by-k), the error standard
+## deviation of estimated @var{x}; @var{mse} (k-by-1), the estimated
+## data error covariance scale factors (@math{\sigma^2}); and @var{S}
+## (p-by-p, or p-by-p-by-k if k > 1), the error covariance of @var{x}.
+##
+## Reference: @nospell{Golub and Van Loan} (1996),
+## Matrix Computations (3rd Ed.), Johns Hopkins, Section 5.6.3
+##
+## @end deftypefn
+## @seealso{ols, gls, lsqnonneg}
+
+## Author: Nir Krakauer
+
+function [x, stdx, mse, S] = lscov (A, b, V = [], alg)
+
+  if (nargin < 2 || (rows (A) != rows (b)))
+    print_usage ();
+  endif
+  
+  n = rows (A);
+  p = columns (A);
+  k = columns (b);
+  
+  if (! isempty (V))
+    if (rows (V) != n || ! any (columns (V) == [1 n]))
+      error ("lscov: V should be a square matrix or a vector with the same number of rows as A");
+    endif
+    
+    if (isvector (V))
+      ## n-by-1 vector of inverse variances
+      v = diag (sqrt (V));
+      A = v * A;
+      b = v * b;
+    else
+      ## n-by-n covariance matrix
+      try
+        ## ordinarily V will be positive definite
+        B = chol (V)';
+      catch
+        ## if V is only positive semidefinite, use its
+        ## eigendecomposition to find a factor B such that V = B*B'
+        [B, lambda] = eig (V);
+        image_dims = (diag (lambda) > 0);
+        B = B(:, image_dims) * sqrt (lambda(image_dims, image_dims));
+      end_try_catch     
+      A = B \ A;
+      b = B \ b;
+    endif
+  endif
+  
+  pinv_A = pinv (A); #pseudoinverse
+
+  x = pinv_A * b;
+  
+  if (isargout (3))
+    dof = n - p; #degrees of freedom remaining after fit
+    SSE = sumsq (b - A * x);
+    mse = SSE / dof;
+  endif
+  
+  s = pinv_A * pinv_A';
+
+  stdx = sqrt (diag (s) * mse);
+  
+  if (isargout (4))
+    if (k == 1)
+      S = mse * s;
+    else
+      S = nan (p, p, k);
+      for i = 1:k
+        S(:, :, i) = mse(i) * s;
+      endfor
+    endif
+  endif
+endfunction
+
+%!test
+%! ## Longley data from the NIST Statistical Reference Dataset
+%! Z = [  60323    83.0   234289   2356     1590    107608  1947
+%!        61122    88.5   259426   2325     1456    108632  1948
+%!        60171    88.2   258054   3682     1616    109773  1949
+%!        61187    89.5   284599   3351     1650    110929  1950
+%!        63221    96.2   328975   2099     3099    112075  1951
+%!        63639    98.1   346999   1932     3594    113270  1952
+%!        64989    99.0   365385   1870     3547    115094  1953
+%!        63761   100.0   363112   3578     3350    116219  1954
+%!        66019   101.2   397469   2904     3048    117388  1955
+%!        67857   104.6   419180   2822     2857    118734  1956
+%!        68169   108.4   442769   2936     2798    120445  1957
+%!        66513   110.8   444546   4681     2637    121950  1958
+%!        68655   112.6   482704   3813     2552    123366  1959
+%!        69564   114.2   502601   3931     2514    125368  1960
+%!        69331   115.7   518173   4806     2572    127852  1961
+%!        70551   116.9   554894   4007     2827    130081  1962 ];
+%! ## Results certified by NIST using 500 digit arithmetic
+%! ## b and standard error in b
+%! V = [  -3482258.63459582         890420.383607373
+%!         15.0618722713733         84.9149257747669
+%!        -0.358191792925910E-01    0.334910077722432E-01
+%!        -2.02022980381683         0.488399681651699
+%!        -1.03322686717359         0.214274163161675
+%!        -0.511041056535807E-01    0.226073200069370
+%!         1829.15146461355         455.478499142212 ];
+%! rsd =  304.854073561965;
+%! y = Z(:,1); X = [ones(rows(Z),1), Z(:,2:end)];
+%! alpha = 0.05;
+%! [b, stdb, mse] = lscov (X, y);
+%! assert(b, V(:,1), 3e-6);
+%! assert(stdb, V(:,2), -1.e-5);
+%! assert(sqrt (mse), rsd, -1E-6);
+
+%!test
+%! ## Adapted from example in Matlab documentation
+%! x1 = [.2 .5 .6 .8 1.0 1.1]'; 
+%! x2 = [.1 .3 .4 .9 1.1 1.4]'; 
+%! X = [ones(size(x1)) x1 x2]; 
+%! y = [.17 .26 .28 .23 .27 .34]';
+%! [b, se_b, mse, S] = lscov(X, y);
+%! assert(b, [0.1203 0.3284 -0.1312]', 1E-4);
+%! assert(se_b, [0.0643 0.2267 0.1488]', 1E-4);
+%! assert(mse, 0.0015, 1E-4);
+%! assert(S, [0.0041 -0.0130 0.0075; -0.0130 0.0514 -0.0328; 0.0075 -0.0328 0.0221], 1E-4);
+%! w = [1 1 1 1 1 .1]'; 
+%! [bw, sew_b, msew] = lscov (X, y, w);
+%! assert(bw, [0.1046 0.4614 -0.2621]', 1E-4);
+%! assert(sew_b, [0.0309 0.1152 0.0814]', 1E-4);
+%! assert(msew, 3.4741e-004, -1E-4);
+%! V = .2*ones(length(x1)) + .8*diag(ones(size(x1)));
+%! [bg, sew_b, mseg] = lscov (X, y, V);
+%! assert(bg, [0.1203 0.3284 -0.1312]', 1E-4);
+%! assert(sew_b, [0.0672 0.2267 0.1488]', 1E-4);
+%! assert(mseg, 0.0019, 1E-4);
+%! y2 = [y 2*y];
+%! [b2, se_b2, mse2, S2] = lscov (X, y2);
+%! assert(b2, [b 2*b], eps)
+%! assert(se_b2, [se_b 2*se_b], eps)
+%! assert(mse2, [mse 4*mse], eps)
+%! assert(S2(:, :, 1), S, eps)
+%! assert(S2(:, :, 2), 4*S, eps)
+
+%!test
+%! ## Artificial example with positive semidefinite weight matrix
+%! x = (0:0.2:2)';
+%! y = round(100*sin(x) + 200*cos(x));
+%! X = [ones(size(x)) sin(x) cos(x)];
+%! V = eye(numel(x));
+%! V(end, end-1) = V(end-1, end) = 1;
+%! [b, seb, mseb, S] = lscov (X, y, V);
+%! assert(b, [0 100 200]', 0.2);
--- a/scripts/statistics/base/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/statistics/base/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -11,6 +11,7 @@
   statistics/base/kendall.m \
   statistics/base/kurtosis.m \
   statistics/base/logit.m \
+  statistics/base/lscov.m \
   statistics/base/mahalanobis.m \
   statistics/base/mean.m \
   statistics/base/meansq.m \
--- a/scripts/statistics/base/moment.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/statistics/base/moment.m	Mon Jan 12 09:17:35 2015 -0800
@@ -103,6 +103,7 @@
 ##
 ## @end ifnottex
 ## @end table
+##
 ## If the optional argument @var{dim} is given, operate along this dimension.
 ##
 ## If both @var{type} and @var{dim} are given they may appear in any order.
--- a/scripts/statistics/base/prctile.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/statistics/base/prctile.m	Mon Jan 12 09:17:35 2015 -0800
@@ -30,10 +30,8 @@
 ##
 ## If @var{p} is unspecified, return the quantiles for @code{[0 25 50 75 100]}.
 ## The optional argument @var{dim} determines the dimension along which
-## the percentiles are calculated.  If @var{dim} is omitted, and @var{x} is
-## a vector or matrix, it defaults to 1 (column-wise quantiles).  When
-## @var{x} is an N-D array, @var{dim} defaults to the first non-singleton
-## dimension.
+## the percentiles are calculated.  If @var{dim} is omitted it defaults to the
+## the first non-singleton dimension.
 ## @seealso{quantile}
 ## @end deftypefn
 
@@ -59,14 +57,10 @@
   endif
 
   nd = ndims (x);
+  sz = size (x);
   if (nargin < 3)
-    if (nd == 2)
-      ## If a matrix or vector, always use 1st dimension.
-      dim = 1;
-    else
-      ## If an N-d array, find the first non-singleton dimension.
-      (dim = find (sz > 1, 1)) || (dim = 1);
-    endif
+    ## Find the first non-singleton dimension.
+    (dim = find (sz > 1, 1)) || (dim = 1);
   else
     if (!(isscalar (dim) && dim == fix (dim))
         || !(1 <= dim && dim <= nd))
@@ -84,11 +78,26 @@
 
 %!test
 %! pct = 50;
+%! q = prctile (1:4, pct);
+%! qa = 2.5;
+%! assert (q, qa);
 %! q = prctile (1:4, pct, 1);
 %! qa = [1, 2, 3, 4];
 %! assert (q, qa);
 %! q = prctile (1:4, pct, 2);
-%! qa = 2.5000;
+%! qa = 2.5;
+%! assert (q, qa);
+
+%!test
+%! pct = [50 75];
+%! q = prctile (1:4, pct);
+%! qa = [2.5 3.5];
+%! assert (q, qa);
+%! q = prctile (1:4, pct, 1);
+%! qa = [1, 2, 3, 4; 1, 2, 3, 4];
+%! assert (q, qa);
+%! q = prctile (1:4, pct, 2);
+%! qa = [2.5 3.5];
 %! assert (q, qa);
 
 %!test
--- a/scripts/statistics/base/qqplot.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/statistics/base/qqplot.m	Mon Jan 12 09:17:35 2015 -0800
@@ -62,7 +62,7 @@
     print_usage ();
   endif
 
-  if (!(isnumeric (x) && isvector (x)))
+  if (! (isnumeric (x) && isvector (x)))
     error ("qqplot: X must be a numeric vector");
   endif
 
@@ -97,7 +97,7 @@
   endif
 
   if (nargout == 0)
-    plot (q, s);
+    plot (q, s, "-x");
     q_label = strrep (q_label, '_inv', '\_inv');
     if (q_label(1) == '@')
       q_label = q_label(6:end);  # Strip "@(y) " from anon. function
@@ -111,4 +111,3 @@
 
 endfunction
 
-
--- a/scripts/statistics/base/quantile.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/statistics/base/quantile.m	Mon Jan 12 09:17:35 2015 -0800
@@ -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
@@ -75,17 +73,17 @@
 ## @var{x} is normally distributed.
 ## @end enumerate
 ##
-## Hyndman and Fan (1996) recommend method 8.  Maxima, S, and R
+## @nospell{Hyndman and Fan} (1996) recommend method 8.  Maxima, S, and R
 ## (versions prior to 2.0.0) use 7 as their default.  Minitab and SPSS
 ## use method 6.  @sc{matlab} uses method 5.
 ##
 ## References:
 ##
 ## @itemize @bullet
-## @item Becker, R. A., Chambers, J. M. and Wilks, A. R. (1988) The New
-## S Language.  Wadsworth & Brooks/Cole.
+## @item @nospell{Becker, R. A., Chambers, J. M. and Wilks, A. R.} (1988)
+## The New S Language.  Wadsworth & Brooks/Cole.
 ##
-## @item Hyndman, R. J. and Fan, Y. (1996) Sample quantiles in
+## @item @nospell{Hyndman, R. J. and Fan, Y.} (1996) Sample quantiles in
 ## statistical packages, American Statistician, 50, 361--365.
 ##
 ## @item R: A Language and Environment for Statistical Computing;
@@ -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/betapdf.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/statistics/distributions/betapdf.m	Mon Jan 12 09:17:35 2015 -0800
@@ -57,26 +57,26 @@
   if (isscalar (a) && isscalar (b))
     pdf(k) = exp ((a - 1) * log (x(k))
                   + (b - 1) * log (1 - x(k))
-                  + lgamma (a + b) - lgamma (a) - lgamma (b));
+                  + gammaln (a + b) - gammaln (a) - gammaln (b));
   else
     pdf(k) = exp ((a(k) - 1) .* log (x(k))
                   + (b(k) - 1) .* log (1 - x(k))
-                  + lgamma (a(k) + b(k)) - lgamma (a(k)) - lgamma (b(k)));
+                  + gammaln (a(k) + b(k)) - gammaln (a(k)) - gammaln (b(k)));
   endif
 
   ## Most important special cases when the density is finite.
   k = (x == 0) & (a == 1) & (b > 0) & (b != 1);
   if (isscalar (a) && isscalar (b))
-    pdf(k) = exp (lgamma (a + b) - lgamma (a) - lgamma (b));
+    pdf(k) = exp (gammaln (a + b) - gammaln (a) - gammaln (b));
   else
-    pdf(k) = exp (lgamma (a(k) + b(k)) - lgamma (a(k)) - lgamma (b(k)));
+    pdf(k) = exp (gammaln (a(k) + b(k)) - gammaln (a(k)) - gammaln (b(k)));
   endif
 
   k = (x == 1) & (b == 1) & (a > 0) & (a != 1);
   if (isscalar (a) && isscalar (b))
-    pdf(k) = exp (lgamma (a + b) - lgamma (a) - lgamma (b));
+    pdf(k) = exp (gammaln (a + b) - gammaln (a) - gammaln (b));
   else
-    pdf(k) = exp (lgamma (a(k) + b(k)) - lgamma (a(k)) - lgamma (b(k)));
+    pdf(k) = exp (gammaln (a(k) + b(k)) - gammaln (a(k)) - gammaln (b(k)));
   endif
 
   k = (x >= 0) & (x <= 1) & (a == 1) & (b == 1);
--- a/scripts/statistics/distributions/empirical_pdf.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/statistics/distributions/empirical_pdf.m	Mon Jan 12 09:17:35 2015 -0800
@@ -37,7 +37,16 @@
     error ("empirical_pdf: DATA must be a vector");
   endif
 
-  pdf = discrete_pdf (x, data, ones (size (data)));
+  uniq_vals = unique (data);
+  if (numel (data) != numel (uniq_vals))
+    ## Handle ties, multiple elements with same value
+    p = histc (data, uniq_vals);
+    data = uniq_vals;
+  else
+    p = ones (size (data));
+  endif
+
+  pdf = discrete_pdf (x, data, p);
 
 endfunction
 
@@ -52,6 +61,9 @@
 %!assert (empirical_pdf (single (x), v), single (y))
 %!assert (empirical_pdf (x, single (v)), single (y))
 
+%% Test distribution with ties
+%!assert (empirical_pdf (2, [1 2 3 2]), 0.5)
+
 %% Test input validation
 %!error empirical_pdf ()
 %!error empirical_pdf (1)
--- a/scripts/statistics/distributions/normrnd.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/statistics/distributions/normrnd.m	Mon Jan 12 09:17:35 2015 -0800
@@ -83,7 +83,7 @@
   endif
 
   if (isscalar (mu) && isscalar (sigma))
-    if (isfinite (mu) && (sigma > 0) && (sigma < Inf))
+    if (isfinite (mu) && (sigma >= 0) && (sigma < Inf))
       rnd =  mu + sigma * randn (sz, cls);
     else
       rnd = NaN (sz, cls);
--- a/scripts/statistics/tests/cor_test.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/statistics/tests/cor_test.m	Mon Jan 12 09:17:35 2015 -0800
@@ -22,7 +22,7 @@
 ## populations.
 ##
 ## The optional argument string @var{alt} describes the alternative
-## hypothesis, and can be @qcode{"!="} or @qcode{"<>"} (non-zero),
+## hypothesis, and can be @qcode{"!="} or @qcode{"<>"} (nonzero),
 ## @qcode{">"} (greater than 0), or @qcode{"<"} (less than 0).  The
 ## default is the two-sided case.
 ##
--- a/scripts/statistics/tests/hotelling_test_2.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/statistics/tests/hotelling_test_2.m	Mon Jan 12 09:17:35 2015 -0800
@@ -26,7 +26,7 @@
 ## Hotelling's two-sample @math{T^2} is returned in @var{tsq}.  Under the null,
 ## @tex
 ## $$
-## {n_x+n_y-p-1) T^2 \over p(n_x+n_y-2)}
+## {(n_x+n_y-p-1) T^2 \over p(n_x+n_y-2)}
 ## $$
 ## @end tex
 ## @ifnottex
--- a/scripts/statistics/tests/kruskal_wallis_test.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/statistics/tests/kruskal_wallis_test.m	Mon Jan 12 09:17:35 2015 -0800
@@ -18,7 +18,7 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {[@var{pval}, @var{k}, @var{df}] =} kruskal_wallis_test (@var{x1}, @dots{})
-## Perform a Kruskal-Wallis one-factor analysis of variance.
+## Perform a @nospell{Kruskal-Wallis} one-factor analysis of variance.
 ##
 ## Suppose a variable is observed for @var{k} > 1 different groups, and
 ## let @var{x1}, @dots{}, @var{xk} be the corresponding data vectors.
@@ -36,7 +36,7 @@
 ## where @var{sum_ties} is the sum of @var{t}^2 - @var{t} over each group
 ## of ties where @var{t} is the number of ties in the group and @var{n}
 ## is the total number of values in the input data.  For more info on
-## this adjustment see William H. Kruskal and W. Allen Wallis,
+## this adjustment see @nospell{William H. Kruskal and W. Allen Wallis},
 ## @cite{Use of Ranks in One-Criterion Variance Analysis}, 
 ## Journal of the American Statistical Association, Vol. 47,
 ## No. 260 (Dec 1952).
--- a/scripts/statistics/tests/manova.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/statistics/tests/manova.m	Mon Jan 12 09:17:35 2015 -0800
@@ -28,7 +28,7 @@
 ## and columns are variables.  The vector @var{g} specifies the
 ## corresponding group labels (e.g., numbers from 1 to @var{k}).
 ##
-## The LR test statistic (Wilks' Lambda) and approximate p-values are
+## The LR test statistic (@nospell{Wilks' Lambda}) and approximate p-values are
 ## computed and displayed.
 ## @end deftypefn
 
--- a/scripts/statistics/tests/mcnemar_test.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/statistics/tests/mcnemar_test.m	Mon Jan 12 09:17:35 2015 -0800
@@ -19,8 +19,8 @@
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {[@var{pval}, @var{chisq}, @var{df}] =} mcnemar_test (@var{x})
 ## For a square contingency table @var{x} of data cross-classified on
-## the row and column variables, McNemar's test can be used for testing
-## the null hypothesis of symmetry of the classification probabilities.
+## the row and column variables, @nospell{McNemar's} test can be used for
+## testing the null hypothesis of symmetry of the classification probabilities.
 ##
 ## Under the null, @var{chisq} is approximately distributed as chisquare
 ## with @var{df} degrees of freedom.
--- a/scripts/statistics/tests/t_test.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/statistics/tests/t_test.m	Mon Jan 12 09:17:35 2015 -0800
@@ -82,3 +82,34 @@
 
 endfunction
 
+
+%!test
+%! ## Two-sided (also the default option)
+%! x = rand (10,1); n = length (x);
+%! u0 = 0.5; # true mean
+%! xbar = mean (x);
+%! pval = t_test (x, u0, "!=");
+%! if (xbar >= u0)
+%!   tval = abs (tinv (0.5*pval, n-1));
+%! else
+%!   tval = -abs (tinv (0.5*pval, n-1));
+%! endif
+%! unew = tval * std(x)/sqrt(n) + u0;
+%! assert (xbar, unew, 100*eps);
+
+%!test
+%! x = rand (10,1); n = length (x);
+%! u0 = 0.5;
+%! pval = t_test (x, u0, ">");
+%! tval = tinv (1-pval, n-1);
+%! unew = tval * std(x)/sqrt(n) + u0;
+%! assert (mean (x), unew, 100*eps);
+
+%!test
+%! x = rand (10,1); n = length (x);
+%! u0 = 0.5;
+%! pval = t_test (x, u0, "<");
+%! tval = tinv (pval, n-1);
+%! unew = tval * std(x)/sqrt(n) + u0;
+%! assert (mean (x), unew, 100*eps);
+
--- a/scripts/statistics/tests/z_test.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/statistics/tests/z_test.m	Mon Jan 12 09:17:35 2015 -0800
@@ -86,3 +86,33 @@
 
 endfunction
 
+
+%!test
+%! ## Two-sided (also the default option)
+%! x = rand (10,1); n = length (x);
+%! u0 = 0.5; v = 1/12; # true mean, var
+%! pval = z_test (x, u0, v, "!=");
+%! if (mean (x) >= u0)
+%!   zval = abs (norminv (0.5*pval));
+%! else
+%!   zval = -abs (norminv (0.5*pval));
+%! endif
+%! unew = zval * sqrt (v/n) + u0;
+%! assert (mean (x), unew, 100*eps);
+
+%!test
+%! x = rand (10,1); n = length (x);
+%! u0 = 0.5; v = 1/12;
+%! pval = z_test (x, u0, v, ">");
+%! zval = norminv (1-pval);
+%! unew = zval * sqrt (v/n) + u0;
+%! assert (mean (x), unew, 100*eps);
+
+%!test
+%! x = rand (10,1); n = length (x);
+%! u0 = 0.5; v = 1/12;
+%! pval = z_test (x, u0, v, "<");
+%! zval = norminv (pval);
+%! unew = zval * sqrt (v/n) + u0;
+%! assert (mean (x), unew, 100*eps);
+
--- a/scripts/strings/findstr.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/strings/findstr.m	Mon Jan 12 09:17:35 2015 -0800
@@ -35,7 +35,7 @@
 ##
 ## @strong{Caution:} @code{findstr} is scheduled for deprecation.  Use
 ## @code{strfind} in all new code.
-## @seealso{strfind, strmatch, strcmp, strncmp, strcmpi, strncmpi, find}
+## @seealso{strfind, strcmp, strncmp, strcmpi, strncmpi, find}
 ## @end deftypefn
 
 ## Note that this implementation swaps the strings if second one is longer
--- a/scripts/strings/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/strings/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -23,7 +23,6 @@
   strings/strchr.m \
   strings/strjoin.m \
   strings/strjust.m \
-  strings/strmatch.m \
   strings/strsplit.m \
   strings/strtok.m \
   strings/strtrim.m \
--- a/scripts/strings/strmatch.m	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,119 +0,0 @@
-## Copyright (C) 2000-2013 Paul Kienzle
-## Copyright (C) 2003 Alois Schloegl
-## Copyright (C) 2010 VZLU Prague
-##
-## This file is part of Octave.
-##
-## Octave is free software; you can redistribute it and/or modify it
-## under the terms of the GNU General Public License as published by
-## the Free Software Foundation; either version 3 of the License, or (at
-## your option) any later version.
-##
-## Octave is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-## General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with Octave; see the file COPYING.  If not, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn  {Function File} {} strmatch (@var{s}, @var{A})
-## @deftypefnx {Function File} {} strmatch (@var{s}, @var{A}, "exact")
-## Return indices of entries of @var{A} which begin with the string @var{s}.
-## The second argument @var{A} must be a string, character matrix, or a cell
-## array of strings.  If the third argument @qcode{"exact"} is not given, then
-## @var{s} only needs to match @var{A} up to the length of @var{s}.
-## Trailing spaces and nulls in @var{s} and @var{A} are ignored when matching.
-##
-## For example:
-##
-## @example
-## @group
-## strmatch ("apple", "apple juice")
-##      @result{} 1
-##
-## strmatch ("apple", ["apple  "; "apple juice"; "an apple"])
-##      @result{} [1; 2]
-##
-## strmatch ("apple", ["apple  "; "apple juice"; "an apple"], "exact")
-##      @result{} [1]
-## @end group
-## @end example
-##
-## @strong{Caution:} @code{strmatch} is scheduled for deprecation.  Use
-## @code{strncmp} (normal case), or @code{strcmp} (@qcode{"exact"} case), or
-## @code{regexp} in all new code.
-## @seealso{strfind, findstr, strcmp, strncmp, strcmpi, strncmpi, find}
-## @end deftypefn
-
-## Author: Paul Kienzle, Alois Schloegl
-## Adapted-by: jwe
-
-function idx = strmatch (s, A, exact)
-
-  if (nargin < 2 || nargin > 3)
-    print_usage ();
-  endif
-
-  if (! ischar (s) || (! isempty (s) && ! isvector (s)))
-    error ("strmatch: S must be a string");
-  elseif (! (ischar (A) || iscellstr (A)))
-    error ("strmatch: A must be a string or cell array of strings");
-  endif
-
-  ## Trim blanks and nulls from search string
-  s = regexprep (s, "[ \\0]+$", '');
-  len = length (s);
-
-  exact = nargin == 3 && ischar (exact) && strcmp (exact, "exact");
-
-  if (ischar (A))
-    [nr, nc] = size (A);
-    if (len > nc)
-      idx = [];
-    else
-      match = all (bsxfun (@eq, A(:,1:len), s), 2);
-      if (exact)
-        AA = A(:,len+1:nc);
-        match &= all (AA == " " | AA == "\0", 2);
-      endif
-      idx = find (match);
-    endif
-  else
-    if (len > 0)
-      idx = find (strncmp (s, A, len));
-    else
-      idx = find (strcmp (s, A));
-    endif
-    if (exact)
-      ## We can't just use strcmp, because we need to ignore spaces at end.
-      B = regexprep (A(idx), "[ \\0]+$", '');
-      idx = idx(strcmp (s, B));
-    endif
-  endif
-
-endfunction
-
-
-%!assert (strmatch ("a", {"aaa", "bab", "bbb"}), 1)
-%!assert (strmatch ("apple", "apple juice"), 1)
-%!assert (strmatch ("apple", ["apple pie"; "apple juice"; "an apple"]), [1; 2])
-%!assert (strmatch ("apple", {"apple pie"; "apple juice"; "tomato"}), [1; 2])
-%!assert (strmatch ("apple pie", "apple"), [])
-%!assert (strmatch ("a ", "a"), 1)
-%!assert (strmatch ("a", "a \0", "exact"), 1)
-%!assert (strmatch ("a b", {"a b", "a c", "c d"}), 1)
-%!assert (strmatch ("", {"", "foo", "bar", ""}), [1, 4])
-%!assert (strmatch ('', { '', '% comment', 'var a = 5', ''}, 'exact'), [1,4])
-
-%% Test input validation
-%!error <Invalid call to strmatch> strmatch ()
-%!error <Invalid call to strmatch> strmatch ("a")
-%!error <Invalid call to strmatch> strmatch ("a", "aaa", "exact", 1)
-%!error <S must be a string> strmatch (1, "aaa")
-%!error <S must be a string> strmatch (char ("a", "bb"), "aaa")
-%!error <A must be a string> strmatch ("a", 1)
-%!error <A must be a string> strmatch ("a", {"hello", [1]})
-
--- a/scripts/strings/validatestring.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/strings/validatestring.m	Mon Jan 12 09:17:35 2015 -0800
@@ -53,7 +53,7 @@
 ## @end group
 ## @end smallexample
 ##
-## @seealso{strcmp, strcmpi}
+## @seealso{strcmp, strcmpi, validateattributes, inputParser}
 ## @end deftypefn
 
 ## Author: Bill Denney <bill@denney.ws>
@@ -100,22 +100,21 @@
   ## Make static part of error string that uses funcname, varname, and position
   errstr = "";
   if (! isempty (funcname))
-    errstr = sprintf ("Function: %s ", funcname);
+    errstr = [funcname ": "];
   endif
   if (! isempty (varname))
-    errstr = sprintf ("%sVariable: %s ", errstr, varname);
+    errstr = [errstr varname " "];
+  else
+    errstr = sprintf ("%s'%s' ", errstr, str);
   endif
   if (position > 0)
-    errstr = sprintf ("%sArgument position %d ", errstr, position);
-  endif
-  if (! isempty (errstr))
-    errstr(end:end+1) = ":\n";
+    errstr = sprintf ("%s(argument #%i) ", errstr, position);
   endif
 
   matches = strncmpi (str, strarray(:), length (str));
   nmatches = sum (matches);
   if (nmatches == 0)
-    error ("validatestring: %s'%s' does not match any of\n%s", errstr, str,
+    error ("%sdoes not match any of\n%s", errstr,
            sprintf ("%s, ", strarray{:})(1:end-2));
   elseif (nmatches == 1)
     str = strarray{matches};
@@ -130,8 +129,8 @@
     if (all (submatch))
       str = short_str;
     else
-      error ("validatestring: %smultiple unique matches were found for '%s':\n%s",
-             errstr, str, sprintf ("%s, ", strarray{match_idx})(1:end-2));
+      error ("%sallows multiple unique matches:\n%s",
+             errstr, sprintf ("%s, ", strarray{match_idx})(1:end-2));
     endif
   endif
 
@@ -147,10 +146,10 @@
 %!assert (validatestring ("d", strarray), "def")
 
 %!error <'xyz' does not match any> validatestring ("xyz", strarray)
-%!error <Function: DUMMY_TEST> validatestring ("xyz", strarray, "DUMMY_TEST")
-%!error <Function: DUMMY_TEST Variable: DUMMY_VAR:> validatestring ("xyz", strarray, "DUMMY_TEST", "DUMMY_VAR")
-%!error <Function: DUMMY_TEST Variable: DUMMY_VAR Argument position 5> validatestring ("xyz", strarray, "DUMMY_TEST", "DUMMY_VAR", 5)
-%!error <multiple unique matches were found for 'abc'> validatestring ("abc", strarray)
+%!error <DUMMY_TEST: 'xyz' does not> validatestring ("xyz", strarray, "DUMMY_TEST")
+%!error <DUMMY_TEST: DUMMY_VAR does> validatestring ("xyz", strarray, "DUMMY_TEST", "DUMMY_VAR")
+%!error <DUMMY_TEST: DUMMY_VAR \(argument #5\) does> validatestring ("xyz", strarray, "DUMMY_TEST", "DUMMY_VAR", 5)
+%!error <'abc' allows multiple unique matches> validatestring ("abc", strarray)
 
 %% Test input validation
 %!error validatestring ("xyz")
--- a/scripts/testfun/__have_feature__.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/testfun/__have_feature__.m	Mon Jan 12 09:17:35 2015 -0800
@@ -33,3 +33,7 @@
   endif
 endfunction
 
+
+## No test coverage for internal function.  It is tested through calling fcn.
+%!assert (1)
+
--- a/scripts/testfun/__printf_assert__.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/testfun/__printf_assert__.m	Mon Jan 12 09:17:35 2015 -0800
@@ -26,3 +26,7 @@
   _assert_printf = cat (2, _assert_printf, sprintf (varargin{:}));
 endfunction
 
+
+## No test coverage for internal function.  It is tested through calling fcn.
+%!assert (1)
+
--- a/scripts/testfun/__prog_output_assert__.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/testfun/__prog_output_assert__.m	Mon Jan 12 09:17:35 2015 -0800
@@ -33,3 +33,7 @@
   _assert_printf = "";
 endfunction
 
+
+## No test coverage for internal function.  It is tested through calling fcn.
+%!assert (1)
+
--- a/scripts/testfun/__run_test_suite__.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/testfun/__run_test_suite__.m	Mon Jan 12 09:17:35 2015 -0800
@@ -40,95 +40,102 @@
   global topsrcdir = fcnfiledir;
   global topbuilddir = testsdir;
   pso = page_screen_output ();
-  warn_state = warning ("query", "quiet");
-  warning ("on", "quiet");
+  orig_wstate = warning ();
   logfile = make_absolute_filename ("fntests.log");
-  try
+  unwind_protect
     page_screen_output (false);
+    warning ("on", "quiet");
     warning ("off", "Octave:deprecated-function");
-    fid = fopen (logfile, "wt");
-    if (fid < 0)
-      error ("could not open %s for writing", logfile);
-    endif
-    test ("", "explain", fid);
-    dp = dn = dxf = dsk = 0;
-    puts ("\nIntegrated test scripts:\n\n");
-    for i = 1:length (fcndirs)
-      [p, n, xf, sk] = run_test_script (fid, fcndirs{i});
-      dp += p;
-      dn += n;
-      dxf += xf;
-      dsk += sk;
-    endfor
-    puts ("\nFixed test scripts:\n\n");
-    for i = 1:length (fixedtestdirs)
-      [p, n, xf, sk] = run_test_dir (fid, fixedtestdirs{i});
-      dp += p;
-      dn += n;
-      dxf += xf;
-      dsk += sk;
-    endfor
-    puts ("\nSummary:\n\n");
-    nfail = dn - dp;
-    printf ("  PASS    %6d\n", dp);
-    printf ("  FAIL    %6d\n", nfail);
-    if (dxf > 0)
-      printf ("  XFAIL   %6d\n", dxf);
-    endif
-    if (dsk > 0)
-      printf ("  SKIPPED %6d\n", dsk);
-    endif
-    puts ("\n");
-    printf ("See the file %s for additional details.\n", logfile);
-    if (dxf > 0)
+    try
+      fid = fopen (logfile, "wt");
+      if (fid < 0)
+        error ("could not open %s for writing", logfile);
+      endif
+      test ("", "explain", fid);
+      dp = dn = dxf = dsk = 0;
+      puts ("\nIntegrated test scripts:\n\n");
+      for i = 1:length (fcndirs)
+        [p, n, xf, sk] = run_test_script (fid, fcndirs{i});
+        dp += p;
+        dn += n;
+        dxf += xf;
+        dsk += sk;
+      endfor
+      puts ("\nFixed test scripts:\n\n");
+      for i = 1:length (fixedtestdirs)
+        [p, n, xf, sk] = run_test_dir (fid, fixedtestdirs{i});
+        dp += p;
+        dn += n;
+        dxf += xf;
+        dsk += sk;
+      endfor
+      puts ("\nSummary:\n\n");
+      nfail = dn - dp - dxf;
+      printf ("  PASS    %6d\n", dp);
+      printf ("  FAIL    %6d\n", nfail);
+      if (dxf > 0)
+        printf ("  XFAIL   %6d\n", dxf);
+      endif
+      if (dsk > 0)
+        printf ("  SKIPPED %6d\n", dsk);
+      endif
       puts ("\n");
-      puts ("Expected failures (listed as XFAIL above) are known bugs.\n");
-      puts ("Please help improve Octave by contributing fixes for them.\n");
-    endif
-    if (dsk > 0)
-      puts ("\n");
-      puts ("Tests are most often skipped because the features they require\n");
-      puts ("have been disabled.  Features are most often disabled because\n");
-      puts ("they require dependencies that were not present when Octave\n");
-      puts ("was built.  The configure script should have printed a summary\n");
-      puts ("at the end of its run indicating which dependencies were not found.\n");
-    endif
+      printf ("See the file %s for additional details.\n", logfile);
+      if (dxf > 0)
+        puts ("\n");
+        puts ("Expected failures (listed as XFAIL above) are known bugs.\n");
+        puts ("Please help improve Octave by contributing fixes for them.\n");
+      endif
+      if (dsk > 0)
+        puts ("\n");
+        puts ("Tests are most often skipped because the features they require\n");
+        puts ("have been disabled.  Features are most often disabled because\n");
+        puts ("they require dependencies that were not present when Octave\n");
+        puts ("was built.  The configure script should have printed a summary\n");
+        puts ("at the end of its run indicating which dependencies were not found.\n");
+      endif
 
-    ## Weed out deprecated and private functions
-    weed_idx = cellfun (@isempty, regexp (files_with_tests, '\<deprecated\>|\<private\>', 'once'));
-    files_with_tests = files_with_tests(weed_idx);
-    weed_idx = cellfun (@isempty, regexp (files_with_no_tests, '\<deprecated\>|\<private\>', 'once'));
-    files_with_no_tests = files_with_no_tests(weed_idx);
+      ## Weed out deprecated and private functions
+      weed_idx = cellfun (@isempty, regexp (files_with_tests, '\<deprecated\>|\<private\>', 'once'));
+      files_with_tests = files_with_tests(weed_idx);
+      weed_idx = cellfun (@isempty, regexp (files_with_no_tests, '\<deprecated\>|\<private\>', 'once'));
+      files_with_no_tests = files_with_no_tests(weed_idx);
 
-    report_files_with_no_tests (files_with_tests, files_with_no_tests, ".m");
+      report_files_with_no_tests (files_with_tests, files_with_no_tests, ".m");
 
-    puts ("\nPlease help improve Octave by contributing tests for these files\n");
-    printf ("(see the list in the file %s).\n\n", logfile);
+      puts ("\nPlease help improve Octave by contributing tests for these files\n");
+      printf ("(see the list in the file %s).\n\n", logfile);
 
-    fprintf (fid, "\nFiles with no tests:\n\n%s",
-                  list_in_columns (files_with_no_tests, 80));
-    fclose (fid);
-
+      fprintf (fid, "\nFiles with no tests:\n\n%s",
+                    list_in_columns (files_with_no_tests, 80));
+      fclose (fid);
+    catch
+      disp (lasterr ());
+    end_try_catch
+  unwind_protect_cleanup
+    warning ("off", "all");
+    warning (orig_wstate);
     page_screen_output (pso);
-    warning (warn_state.state, "quiet");
-  catch
-    page_screen_output (pso);
-    warning (warn_state.state, "quiet");
-    disp (lasterr ());
-  end_try_catch
+  end_unwind_protect
 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");
@@ -184,7 +191,7 @@
   endfor
   saved_dir = pwd ();
   unwind_protect
-    chdir (d);
+    cd (d);
     for i = 1:length (lst)
       nm = lst(i).name;
       if (length (nm) > 4 && strcmpi (nm((end-3):end), ".tst"))
@@ -193,7 +200,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;
@@ -205,7 +212,7 @@
       endif
     endfor
   unwind_protect_cleanup
-    chdir (saved_dir);
+    cd (saved_dir);
   end_unwind_protect
 endfunction
 
@@ -244,7 +251,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;
@@ -272,3 +279,7 @@
   printf ("\n%d (of %d) %s files have no tests.\n", n_without, n_tot, typ);
 endfunction
 
+
+## No test coverage for internal function.  It is tested through calling fcn.
+%!assert (1)
+
--- a/scripts/testfun/assert.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/testfun/assert.m	Mon Jan 12 09:17:35 2015 -0800
@@ -18,21 +18,24 @@
 
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {} assert (@var{cond})
+## @deftypefnx {Function File} {} assert (@var{cond}, @var{errmsg})
 ## @deftypefnx {Function File} {} assert (@var{cond}, @var{errmsg}, @dots{})
 ## @deftypefnx {Function File} {} assert (@var{cond}, @var{msg_id}, @var{errmsg}, @dots{})
 ## @deftypefnx {Function File} {} assert (@var{observed}, @var{expected})
 ## @deftypefnx {Function File} {} assert (@var{observed}, @var{expected}, @var{tol})
 ##
-## Produce an error if the specified condition is not met.  @code{assert} can
-## be called in three different ways.
+## Produce an error if the specified condition is not met.
+##
+## @code{assert} can be called in three different ways.
 ##
 ## @table @code
 ## @item  assert (@var{cond})
+## @itemx assert (@var{cond}, @var{errmsg})
 ## @itemx assert (@var{cond}, @var{errmsg}, @dots{})
 ## @itemx assert (@var{cond}, @var{msg_id}, @var{errmsg}, @dots{})
 ## Called with a single argument @var{cond}, @code{assert} produces an
-## error if @var{cond} is zero.  When called with more than one argument the
-## additional arguments are passed to the @code{error} function.
+## error if @var{cond} is false (numeric zero).  Any additional arguments are
+## passed to the @code{error} function for processing.
 ##
 ## @item assert (@var{observed}, @var{expected})
 ## Produce an error if observed is not the same as expected.  Note that
@@ -46,12 +49,13 @@
 ## an error if @code{abs (@var{observed} - @var{expected}) > abs (@var{tol})}.
 ## If @var{tol} is negative then it is a relative tolerance which will produce
 ## an error if @code{abs (@var{observed} - @var{expected}) >
-## abs (@var{tol} * @var{expected})}.  If @var{expected} is zero @var{tol} will
-## always be interpreted as an absolute tolerance.  If @var{tol} is not scalar
-## its dimensions must agree with those of @var{observed} and @var{expected}
-## and tests are performed on an element-wise basis.
+## abs (@var{tol} * @var{expected})}.
+## If @var{expected} is zero @var{tol} will always be interpreted as an
+## absolute tolerance.  If @var{tol} is not scalar its dimensions must agree
+## with those of @var{observed} and @var{expected} and tests are performed on
+## an element-by-element basis.
 ## @end table
-## @seealso{test, fail, error}
+## @seealso{fail, test, error, isequal}
 ## @end deftypefn
 
 function assert (cond, varargin)
@@ -162,7 +166,7 @@
           err.reason{end+1} = ["Expected struct, but observed " class(cond)];
         elseif (ndims (cond) != ndims (expected)
                 || any (size (cond) != size (expected))
-                || rows (fieldnames (cond)) != rows (fieldnames (expected)))
+                || numfields (cond) != numfields (expected))
 
           err.index{end+1} = ".";
           err.observed{end+1} = ["O(" sprintf("%dx", size(cond))(1:end-1) ")"];
--- a/scripts/testfun/demo.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/testfun/demo.m	Mon Jan 12 09:17:35 2015 -0800
@@ -25,12 +25,14 @@
 ## Run example code block @var{n} associated with the function @var{name}.
 ## If @var{n} is not specified, all examples are run.
 ##
-## Examples are stored in the script file, or in a file with the same
-## name but no extension located on Octave's load path.  To keep examples
-## separate from regular script code, all lines are prefixed by @code{%!}.  Each
-## example must also be introduced by the keyword @qcode{"demo"} flush left
-## to the prefix with no intervening spaces.  The remainder of the example
-## can contain arbitrary Octave code.  For example:
+## The preferred location for example code blocks is embedded within the script
+## m-file immediately following the code that it exercises.  Alternatively,
+## the examples may be stored in a file with the same name but no extension
+## located on Octave's load path.  To separate examples from regular script
+## code all lines are prefixed by @code{%!}.  Each example must also be
+## introduced by the keyword @qcode{"demo"} flush left to the prefix with no
+## intervening spaces.  The remainder of the example can contain arbitrary
+## Octave code.  For example:
 ##
 ## @example
 ## @group
@@ -38,78 +40,84 @@
 ## %! t = 0:0.01:2*pi;
 ## %! x = sin (t);
 ## %! plot (t, x);
-## %! %-------------------------------------------------
-## %! % the figure window shows one cycle of a sine wave
+## %! title ("one cycle of a sine wave");
+## %! #-------------------------------------------------
+## %! # the figure window shows one cycle of a sine wave
 ## @end group
 ## @end example
 ##
-## Note that the code is displayed before it is executed, so a simple
-## comment at the end suffices for labeling what is being shown.  It is
-## generally not necessary to use @code{disp} or @code{printf} within the demo.
+## Note that the code is displayed before it is executed so that a simple
+## comment at the end suffices for labeling what is being shown.  For plots,
+## labeling can also be done with @code{title} or @code{text}.  It is generally
+## @strong{not} necessary to use @code{disp} or @code{printf} within the demo.
 ##
-## Demos are run in a function environment with no access to external
-## variables.  This means that every demo must have separate initialization
-## code.  Alternatively, all demos can be combined into a single large demo
-## with the code
+## Demos are run in a stand-alone function environment with no access to
+## external variables.  This means that every demo must have separate
+## initialization code.  Alternatively, all demos can be combined into a single
+## large demo with the code
 ##
 ## @example
-## %! input("Press <enter> to continue: ","s");
+## %! input ("Press <enter> to continue: ", "s");
 ## @end example
 ##
 ## @noindent
-## between the sections, but this is discouraged.  Other techniques
+## between the sections, but this usage is discouraged.  Other techniques
 ## to avoid multiple initialization blocks include using multiple plots
 ## with a new @code{figure} command between each plot, or using @code{subplot}
 ## to put multiple plots in the same window.
 ##
-## Also, because demo evaluates within a function context, you cannot
-## define new functions inside a demo.  If you must have function blocks,
-## rather than just anonymous functions or inline functions, you will have to
-## use @code{eval (example ("function",n))} to see them.  Because eval only
-## evaluates one line, or one statement if the statement crosses
-## multiple lines, you must wrap your demo in @qcode{"if 1 <demo stuff> endif"}
-## with the @qcode{"if"} on the same line as @qcode{"demo"}.  For example:
+## Finally, because @code{demo} evaluates within a function context it is
+## not possible to define new functions within the code.  Anonymous functions
+## make a good substitute in most instances.  If function blocks
+## @strong{must} be used then the code @code{eval (example ("function", n))}
+## will allow Octave to see them.  This has its own problems, however, as
+## @code{eval} only evaluates one line or statement at a time.  In this case
+## the function declaration must be wrapped with
+## @qcode{"if 1 <demo stuff> endif"} where @qcode{"if"} is on the same line
+## as @qcode{"demo"}.  For example:
 ##
 ## @example
 ## @group
 ## %!demo if 1
-## %!  function y=f(x)
-## %!    y=x;
+## %!  function y = f(x)
+## %!    y = x;
 ## %!  endfunction
 ## %!  f(3)
 ## %! endif
 ## @end group
 ## @end example
 ##
-## @seealso{test, example}
+## @seealso{rundemos, example, test}
 ## @end deftypefn
 
 ## FIXME: modify subplot so that gnuplot_has_multiplot == 0 causes it to
 ## use the current figure window but pause if not plotting in the
 ## first subplot.
 
-function demo (name, n)
+function demo (name, n = 0)
 
   if (nargin < 1 || nargin > 2)
     print_usage ();
   endif
 
-  if (nargin < 2)
-    n = 0;
-  elseif (ischar (n))
+  if (ischar (n))
     n = str2double (n);
   endif
 
+  if (! (isreal (n) && isscalar (n) && n == fix (n)))
+    error ("demo: N must be a scalar integer");
+  endif
+
   [code, idx] = test (name, "grabdemo");
 
   if (idx == -1)
-    warning ("no function %s found", name);
+    warning ("demo: no function %s found", name);
     return;
   elseif (isempty (idx))
-    warning ("no demo available for %s", name);
+    warning ("demo: no demo available for %s", name);
     return;
   elseif (n >= length (idx))
-    warning ("only %d demos available for %s", length (idx) - 1, name);
+    warning ("demo: only %d demos available for %s", length (idx) - 1, name);
     return;
   endif
 
@@ -128,7 +136,7 @@
     try
       block = code(idx(doidx(i)):idx(doidx(i)+1)-1);
       ## Use an environment without variables
-      eval (["function __demo__()\n" block "\nendfunction"]);
+      eval (["function __demo__ ()\n" block "\nendfunction"]);
       ## Display the code that will be executed before executing it
       printf ("%s example %d:%s\n\n", name, doidx(i), block);
       __demo__;
@@ -146,9 +154,15 @@
 %! t = 0:0.01:2*pi;
 %! x = sin (t);
 %! plot (t, x);
-%! %-------------------------------------------------
-%! % the figure window shows one cycle of a sine wave
+%! title ("one cycle of a sine wave");
+%! #-------------------------------------------------
+%! # the figure window shows one cycle of a sine wave
 
 %!error demo ()
 %!error demo (1, 2, 3)
+%!error <N must be a scalar integer> demo ("demo", {1})
+%!error <N must be a scalar integer> demo ("demo", ones (2,2))
+%!error <N must be a scalar integer> demo ("demo", 1.5)
+%!warning <no function .* found> demo ("_%NOT_A_FUNCTION%_");
+%!warning <only 1 demos available for demo> demo ("demo", 10);
 
--- a/scripts/testfun/example.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/testfun/example.m	Mon Jan 12 09:17:35 2015 -0800
@@ -35,31 +35,46 @@
 ## @seealso{demo, test}
 ## @end deftypefn
 
-function [code_r, idx_r] = example (name, n)
+function [ex_code, ex_idx] = example (name, n = 0)
 
   if (nargin < 1 || nargin > 2)
     print_usage ();
   endif
 
-  if (nargin < 2)
-    n = 0;
-  elseif (ischar (n))
+  if (ischar (n))
     n = str2double (n);
   endif
 
+  if (! (isreal (n) && isscalar (n) && n == fix (n)))
+    error ("example: N must be a scalar integer");
+  endif
+
   [code, idx] = test (name, "grabdemo");
+
+  if (idx == -1)
+    warning ("example: no function %s found", name);
+    return;
+  elseif (isempty (idx))
+    warning ("example: no example available for %s", name);
+    return;
+  elseif (n >= length (idx))
+    warning ("example: only %d examples available for %s",
+             length (idx) - 1, name);
+    return;
+  endif
+
   if (nargout > 0)
     if (n > 0)
       if (n <= length (idx))
-        code_r = code(idx(n):idx(n+1)-1);
-        idx_r = [1, length(code_r)+1];
+        ex_code = code(idx(n):idx(n+1)-1);
+        ex_idx = [1, length(ex_code)+1];
       else
-        code_r = "";
-        idx_r = [];
+        ex_code = "";
+        ex_idx = [];
       endif
     else
-      code_r = code;
-      idx_r = idx;
+      ex_code = code;
+      ex_idx = idx;
     endif
   else
     if (n > 0)
@@ -67,13 +82,6 @@
     else
       doidx = 1:length (idx) - 1;
     endif
-    if (isempty (idx))
-      warning ("no example available for %s", name);
-      return;
-    elseif (n >= length (idx))
-      warning ("only %d examples available for %s", length (idx) - 1, name);
-      return;
-    endif
 
     for i = 1:length (doidx)
       block = code(idx(doidx(i)):idx(doidx(i)+1)-1);
@@ -90,17 +98,24 @@
 
 %!demo
 %! clf;
-%! t = 0:0.01:2*pi;  x = sin (t);
+%! t = 0:0.01:2*pi;
+%! x = sin (t);
 %! plot (t,x)
 
-%!assert (example ("example",1), "\n example (\"example\");");
+%!assert (example ("example", 1), "\n example (\"example\");");
+
 %!test
 %! [code, idx] = example ("example");
 %! assert (code, ...
-%!         "\n example (\"example\");\n clf;\n t = 0:0.01:2*pi;  x = sin (t);\n plot (t,x)")
+%!         "\n example (\"example\");\n clf;\n t = 0:0.01:2*pi;\n x = sin (t);\n plot (t,x)");
 %! assert (idx, [1, 23, 73]);
 
 %% Test input validation
-%!error example
+%!error example ()
 %!error example ("example", 3, 5)
+%!error <N must be a scalar integer> example ("example", {1})
+%!error <N must be a scalar integer> example ("example", ones (2,2))
+%!error <N must be a scalar integer> example ("example", 1.5)
+%!warning <no function .* found> example ("_%NOT_A_FUNCTION%_");
+%!warning <only 2 examples available for example> example ("example", 10);
 
--- a/scripts/testfun/fail.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/testfun/fail.m	Mon Jan 12 09:17:35 2015 -0800
@@ -22,51 +22,51 @@
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {} fail (@var{code})
 ## @deftypefnx {Function File} {} fail (@var{code}, @var{pattern})
+## @deftypefnx {Function File} {} fail (@var{code}, "warning")
 ## @deftypefnx {Function File} {} fail (@var{code}, "warning", @var{pattern})
 ##
 ## Return true if @var{code} fails with an error message matching
-## @var{pattern}, otherwise produce an error.  Note that @var{code}
-## is a string and if @var{code} runs successfully, the error produced is:
+## @var{pattern}, otherwise produce an error.
+##
+## @var{code} must be in the form of a string that is passed to the Octave
+## interpreter via the @code{evalin} function, i.e., a (quoted) string constant
+## or a string variable.
+##
+## Note that if @var{code} runs successfully, rather than failing, the error
+## printed is:
 ##
 ## @example
 ##           expected error <.> but got none
 ## @end example
 ##
-##
-## Code must be in the form of a string that may be passed by
-## @code{fail} to the Octave interpreter via the @code{evalin} function,
-## that is, a (quoted) string constant or a string variable.
-##
-## If called with two arguments, the behavior is similar to
-## @code{fail (@var{code})}, except the return value will only be true if
-## code fails with an error message containing pattern (case sensitive).
-## If the code fails with a different error to that given in pattern,
-## the message produced is:
+## If called with two arguments, the return value will be true only if
+## @var{code} fails with an error message containing @var{pattern}
+## (case sensitive).  If the code fails with a different error than the one
+## specified in @var{pattern} then the message produced is:
 ##
 ## @example
 ## @group
-##           expected <pattern>
+##           expected <@var{pattern}>
 ##           but got <text of actual error>
 ## @end group
 ## @end example
 ##
 ## The angle brackets are not part of the output.
 ##
-## Called with three arguments, the behavior is similar to
-## @code{fail (@var{code}, @var{pattern})}, but produces an error if no
-## warning is given during code execution or if the code fails.
-## @seealso{assert}
+## When called with the @qcode{"warning"} option @code{fail} will produce
+## an error if executing the code produces no warning.
+## @seealso{assert, error}
 ## @end deftypefn
 
 ## Author: Paul Kienzle <pkienzle@users.sf.net>
 
-function ret = fail (code, pattern, warning_pattern)
+function retval = fail (code, pattern, warning_pattern)
 
   if (nargin < 1 || nargin > 3)
     print_usage ();
   endif
 
-  ## sort out arguments
+  ## Parse input arguments
   test_warning = (nargin > 1 && strcmp (pattern, "warning"));
   if (nargin == 3)
     pattern = warning_pattern;
@@ -74,52 +74,50 @@
     pattern = "";
   endif
 
-  ## match any nonempty message
+  ## Match any nonempty message
   if (isempty (pattern))
     pattern = ".";
   endif
 
-  ## allow assert (fail ())
+  ## Allow assert (fail ())
   if (nargout)
-    ret = 1;
+    retval = true;
   endif
 
   if (test_warning)
     ## Perform the warning test.
     ## Clear old warnings.
-    lastwarn ();
+    lastwarn ("");
     ## Make sure warnings are turned on.
     state = warning ("query", "quiet");
     warning ("on", "quiet");
     try
-      ## printf ("lastwarn before %s: %s\n",code,lastwarn);
-      evalin ("caller", sprintf ("%s;", code));
-      ## printf ("lastwarn after %s: %s\n",code,lastwarn);
+      evalin ("caller", [code ";"]);
       ## Retrieve new warnings.
-      err = lastwarn ();
+      warn = lastwarn ();
       warning (state.state, "quiet");
-      if (isempty (err))
+      if (isempty (warn))
         msg = sprintf ("expected warning <%s> but got none", pattern);
       else
         ## Transform "warning: ...\n" to "...".
-        err([1:9, end]) = [];
-        if (! isempty (regexp (err, pattern, "once")))
+        warn([1:9, end]) = [];
+        if (! isempty (regexp (warn, pattern, "once")))
           return;
         endif
-        msg = sprintf ("expected warning <%s>\nbut got <%s>", pattern, err);
+        msg = sprintf ("expected warning <%s>\nbut got <%s>", pattern, warn);
       endif
     catch
       warning (state.state, "quiet");
       err = lasterr;
       ## Transform "error: ...\n", to "...".
-      err([1:7, end]) = [];
-      msg = sprintf ("expected warning <%s> but got error <%s>", pattern, err);
+      err([1:6, end]) = [];
+      msg = sprintf ("expected warning <%s>\nbut got error <%s>", pattern, err);
     end_try_catch
 
   else
     ## Perform the error test.
     try
-      evalin ("caller", sprintf ("%s;", code));
+      evalin ("caller", [code ";"]);
       msg = sprintf ("expected error <%s> but got none", pattern);
     catch
       err = lasterr ();
@@ -147,8 +145,12 @@
 ##% !fail ("warning ('next test')",'warning','next test');  ## only allowed one warning test?!?
 
 %% Test that fail() itself will generate an error
-%!error fail ("1")
-%!error <undefined> fail ("a*[2;3]", "nonconformant")
-%!error <expected error>  fail ("a*[2,3]", "usage:")
+%!error <expected error> fail ("1")
+%!error <'a' undefined> fail ("a*[2;3]", "nonconformant")
+%!error <expected error .usage:>  fail ("a*[2,3]", "usage:")
 %!error <warning failure> fail ("warning ('warning failure')", "warning", "success")
 
+%% Test input validation
+%!error fail ()
+%!error fail (1,2,3,4)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/testfun/private/compare_plot_demos.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,119 @@
+## Copyright (C) 2012 Ben Abbott  <bpabbott@mac.com>
+##
+## 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} {} compare_plot_demos ()
+## @deftypefnx {Function File} {} compare_plot_demos ("toolkits", @{@var{toolkit1}, @var{toolkit2}, @dots{}@})
+##
+## Uses @code{dump_demos} and @code{html_compare_plot_demos} to produce an
+## html comparison of the plot demos for each of Octave's graphics toolkits.
+##
+## An m-file named @file{dump_plots.m} will be created in the current working
+## directory.  This function will be used to render and save the plot demo
+## images.
+##
+## If they do not already exist, directories for each available graphics
+## toolkit are created.  Each toolkit's directory will be populated with images
+## of each plot demo in the png format.
+##
+## Finally, an html document named @file{compare_plot_demos.html} is produced.
+## This page places each toolkit's images side by side for a convenient
+## comparison of the results.
+##
+## If the property @qcode{"toolkits"} is given then compare only the listed
+## toolkits in the cell string.  The list may also include the toolkit
+## @qcode{"matlab"}.
+##
+## @end deftypefn
+
+## Author: Ben Abbott  <bpabbott@mac.com>
+
+function compare_plot_demos (varargin)
+
+  arg.toolkits = available_graphics_toolkits ();
+  arg.directories = {"plot/appearance", "plot/draw", "plot/util", "image"};
+  arg.fmt = "png";
+  arg.fcn_file = "dump_plot_demos.m";
+  arg.replace_images = false;
+
+  for n = 1:2:numel(varargin)
+    if (! ischar (varargin{n}))
+      print_usage ();
+    else
+      arg.(varargin{n}) = varargin{n+1};
+    endif
+  endfor
+
+  if (ischar (arg.toolkits))
+    arg.toolkits = {arg.toolkits};
+  elseif (! iscellstr (arg.toolkits))
+    error ('compare_plot_demos: Invalid value for "toolkits"')
+  endif
+
+  if (ischar (arg.directories))
+    arg.directories = {arg.directories};
+  elseif (! iscellstr (arg.directories))
+    error ('compare_plot_demos: Invalid value for "directory"')
+  endif
+
+  if (! ischar (arg.fmt))
+    error ('compare_plot_demos: Invalid value for "fmt"')
+  endif
+
+  ## Generate arg.fcn_file for rendering/saving the plot demo images
+  dump_demos (arg.directories, arg.fcn_file, arg.fmt);
+
+  [~, fcn_name] = fileparts (arg.fcn_file);
+
+  ## Generate the plot demo images for each toolkit
+  cwd = pwd ();
+  unwind_protect
+    addpath (pwd);
+    for n = 1:numel (arg.toolkits)
+      if (! isdir (fullfile (cwd, arg.toolkits{n})))
+        mkdir (arg.toolkits{n});
+      endif
+      cd (arg.toolkits{n});
+      if (arg.replace_images && ! isempty (dir (["*." arg.fmt])))
+        delete (["*." arg.fmt]);
+      endif
+      if (! strcmp (arg.toolkits{n}, "matlab"))
+        close all;
+        graphics_toolkit (arg.toolkits{n});
+        try
+          eval (fcn_name);
+        catch
+          printf ("Error running plot demos for ""%s"" toolkit\n", arg.toolkits{n});
+          disp (lasterror);
+        end_try_catch
+      endif
+      cd (cwd);
+    endfor
+  unwind_protect_cleanup
+    rmpath (cwd);
+  end_unwind_protect
+  if (! strcmp (arg.toolkits, "matlab"))
+    ## Generate the html comparison of the images
+    html_compare_plot_demos (arg.toolkits);
+  else
+    ## We need to run matlab manually before the html page can be created
+    printf ('\nNow run %s in Matlab.\nAfter this run html_compare_plot_demos,\n', arg.fcn_file);
+    printf ('for example html_compare_plot_demos ({"fltk", "gnuplot", "matlab"}), to create the html page.\n');
+  endif
+endfunction
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/testfun/private/dump_demos.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,187 @@
+## Copyright (C) 2010 Søren Hauberg
+##
+## 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} {} dump_demos ()
+## @deftypefnx {Function File} {} dump_demos (@var{dirs})
+## @deftypefnx {Function File} {} dump_demos (@var{dirs}, @var{mfile})
+## @deftypefnx {Function File} {} dump_demos (@var{dirs}, @var{mfile}, @var{fmt})
+## Produce a script, with the name specified by @var{mfile}, containing
+## the demos in the directories, @var{dirs}.  The demos are assumed to produce
+## graphical output, whose renderings are saved with the specified format,
+## @var{fmt}.
+##
+## The defaults for each input are;
+##
+## @table @var
+##   @item @var{dirs}
+##   @code{@{"plot/appearance", "plot/draw", "plot/util", "image"@}}
+##
+##   @item @var{mfile}
+##   @qcode{"dump.m"}
+##
+##   @item @var{fmt}
+##   @qcode{"png"}
+## @end table
+##
+## For example, to produce PNG output for all demos of the functions
+## in the plot directory;
+##
+## @example
+## dump_demos plot dump.m png
+## @end example
+## @seealso{fntests, test, demo}
+## @end deftypefn
+
+## Author: Søren Hauberg  <soren@hauberg.org>
+
+function dump_demos (dirs={"plot/appearance", "plot/draw", "plot/util", "image"}, output="dump_plot_demos.m", fmt="png")
+
+  if (nargin > 3)
+    print_usage ();
+  endif
+
+  if (ischar (dirs))
+    dirs = {dirs};
+  elseif (! iscellstr (dirs))
+    error ("dump_demos: DIRS must be a cell array of strings with directory names");
+  endif
+
+  [~, funcname, ext] = fileparts (output);
+  if (isempty (ext))
+    output = [output ".m"];
+  endif
+
+  ## Create script beginning (close figures, etc.)
+  fid = fopen (output, "w");
+  fprintf (fid, "%% DO NOT EDIT!  Generated automatically by dump_demos.m\n");
+  fprintf (fid, "function %s ()\n", funcname);
+  fprintf (fid, "close all\n");
+  fprintf (fid, "more off\n");
+  fprintf (fid, "diary diary.log\n");
+
+  ## Run and print the demos in each directory
+  for i = 1:numel (dirs)
+    d = dirs{i};
+    if (! is_absolute_filename (d))
+      d = dir_in_loadpath (d);
+    endif
+    if (! exist (d, "dir"))
+      error ("dump_demos: directory %s does not exist", d);
+    endif
+    dump_all_demos (d, fid, fmt);
+  endfor
+
+  ## Stop and flush diary
+  fprintf (fid, "diary off\n");
+
+  ## Create script ending
+  fprintf (fid, "end\n\n")
+
+  ## Close script
+  fclose (fid);
+endfunction
+
+function dump_all_demos (directory, fid, fmt)
+  dirinfo = dir (fullfile (directory, "*.m"));
+  flist = {dirinfo.name};
+  ## Remove uigetdir, uigetfile, uiputfile, etc.
+  flist = flist(! strncmp (flist, "ui", 2));
+  ## Remove linkaxes, linkprops
+  flist = flist(! strncmp (flist, "link", 4));
+  ## Remove colormap
+  flist = flist(! strncmp (flist, "colormap", 8));
+  for i = 1:numel (flist)
+    fcn = flist{i};
+    fcn(end-1:end) = [];  # remove .m
+    demos = get_demos (fcn);
+    for d = 1:numel (demos)
+      idx = sprintf ("%02d", d);
+      base_fn = sprintf ("%s_%s", fcn, idx);
+      fn = sprintf ('%s.%s', base_fn, fmt);
+      fprintf (fid, "\ntry\n");
+      ## First check if the file already exists, skip demo if found
+      fprintf (fid, " if (! exist ('%s', 'file'))\n", fn);
+      ## Invoke the ancient, deprecated random seed
+      ## generators, but there is an initialization mismatch with the more modern
+      ## generators reported here (https://savannah.gnu.org/bugs/?42557).
+      fprintf (fid, "  rand ('seed', 1);\n");
+      fprintf (fid, "  tic ();\n");
+      fprintf (fid, "  %s\n\n", demos{d});
+      fprintf (fid, "  t_plot = toc ();\n");
+      fprintf (fid, "  fig = (get (0, 'currentfigure'));\n");
+      fprintf (fid, "  if (~ isempty (fig))\n");
+      fprintf (fid, "    figure (fig);\n");
+      fprintf (fid, "      fprintf ('Printing ""%s"" ... ');\n", fn);
+      fprintf (fid, "      tic ();\n");
+      fprintf (fid, "      print ('-d%s', '%s');\n", fmt, fn);
+      fprintf (fid, "      t_print = toc ();\n");
+      fprintf (fid, "      fprintf ('[%%f %%f] done\\n',t_plot, t_print);\n");
+      fprintf (fid, "  end\n");
+      # Temporary fix for cruft accumulating in figure window.
+      fprintf (fid, "  close ('all');\n");
+      fprintf (fid, " else\n");
+      fprintf (fid, "   fprintf ('File ""%s"" already exists.\\n');\n", fn);
+      fprintf (fid, " end\n");
+      fprintf (fid, "catch\n");
+      fprintf (fid, "  fprintf ('ERROR in %s: %%s\\n', lasterr ());\n", base_fn);
+      fprintf (fid, "  err_fid = fopen ('%s.err', 'w');\n", base_fn);
+      fprintf (fid, "  fprintf (err_fid, '%%s', lasterr ());\n");
+      fprintf (fid, "  fclose (err_fid);\n");
+      fprintf (fid, "end\n\n");
+    endfor
+  endfor
+  fprintf (fid, "close all\n");
+endfunction
+
+function retval = get_demos (fcn)
+  [code, idx] = test (fcn, "grabdemo");
+  num_demos = length (idx) - 1;
+  retval = cell (1, num_demos);
+  ## Now split the demos into a cell array
+  for k = 1:num_demos
+    retval{k} = oct2mat (code(idx(k):idx(k+1)-1));
+  endfor
+endfunction
+
+function code = oct2mat (code)
+  ## Simple hacks to make things Matlab compatible
+  code = strrep (code, "%!", "%%");
+  code = strrep (code, "!", "~");
+  ## Simply replacing double quotes with single quotes
+  ## causes problems with strings like 'hello "world"'
+  ## More complicated regexprep targets only full double quoted strings
+  code = regexprep (code, "^([^']*)\"(.*)\"", "$1'$2'",
+                          "lineanchors", "dotexceptnewline");
+  code = strrep (code, "#", "%");
+  ## Fix the format specs for the errorbar demos changed by the line above
+  code = strrep (code, "%r", "#r");
+  code = strrep (code, "%~", "#~");
+  endkeywords = {"endfor", "endfunction", "endif", "endwhile", "end_try_catch"};
+  for k = 1:numel (endkeywords)
+    code = strrep (code, endkeywords{k}, "end");
+  endfor
+  commentkeywords = {"unwind_protect", "end_unwind_protect"};
+  for k = 1:numel (commentkeywords)
+    code = strrep (code, commentkeywords{k}, ["%" commentkeywords{k}]);
+  endfor
+
+  ## Fix up sombrero which now has default argument in Octave
+  code = strrep (code, "sombrero ()", "sombrero (41)");
+endfunction
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/testfun/private/html_compare_plot_demos.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,135 @@
+## Copyright (C) 2010 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/>.
+
+## -*- texinfo -*-
+## @deftypefn  {Function File} {} html_compare (@var{toolkits})
+## @deftypefnx {Function File} {} html_compare (@var{toolkits}, @var{name}, @var{value}, @dots{})
+##
+## Produces an html document to compare the plot demos produced by
+## @var{toolkits}.
+##
+## Valid property names, and their defaults, are:
+##
+## @table @samp
+##   @item fmt
+##   @code{"png"}
+##
+##   @item output
+##   @code{"compare_plot_demos.html"}
+##
+##   @item template
+##   @code{"html_plot_demos_template.html"}
+##
+##   @item column_width
+##   @code{600}
+## @end table
+##
+## The template parameter refers to a specially formatted html file
+## which accompanies this m-file script.
+##
+## Additional toolkit description can be added to the column header
+## with a parameter named equal to the toolkit.  For example:
+##
+## @example
+## @group
+##   @code{html_compare_plot_demos ({"gnuplot", "fltk"}, "gnuplot", " 4.6 patchlevel 5")}
+## @end group
+## @end example
+##
+## @seealso{compare_plot_demos, dump_demos, demo}
+## @end deftypefn
+
+## Author: Ben Abbott  <bpabbott@mac.com>
+
+function html_compare_plot_demos (toolkits, varargin)
+
+  ## Set defaults
+  in.fmt = "png";
+  in.figfiles = {};
+  in.output= "compare_plot_demos.html";
+  in.template = "html_plot_demos_template.html";
+  in.column_width = 600;
+
+  ## Parse inputs
+  for n = 1:2:numel(varargin)
+    in.(lower(varargin{n})) = varargin{n+1};
+  endfor
+
+  ## Compile a list of all files for all toolkits
+  for t = 1:numel(toolkits)
+    filter = sprintf ("%s/*.%s", toolkits{t}, in.fmt);
+    in.figfiles = union (in.figfiles, {dir(filter).name});
+  endfor
+
+  fid = fopen (which (in.template), "r");
+  template = char (fread (fid)) .';
+  fclose (fid);
+
+  anchor = "<!-- ##ADD TABLE HERE## -->";
+  n = findstr (template, anchor);
+  header = template(1:n-1);
+  trailer = template(n+numel(anchor):end);
+
+  fid = fopen (in.output, "w");
+  unwind_protect
+    fputs (fid, header);
+    fprintf (fid, "<p><b>\nGenerated on %s by %s with GNU Octave %s</p>",
+             datestr (now (), 0), mfilename, version);
+
+    ## Create table header
+    fprintf (fid, "<table border='1'><tr>\n");
+    for t = 1:numel(toolkits)
+      ## set default
+      column_header = upper (toolkits{t});
+      if (isfield (in, toolkits{t}))
+        column_header = strcat (column_header, in.(toolkits{t}));
+      endif
+      fprintf (fid, '<th>%s <a href="%s/diary.log">diary</a></th>\n', column_header, toolkits{t});
+    endfor
+    fprintf (fid, "</tr>\n");
+
+    for m = 1:numel(in.figfiles)
+      [~, file] = fileparts (in.figfiles{m});
+      fn = strcat (file, ".", in.fmt);
+      fprintf (fid, "<tr>\n");
+      for k = toolkits
+        ffn = fullfile (k{:}, fn);
+        fprintf (fid, "  <td>%s<br>", ffn);
+        if (exist (ffn, "file"))
+          fprintf (fid, "<img src='%s' style='width: %dpx;'>", ffn, in.column_width);
+        else
+          err_fn = regexprep(ffn, ".png", ".err");
+          if (! exist (err_fn, "file"))
+            warning("File %s doesn't exist...", err_fn);
+          else
+            err_fid = fopen (err_fn);
+            msg = char (fread (err_fid))';
+            fclose (err_fid);
+            fprintf (fid, "%s", strrep (msg, "\n", "<br>"));
+          endif
+        endif
+        fprintf (fid, "</td>\n");
+      endfor
+      fprintf (fid, "</tr>\n");
+    endfor
+    fputs (fid, trailer);
+  unwind_protect_cleanup
+    fclose (fid);
+  end_unwind_protect
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/testfun/private/html_plot_demos_template.html	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,62 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+  <head>
+  <meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
+  <meta name="date" content="##DATE##"/>
+  <meta name="author" content="The Octave-Forge Community" />
+  <meta name="description" content="Octave-Forge is a collection of packages providing extra functionality for GNU Octave." />
+  <meta name="keywords" lang="en" content="Octave-Forge, Octave, extra packages" />
+  <title>Comparision of plots</title>
+
+  <link rel="stylesheet" type="text/css" href="../octave-forge.css" />
+  <script src="../fixed.js" type="text/javascript"></script>
+   <script src="../javascript.js" type="text/javascript"></script>
+  <link rel="shortcut icon" href="../favicon.ico" />
+  </head>
+  <body onload="javascript:fix_top_menu(); javascript:show_left_menu ();">
+  <div id="top-menu" class="menu">
+   <table class="menu">
+
+      <tr>
+        <td style="width: 90px;" class="menu" rowspan="2">
+          <a name="top">
+          <img src="../oct.png" alt="Octave logo" />
+          </a>
+        </td>
+        <td class="menu" style="padding-top: 0.9em;">
+          <big class="menu">Octave-Forge</big><small class="menu"> - Extra packages for GNU Octave</small>
+
+        </td>
+      </tr>
+      <tr>
+        <td class="menu">
+
+ <a href="../index.html" class="menu">Home</a> &middot;
+ <a href="../packages.php" class="menu">Packages</a> &middot;
+ <a href="../developers.html" class="menu">Developers</a> &middot;
+ <a href="../docs.html" class="menu">Documentation</a> &middot;
+ <a href="../FAQ.html" class="menu">FAQ</a> &middot;
+ <a href="../bugs.html" class="menu">Bugs</a> &middot;
+ <a href="../archive.html" class="menu">Mailing Lists</a> &middot;
+ <a href="../links.html" class="menu">Links</a> &middot;
+ <a href="http://sourceforge.net/svn/?group_id=2888" class="menu">SVN</a>
+
+        </td>
+      </tr>
+    </table>
+  </div>
+
+<div id="content">
+<!-- ##ADD TABLE HERE## -->
+</tr>
+</table>
+
+<div id="sf_logo">
+  <a href="http://sourceforge.net"><img src="http://sourceforge.net/sflogo.php?group_id=2888&amp;type=1"
+     width="88" height="31" style="border: 0;" alt="SourceForge.net Logo"/></a>
+</div>
+</div>
+</body>
+</html>
+
--- a/scripts/testfun/rundemos.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/testfun/rundemos.m	Mon Jan 12 09:17:35 2015 -0800
@@ -19,13 +19,14 @@
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {} rundemos ()
 ## @deftypefnx {Function File} {} rundemos (@var{directory})
-## Execute built-in demos for all function files in the specified directory.
-## Also executes demos in any C++ source files found in the directory, for
-## use with dynamically linked functions.
+## Execute built-in demos for all m-files in the specified @var{directory}.
+##
+## Demo blocks in any C++ source files (@file{*.cc}) will also be executed
+## for use with dynamically linked oct-file functions.
 ##
 ## If no directory is specified, operate on all directories in Octave's
 ## search path for functions.
-## @seealso{runtests, path}
+## @seealso{demo, runtests, path}
 ## @end deftypefn
 
 ## Author: jwe
@@ -42,7 +43,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
@@ -72,7 +73,7 @@
         try
           demo (f);
         catch
-          printf ("error: %s\n\n", lasterror().message);
+          printf ("error: %s\n\n", lasterror ().message);
         end_try_catch
         if (i != numel (flist))
           input ("Press <enter> to continue: ", "s");
--- a/scripts/testfun/runtests.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/testfun/runtests.m	Mon Jan 12 09:17:35 2015 -0800
@@ -19,13 +19,14 @@
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {} runtests ()
 ## @deftypefnx {Function File} {} runtests (@var{directory})
-## Execute built-in tests for all function files in the specified directory.
-## Also executes tests in any C++ source files found in the directory, for
-## use with dynamically linked functions.
+## Execute built-in tests for all m-files in the specified @var{directory}.
+##
+## Test blocks in any C++ source files (@file{*.cc}) will also be executed
+## for use with dynamically linked oct-file functions.
 ##
 ## If no directory is specified, operate on all directories in Octave's
 ## search path for functions.
-## @seealso{rundemos, path}
+## @seealso{rundemos, test, path}
 ## @end deftypefn
 
 ## Author: jwe
@@ -42,7 +43,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 12 09:13:19 2015 -0800
+++ b/scripts/testfun/test.m	Mon Jan 12 09:17:35 2015 -0800
@@ -20,125 +20,174 @@
 ## @deftypefn  {Command} {} test @var{name}
 ## @deftypefnx {Command} {} test @var{name} quiet|normal|verbose
 ## @deftypefnx {Function File} {} test ("@var{name}", "quiet|normal|verbose", @var{fid})
-## @deftypefnx {Function File} {} test ([], "explain", @var{fid})
+## @deftypefnx {Function File} {} test ("@var{name}", "quiet|normal|verbose", @var{fname})
 ## @deftypefnx {Function File} {@var{success} =} test (@dots{})
-## @deftypefnx {Function File} {[@var{n}, @var{max}] =} test (@dots{})
+## @deftypefnx {Function File} {[@var{n}, @var{nmax}, @var{nxfail}, @var{nskip}] =} test (@dots{})
 ## @deftypefnx {Function File} {[@var{code}, @var{idx}] =} test ("@var{name}", "grabdemo")
+## @deftypefnx {Function File} {} test ([], "explain", @var{fid})
+## @deftypefnx {Function File} {} test ([], "explain", @var{fname})
+##
+## Perform built-in self-tests from the first file in the loadpath matching
+## @var{name}.
+##
+## @code{test} can be called in either command or functional form.  The exact
+## operation of test is determined by a combination of mode (interactive or
+## batch), reporting level (@qcode{"quiet"}, @qcode{"normal"},
+## @qcode{"verbose"}), and whether a logfile or summary output variable is
+## used.
 ##
-## Perform tests from the first file in the loadpath matching @var{name}.
-## @code{test} can be called as a command or as a function.  Called with
-## a single argument @var{name}, the tests are run interactively and stop
-## after the first error is encountered.
+## The default mode when @code{test} is called from the command line is
+## interactive.  In this mode, tests will be run until the first error is
+## encountered, or all tests complete successfully.  In batch mode, all tests
+## are run regardless of any failures, and the results are collected for
+## reporting.  Tests which require user interaction, i.e., demo blocks,
+## are never run in batch mode.
 ##
-## With a second argument the tests which are performed and the amount of
-## output is selected.
+## Batch mode is enabled by either 1) specifying a logfile using the third
+## argument @var{fname} or @var{fid}, or 2) requesting an output argument
+## such as @var{success}, @var{n}, etc.
+##
+## The optional second argument determines the amount of output to generate and
+## which types of tests to run.  The default value is @qcode{"normal"}. 
+## Requesting an output argument will suppress printing the final summary
+## message and any intermediate warnings, unless verbose reporting is
+## enabled.
 ##
 ## @table @asis
 ## @item @qcode{"quiet"}
-##  Don't report all the tests as they happen, just the errors.
+## Print a summary message when all tests pass, or print an error with the
+## results of the first bad test when a failure occurs.  Don't run tests which
+## require user interaction.
 ##
 ## @item @qcode{"normal"}
-## Report all tests as they happen, but don't do tests which require
-## user interaction.
+## Display warning messages about skipped tests or failing xtests during test
+## execution.
+## Print a summary message when all tests pass, or print an error with the
+## results of the first bad test when a failure occurs.  Don't run tests which
+## require user interaction.
 ##
 ## @item @qcode{"verbose"}
-## Do tests which require user interaction.
+## Display tests before execution.  Print all warning messages.  In interactive
+## mode, run all tests including those which require user interaction.
 ## @end table
 ##
-## The argument @var{fid} can be used to allow batch processing.  Errors
-## can be written to the already open file defined by @var{fid}, and
-## hopefully when Octave crashes this file will tell you what was happening
-## when it did.  You can use @code{stdout} if you want to see the results as
-## they happen.  You can also give a file name rather than an @var{fid}, in
-## which case the contents of the file will be replaced with the log from
-## the current test.
+## The optional third input argument specifies a logfile where results of the
+## tests should be written.  The logfile may be a character string
+## (@var{fname}) or an open file descriptor ID (@var{fid}).  To enable batch
+## processing, but still print the results to the screen, use @code{stdout} for
+## @var{fid}.
+##
+## When called with just a single output argument @var{success}, @code{test}
+## returns true if all of the tests were successful.  If called with more
+## than one output argument then the number of successful tests (@var{n}),
+## the total number of tests in the file (@var{nmax}), the number of xtest
+## failures (@var{nxfail}), and the number of skipped tests (@var{nskip} are
+## returned.
+##
+## Example
 ##
-## Called with a single output argument @var{success}, @code{test} returns
-## true if all of the tests were successful.  Called with two output arguments
-## @var{n} and @var{max}, the number of successful tests and the total number
-## of tests in the file @var{name} are returned.
+## @example
+## @group
+## test sind
+## @result{}
+## PASSES 5 out of 5 tests
+##
+## [n, nmax] = test ("sind")
+## @result{}
+## n =  5
+## nmax =  5
+## @end group
+## @end example
+## 
+## Additional Calling Syntaxes
 ##
 ## If the second argument is the string @qcode{"grabdemo"}, the contents of
-## the demo blocks are extracted but not executed.  Code for all code blocks
-## is concatenated and returned as @var{code} with @var{idx} being a vector
-## of positions of the ends of the demo blocks.
+## any built-in demo blocks are extracted but not executed.  The text for all
+## code blocks is concatenated and returned as @var{code} with @var{idx} being
+## a vector of positions of the ends of each demo block.  For an easier way to
+## extract demo blocks from files, @xref{XREFexample,,example}.
 ##
-## If the second argument is @qcode{"explain"}, then @var{name} is ignored
-## and an explanation of the line markers used is written to the file
-## @var{fid}.
-## @seealso{assert, fail, error, demo, example}
+## If the second argument is @qcode{"explain"} then @var{name} is ignored and
+## an explanation of the line markers used in @code{test} output reports is
+## written to the file specified by @var{fname} or @var{fid}.
+##
+## @seealso{assert, fail, demo, example, error}
 ## @end deftypefn
 
-## FIXME: * Consider using keyword fail rather then error?  This allows us
-## to make a functional form of error blocks, which means we
-## can include them in test sections which means that we can use
-## octave flow control for both kinds of tests.
+## Programming Note: All variables for test() must use the internal prefix "__".
+## Shared variables are eval'ed into the current workspace and therefore might
+## collide with the names used in the test.m function itself.
 
-function [__ret1, __ret2, __ret3, __ret4] = test (__name, __flag, __fid)
-  ## Information from test will be introduced by "key".
-  persistent __signal_fail =  "!!!!! ";
+function [__n, __nmax, __nxfail, __nskip] = test (__name, __flag = "normal", __fid = [])
+
+  ## Output from test is prefixed by a "key" to quickly understand the issue.
+  persistent __signal_fail  = "!!!!! ";
   persistent __signal_empty = "????? ";
-  persistent __signal_block = "  ***** ";
-  persistent __signal_file =  ">>>>> ";
-  persistent __signal_skip = "----- ";
-
-  __xfail = 0;
-  __xskip = 0;
+  persistent __signal_block = "***** ";
+  persistent __signal_file  = ">>>>> ";
+  persistent __signal_skip  = "----- ";
 
-  if (nargin < 2 || isempty (__flag))
-    __flag = "quiet";
-  endif
-  if (nargin < 3)
-    __fid = [];
-  endif
-  if (nargin < 1 || nargin > 3
-      || (! ischar (__name) && ! isempty (__name)) || ! ischar (__flag))
+  if (nargin < 1 || nargin > 3)
+    print_usage ();
+  elseif (! isempty (__name) && ! ischar (__name))
+    error ("test: NAME must be a string");
+  elseif (! ischar (__flag))
+    error ("test: second argument must be a string");
+  elseif (isempty (__name) && (nargin != 3 || ! strcmp (__flag, "explain")))
     print_usage ();
   endif
-  if (isempty (__name) && (nargin != 3 || ! strcmp (__flag, "explain")))
-    print_usage ();
-  endif
-  __batch = (! isempty (__fid));
 
   ## Decide if error messages should be collected.
-  __close_fid = 0;
-  if (__batch)
+  __logfile = ! isempty (__fid);
+  __batch = __logfile || nargout > 0;
+  __close_fid = false;
+  if (__logfile)
     if (ischar (__fid))
-      __fid = fopen (__fid, "wt");
+      __fname = __fid;
+      __fid = fopen (__fname, "wt");
       if (__fid < 0)
-        error ("test: could not open log file");
+        error ("test: could not open log file %s", __fname);
       endif
-      __close_fid = 1;
+      __close_fid = true;
     endif
-    fprintf (__fid, "%sprocessing %s\n", __signal_file, __name);
-    fflush (__fid);
+    if (! strcmp (__flag, "explain"))
+      fprintf (__fid, "%sprocessing %s\n", __signal_file, __name);
+      fflush (__fid);
+    endif
   else
     __fid = stdout;
   endif
 
   if (strcmp (__flag, "normal"))
-    __grabdemo = 0;
-    __rundemo = 0;
-    __verbose = __batch;
+    __grabdemo = false;
+    __rundemo  = false;
+    if (__logfile)
+      __verbose = 1;
+    elseif (__batch)
+      __verbose = -1;
+    else
+      __verbose = 0;
+    endif
   elseif (strcmp (__flag, "quiet"))
-    __grabdemo = 0;
-    __rundemo = 0;
-    __verbose = 0;
+    __grabdemo = false;
+    __rundemo  = false;
+    __verbose  = -1;
   elseif (strcmp (__flag, "verbose"))
-    __grabdemo = 0;
-    __rundemo = 1;
-    __verbose = 1;
+    __grabdemo = false;
+    __rundemo  = true;
+    __verbose  = 1;
   elseif (strcmp (__flag, "grabdemo"))
-    __grabdemo = 1;
-    __rundemo = 0;
-    __verbose = 0;
+    __grabdemo = true;
+    __rundemo  = false;
+    __verbose  = -1;
     __demo_code = "";
     __demo_idx = [];
   elseif (strcmp (__flag, "explain"))
     fprintf (__fid, "# %s new test file\n", __signal_file);
     fprintf (__fid, "# %s no tests in file\n", __signal_empty);
     fprintf (__fid, "# %s test had an unexpected result\n", __signal_fail);
-    fprintf (__fid, "# %s code for the test\n", __signal_block);
+    fprintf (__fid, "# %s test was skipped\n", __signal_skip);
+    fprintf (__fid, "# %s code for the test\n\n", __signal_block);
     fprintf (__fid, "# Search for the unexpected results in the file\n");
     fprintf (__fid, "# then page back to find the file name which caused it.\n");
     fprintf (__fid, "# The result may be an unexpected failure (in which\n");
@@ -162,17 +211,16 @@
     __file = file_in_loadpath ([__name ".cc"], "all");
   endif
   if (iscell (__file))
-      ## If repeats, return first in path.
     if (isempty (__file))
       __file = "";
     else
-      __file = __file{1};
+      __file = __file{1};  # If repeats, return first in path.
     endif
   endif
   if (isempty (__file))
     if (__grabdemo)
-      __ret1 = "";
-      __ret2 = -1;
+      __n = "";
+      __nmax = -1;
     else
       ftype = exist (__name);
       if (ftype == 3)
@@ -188,7 +236,11 @@
       endif
       fflush (__fid);
       if (nargout > 0)
-        __ret1 = __ret2 = 0;
+        if (nargout == 1)
+          __n = false;
+        else
+          __n = __nmax = 0;
+        endif
       endif
     endif
     if (__close_fid)
@@ -202,13 +254,17 @@
 
   if (isempty (__body))
     if (__grabdemo)
-      __ret1 = "";
-      __ret2 = [];
+      __n = "";
+      __nmax = [];
     else
       fprintf (__fid, "%s%s has no tests available\n", __signal_empty, __file);
       fflush (__fid);
       if (nargout > 0)
-        __ret1 = __ret2 = 0;
+        if (nargout == 1)
+          __n = false;
+        else
+          __n = __nmax = 0;
+        endif
       endif
     endif
     if (__close_fid)
@@ -217,10 +273,10 @@
     return;
   else
     ## Add a dummy comment block to the end for ease of indexing.
-    if (__body (length (__body)) == "\n")
-      __body = sprintf ("\n%s#", __body);
+    if (__body(end) == "\n")
+      __body = ["\n" __body "#"];
     else
-      __body = sprintf ("\n%s\n#", __body);
+      __body = ["\n" __body "\n#"];
     endif
   endif
 
@@ -228,354 +284,368 @@
   __lineidx = find (__body == "\n");
   __blockidx = __lineidx(find (! isspace (__body(__lineidx+1))))+1;
 
-  ## Ready to start tests ... if in batch mode, tell us what is happening.
-  if (__verbose)
+  ## Ready to start tests.
+  ## If in batch mode, with a logfile, report what is happening.
+  if (__verbose > 0)
     disp ([__signal_file, __file]);
   endif
 
   ## Assume all tests will pass.
-  __all_success = 1;
+  __all_success = true;
 
   ## Process each block separately, initially with no shared variables.
   __tests = __successes = 0;
+  __xfail = __xskip = 0;
   __shared = " ";
   __shared_r = " ";
-  __clear = "";
-  for __i = 1:length (__blockidx)-1
-
-    ## Extract the block.
-    __block = __body(__blockidx(__i):__blockidx(__i+1)-2);
+  __clearfcn = "";
+  for __i = 1:numel (__blockidx)-1
 
-    ## Let the user/logfile know what is happening.
-    if (__verbose)
-      fprintf (__fid, "%s%s\n", __signal_block, __block);
-      fflush (__fid);
-    endif
+    ## FIXME: Should other global settings be similarly saved and restored?
+    orig_wstate = warning ();
+    unwind_protect
+
+      ## Extract the block.
+      __block = __body(__blockidx(__i):__blockidx(__i+1)-2);
 
-    ## Split __block into __type and __code.
-    __idx = find (! isletter (__block));
-    if (isempty (__idx))
-      __type = __block;
-      __code = "";
-    else
-      __type = __block(1:__idx(1)-1);
-      __code = __block(__idx(1):length (__block));
-    endif
+      ## Print the code block before execution if in verbose mode.
+      if (__verbose > 0)
+        fprintf (__fid, "%s%s\n", __signal_block, __block);
+        fflush (__fid);
+      endif
 
-    ## Assume the block will succeed.
-    __success = 1;
-    __msg = [];
+      ## Split __block into __type and __code.
+      __idx = find (! isletter (__block));
+      if (isempty (__idx))
+        __type = __block;
+        __code = "";
+      else
+        __type = __block(1:__idx(1)-1);
+        __code = __block(__idx(1):length (__block));
+      endif
+
+      ## Assume the block will succeed.
+      __success = true;
+      __msg = [];
+      __isxtest = false;
 
 ### DEMO
 
-    ## If in __grabdemo mode, then don't process any other block type.
-    ## So that the other block types don't have to worry about
-    ## this __grabdemo mode, the demo block processor grabs all block
-    ## types and skips those which aren't demo blocks.
+      ## If in __grabdemo mode, then don't process any other block type.
+      ## So that the other block types don't have to worry about
+      ## this __grabdemo mode, the demo block processor grabs all block
+      ## types and skips those which aren't demo blocks.
+
+      __isdemo = strcmp (__type, "demo");
+      if (__grabdemo || __isdemo)
+        __istest = false;
 
-    __isdemo = strcmp (__type, "demo");
-    if (__grabdemo || __isdemo)
-      __istest = 0;
+        if (__grabdemo && __isdemo)
+          if (isempty (__demo_code))
+            __demo_code = __code;
+            __demo_idx = [1, length(__demo_code)+1];
+          else
+            __demo_code = [__demo_code, __code];
+            __demo_idx = [__demo_idx, length(__demo_code)+1];
+          endif
 
-      if (__grabdemo && __isdemo)
-        if (isempty (__demo_code))
-          __demo_code = __code;
-          __demo_idx = [1, length(__demo_code)+1];
-        else
-          __demo_code = [__demo_code, __code];
-          __demo_idx = [__demo_idx, length(__demo_code)+1];
+        elseif (__rundemo && __isdemo)
+          try
+            ## process the code in an environment without variables
+            eval (sprintf ("function __test__ ()\n%s\nendfunction", __code));
+            __test__;
+            input ("Press <enter> to continue: ", "s");
+          catch
+            __success = false;
+            __msg = [__signal_fail "demo failed\n" lasterr()];
+          end_try_catch
+          clear __test__;
+
         endif
-
-      elseif (__rundemo && __isdemo)
-        try
-          ## process the code in an environment without variables
-          eval (sprintf ("function __test__ ()\n%s\nendfunction", __code));
-          __test__;
-          input ("Press <enter> to continue: ", "s");
-        catch
-          __success = 0;
-          __msg = sprintf ("%sdemo failed\n%s",  __signal_fail, lasterr ());
-        end_try_catch
-        clear __test__;
-
-      endif
-      ## Code already processed.
-      __code = "";
+        ## Code already processed.
+        __code = "";
 
 ### SHARED
 
-    elseif (strcmp (__type, "shared"))
-      __istest = 0;
+      elseif (strcmp (__type, "shared"))
+        __istest = false;
 
-      ## Separate initialization code from variables.
-      __idx = find (__code == "\n");
-      if (isempty (__idx))
-        __vars = __code;
-        __code = "";
-      else
-        __vars = __code (1:__idx(1)-1);
-        __code = __code (__idx(1):length (__code));
-      endif
+        ## Separate initialization code from variables.
+        __idx = find (__code == "\n");
+        if (isempty (__idx))
+          __vars = __code;
+          __code = "";
+        else
+          __vars = __code (1:__idx(1)-1);
+          __code = __code (__idx(1):length (__code));
+        endif
 
-      ## Strip comments off the variables.
-      __idx = find (__vars == "%" | __vars == "#");
-      if (! isempty (__idx))
-        __vars = __vars(1:__idx(1)-1);
-      endif
+        ## Strip comments off the variables.
+        __idx = find (__vars == "%" | __vars == "#");
+        if (! isempty (__idx))
+          __vars = __vars(1:__idx(1)-1);
+        endif
 
-      ## Assign default values to variables.
-      try
-        __vars = deblank (__vars);
-        if (! isempty (__vars))
-          eval ([strrep(__vars, ",", "=[];"), "=[];"]);
-          __shared = __vars;
-          __shared_r = ["[ ", __vars, "] = "];
-        else
-          __shared = " ";
-          __shared_r = " ";
-        endif
-      catch
-        ## Couldn't declare, so don't initialize.
-        __code = "";
-        __success = 0;
-        __msg = sprintf ("%sshared variable initialization failed\n",
-                         __signal_fail);
-      end_try_catch
+        ## Assign default values to variables.
+        try
+          __vars = deblank (__vars);
+          if (! isempty (__vars))
+            eval ([strrep(__vars, ",", "=[];"), "=[];"]);
+            __shared = __vars;
+            __shared_r = ["[ " __vars "] = "];
+          else
+            __shared = " ";
+            __shared_r = " ";
+          endif
+        catch
+          ## Couldn't declare, so don't initialize.
+          __code = "";
+          __success = false;
+          __msg = [__signal_fail "shared variable initialization failed\n"];
+        end_try_catch
 
-      ## Initialization code will be evaluated below.
+        ## Initialization code will be evaluated below.
 
 ### FUNCTION
 
-    elseif (strcmp (__type, "function"))
-      __istest = 0;
-      persistent __fn = 0;
-      __name_position = function_name (__block);
-      if (isempty (__name_position))
-        __success = 0;
-        __msg = sprintf ("%stest failed: missing function name\n",
-                         __signal_fail);
-      else
-        __name = __block(__name_position(1):__name_position(2));
-        __code = __block;
-        try
-          eval (__code);  # Define the function
-          __clear = sprintf ("%sclear %s;\n", __clear, __name);
-        catch
-          __success = 0;
-          __msg = sprintf ("%stest failed: syntax error\n%s",
-                           __signal_fail, lasterr ());
-        end_try_catch
-      endif
-      __code = "";
+      elseif (strcmp (__type, "function"))
+        __istest = false;
+        persistent __fn = 0;
+        __name_position = function_name (__block);
+        if (isempty (__name_position))
+          __success = false;
+          __msg = [__signal_fail "test failed: missing function name\n"];
+        else
+          __name = __block(__name_position(1):__name_position(2));
+          __code = __block;
+          try
+            eval (__code);  # Define the function
+            __clearfcn = sprintf ("%sclear %s;\n", __clearfcn, __name);
+          catch
+            __success = false;
+            __msg = [__signal_fail "test failed: syntax error\n" lasterr()];
+          end_try_catch
+        endif
+        __code = "";
 
 ### ENDFUNCTION
 
-    elseif (strcmp (__type, "endfunction"))
-      ## endfunction simply declares the end of a previous function block.
-      ## There is no processing to be done here, just skip to next block.
-      __istest = 0;
-      __code = "";
+      elseif (strcmp (__type, "endfunction"))
+        ## endfunction simply declares the end of a previous function block.
+        ## There is no processing to be done here, just skip to next block.
+        __istest = false;
+        __code = "";
 
 ### ASSERT/FAIL
 
-    elseif (strcmp (__type, "assert") || strcmp (__type, "fail"))
-      __istest = 1;
-      ## Put the keyword back on the code.
-      __code = __block;
-      ## The code will be evaluated below as a test block.
+      elseif (strcmp (__type, "assert") || strcmp (__type, "fail"))
+        __istest = true;
+        ## Put the keyword back on the code.
+        __code = __block;
+        ## The code will be evaluated below as a test block.
 
 ### ERROR/WARNING
 
-    elseif (strcmp (__type, "error") || strcmp (__type, "warning"))
-      __istest = 1;
-      __warning = strcmp (__type, "warning");
-      [__pattern, __id, __code] = getpattern (__code);
-      if (__id)
-        __patstr = ["id=",__id];
-      else
-        if (! strcmp (__pattern, '.'))
-          __patstr = ["<",__pattern,">"];
+      elseif (strcmp (__type, "error") || strcmp (__type, "warning"))
+        __istest = true;
+        __iswarning = strcmp (__type, "warning");
+        [__pattern, __id, __code] = getpattern (__code);
+        if (__id)
+          __patstr = ["id=" __id];
         else
-          __patstr = ifelse (__warning, "a warning", "an error");
+          if (! strcmp (__pattern, '.'))
+            __patstr = ["<" __pattern ">"];
+          else
+            __patstr = ifelse (__iswarning, "a warning", "an error");
+          endif
         endif
-      endif
-      try
-        eval (sprintf ("function __test__(%s)\n%s\nendfunction",
-                       __shared, __code));
-      catch
-        __success = 0;
-        __msg = sprintf ("%stest failed: syntax error\n%s",
-                         __signal_fail, lasterr ());
-      end_try_catch
+        try
+          eval (sprintf ("function __test__(%s)\n%s\nendfunction",
+                         __shared, __code));
+        catch
+          __success = false;
+          __msg = [__signal_fail "test failed: syntax error\n" lasterr()];
+        end_try_catch
 
-      if (__success)
-        __success = 0;
-        __warnstate = warning ("query", "quiet");
-        warning ("on", "quiet");
-        ## Clear error and warning strings before starting
-        lasterr ("");
-        lastwarn ("");
-        try
-          ## FIXME: lastwarn () must be called once from *WITHIN* the try block
-          ##        or subsequent warning/lastwarn statements may fail.
-          ##        Likely this is something to do with the specialness of
-          ##        the try block which is disabling normal errors.
-          lastwarn ();
-          eval (sprintf ("__test__(%s);", __shared));
-          if (! __warning)
-            __msg = sprintf ("%serror failed.\nExpected %s but got no error\n",
-                             __signal_fail, __patstr);
-          else
+        if (__success)
+          __success = false;
+          __warnstate = warning ("query", "quiet");
+          warning ("on", "quiet");
+          ## Clear error and warning strings before starting
+          lasterr ("");
+          lastwarn ("");
+          try
+            eval (sprintf ("__test__(%s);", __shared));
+            if (! __iswarning)
+              __msg = [__signal_fail "error failed.\n" ...
+                                     "Expected " __patstr ", but got no error\n"];
+            else
+              if (! isempty (__id))
+                [~, __err] = lastwarn ();
+                __mismatch = ! strcmp (__err, __id);
+              else
+                __err = trimerr (lastwarn (), "warning");
+                __mismatch = isempty (regexp (__err, __pattern, "once"));
+              endif
+              warning (__warnstate.state, "quiet");
+              if (isempty (__err))
+                __msg = [__signal_fail "warning failed.\n" ...
+                                       "Expected " __patstr ", but got no warning\n"];
+              elseif (__mismatch)
+                __msg = [__signal_fail "warning failed.\n" ...
+                                       "Expected " __patstr ", but got <" __err ">\n"];
+              else
+                __success = true;
+              endif
+            endif
+
+          catch
             if (! isempty (__id))
-              [~, __err] = lastwarn ();
+              [~, __err] = lasterr ();
               __mismatch = ! strcmp (__err, __id);
             else
-              __err = trimerr (lastwarn (), "warning");
+              __err = trimerr (lasterr (), "error");
               __mismatch = isempty (regexp (__err, __pattern, "once"));
             endif
             warning (__warnstate.state, "quiet");
-            if (isempty (__err))
-              __msg = sprintf (["%swarning failed.\n" ...
-                                "Expected %s but got no warning\n"],
-                               __signal_fail, __patstr);
+            if (__iswarning)
+              __msg = [__signal_fail "warning failed.\n" ...
+                                     "Expected warning " __patstr ...
+                                     ", but got error <" __err ">\n"];
             elseif (__mismatch)
-              __msg = sprintf ("%swarning failed.\nExpected %s but got <%s>\n",
-                               __signal_fail, __patstr, __err);
+              __msg = [__signal_fail "error failed.\n" ...
+                                     "Expected " __patstr ", but got <" __err ">\n"];
             else
-              __success = 1;
+              __success = true;
             endif
+          end_try_catch
+          clear __test__;
+        endif
+        ## Code already processed.
+        __code = "";
+
+### TESTIF
+
+      elseif (strcmp (__type, "testif"))
+        __e = regexp (__code, '.$', 'lineanchors', 'once');
+        ## Strip any comment from testif line before looking for features
+        __feat_line = strtok (__code(1:__e), '#%'); 
+        __feat = regexp (__feat_line, '\w+', 'match');
+        __feat = strrep (__feat, "HAVE_", "");
+        __have_feat = __have_feature__ (__feat);
+        if (__have_feat)
+          __istest = true;
+          __code = __code(__e + 1 : end);
+        else
+          __xskip++;
+          __istest = false;
+          __code = ""; # Skip the code.
+          __msg = [__signal_skip "skipped test\n"];
+        endif
+
+### TEST
+
+      elseif (strcmp (__type, "test"))
+        __istest = true;
+        ## Code will be evaluated below.
+
+### XTEST
+
+      elseif (strcmp (__type, "xtest"))
+        __istest = false;
+        __isxtest = true;
+        ## Code will be evaluated below.
+
+### Comment block.
+
+      elseif (strcmp (__block(1:1), "#"))
+        __istest = false;
+        __code = ""; # skip the code
+
+### Unknown block.
+
+      else
+        __istest = true;
+        __success = false;
+        __msg = [__signal_fail "unknown test type!\n"];
+        __code = ""; # skip the code
+      endif
+
+      ## evaluate code for test, shared, and assert.
+      if (! isempty(__code))
+        try
+          ## FIXME: Must check for embedded test functions, which cause
+          ## segfaults, until issues with subfunctions in functions are resolved.
+          embed_func = regexp (__code, '^\s*function ', 'once', 'lineanchors');
+          if (isempty (embed_func))
+            eval (sprintf ("function %s__test__(%s)\n%s\nendfunction",
+                           __shared_r, __shared, __code));
+            eval (sprintf ("%s__test__(%s);", __shared_r, __shared));
+          else
+            error (["Functions embedded in %!test blocks are not allowed.\n", ...
+                    "Use the %!function/%!endfunction syntax instead to define shared functions for testing.\n"]);
           endif
-
         catch
-          if (! isempty (__id))
-            [~, __err] = lasterr ();
-            __mismatch = ! strcmp (__err, __id);
+          if (strcmp (__type, "xtest"))
+            __msg = [__signal_fail "known failure\n" lasterr()];
+            __xfail++;
+            __success = false;
           else
-            __err = trimerr (lasterr (), "error");
-            __mismatch = isempty (regexp (__err, __pattern, "once"));
+            __msg = [__signal_fail "test failed\n" lasterr()];
+            __success = false;
           endif
-          warning (__warnstate.state, "quiet");
-          if (__warning)
-            __msg = sprintf (["%swarning failed.\n" ...
-                              "Expected warning %s but got error <%s>\n"],
-                             __signal_fail, __patstr, __err);
-          elseif (__mismatch)
-            __msg = sprintf ("%serror failed.\nExpected %s but got <%s>\n",
-                             __signal_fail, __patstr, __err);
-          else
-            __success = 1;
+          if (isempty (lasterr ()))
+            error ("empty error text, probably Ctrl-C --- aborting");
           endif
         end_try_catch
         clear __test__;
       endif
-      ## Code already processed.
-      __code = "";
-
-### TESTIF
-
-    elseif (strcmp (__type, "testif"))
-      __e = regexp (__code, '.$', 'lineanchors', 'once');
-      ## Strip comment any comment from testif line before looking for features
-      __feat_line = strtok (__code(1:__e), '#%'); 
-      __feat = regexp (__feat_line, '\w+', 'match');
-      __feat = strrep (__feat, "HAVE_", "");
-      __have_feat = __have_feature__ (__feat);
-      if (__have_feat)
-        __istest = 1;
-        __code = __code(__e + 1 : end);
-      else
-        __xskip++;
-        __istest = 0;
-        __code = ""; # Skip the code.
-        __msg = sprintf ("%sskipped test\n", __signal_skip);
-      endif
-
-### TEST
-
-    elseif (strcmp (__type, "test") || strcmp (__type, "xtest"))
-      __istest = 1;
-      ## Code will be evaluated below.
-
-### Comment block.
-
-    elseif (strcmp (__block(1:1), "#"))
-      __istest = 0;
-      __code = ""; # skip the code
-
-### Unknown block.
-
-    else
-      __istest = 1;
-      __success = 0;
-      __msg = sprintf ("%sunknown test type!\n", __signal_fail);
-      __code = ""; # skip the code
-    endif
 
-    ## evaluate code for test, shared, and assert.
-    if (! isempty(__code))
-      try
-        ## FIXME: need to check for embedded test functions, which cause
-        ## segfaults, until issues with subfunctions in functions are resolved.
-        embed_func = regexp (__code, '^\s*function ', 'once', 'lineanchors');
-        if (isempty (embed_func))
-          eval (sprintf ("function %s__test__(%s)\n%s\nendfunction",
-                         __shared_r,__shared, __code));
-          eval (sprintf ("%s__test__(%s);", __shared_r, __shared));
-        else
-          error (["Functions embedded in %!test blocks are not allowed.\n", ...
-                  "Use the %!function/%!endfunction syntax instead to define shared functions for testing.\n"]);
+      ## All done.  Remember if we were successful and print any messages.
+      if (! isempty (__msg) && (__verbose >= 0 || __logfile))
+        ## Make sure the user knows what caused the error.
+        if (__verbose < 1)
+          fprintf (__fid, "%s%s\n", __signal_block, __block);
+          fflush (__fid);
+        endif
+        fprintf (__fid, "%s\n", __msg);
+        fflush (__fid);
+        ## Show the variable context.
+        if (! strcmp (__type, "error") && ! strcmp (__type, "testif")
+            && ! all (__shared == " "))
+          fputs (__fid, "shared variables ");
+          eval (sprintf ("fdisp(__fid,var2struct(%s));", __shared));
+          fflush (__fid);
         endif
-      catch
-        if (strcmp (__type, "xtest"))
-           __msg = sprintf ("%sknown failure\n%s", __signal_fail, lasterr ());
-           __xfail++;
-        else
-           __msg = sprintf ("%stest failed\n%s", __signal_fail, lasterr ());
-           __success = 0;
+      endif
+      if (! __success && ! __isxtest)
+        __all_success = false;
+        ## Stop after 1 error if not in batch mode or only pass/fail requested.
+        if (! __batch || nargout == 1)
+          if (nargout > 0)
+            if (nargout == 1)
+              __n = false;
+            else
+              __n = __nmax = 0;
+            endif
+          endif
+          if (__close_fid)
+            fclose (__fid);
+          endif
+          return;
         endif
-        if (isempty (lasterr ()))
-          error ("empty error text, probably Ctrl-C --- aborting");
-        endif
-      end_try_catch
-      clear __test__;
-    endif
+      endif
+      __tests += (__istest || __isxtest);
+      __successes += __success && (__istest || __isxtest);
 
-    ## All done.  Remember if we were successful and print any messages.
-    if (! isempty (__msg))
-      ## Make sure the user knows what caused the error.
-      if (! __verbose)
-        fprintf (__fid, "%s%s\n", __signal_block, __block);
-        fflush (__fid);
-      endif
-      fputs (__fid, __msg);
-      fputs (__fid, "\n");
-      fflush (__fid);
-      ## Show the variable context.
-      if (! strcmp (__type, "error") && ! strcmp (__type, "testif")
-          && ! all (__shared == " "))
-        fputs (__fid, "shared variables ");
-        eval (sprintf ("fdisp(__fid,bundle(%s));", __shared));
-        fflush (__fid);
-      endif
-    endif
-    if (__success == 0)
-      __all_success = 0;
-      ## Stop after one error if not in batch mode.
-      if (! __batch)
-        if (nargout > 0)
-          __ret1 = __ret2 = 0;
-        endif
-        if (__close_fid)
-          fclose (__fid);
-        endif
-        return;
-      endif
-    endif
-    __tests += __istest;
-    __successes += __success * __istest;
+    unwind_protect_cleanup
+      warning ("off", "all");
+      warning (orig_wstate);
+    end_unwind_protect
   endfor
-  ## Clear any test functions created
-  eval (__clear, "");
+
+  ## Clear any functions created during test run 
+  eval (__clearfcn, "");
 
   if (nargout == 0)
     if (__tests || __xfail || __xskip)
@@ -595,20 +665,22 @@
       printf ("%s%s has no tests available\n", __signal_empty, __file);
     endif
   elseif (__grabdemo)
-    __ret1 = __demo_code;
-    __ret2 = __demo_idx;
+    __n    = __demo_code;
+    __nmax = __demo_idx;
   elseif (nargout == 1)
-    __ret1 = __all_success;
+    __n = __all_success;
   else
-    __ret1 = __successes;
-    __ret2 = __tests;
-    __ret3 = __xfail;
-    __ret4 = __xskip;
+    __n      = __successes;
+    __nmax   = __tests;
+    __nxfail = __xfail;
+    __nskip  = __xskip;
   endif
+
 endfunction
 
+
 ## Create structure with fieldnames the name of the input variables.
-function s = varstruct (varargin)
+function s = var2struct (varargin)
   for i = 1:nargin
     s.(deblank (argn(i,:))) = varargin{i};
   endfor
@@ -670,25 +742,13 @@
   str = str(idx:end);
 endfunction
 
-## Make a structure out of the named variables
-## (based on Etienne Grossmann's tar function).
-function s = bundle (varargin)
-  for i = 1:nargin
-    s.(deblank (argn(i,:))) = varargin{i};
-  endfor
-endfunction
-
 function body = __extract_test_code (nm)
   fid = fopen (nm, "rt");
-  body = [];
+  body = "";
   if (fid >= 0)
-    while (! feof (fid))
-      ln = fgetl (fid);
-      if (length (ln) >= 2 && strcmp (ln(1:2), "%!"))
-        body = [body, "\n"];
-        if (length (ln) > 2)
-          body = [body, ln(3:end)];
-        endif
+    while (ischar (ln = fgets (fid)))
+      if (strncmp (ln, "%!", 2))
+        body = [body, ln(3:end)];
       endif
     endwhile
     fclose (fid);
@@ -696,23 +756,24 @@
 endfunction
 
 
-### example from toeplitz
+## example from toeplitz
 %!shared msg1,msg2
-%! msg1="C must be a vector";
-%! msg2="C and R must be vectors";
-%!fail ('toeplitz ([])', msg1);
-%!fail ('toeplitz ([1,2;3,4])', msg1);
-%!fail ('toeplitz ([1,2],[])', msg2);
-%!fail ('toeplitz ([1,2],[1,2;3,4])', msg2);
-%!fail ('toeplitz ([1,2;3,4],[1,2])', msg2);
-% !fail ('toeplitz','usage: toeplitz'); # usage doesn't generate an error
-% !fail ('toeplitz (1, 2, 3)', 'usage: toeplitz');
-%!test  assert (toeplitz ([1,2,3], [1,4]), [1,4; 2,1; 3,2]);
-%!demo  toeplitz ([1,2,3,4],[1,5,6])
+%! msg1 = "C must be a vector";
+%! msg2 = "C and R must be vectors";
+%!fail ("toeplitz ([])", msg1)
+%!fail ("toeplitz ([1,2;3,4])", msg1)
+%!fail ("toeplitz ([1,2],[])", msg2)
+%!fail ("toeplitz ([1,2],[1,2;3,4])", msg2)
+%!fail ("toeplitz ([1,2;3,4],[1,2])", msg2)
+%!test fail ("toeplitz", "Invalid call to toeplitz")
+%!fail ("toeplitz (1, 2, 3)", "Invalid call to toeplitz")
+%!test assert (toeplitz ([1,2,3], [1,4]), [1,4; 2,1; 3,2])
+%!assert (toeplitz ([1,2,3], [1,4]), [1,4; 2,1; 3,2])
+%!demo toeplitz ([1,2,3,4],[1,5,6])
 
-### example from kron
-%!#error kron  # FIXME suppress these until we can handle output
-%!#error kron(1,2,3)
+## example from kron
+%!error <Invalid call to kron> kron ()
+%!error <Invalid call to kron> kron (1)
 %!test assert (isempty (kron ([], rand (3, 4))))
 %!test assert (isempty (kron (rand (3, 4), [])))
 %!test assert (isempty (kron ([], [])))
@@ -732,101 +793,110 @@
 %!assert (kron ([1, 2; 3, 4], A), [ A, 2*A; 3*A, 4*A ])
 %!test
 %! res = [1,-1,2,-2,3,-3; 2,-2,4,-4,6,-6; 4,-4,5,-5,6,-6; 8,-8,10,-10,12,-12];
-%! assert (kron (A, B), res)
+%! assert (kron (A, B), res);
+%!shared  # clear out shared variables
+
+## Now verify test() itself
 
-### an extended demo from specgram
-%!#demo
-%! ## Speech spectrogram
-%! [x, Fs] = auload (file_in_loadpath ("sample.wav")); # audio file
-%! step = fix (5*Fs/1000);     # one spectral slice every 5 ms
-%! window = fix (40*Fs/1000);  # 40 ms data window
-%! fftn = 2^nextpow2 (window); # next highest power of 2
-%! [S, f, t] = specgram (x, fftn, Fs, window, window-step);
-%! S = abs (S (2:fftn*4000/Fs,:)); # magnitude in range 0<f<=4000 Hz.
-%! S = S/max(max(S));          # normalize magnitude so that max is 0 dB.
-%! S = max (S, 10^(-40/10));   # clip below -40 dB.
-%! S = min (S, 10^(-3/10));    # clip above -3 dB.
-%! imagesc (flipud (20*log10 (S)), 1);
-%! % you should now see a spectrogram in the image window
-
-
-## now test 'test' itself
-
-## usage and error testing
-% !fail ('test','usage.*test')           # no args, generates usage()
-% !fail ('test (1,2,3,4)','usage.*test') # too many args, generates usage()
-%!fail ('test ("test", "bogus")','unknown flag')  # incorrect args
+## Test 'fail' keyword
+%!fail ("test", "Invalid call to test")  # no args, generates usage()
+%!fail ("test (1,2,3,4)", "usage.*test") # too many args, generates usage()
+%!fail ('test ("test", "bogus")', "unknown flag")  # incorrect args
 %!fail ('garbage','garbage.*undefined')  # usage on nonexistent function should be
 
-%!error test                     # no args, generates usage()
-%!error test (1,2,3,4)           # too many args, generates usage()
-%!error <unknown flag> test ("test", 'bogus'); # incorrect args, generates error()
-%!error <garbage' undefined> garbage           # usage on nonexistent function should be
-
-%!error test ("test", 'bogus');  # test without pattern
+## Test 'error' keyword 
+%!error test              # no args, generates usage()
+%!error test (1,2,3,4)    # too many args, generates usage()
+%!error <unknown flag> test ("test", "bogus"); # incorrect args
+%!error test ("test", "bogus");  # test without pattern
+%!error <'garbage' undefined> garbage; # usage on nonexistent function is error
 
-%!test
-%! lastwarn();            # clear last warning just in case
-
-%!warning <warning message> warning ('warning message');
+## Test 'warning' keyword 
+%!warning warning ("warning message");   # no pattern
+%!warning <warning message> warning ("warning message");   # with pattern
 
-## test of shared variables
+## Test 'shared' keyword
 %!shared a                # create a shared variable
-%!test   a=3;             # assign to a shared variable
-%!test   assert (a,3)     # variable should equal 3
+%!test a = 3;             # assign to a shared variable
+%!test assert (a, 3)      # variable should equal 3
 %!shared b,c              # replace shared variables
 %!test assert (!exist ("a", "var"));  # a no longer exists
 %!test assert (isempty (b));   # variables start off empty
 %!shared a,b,c            # recreate a shared variable
 %!test assert (isempty (a));   # value is empty even if it had a previous value
 %!test a=1; b=2; c=3;   # give values to all variables
-%!test assert ([a,b,c],[1,2,3]); # test all of them together
-%!test c=6;             # update a value
-%!test assert ([a, b, c],[1, 2, 6]); # show that the update sticks
-%!shared                     # clear all shared variables
+%!test assert ([a,b,c], [1,2,3]); # test all of them together
+%!test c=6;               # update a value
+%!test assert ([a,b,c], [1,2,6]); # show that the update sticks
+%!shared                  # clear all shared variables
 %!test assert (!exist ("a", "var")) # show that they are cleared
-%!shared a,b,c               # support for initializer shorthand
+%!shared a,b,c            # support for initializer shorthand
 %! a=1; b=2; c=4;
+%!shared                  # clear all shared variables for remainder of tests
 
+## Test 'function' keyword 
 %!function x = __test_a (y)
 %! x = 2*y;
 %!endfunction
-%!assert (__test_a (2),4);       # Test a test function
+%!assert (__test_a (2), 4)  # Test a test function
 
 %!function __test_a (y)
 %! x = 2*y;
 %!endfunction
 %!test
-%! __test_a (2);                # Test a test function with no return value
+%! __test_a (2);            # Test a test function with no return value
 
 %!function [x,z] = __test_a (y)
 %! x = 2*y;
 %! z = 3*y;
 %!endfunction
-%!test                   # Test a test function with multiple returns
-%! [x,z] = __test_a (3);
+%!test                      
+%! [x,z] = __test_a (3);    # Test a test function with multiple returns
 %! assert (x,6);
 %! assert (z,9);
 
-## test of assert block
-%!assert (isempty ([]))      # support for test assert shorthand
+## Test 'assert' keyword 
+%!assert (isempty ([]))     # support for test assert shorthand
+%!assert (size (ones (1,2,3)), [1 2 3])
 
-## demo blocks
-%!demo                   # multiline demo block
+## Test 'demo' keyword 
+%!demo                      # multiline demo block
 %! t = [0:0.01:2*pi]; x = sin (t);
 %! plot (t,x);
 %! % you should now see a sine wave in your figure window
-%!demo a=3               # single line demo blocks work too
+
+%!demo a=3                  # single line demo blocks work too
+
+%!test
+%! [code, idx] = test ("test", "grabdemo");
+%! assert (numel (idx), 4);
+%! assert (code(idx(3):end),
+%!         " a=3                  # single line demo blocks work too");
 
-## this is a comment block. it can contain anything.
+## Test 'testif' keyword 
+%!testif HAVE_BOGUS_FEATURE
+%! error ("testif executed code despite not having feature");
+
+## Test 'xtest' keyword 
+%!xtest
+%! assert (1, 1);      # Test passes
+%!xtest
+%! assert (0, 1);      # Test fails
+
+## Test comment block. it can contain anything.
 %!##
 %! it is the "#" as the block type that makes it a comment
 %! and it stays as a comment even through continuation lines
 %! which means that it works well with commenting out whole tests
 
-% !# failure tests.  All the following should fail. These tests should
-% !# be disabled unless you are developing test() since users don't
-% !# like to be presented with expected failures.  I use % ! to disable.
+%% Test test() input validation
+%!error <NAME must be a string> test (1)
+%!error <second argument must be a string> test ("ls", 1)
+%!error test ([], "normal")
+
+## All of the following tests should fail.  These tests should
+## be disabled unless you are developing test() since users don't
+## like to be presented with expected failures.  I use '% !' to disable.
 % !test   error("---------Failure tests.  Use test('test','verbose',1)");
 % !test   assert([a,b,c],[1,3,6]);   # variables have wrong values
 % !bogus                     # unknown block type
@@ -839,10 +909,10 @@
 % !demo   with syntax error  # syntax errors in demo fail properly
 % !shared a,b,c
 % !demo                      # shared variables not available in demo
-% ! assert(exist("a", "var"))
+% ! assert (exist ("a", "var"))
 % !error
-% ! test('/etc/passwd');
-% ! test("nonexistent file");
+% ! test ('/etc/passwd');
+% ! test ("nonexistent file");
 % ! ## These don't signal an error, so the test for an error fails. Note
 % ! ## that the call doesn't reference the current fid (it is unavailable),
 % ! ## so of course the informational message is not printed in the log.
--- a/scripts/time/datestr.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/time/datestr.m	Mon Jan 12 09:17:35 2015 -0800
@@ -37,16 +37,16 @@
 ##
 ## @multitable @columnfractions 0.1 0.45 0.35
 ## @headitem Code @tab Format @tab Example
-## @item 0 @tab dd-mmm-yyyy HH:MM:SS   @tab 07-Sep-2000 15:38:09
-## @item 1 @tab dd-mmm-yyyy            @tab 07-Sep-2000
-## @item 2 @tab mm/dd/yy               @tab 09/07/00
-## @item 3 @tab mmm                    @tab Sep
-## @item 4 @tab m                      @tab S
-## @item 5 @tab mm                     @tab 09
-## @item 6 @tab mm/dd                  @tab 09/07
-## @item 7 @tab dd                     @tab 07
-## @item 8 @tab ddd                    @tab Thu
-## @item 9 @tab d                      @tab T
+## @item 0 @tab dd-mmm-yyyy HH:MM:SS    @tab 07-Sep-2000 15:38:09
+## @item 1 @tab dd-mmm-yyyy             @tab 07-Sep-2000
+## @item 2 @tab mm/dd/yy                @tab 09/07/00
+## @item 3 @tab mmm                     @tab Sep
+## @item 4 @tab m                       @tab S
+## @item 5 @tab mm                      @tab 09
+## @item 6 @tab mm/dd                   @tab 09/07
+## @item 7 @tab dd                      @tab 07
+## @item 8 @tab ddd                     @tab Thu
+## @item 9 @tab d                       @tab T
 ## @item 10 @tab yyyy                   @tab 2000
 ## @item 11 @tab yy                     @tab 00
 ## @item 12 @tab mmmyy                  @tab Sep00
@@ -193,7 +193,7 @@
     endif
   endif
 
-  retval = [];
+  retval = "";
   for i = 1 : rows (v)
 
     if (isempty (f))
@@ -213,8 +213,8 @@
     endif
 
     df_orig = df;
-    df = strrep (df, 'AM', "%p");
-    df = strrep (df, 'PM', "%p");
+    df = strrep (df, "AM", "%p");
+    df = strrep (df, "PM", "%p");
     if (strcmp (df, df_orig))
       ## PM not set.
       df = strrep (df, "HH", "%H");
@@ -222,20 +222,20 @@
       df = strrep (df, "HH", sprintf ("%2d", v(i,4)));
     endif
 
-    df = regexprep (df, '[Yy][Yy][Yy][Yy]', "%Y");
+    df = regexprep (df, "[Yy][Yy][Yy][Yy]", "%Y");
 
-    df = regexprep (df, '[Yy][Yy]', "%y");
+    df = regexprep (df, "[Yy][Yy]", "%y");
 
-    df = regexprep (df, '[Dd][Dd][Dd][Dd]', "%A");
+    df = regexprep (df, "[Dd][Dd][Dd][Dd]", "%A");
 
-    df = regexprep (df, '[Dd][Dd][Dd]', "%a");
+    df = regexprep (df, "[Dd][Dd][Dd]", "%a");
 
-    df = regexprep (df, '[Dd][Dd]', "%d");
+    df = regexprep (df, "[Dd][Dd]", "%d");
 
     wday = weekday (datenum (v(i,1), v(i,2), v(i,3)));
     tmp = names_d{wday};
-    df = regexprep (df, '([^%])[Dd]', sprintf ("$1%s", tmp));
-    df = regexprep (df, '^[Dd]', sprintf ("%s", tmp));
+    df = regexprep (df, "([^%])[Dd]", sprintf ("$1%s", tmp));
+    df = regexprep (df, "^[Dd]", sprintf ("%s", tmp));
 
     df = strrep (df, "mmmm", "%B");
 
@@ -244,17 +244,18 @@
     df = strrep (df, "mm", "%m");
 
     tmp = names_m{v(i,2)};
-    pos = regexp (df, '[^%]m') + 1;
+    pos = regexp (df, "[^%]m") + 1;
     df(pos) = tmp;
-    df = regexprep (df, '^m', tmp);
+    df = regexprep (df, "^m", tmp);
 
     df = strrep (df, "MM", "%M");
 
-    df = regexprep (df, '[Ss][Ss]', "%S");
+    df = regexprep (df, "[Ss][Ss]", "%S");
 
-    df = strrep (df, "FFF", sprintf ("%03d", 1000 * (v(i,6) - fix (v(i,6)))));
+    df = strrep (df, "FFF", sprintf ("%03d",
+                                     round (1000 * (v(i,6) - fix (v(i,6))))));
 
-    df = strrep (df, 'QQ', sprintf ("Q%d", fix ((v(i,2) + 2) / 3)));
+    df = strrep (df, "QQ", sprintf ("Q%d", fix ((v(i,2) + 2) / 3)));
 
     vi = v(i,:);
     tm.year = vi(1) - 1900;
@@ -266,7 +267,7 @@
     tm.sec = fix (sec);
     tm.usec = fix ((sec - tm.sec) * 1e6);
     tm.wday = wday - 1;
-    ## FIXME -- Do we need YDAY and DST?  How should they be computed?
+    ## FIXME: Do we need YDAY and DST?  How should they be computed?
     ## We don't want to use "localtime (mktime (tm))" because that
     ## doesn't correctly handle dates before 1970-01-01 on some systems.
     ## tm.yday = ?;
--- a/scripts/time/datevec.m	Mon Jan 12 09:13:19 2015 -0800
+++ b/scripts/time/datevec.m	Mon Jan 12 09:17:35 2015 -0800
@@ -113,6 +113,8 @@
     p = (localtime (time ())).year + 1900 - 50;
   endif
 
+  do_resize = false;
+
   if (iscell (date))
 
     nd = numel (date);
@@ -146,6 +148,10 @@
 
   else   # datenum input
 
+    if (! iscolumn (date))
+      date_sz = size (date);
+      do_resize = true;
+    endif
     date = date(:);
 
     ## Move day 0 from midnight -0001-12-31 to midnight 0000-3-1
@@ -182,6 +188,13 @@
 
   if (nargout <= 1)
     y = [y, m, d, h, mi, s];
+  elseif (do_resize)
+    y = reshape (y, date_sz);
+    m = reshape (m, date_sz);
+    d = reshape (d, date_sz);
+    h = reshape (h, date_sz);
+    mi = reshape (mi, date_sz);
+    s = reshape (s, date_sz);
   endif
 
 endfunction
@@ -306,10 +319,15 @@
 %!assert (datevec ("03:38 PM"), [yr,1,1,15,38,0])
 %!assert (datevec ("03/13/1962"), [1962,3,13,0,0,0])
 
-%% Test millisecond format FFF
+## Test millisecond format FFF
 %!assert (datevec ("15:38:21.25", "HH:MM:SS.FFF"), [yr,1,1,15,38,21.025])
 
-# Other tests
+## Test structure of return value (bug #42334)
+%!test
+%! [~, ~, d] = datevec ([1 2; 3 4]);
+%! assert (d, [1 2; 3 4]);
+
+## Other tests
 %!assert (datenum (datevec ([-1e4:1e4])), [-1e4:1e4]');
 %!test
 %! t = linspace (-2e5, 2e5, 10993);
@@ -317,3 +335,9 @@
 %!assert (double (datevec (int64 (datenum ([2014 6 1])))), datevec (datenum ([2014 6 1])))
 %!assert (double (datevec (int64 (datenum ([2014 6 18])))), datevec (datenum ([2014 6 18])))
 
+%% Test input validation
+%!error datevec ()
+%!error datevec (1,2,3,4)
+%!error <none of the standard formats match> datevec ("foobar")
+%!error <DATE not parsed correctly with given format> datevec ("foobar", "%d")
+
--- a/src/main.in.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/src/main.in.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -603,8 +603,8 @@
 
               retval = 1;
             }
-
-          retval = octave_exec (file, new_argv);
+          else
+            retval = octave_exec (file, new_argv);
         }
       else
         {
--- a/src/mkoctfile.in.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/src/mkoctfile.in.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -552,7 +552,7 @@
         }
       else
         {
-          std::cerr << "mkoctfile: unrecognized argument " << arg;
+          std::cerr << "mkoctfile: unrecognized argument " << arg << std::endl;
           return 1;
         }
 
@@ -671,8 +671,8 @@
         }
       else
         {
-          std::cerr << "mkoctfile: no way to compile Fortran file "
-                    << f << std::endl;
+          std::cerr << "mkoctfile: no way to compile Fortran file " << f
+                    << std::endl;
           return 1;
         }
     }
--- a/src/octave-config.in.cc	Mon Jan 12 09:13:19 2015 -0800
+++ b/src/octave-config.in.cc	Mon Jan 12 09:17:35 2015 -0800
@@ -56,23 +56,24 @@
 "  -p VAR, --print VAR   Print the value of the given configuration\n"
 "                        variable VAR.  Recognized variables are:\n"
 "\n"
-"                          API_VERSION            LOCALAPIOCTFILEDIR\n"
-"                          ARCHLIBDIR             LOCALARCHLIBDIR\n"
-"                          BINDIR                 LOCALFCNFILEDIR\n"
-"                          CANONICAL_HOST_TYPE    LOCALOCTFILEDIR\n"
-"                          DATADIR                LOCALSTARTUPFILEDIR\n"
-"                          DATAROOTDIR            LOCALVERARCHLIBDIR\n"
-"                          DEFAULT_PAGER          LOCALVERFCNFILEDIR\n"
-"                          EXEC_PREFIX            LOCALVEROCTFILEDIR\n"
-"                          FCNFILEDIR             MAN1DIR\n"
-"                          IMAGEDIR               MAN1EXT\n"
-"                          INCLUDEDIR             MANDIR\n"
+"                          API_VERSION            LOCALARCHLIBDIR\n"
+"                          ARCHLIBDIR             LOCALFCNFILEDIR\n"
+"                          BINDIR                 LOCALOCTFILEDIR\n"
+"                          CANONICAL_HOST_TYPE    LOCALSTARTUPFILEDIR\n"
+"                          DATADIR                LOCALVERARCHLIBDIR\n"
+"                          DATAROOTDIR            LOCALVERFCNFILEDIR\n"
+"                          DEFAULT_PAGER          LOCALVEROCTFILEDIR\n"
+"                          EXEC_PREFIX            MAN1DIR\n"
+"                          FCNFILEDIR             MAN1EXT\n"
+"                          IMAGEDIR               MANDIR\n"
+"                          INCLUDEDIR             OCTDATADIR\n"
 "                          INFODIR                OCTFILEDIR\n"
 "                          INFOFILE               OCTINCLUDEDIR\n"
 "                          LIBDIR                 OCTLIBDIR\n"
 "                          LIBEXECDIR             PREFIX\n"
 "                          LOCALAPIARCHLIBDIR     STARTUPFILEDIR\n"
 "                          LOCALAPIFCNFILEDIR     VERSION\n"
+"                          LOCALAPIOCTFILEDIR\n"
 "\n"
 "  -v, --version         Print the Octave version number.\n"
 "\n";
@@ -113,6 +114,7 @@
   vars["LOCALVEROCTFILEDIR"] = subst_octave_home (%OCTAVE_LOCALVEROCTFILEDIR%);
   vars["MAN1DIR"] = subst_octave_home (%OCTAVE_MAN1DIR%);
   vars["MANDIR"] = subst_octave_home (%OCTAVE_MANDIR%);
+  vars["OCTDATADIR"] = subst_octave_home (%OCTAVE_OCTDATADIR%);
   vars["OCTFILEDIR"] = subst_octave_home (%OCTAVE_OCTFILEDIR%);
   vars["OCTINCLUDEDIR"] = subst_octave_home (%OCTAVE_OCTINCLUDEDIR%);
   vars["OCTLIBDIR"] = subst_octave_home (%OCTAVE_OCTLIBDIR%);
--- a/test/Makefile.am	Mon Jan 12 09:13:19 2015 -0800
+++ b/test/Makefile.am	Mon Jan 12 09:17:35 2015 -0800
@@ -56,6 +56,7 @@
 include bug-36025/module.mk
 include bug-38236/module.mk
 include bug-38691/module.mk
+include classdef/module.mk
 include classes/module.mk
 include class-concat/module.mk
 include ctor-vs-method/module.mk
@@ -70,6 +71,11 @@
 check: sparse.tst bc-overload-tests.stamp
 	$(top_builddir)/run-octave $(RUN_OCTAVE_OPTIONS) --norc --silent --no-history $(srcdir)/fntests.m $(srcdir)
 
+if AMCOND_HAVE_LLVM
+check-jit: sparse.tst bc-overload-tests.stamp
+	$(top_builddir)/run-octave $(RUN_OCTAVE_OPTIONS) --jit-compiler --norc --silent --no-history $(srcdir)/fntests.m $(srcdir)
+endif
+
 sparse.tst: build-sparse-tests.sh
 	$(srcdir)/build-sparse-tests.sh
 
--- a/test/build-sparse-tests.sh	Mon Jan 12 09:13:19 2015 -0800
+++ b/test/build-sparse-tests.sh	Mon Jan 12 09:17:35 2015 -0800
@@ -464,7 +464,7 @@
 print_mapper_test cos
 print_mapper_test cosh
 print_mapper_test exp
-print_mapper_test finite
+print_mapper_test isfinite
 print_mapper_test fix
 print_mapper_test floor
 print_mapper_test imag
@@ -508,19 +508,18 @@
 print_real_mapper_test isspace 0
 print_real_mapper_test isupper 0
 print_real_mapper_test isxdigit 0
-#print_real_mapper_test lgamma 1
+#print_real_mapper_test gammaln 1
 
 # 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");
 
@@ -856,7 +855,7 @@
 %!assert (as(idx'), sparse (af(idx')));
 %!assert (as(flipud (idx(:))), sparse (af(flipud (idx(:)))))
 %!assert (as([idx,idx]), sparse (af([idx,idx])))
-%!error (as(reshape ([idx;idx], [1,length(idx),2])))
+%!assert (as(reshape ([idx;idx], [1,length(idx),2])), sparse(af(reshape ([idx;idx], [1,length(idx),2]))))
 
 %% Slice tests
 %!assert (as(ridx,cidx), sparse (af(ridx,cidx)))
@@ -915,7 +914,7 @@
 gen_save_tests() {
     cat >>$TESTS <<EOF
 %!test # save ascii
-%! savefile = tmpnam ();
+%! savefile = tempname ();
 %! as_save = as;
 %! save ("-text", savefile, "bf", "as_save", "af");
 %! clear as_save;
@@ -923,7 +922,7 @@
 %! unlink (savefile);
 %! assert (as_save, sparse (af));
 %!test # save binary
-%! savefile = tmpnam ();
+%! savefile = tempname ();
 %! as_save = as;
 %! save ("-binary", savefile, "bf", "as_save", "af");
 %! clear as_save;
@@ -931,7 +930,7 @@
 %! unlink (savefile);
 %! assert (as_save, sparse (af));
 %!testif HAVE_HDF5   # save hdf5
-%! savefile = tmpnam ();
+%! savefile = tempname ();
 %! as_save = as;
 %! save ("-hdf5", savefile, "bf", "as_save", "af");
 %! clear as_save;
@@ -942,7 +941,7 @@
 ## saving sparse matrices to MAT files when using 64-bit indexing since
 ## that is not implemented yet.
 %!test # save matlab
-%! savefile = tmpnam ();
+%! savefile = tempname ();
 %! as_save = as;
 %! save ("-mat", savefile, "bf", "as_save", "af");
 %! clear as_save;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/classdef/classdef.tst	Mon Jan 12 09:17:35 2015 -0800
@@ -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 12 09:17:35 2015 -0800
@@ -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 12 09:17:35 2015 -0800
@@ -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 12 09:17:35 2015 -0800
@@ -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 12 09:17:35 2015 -0800
@@ -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/error.tst	Mon Jan 12 09:13:19 2015 -0800
+++ b/test/error.tst	Mon Jan 12 09:17:35 2015 -0800
@@ -59,6 +59,36 @@
 %! assert (warning ("query", "backtrace"), st);
 %! warning (ws.state, "backtrace");
 
+%!shared t1_opts, t2_opts, t1_id, t1_state, saved_opts, saved_id, saved_state
+%! saved_opts = warning ();
+%! saved_id = {saved_opts.identifier};
+%! saved_state = {saved_opts.state};
+%! warning ("off", "all");
+%! assert (warning (), struct ("identifier", {"all"}, "state", {"off"}));
+%! warning ("off", "all");
+%! warning (saved_opts);
+%! t1_opts = struct ("identifier", {"foo:bar"}, "state", {"off"});
+%! t1_id = {t1_opts.identifier};
+%! t1_state = {t1_opts.state};
+%! warning (t1_opts);
+%! t2_opts = struct ("identifier", [saved_id, t1_id], "state", [saved_state, t1_state]);
+%! assert (warning (), t2_opts);
+%! warning ("off", "all");
+%! warning (saved_opts);
+
+## Bug 36393
+
+%!test
+%! w0 = warning;
+%! warnoffId = "MATLAB:singularMatrix";
+%! warnstat = warning ("query", warnoffId);
+%! warnoff = warnstat;
+%! warnoff.state = "off";
+%! warning (warnoff); %update warning status
+%! warning (warnstat); %reset warning status
+%! w = warning;
+%! assert (w, w0);
+
 ## Test usage() function
 
 %!function g ()
--- a/test/fcn-handle-derived-resolution/@derived/derived.m	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,5 +0,0 @@
-function r = derived (n)
-  s.a = n;
-  p = parent (n);
-  r = class (s, 'derived', p);
-end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/fcn-handle-derived-resolution/@fhdr_derived/fhdr_derived.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,5 @@
+function r = fhdr_derived (n)
+  s.a = n;
+  p = fhdr_parent (n);
+  r = class (s, 'fhdr_derived', p);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/fcn-handle-derived-resolution/@fhdr_other/fhdr_other.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,4 @@
+function r = fhdr_other (n)
+  s.d = fhdr_derived (n);
+  r = class (s, 'fhdr_other');
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/fcn-handle-derived-resolution/@fhdr_other/getsize_arrayfun.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,3 @@
+function r = getsize_arrayfun (x)
+  r = arrayfun (@(i) numel (x(i).d), 1:numel (x), 'uniformoutput', true);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/fcn-handle-derived-resolution/@fhdr_other/getsize_cellfun.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,3 @@
+function r = getsize_cellfun (x)
+  r = cellfun (@numel, {x.d});
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/fcn-handle-derived-resolution/@fhdr_other/getsize_loop.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,7 @@
+function r = getsize_loop (x)
+  n = numel (x);
+  r = zeros (1, n);
+  for i = 1:n
+    r(i) = numel (x(i).d);
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/fcn-handle-derived-resolution/@fhdr_parent/fhdr_parent.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,4 @@
+function r = fhdr_parent (n)
+  s.a = rand (n, 1);
+  r = class (s, 'fhdr_parent');
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/fcn-handle-derived-resolution/@fhdr_parent/numel.m	Mon Jan 12 09:17:35 2015 -0800
@@ -0,0 +1,3 @@
+function r = numel (x, varargin)
+  r = numel (x.a, varargin{:});
+end
--- a/test/fcn-handle-derived-resolution/@other/getsize_arrayfun.m	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-function r = getsize_arrayfun (x)
-  r = arrayfun (@(i) numel (x(i).d), 1:numel (x), 'uniformoutput', true);
-end
--- a/test/fcn-handle-derived-resolution/@other/getsize_cellfun.m	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-function r = getsize_cellfun (x)
-  r = cellfun (@numel, {x.d});
-end
--- a/test/fcn-handle-derived-resolution/@other/getsize_loop.m	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-function r = getsize_loop (x)
-  n = numel (x);
-  r = zeros (1, n);
-  for i = 1:n
-    r(i) = numel (x(i).d);
-  end
-end
--- a/test/fcn-handle-derived-resolution/@other/other.m	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-function r = other (n)
-  s.d = derived (n);
-  r = class (s, 'other');
-end
--- a/test/fcn-handle-derived-resolution/@parent/numel.m	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-function r = numel (x, varargin)
-  r = numel (x.a, varargin{:});
-end
--- a/test/fcn-handle-derived-resolution/@parent/parent.m	Mon Jan 12 09:13:19 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-function r = parent (n)
-  s.a = rand (n, 1);
-  r = class (s, 'parent');
-end
--- a/test/fcn-handle-derived-resolution/fcn-handle-derived-resolution.tst	Mon Jan 12 09:13:19 2015 -0800
+++ b/test/fcn-handle-derived-resolution/fcn-handle-derived-resolution.tst	Mon Jan 12 09:17:35 2015 -0800
@@ -22,38 +22,46 @@
 %%  Note: This script and all classes are also intended to run
 %%        in Matlab to test compatibility.  Don't break that!
 
-%!shared
-%! clear -classes
+%% FIXME: Can't use 'clear -classes' because it also clears all functions in the
+%% namespace of test.m (bug #35881).  This is a problem only if Octave would
+%% re-use a class definition that was defined somewhere else.  Unfortunately,
+%% that is exactly the case when running 'make check' since the ctor-vs-method
+%% test also uses an @parent, @derived, and @other class.
+%% Until the bug is fixed, it suffices to make the class names unique so that
+%% there is no re-use.  Using the prefix fhdr (fcn-handle-derived-resolution)
+%% for this directory.
+%%!shared
+%%! #clear -classes
 
 %!test
-%! p = parent (7);
+%! p = fhdr_parent (7);
 %! assert (numel (p), 7)
 
 %!test
-%! d = derived (13);
+%! d = fhdr_derived (13);
 %! assert (numel (d), 13)
 
 %!test
-%! p = parent (11);
+%! p = fhdr_parent (11);
 %! f = @numel;
 %! assert (f (p), 11)
 
 %!test
-%! d = parent (21);
+%! d = fhdr_parent (21);
 %! f = @numel;
 %! assert (f (d), 21)
 
 %!test
-%! o(1) = other (13);
-%! o(2) = other (42);
+%! o(1) = fhdr_other (13);
+%! o(2) = fhdr_other (42);
 %! assert (getsize_loop (o), [13, 42])
 
 %!test
-%! o(1) = other (13);
-%! o(2) = other (42);
+%! o(1) = fhdr_other (13);
+%! o(2) = fhdr_other (42);
 %! assert (getsize_cellfun (o), [13, 42])
 
 %!test
-%! o(1) = other (13);
-%! o(2) = other (42);
+%! o(1) = fhdr_other (13);
+%! o(2) = fhdr_other (42);
 %! assert (getsize_arrayfun (o), [13, 42])
--- a/test/fcn-handle-derived-resolution/module.mk	Mon Jan 12 09:13:19 2015 -0800
+++ b/test/fcn-handle-derived-resolution/module.mk	Mon Jan 12 09:17:35 2015 -0800
@@ -1,11 +1,11 @@
 fcn_handle_derived_resolution_FCN_FILES = \
-  fcn-handle-derived-resolution/@derived/derived.m \
-  fcn-handle-derived-resolution/@other/getsize_arrayfun.m \
-  fcn-handle-derived-resolution/@other/getsize_cellfun.m \
-  fcn-handle-derived-resolution/@other/getsize_loop.m \
-  fcn-handle-derived-resolution/@other/other.m \
-  fcn-handle-derived-resolution/@parent/numel.m \
-  fcn-handle-derived-resolution/@parent/parent.m \
+  fcn-handle-derived-resolution/@fhdr_derived/fhdr_derived.m \
+  fcn-handle-derived-resolution/@fhdr_other/getsize_arrayfun.m \
+  fcn-handle-derived-resolution/@fhdr_other/getsize_cellfun.m \
+  fcn-handle-derived-resolution/@fhdr_other/getsize_loop.m \
+  fcn-handle-derived-resolution/@fhdr_other/fhdr_other.m \
+  fcn-handle-derived-resolution/@fhdr_parent/numel.m \
+  fcn-handle-derived-resolution/@fhdr_parent/fhdr_parent.m \
   fcn-handle-derived-resolution/fcn-handle-derived-resolution.tst
 
 FCN_FILES += $(fcn_handle_derived_resolution_FCN_FILES)
--- a/test/io.tst	Mon Jan 12 09:13:19 2015 -0800
+++ b/test/io.tst	Mon Jan 12 09:17:35 2015 -0800
@@ -295,7 +295,7 @@
 
 %% Note use fprintf so output not sent to stdout
 %!test
-%! nm = tmpnam ();
+%! nm = tempname ();
 %! fid1 = fopen (nm,"w");
 %! x = fprintf (fid1, "%s: %d\n", "test", 1);
 %! fclose (fid1);
@@ -340,7 +340,7 @@
 %!     elseif (j == 4)
 %!       mode_list = {"W+"; "R+"; "A+"};
 %!     endif
-%!     nm = tmpnam ();
+%!     nm = tempname ();
 %!     for k = 1:3
 %!       mode = mode_list{k};
 %!       [id, err] = fopen (nm, mode, arch);
@@ -397,12 +397,12 @@
 %!error fclose (0)
 %!error <Invalid call to fclose> fclose (1, 2)
 
-%!assert (ischar (tmpnam ()))
+%!assert (ischar (tempname ()))
 
-%!warning tmpnam (1);
-%!warning tmpnam ("foo", 1);
+%!error <DIR must be a string> tempname (1);
+%!error <PREFIX must be a string> tempname ("foo", 1);
 
-%!error <Invalid call to tmpnam> tmpnam (1, 2, 3)
+%!error <Invalid call to tempname> tempname (1, 2, 3)
 
 %!test
 %! type_list = ["char"; "char*1"; "integer*1"; "int8";
@@ -413,7 +413,7 @@
 %! "real*8"; "int16"; "integer*2"; "int32"; "integer*4"];
 %!
 %! n = rows (type_list);
-%! nm = tmpnam ();
+%! nm = tempname ();
 %! id = fopen (nm, "wb");
 %! if (id > 0)
 %!   for i = 1:n
@@ -440,7 +440,7 @@
 
 %!test
 %! x = char (128:255)';
-%! nm = tmpnam ();
+%! nm = tempname ();
 %! id = fopen (nm, "wb");
 %! fwrite (id, x);
 %! fclose (id);
@@ -451,7 +451,7 @@
 %! assert (x, y);
 
 %!test
-%! nm = tmpnam ();
+%! nm = tempname ();
 %! id = fopen (nm, "wb");
 %! if (id > 0)
 %!   fprintf (id, "%d\n", 1:100);
--- a/test/jit.tst	Mon Jan 12 09:13:19 2015 -0800
+++ b/test/jit.tst	Mon Jan 12 09:17:35 2015 -0800
@@ -26,8 +26,8 @@
 %! __old_jit_startcnt__ = jit_startcnt (1000);
 
 ## Test some simple cases that compile.
-
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! for i=1:1e6
 %!   if (i < 5)
 %!     break;
@@ -36,8 +36,10 @@
 %!   endif
 %! endfor
 %! assert (i, 1);
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! while (1)
 %!   if (1)
 %!     break;
@@ -45,33 +47,133 @@
 %!     break;
 %!   endif
 %! endwhile
+%! assert (jit_failure_count, 0);
+
+%!testif HAVE_LLVM
+%! jit_failure_count (0)
+%! do
+%!   break;
+%! until (0)
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
+%! do
+%!   if (1)
+%!     break;
+%!   end;
+%! until (0)
+%! assert (jit_failure_count, 0);
+
+%!testif HAVE_LLVM
+%! jit_failure_count (0)
+%! i=1;
+%! do
+%!   continue;
+%!   i=i+1;
+%! until (1)
+%! assert (i, 1);
+%! assert (jit_failure_count, 0);
+
+%!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! for i=1:1e6
 %!   if (i == 100)
 %!     break;
 %!   endif
 %! endfor
 %! assert (i, 100);
+%! assert (jit_failure_count, 0);
 
 ## Also test parfor keyword
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! parfor i=1:1e6
 %!   if (i == 100)
 %!     break;
 %!   endif
 %! endparfor
 %! assert (i, 100);
+%! assert (jit_failure_count, 0);
+## Test some switch statements
+%!testif HAVE_LLVM
+%! jit_failure_count (0)
+%! do
+%!   switch (1)
+%!   end;
+%! until(1)
+%! assert (jit_failure_count, 0);
+
+%!testif HAVE_LLVM
+%! jit_failure_count (0)
+%! do
+%!   switch (1)
+%!   case 1
+%!     break;
+%!   end;
+%! until(1)
+%! assert (jit_failure_count, 0);
+
+%!testif HAVE_LLVM
+%! jit_failure_count (0)
+%! do
+%!   switch (1)
+%!   otherwise
+%!     break;
+%!   end;
+%! until(1)
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
+%! do
+%!   switch (1)
+%!   case 1
+%!     break;
+%!   otherwise
+%!     break;
+%!   end;
+%! until(1)
+%! assert (jit_failure_count, 0);
+
+%!testif HAVE_LLVM
+%! jit_failure_count (0)
+%! i=0;
+%! a=0;
+%! b=0;
+%! do
+%!   i=i+1;
+%!   switch (i)
+%!   case 1
+%!     continue;
+%!   case 2
+%!     b=1;
+%!     continue;
+%!   case 4
+%!     break;
+%!   otherwise
+%!     a=a+5;
+%!   end;
+%!   a=a+1;
+%! until(0);
+%! assert (i, 4);
+%! assert (a, 6);
+%! assert (b, 1);
+%! assert (jit_failure_count, 0);
+
+## Some more complex calculations
+%!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! inc = 1e-5;
 %! result = 0;
 %! for ii = 0:inc:1
 %!   result = result + inc * (1/3 * ii * ii);
 %! endfor
 %! assert (abs (result - 1/9) < 1e-5);
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! inc = 1e-5;
 %! result = 0;
 %! for ii = 0:inc:1
@@ -79,8 +181,10 @@
 %!   result = result + inc * (1/3 * ii ^ 2);
 %! endfor
 %! assert (abs (result - 1/9) < 1e-5);
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! temp = 1+1i;
 %! nan = NaN;
 %! while (1)
@@ -89,8 +193,10 @@
 %!   break;
 %! endwhile
 %! assert (imag (temp), 0);
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! temp = 1+1i;
 %! nan = NaN+1i;
 %! while (1)
@@ -100,24 +206,30 @@
 %!   break;
 %! endwhile
 %! assert (imag (temp), 0);
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! temp = 1+1i;
 %! while (1)
 %!   temp = temp * 5;
 %!   break;
 %! endwhile
 %! assert (temp, 5+5i);
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! nr = 1001;
 %! mat = zeros (1, nr);
 %! for i = 1:nr
 %!   mat(i) = i;
 %! endfor
 %! assert (mat == 1:nr);
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! nr = 1001;
 %! mat = 1:nr;
 %! mat(end) = 0; # force mat to a matrix
@@ -126,8 +238,10 @@
 %!   total = mat(i) + total;
 %! endfor
 %! assert (sum (mat) == total);
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! nr = 1001;
 %! mat = [3 1 5];
 %! try
@@ -141,6 +255,7 @@
 %! catch
 %! end_try_catch
 %! assert (result == 500);
+%! assert (jit_failure_count, 0);
 
 %!function result = gen_test (n)
 %!  result = double (rand (1, n) > .01);
@@ -176,18 +291,23 @@
 %!endfunction
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! test_set = gen_test (10000);
 %! assert (all (vectorized (test_set, 3) == loopy (test_set, 3)));
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! niter = 1001;
 %! i = 0;
 %! while (i < niter)
 %!   i = i + 1;
 %! endwhile
 %! assert (i == niter);
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! niter = 1001;
 %! result = 0;
 %! m = [5 10];
@@ -195,8 +315,10 @@
 %!   result = result + m(end);
 %! endfor
 %! assert (result == m(end) * niter);
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! ndim = 100;
 %! result = 0;
 %! m = zeros (ndim);
@@ -209,8 +331,10 @@
 %!   i = i + 1;
 %! endwhile
 %! assert (result == sum (sum (m)));
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! ndim = 100;
 %! m = zeros (ndim);
 %! i = 1;
@@ -223,8 +347,10 @@
 %! m2 = zeros (ndim);
 %! m2(:) = 1:(ndim^2);
 %! assert (all (m == m2));
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! ndim = 2;
 %! m = zeros (ndim, ndim, ndim, ndim);
 %! result = 0;
@@ -244,6 +370,7 @@
 %! expected = ones (ndim, ndim, ndim, ndim);
 %! assert (all (m == expected));
 %! assert (result == sum (expected (:)));
+%! assert (jit_failure_count, 0);
 
 %!function test_divide ()
 %! state = warning ("query", "Octave:divide-by-zero").state;
@@ -259,21 +386,26 @@
 %!endfunction
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! lasterr ("");
 %! try
 %!   test_divide ();
 %! end_try_catch
 %! assert (strcmp (lasterr (), "division by zero"));
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! while (1)
 %!   a = 0;
 %!   result = a / 1;
 %!   break;
 %! endwhile
 %! assert (result, 0);
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! m = zeros (2, 1001);
 %! for i=1:1001
 %!   m(end, i) = i;
@@ -283,38 +415,49 @@
 %! m2(1, :) = fliplr (1:1001);
 %! m2(2, :) = 1:1001;
 %! assert (m, m2);
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! m = [1 2 3];
 %! for i=1:1001
 %!   m = sin (m);
 %!   break;
 %! endfor
 %! assert (m == sin ([1  2 3]));
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! i = 0;
 %! while i < 10
 %!   i += 1;
 %! endwhile
 %! assert (i == 10);
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! i = 0;
 %! while i < 10
 %!   a = ++i;
 %! endwhile
 %! assert (i == 10);
 %! assert (a == 10);
+%! assert (jit_failure_count, 0);
+
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! i = 0;
 %! while i < 10
 %!   a = i++;
 %! endwhile
 %! assert (i == 10);
 %! assert (a == 9);
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! num = 2;
 %! a = zeros (1, num);
 %! i = 1;
@@ -323,6 +466,7 @@
 %!   ++i;
 %! endwhile
 %! assert (a, ones (1, num));
+%! assert (jit_failure_count, 0);
 
 %!function test_compute_idom ()
 %! while (li <= length (l1) && si <= length (s1))
@@ -337,11 +481,13 @@
 %! endwhile
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! lasterr ("");
 %! try
 %!   test_compute_idom ();
 %! end_try_catch
 %! assert (! isempty (lasterr ()));
+%! assert (jit_failure_count, 1);
 
 %!function x = test_overload (a)
 %!  while (1)
@@ -351,8 +497,10 @@
 %!endfunction
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! assert (test_overload (1), 1);
 %! assert (test_overload ([1 2]), [1 2]);
+%! assert (jit_failure_count, 0);
 
 %!function a = bubble (a = [3 2 1])
 %!  swapped = 1;
@@ -371,9 +519,12 @@
 %!endfunction
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! assert (bubble (), [1 2 3]);
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! a = 0;
 %! b = 1;
 %! for i=1:1e3
@@ -383,8 +534,10 @@
 %! endfor
 %! assert (a, 2000);
 %! assert (b, 1);
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! a = [1+1i 1+2i];
 %! b = 0;
 %! while (1)
@@ -392,6 +545,7 @@
 %!   break;
 %! endwhile
 %! assert (b, a(1));
+%! assert (jit_failure_count, 0);
 
 %!function test_undef ()
 %!  for i=1:1e7
@@ -400,26 +554,32 @@
 %!endfunction
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! lasterr ("");
 %! try
 %!   test_undef ();
 %! end_try_catch
 %! assert (strncmp (lasterr (), "'XXX' undefined near", 20));
+%! assert (jit_failure_count, 1);
 
 %!shared id
 %! id = @(x) x;
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! assert (id (1), 1);
 %! assert (id (1+1i), 1+1i);
 %! assert (id (1, 2), 1);
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! lasterr ("");
 %! try
 %!   id ();
 %! end_try_catch
 %! assert (strncmp (lasterr (), "'x' undefined near", 18));
+%! assert (jit_failure_count, 0);
 
 ## Restore JIT settings
 %!testif HAVE_LLVM
--- a/test/null-assign.tst	Mon Jan 12 09:13:19 2015 -0800
+++ b/test/null-assign.tst	Mon Jan 12 09:17:35 2015 -0800
@@ -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
--- a/test/parser.tst	Mon Jan 12 09:13:19 2015 -0800
+++ b/test/parser.tst	Mon Jan 12 09:17:35 2015 -0800
@@ -19,6 +19,7 @@
 ## Tests for parser problems belong in this file.
 ## We need many more tests here!
 
+## Test cell construction operator {}
 %!assert ({1 2 {3 4}}, {1,2,{3,4}})
 %!assert ({1, 2 {3 4}}, {1,2,{3,4}})
 %!assert ({1 2, {3 4}}, {1,2,{3,4}})
@@ -28,6 +29,14 @@
 %!assert ({1 2,{3,4}}, {1,2,{3,4}})
 %!assert ({1,2,{3 4}}, {1,2,{3,4}})
 
+## bug #43113 using null comma-separated list in constructor
+%!test
+%! z = cell (1,2,3,0,5);
+%! assert ({1, z{:}, 2}, {1, 2});
+%! assert ({1; z{:}; 2}, {1; 2});
+%! assert ({1 2; z{:}; 3 4}, {1, 2; 3 4});
+%! assert ({1 2; 5 z{:} 6; 3 4}, {1, 2; 5 6; 3 4});
+
 ## Tests for operator precedence as documented in section 8.8 of manual
 ## There are 13 levels of precedence from "parentheses and indexing" (highest)
 ## down to "statement operators" (lowest).
--- a/test/prefer.tst	Mon Jan 12 09:13:19 2015 -0800
+++ b/test/prefer.tst	Mon Jan 12 09:17:35 2015 -0800
@@ -66,16 +66,16 @@
 %! warning (wsn.state, "Octave:str-to-num");
 
 %!test
-%! wir = warning ("query", "Ocave:imag-to-real");
-%! warning ("off", "Ocave:imag-to-real");
+%! wir = warning ("query", "Octave:imag-to-real");
+%! warning ("off", "Octave:imag-to-real");
 %! assert (eye (1+i), 1);
-%! warning (wir.state, "Ocave:imag-to-real");
+%! warning (wir.state, "Octave:imag-to-real");
 
 %!test
-%! wir = warning ("query", "Ocave:imag-to-real");
-%! warning ("on", "Ocave:imag-to-real");
+%! wir = warning ("query", "Octave:imag-to-real");
+%! warning ("on", "Octave:imag-to-real");
 %! fail ("eye (1+i)", "warning");
-%! warning (wir.state, "Ocave:imag-to-real");
+%! warning (wir.state, "Octave:imag-to-real");
 
 %!test
 %! wrre = warning ("query", "Octave:resize-on-range-error");
@@ -115,7 +115,7 @@
 %! sp = save_precision ();
 %! save_precision (1);
 %! x = pi;
-%! nm = tmpnam ();
+%! nm = tempname ();
 %! save ("-text", nm, "x");
 %! clear x;
 %! load (nm);
@@ -127,7 +127,7 @@
 %! sp = save_precision ();
 %! save_precision (5);
 %! x = pi;
-%! nm = tmpnam ();
+%! nm = tempname ();
 %! save ("-text", nm, "x");
 %! clear x;
 %! load (nm);
@@ -160,7 +160,7 @@
 %!test
 %! wndz = warning ("query", "Octave:neg-dim-as-zero");
 %! warning ("on", "Octave:neg-dim-as-zero");
-%! fail ("eye (-1) == []", "warning");
+%! fail ("eye (-1) == []", "warning", "converting negative dimension");
 %! warning (wndz.state, "Octave:neg-dim-as-zero");
 
 %!test
@@ -171,14 +171,8 @@
 
 %!test
 %! watv = warning ("query", "Octave:assign-as-truth-value");
-%! warning ("off", "Octave:assign-as-truth-value");
-%! if (x = 1) 1; endif
-%! warning (watv.state, "Octave:assign-as-truth-value");
-
-%!test
-%! watv = warning ("query", "Octave:assign-as-truth-value");
 %! warning ("on", "Octave:assign-as-truth-value");
-%! fail ("if (x = 1) 1; endif", "warning");
+%! fail ("if (x = 1) 1; endif", "warning", "assignment used as truth value");
 %! warning (watv.state, "Octave:assign-as-truth-value");
 
 %!test
@@ -192,6 +186,6 @@
 %! warning ("on", "Octave:divide-by-zero");
 %! a = 1;
 %! b = 0;
-%! fail ("isinf (a/b);", "warning")
+%! fail ("isinf (a/b);", "warning", "division by zero");
 %! warning (wdbz.state, "Octave:divide-by-zero");
 
--- a/test/system.tst	Mon Jan 12 09:13:19 2015 -0800
+++ b/test/system.tst	Mon Jan 12 09:17:35 2015 -0800
@@ -58,8 +58,8 @@
 %!error <Invalid call to usleep> usleep (1, 2)
 
 %!test
-%! from = tmpnam ();
-%! to = tmpnam ();
+%! from = tempname ();
+%! to = tempname ();
 %! id = fopen (from, "wb");
 %! if (id > 0 && fclose (id) == 0)
 %!   [s, e] = stat (from);
@@ -79,7 +79,7 @@
 %!error <Invalid call to rename> rename ("foo", "bar", 1)
 
 %!test
-%! nm = tmpnam ();
+%! nm = tempname ();
 %! if ((id = fopen (nm, "wb")) > 0)
 %!   [s, err] = stat (nm);
 %!   if (! err && fclose (id) == 0 && unlink (nm) == 0)
@@ -90,6 +90,7 @@
 
 %!error <Invalid call to unlink> unlink ()
 %!error <Invalid call to unlink> unlink ("foo", 1)
+%!error <FILE must be a string> unlink ({})
 
 %!test
 %! [files, status, msg] = readdir (filesep);
@@ -99,7 +100,7 @@
 %!error <Invalid call to readdir> readdir ("foo", 1)
 
 %!test
-%! nm = tmpnam ();
+%! nm = tempname ();
 %! e1 = mkdir (nm);
 %! [s2, e2] = stat (nm);
 %! e3 = rmdir (nm);
@@ -120,14 +121,14 @@
 %! ## Test makes no sense on Windows systems
 %! if (isunix () || ismac ())
 %!   orig_umask = umask (0);
-%!   nm = tmpnam ();
+%!   nm = tempname ();
 %!   id = fopen (nm, "wb");
 %!   s1 = stat (nm);
 %!   fclose (id);
 %!   unlink (nm);
 %!
 %!   umask (777);
-%!   nm = tmpnam ();
+%!   nm = tempname ();
 %!   id = fopen (nm, "wb");
 %!   s2 = stat (nm);
 %!   fclose (id);
@@ -180,22 +181,48 @@
 %!error <Invalid call to lstat> lstat ()
 %!error <Invalid call to lstat> lstat ("foo", 1)
 
+%!test
+%! if (isunix ())
+%!   assert (S_ISCHR (stat ("/dev/null").mode));
+%!   if (exist ("/dev/initctl"))
+%!     assert (S_ISFIFO (stat ("/dev/initctl").mode));
+%!   endif
+%!   assert (S_ISLNK (lstat ("/dev/core").mode));
+%! endif
+%! nm = tempname ();
+%! fid = fopen (nm, "wb");
+%! fclose (fid);
+%! r = [ S_ISREG(stat(nm).mode)
+%!       S_ISDIR(stat(nm).mode)
+%!       S_ISCHR(stat(nm).mode)
+%!       S_ISBLK(stat(nm).mode)
+%!       S_ISFIFO(stat(nm).mode)
+%!       S_ISLNK(lstat(nm).mode)
+%!       S_ISSOCK(stat(nm).mode) ];
+%! unlink (nm);
+%! assert (r(:), [true; false; false; false; false; false; false]);
+
+%!error <octave_base_value::double_value> S_ISREG ({})
+%!error <octave_base_value::double_value> S_ISDIR ({})
+%!error <octave_base_value::double_value> S_ISCHR ({})
+%!error <octave_base_value::double_value> S_ISBLK ({})
+%!error <octave_base_value::double_value> S_ISFIFO ({})
+%!error <octave_base_value::double_value> S_ISLNK ({})
+%!error <octave_base_value::double_value> S_ISSOCK ({})
+
+%!error <Invalid call to S_ISREG> S_ISREG ()
+%!error <Invalid call to S_ISDIR> S_ISDIR ()
+%!error <Invalid call to S_ISCHR> S_ISCHR ()
+%!error <Invalid call to S_ISBLK> S_ISBLK ()
+%!error <Invalid call to S_ISFIFO> S_ISFIFO ()
+%!error <Invalid call to S_ISLNK> S_ISLNK ()
+%!error <Invalid call to S_ISSOCK> S_ISSOCK ()
+
 %!assert (iscell (glob ([filesep "*"])))
 
 %!error <Invalid call to glob> glob ()
 %!error <Invalid call to glob> glob ("foo", 1)
 
-%!test
-%! string_fill_char = char (0);
-%! assert ((fnmatch ("a*a", {"aba"; "xxxba"; "aa"}) == [1; 0; 1]
-%! && fnmatch ({"a*a"; "b*b"}, "bob")
-%! && fnmatch ("x[0-5]*", {"x1"; "x6"}) == [1; 0]
-%! && fnmatch ("x[0-5]*", {"x1"; "x6"; "x001"}) == [1; 0; 1]
-%! && fnmatch ("x???y", {"xabcy"; "xy"}) == [1; 0]));
-
-%!error <Invalid call to fnmatch> fnmatch ()
-%!error <Invalid call to fnmatch> fnmatch ("foo", "bar", 3)
-
 %!assert (ischar (file_in_path (path (), "date.m")))
 
 %!error <invalid option> file_in_path ("foo", "bar", 1)
@@ -253,17 +280,13 @@
 %! warning (wns.state, "Octave:num-to-str");
 
 %!test
-%! putenv ("foobar", "baz");
+%! setenv ("foobar", "baz");
 %! assert (getenv ("foobar"), "baz");
 
-%!error <Invalid call to putenv> putenv ()
-%!error <Invalid call to putenv> putenv ("foo", "bar", 1)
+%!error <Invalid call to setenv> setenv ()
+%!error <Invalid call to setenv> setenv ("foo", "bar", 1)
 
-%!test
-%! wns = warning ("query", "Octave:num-to-str");
-%! warning ("on", "Octave:num-to-str");
-%! fail ("putenv (1, 2)","warning");
-%! warning (wns.state, "Octave:num-to-str");
+%!error <VAR must be a string> setenv (1, 2)
 
 %!test
 %! xdir = pwd ();
@@ -370,4 +393,3 @@
 %!assert (isstruct (octave_config_info ()))
 
 %!assert (isstruct (getrusage ()))
-