changeset 13029:50db905c3cf1

maint: periodic merge of stable to default
author John W. Eaton <jwe@octave.org>
date Tue, 30 Aug 2011 14:37:25 -0400
parents b9a89ca0fb75 (diff) 9b191d0e547f (current diff)
children b646413c3d0e
files doc/interpreter/matrix.txi scripts/plot/private/__print_parse_opts__.m src/DLD-FUNCTIONS/__magick_read__.cc src/data.cc src/oct-parse.yy
diffstat 418 files changed, 8900 insertions(+), 5842 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,67 @@
+Summary of important user-visible changes for version 3.6:
+---------------------------------------------------------
+
+ ** The PCRE library is now required to build Octave.
+
+ ** Octave now features a profiler, thanks to the work of Daniel Kraft
+    under the Google Summer of Code mentorship program. The manual has
+    been updated to reflect this addition.
+
+ ** strread, textscan, and textread have been completely revamped.
+
+    They now support nearly all Matlab functionality including:
+
+    * ML-compatible whitespace and delimiter defaults
+
+    * ML-compatible options: 'whitespace', treatasempty',
+    format string repeat count, user-specified comment style, uneven-length
+    output arrays, %n and %u conversion specifiers (provisionally)
+
+ ** Certain string functions have been modified for greater Matlab compatibility
+    and for 15X greater performance when operating on cell array of strings.
+
+    deblank : Now requires character or cellstr input
+    strtrim : Now requires character or cellstr input.
+              No longer trims nulls ("\0") from string for ML compatibility.
+    strmatch: Follows documentation precisely and ignores trailing spaces
+              in pattern and in string.  Note that Matlab documents this 
+              behavior but the implementation does *not* always follow it.
+ 
+ ** New functions added.
+
+    iscolumn
+    issrow
+    zscore
+    profile
+    profshow
+
+ ** Deprecated functions.
+
+    The following functions were deprecated in Octave 3.2 and have been
+    removed from Octave 3.6.
+                                           
+      create_set          spcholinv    splu   
+      dmult               spcumprod    spmax
+      iscommand           spcumsum     spmin
+      israwcommand        spdet        spprod
+      lchol               spdiag       spqr
+      loadimage           spfind       spsum
+      mark_as_command     sphcat       spsumsq
+      mark_as_rawcommand  spinv        spvcat 
+      spatan2             spkron       str2mat
+      spchol              splchol      unmark_command
+      spchol2inv          split        unmark_rawcommand
+
+    The following functions have been deprecated in Octave 3.6 and will
+    be removed from Octave 3.10 (or whatever version is the second major
+    release after 3.6):
+
+      cut                is_duplicate_entry
+      cor                polyderiv
+      corrcoef           studentize
+      __error_text__     sylvester_matrix
+      error_text
+
 Summary of important user-visible changes for version 3.4.2:
 -----------------------------------------------------------
 
--- a/build-aux/common.mk
+++ b/build-aux/common.mk
@@ -162,8 +162,6 @@
 
 RDYNAMIC_FLAG = @RDYNAMIC_FLAG@
 
-RLD_FLAG = @RLD_FLAG@
-
 FLIBS = @FLIBS@
 
 LIBOCTINTERP = @LIBOCTINTERP@
@@ -535,8 +533,12 @@
   -e "s|%OCTAVE_CONF_MAGICK_LDFLAGS%|\"${MAGICK_LDFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_MAGICK_LIBS%|\"${MAGICK_LIBS}\"|" \
   -e 's|%OCTAVE_CONF_MKOCTFILE_DL_LDFLAGS%|\"@MKOCTFILE_DL_LDFLAGS@\"|' \
+  -e "s|%OCTAVE_CONF_OCTAVE_LINK_DEPS%|\"${OCTAVE_LINK_DEPS}\"|" \
+  -e "s|%OCTAVE_CONF_OCTAVE_LINK_OPTS%|\"${OCTAVE_LINK_OPTS}\"|" \
   -e "s|%OCTAVE_CONF_OCTINCLUDEDIR%|\"${octincludedir}\"|" \
   -e "s|%OCTAVE_CONF_OCTLIBDIR%|\"${octlibdir}\"|" \
+  -e "s|%OCTAVE_CONF_OCT_LINK_DEPS%|\"${OCT_LINK_DEPS}\"|" \
+  -e "s|%OCTAVE_CONF_OCT_LINK_OPTS%|\"${OCT_LINK_OPTS}\"|" \
   -e "s|%OCTAVE_CONF_OPENGL_LIBS%|\"${OPENGL_LIBS}\"|" \
   -e "s|%OCTAVE_CONF_PREFIX%|\"${prefix}\"|" \
   -e "s|%OCTAVE_CONF_PTHREAD_CFLAGS%|\"${PTHREAD_CFLAGS}\"|" \
@@ -551,7 +553,6 @@
   -e "s|%OCTAVE_CONF_RDYNAMIC_FLAG%|\"${RDYNAMIC_FLAG}\"|" \
   -e "s|%OCTAVE_CONF_READLINE_LIBS%|\"${READLINE_LIBS}\"|" \
   -e "s|%OCTAVE_CONF_REGEX_LIBS%|\"${REGEX_LIBS}\"|" \
-  -e "s|%OCTAVE_CONF_RLD_FLAG%|\"${RLD_FLAG}\"|" \
   -e "s|%OCTAVE_CONF_SED%|\"${SED}\"|" \
   -e "s|%OCTAVE_CONF_SHARED_LIBS%|\"${SHARED_LIBS}\"|" \
   -e "s|%OCTAVE_CONF_SHLEXT%|\"${SHLEXT}\"|" \
--- a/configure.ac
+++ b/configure.ac
@@ -27,13 +27,13 @@
 EXTERN_CFLAGS="$CFLAGS"
 EXTERN_CXXFLAGS="$CXXFLAGS"
 
-AC_INIT([GNU Octave], [3.4.2], [http://octave.org/bugs.html], [octave])
+AC_INIT([GNU Octave], [3.5.0+], [http://octave.org/bugs.html], [octave])
 
 dnl PACKAGE_VERSION is set by the AC_INIT VERSION arg
 OCTAVE_VERSION="$PACKAGE_VERSION"
-OCTAVE_API_VERSION_NUMBER="45"
+OCTAVE_API_VERSION_NUMBER="44"
 OCTAVE_API_VERSION="api-v$OCTAVE_API_VERSION_NUMBER+"
-OCTAVE_RELEASE_DATE="2011-06-24"
+OCTAVE_RELEASE_DATE="2011-01-22"
 OCTAVE_COPYRIGHT="Copyright (C) 2011 John W. Eaton and others."
 AC_SUBST(OCTAVE_VERSION)
 AC_SUBST(OCTAVE_API_VERSION_NUMBER)
@@ -1157,7 +1157,7 @@
 
 AC_ARG_ENABLE([dl],
   [AS_HELP_STRING([--enable-dl],
-    [create shared libraries (not all systems)])], [
+    [allow loading of dynamically linked modules (not all systems)])], [
   case "${enableval}" in
     yes) ENABLE_DYNAMIC_LINKING=true ;;
     no) ENABLE_DYNAMIC_LINKING=false ;;
@@ -1170,16 +1170,6 @@
   AC_MSG_ERROR([You can't disable building static AND shared libraries!])
 fi
 
-AC_ARG_ENABLE(rpath,
-  [AS_HELP_STRING([--enable-rpath],
-     [override the default link options for rpath; e.g., --enable-rpath='-rpath $(octlibdir)'])],
-  [ if test "$enableval" = no; then use_rpath=false;
-    else
-      use_rpath=true
-      if test "$enableval" = yes; then true;
-      else enable_rpath_arg="$enableval"; fi
-    fi], [use_rpath=true])
-
 CPICFLAG=-fPIC
 CXXPICFLAG=-fPIC
 FPICFLAG=-fPIC
@@ -1200,7 +1190,6 @@
 DL_LDFLAGS='$(SH_LDFLAGS)'
 MKOCTFILE_DL_LDFLAGS='$(DL_LDFLAGS)'
 SONAME_FLAGS=
-RLD_FLAG=
 NO_OCT_FILE_STRIP=false
 TEMPLATE_AR='$(AR)'
 TEMPLATE_ARFLAGS="$ARFLAGS"
@@ -1221,14 +1210,12 @@
   ;;
   *-*-freebsd*)
     SH_LDFLAGS="-shared -Wl,-x"
-    RLD_FLAG='-Wl,-rpath -Wl,$(octlibdir)'
   ;;
   alpha*-dec-osf*)
     CPICFLAG=
     CXXPICFLAG=
     FPICFLAG=
     SH_LDFLAGS="-shared -Wl,-expect_unresolved -Wl,'*'"
-    RLD_FLAG='-Wl,-rpath -Wl,$(octlibdir)'
   ;;
   *-*-darwin*)
     DL_LDFLAGS='-bundle -bundle_loader $(top_builddir)/src/octave $(LDFLAGS)'
@@ -1335,11 +1322,9 @@
   *-*-linux* | *-*-gnu*)
     MKOCTFILE_DL_LDFLAGS="-shared -Wl,-Bsymbolic"
     SONAME_FLAGS='-Wl,-soname -Wl,$@'
-    RLD_FLAG='-Wl,-rpath -Wl,$(octlibdir)'
   ;;
   i[[3456]]86-*-sco3.2v5*)
     SONAME_FLAGS='-Wl,-h -Wl,$@'
-    RLD_FLAG=
     SH_LDFLAGS=-G
   ;;
   rs6000-ibm-aix* | powerpc-ibm-aix*)
@@ -1356,7 +1341,6 @@
     fi
     SHLEXT=sl
     SH_LDFLAGS="-shared -fPIC"
-    RLD_FLAG='-Wl,+b -Wl,$(octlibdir)'
     library_path_var=SHLIB_PATH
   ;;
   ia64*-hp-hpux*)
@@ -1366,13 +1350,11 @@
       FPICFLAG=+Z
     fi
     SH_LDFLAGS="-shared -fPIC"
-    RLD_FLAG='-Wl,+b -Wl,$(octlibdir)'
   ;;
   *-sgi-*)
     CPICFLAG=
     CXXPICFLAG=
     FPICFLAG=
-    RLD_FLAG='-rpath $(octlibdir)'
   ;;
   sparc-sun-sunos4*)
     if test "$ac_cv_f77_compiler_gnu" = yes; then
@@ -1382,7 +1364,6 @@
     fi
     SH_LD=ld
     SH_LDFLAGS="-assert nodefinitions"
-    RLD_FLAG='-L$(octlibdir)'
   ;;
   sparc-sun-solaris2* | i386-pc-solaris2*)
     if test "$ac_cv_f77_compiler_gnu" = yes; then
@@ -1402,7 +1383,6 @@
       CXXPICFLAG=-KPIC
       SH_LDFLAGS=-G
     fi
-    RLD_FLAG='-R $(octlibdir)'
     ## Template closures in archive libraries need a different mechanism.
     if test "$GXX" = yes; then
       true
@@ -1416,14 +1396,6 @@
 AM_CONDITIONAL([AMCOND_BUILD_COMPILED_AUX_PROGRAMS],
   [test x$BUILD_COMPILED_AUX_PROGRAMS = xtrue])
 
-if $use_rpath; then
-  if test -n "$enable_rpath_arg"; then
-    RLD_FLAG="$enable_rpath_arg"
-  fi
-else
-  RLD_FLAG=""
-fi
-
 AC_MSG_NOTICE([defining FPICFLAG to be $FPICFLAG])
 AC_MSG_NOTICE([defining CPICFLAG to be $CPICFLAG])
 AC_MSG_NOTICE([defining CXXPICFLAG to be $CXXPICFLAG])
@@ -1445,7 +1417,6 @@
 AC_MSG_NOTICE([defining MKOCTFILE_DL_LDFLAGS to be $MKOCTFILE_DL_LDFLAGS])
 AC_MSG_NOTICE([defining SONAME_FLAGS to be $SONAME_FLAGS])
 AC_MSG_NOTICE([defining NO_OCT_FILE_STRIP to be $NO_OCT_FILE_STRIP])
-AC_MSG_NOTICE([defining RLD_FLAG to be $RLD_FLAG])
 AC_MSG_NOTICE([defining TEMPLATE_AR to be $TEMPLATE_AR])
 AC_MSG_NOTICE([defining TEMPLATE_ARFLAGS to be $TEMPLATE_ARFLAGS])
 AC_MSG_NOTICE([defining CRUFT_DLL_DEFS to be $CRUFT_DLL_DEFS])
@@ -1474,7 +1445,6 @@
 AC_SUBST(MKOCTFILE_DL_LDFLAGS)
 AC_SUBST(SONAME_FLAGS)
 AC_SUBST(NO_OCT_FILE_STRIP)
-AC_SUBST(RLD_FLAG)
 AC_SUBST(TEMPLATE_AR)
 AC_SUBST(TEMPLATE_ARFLAGS)
 AC_SUBST(CRUFT_DLL_DEFS)
@@ -1488,28 +1458,42 @@
 
 AC_CHECK_FUNCS(getpwnam, [], [AC_CHECK_LIB(sun, getpwnam)])
 
-NO_UNDEFINED_LDFLAG=
 case "$canonical_host_type" in
   *-*-mingw*)
     if test "$have_msvc" = "yes"; then
       AC_CHECK_LIB(dirent, opendir)
       LIBS="$LIBS -ladvapi32 -lgdi32 -lws2_32 -luser32 -lkernel32"
-      NO_UNDEFINED_LDFLAG=-no-undefined
     else
       LIBS="$LIBS -lgdi32 -lws2_32 -luser32 -lkernel32"
-      NO_UNDEFINED_LDFLAG=-no-undefined
     fi
     LIBS="$LIBS -lgdi32 -lws2_32 -luser32 -lkernel32"
-    NO_UNDEFINED_LDFLAG=-no-undefined
   ;;
   *-*-msdosmsvc*)
     AC_CHECK_LIB(dirent, opendir)
     LIBS="$LIBS -ladvapi32 -lgdi32 -lws2_32 -luser32 -lkernel32"
-    NO_UNDEFINED_LDFLAG=-no-undefined
   ;;
 esac
+
+AC_ARG_ENABLE([no-undefined],
+  [AS_HELP_STRING([--enable-no-undefined],
+    [pass -no-undefined to libtool when linking linking Octave and its shared libraries (on by default)])],
+  [case "${enableval}" in
+    yes) NO_UNDEFINED_LDFLAG="-no-undefined" ;;
+    no)  NO_UNDEFINED_LDFLAG="" ;;
+    *) AC_MSG_ERROR([bad value ${enableval} for --enable-link-all-depenencies]) ;;
+   esac], [NO_UNDEFINED_LDFLAG="-no-undefined"])
 AC_SUBST(NO_UNDEFINED_LDFLAG)
 
+AC_ARG_ENABLE([link-all-dependencies],
+  [AS_HELP_STRING([--enable-link-all-dependencies],
+    [link Octave and its shared libraries with all dependencies, not just those immediately referenced (should not be needed on most systems)])],
+  [case "${enableval}" in
+    yes) link_all_deps=true ;;
+    no)  link_all_deps=false ;;
+    *) AC_MSG_ERROR([bad value ${enableval} for --enable-link-all-depenencies]) ;;
+   esac], [link_all_deps=false])
+AM_CONDITIONAL([AMCOND_LINK_ALL_DEPS], [test x$link_all_deps = xtrue])
+
 ### Type stuff.
 
 AC_TYPE_MODE_T
@@ -1685,7 +1669,7 @@
       OCTAVE_CXX_FLAG(-rdynamic, [RDYNAMIC_FLAG=-rdynamic])
     ;;
     shl_load)
-      shl_load_api=true
+      shl_load_api=truenn
       DL_API_MSG="(shl_load)"
       AC_DEFINE(HAVE_SHL_LOAD_API, 1, [Define if your system has shl_load and shl_findsym for dynamic linking])
     ;;
@@ -1704,12 +1688,18 @@
   DL_LIBS="$lt_cv_dlopen_libs"
   AC_SUBST(DL_LIBS)
 
+  ## Disable dynamic linking if capability is not present.
   if $dlopen_api || $shl_load_api || $loadlibrary_api || $dyld_api; then
-    ENABLE_DYNAMIC_LINKING=true
-    AC_DEFINE(ENABLE_DYNAMIC_LINKING, 1, [Define if using dynamic linking])
+    true
+  else
+    ENABLE_DYNAMIC_LINKING=false
   fi
 fi
 
+if $ENABLE_DYNAMIC_LINKING; then
+  AC_DEFINE(ENABLE_DYNAMIC_LINKING, 1, [Define if using dynamic linking])
+fi
+
 AM_CONDITIONAL([AMCOND_ENABLE_DYNAMIC_LINKING],
   [test x$ENABLE_DYNAMIC_LINKING = xtrue])
 
--- a/doc/faq/OctaveFAQ.texi
+++ b/doc/faq/OctaveFAQ.texi
@@ -63,7 +63,7 @@
 * Getting Octave::
 * Installation::
 * Common problems::
-* How do I ...?::
+* Using Octave::
 * @sc{Matlab} compatibility::
 * Index::
 @end menu
@@ -780,15 +780,16 @@
 @end itemize
 @end itemize
 
-@node How do I ...?
-@chapter  How do I ...?
+@node Using Octave
+@chapter  Using Octave
 
 @menu
 * How do I set the number of displayed decimals?::
+* How does Octave solve linear systems?::
 @end menu
 
 @cindex Tips and tricks
-@cindex How do I @dots{} ?
+@cindex Using Octave
 
 @node How do I set the number of displayed decimals?
 @section How do I set the number of displayed decimals?
@@ -804,6 +805,18 @@
 @end group
 @end example
 
+@node How does Octave solve linear systems?
+@section How does Octave solve linear systems?
+
+@cindex backslash operator
+
+In addition to consulting Octave's source for the precise details, the
+Octave manual contains a complete high-level description of the
+algorithm that Octave uses to decide how to solve a particular linear
+system, e.g. how the backslash operator @code{A\x} will be interpreted.
+Sections ``Techniques Used for Linear Algebra'' and ``Linear Algebra on
+Sparse Matrices'' from the manual describe this procedure.
+
 @node @sc{Matlab} compatibility
 @chapter Porting programs from @sc{Matlab} to Octave
 
--- a/doc/interpreter/container.txi
+++ b/doc/interpreter/container.txi
@@ -563,16 +563,11 @@
 @example
 @group
 c@{1:2@}
+     @result{} ans = a string
      @result{} ans =
           
-          (,
-            [1] = a string
-            [2] =
-          
                0.593993   0.627732
                0.377037   0.033643
-          
-          ,)
 @end group
 @end example
 
--- a/doc/interpreter/contributors.in
+++ b/doc/interpreter/contributors.in
@@ -1,5 +1,6 @@
 Ben Abbott
 Andy Adler
+Giles Anderson
 Joel Andersson
 Muthiah Annamalai
 Shai Ayal
@@ -148,9 +149,11 @@
 Stefan Monnier
 Antoine Moreau
 Kai P. Mueller
+Hannes Müller
 Victor Munoz
 Carmen Navarrete
 Todd Neal
+Philip Nienhuis
 Al Niessner
 Rick Niles
 Takuji Nishimura
@@ -206,6 +209,7 @@
 Daniel J. Sebald
 Dmitri A. Sergatskov
 Baylis Shanks
+Andriy Shinkarchuck
 Joseph P. Skudlarek
 John Smith
 Julius Smith
@@ -232,6 +236,7 @@
 Frederick Umminger
 Utkarsh Upadhyay
 Stefan van der Walt
+David Wells
 Peter Van Wieren
 James R. Van Zandt
 Gregory Vanuxem
@@ -244,6 +249,7 @@
 Andreas Weingessel
 Michael Weitzel
 Fook Fah Yap
+Sean Young
 Michael Zeising
 Federico Zenith
 Alex Zvoleff
--- a/doc/interpreter/debug.txi
+++ b/doc/interpreter/debug.txi
@@ -35,6 +35,8 @@
 * Breakpoints::
 * Debug Mode::
 * Call Stack::
+* Profiling::
+* Profiler Example::
 @end menu
 
 @node Entering Debug Mode
@@ -182,3 +184,256 @@
 @DOCSTRING(dbup)
 
 @DOCSTRING(dbdown)
+
+@node Profiling
+@section Profiling
+@cindex profiler
+@cindex code profiling
+
+Octave supports profiling of code execution on a per-function level. If
+profiling is enabled, each call to a function (supporting built-ins,
+operators, functions in oct- and mex-files, user-defined functions in
+Octave code and anonymous functions) is recorded while running Octave
+code. After that, this data can aid in analyzing the code behaviour, and
+is in particular helpful for finding ``hot spots'' in the code which use
+up a lot of computation time and are the best targets to spend
+optimization efforts on.
+
+The main command for profiling is @code{profile}, which can be used to
+start or stop the profiler and also to query collected data afterwards.
+The data is returned in an Octave data structure which can then be
+examined or further processed by other routines or tools.
+
+@DOCSTRING(profile)
+
+An easy way to get an overview over the collected data is
+@code{profshow}. This function takes the profiler data returned by
+@code{profile} as input and prints a flat profile, for instance:
+
+@example
+@group
+ Function Attr     Time (s)        Calls
+----------------------------------------
+   >myfib    R        2.195        13529
+binary <=             0.061        13529
+ binary -             0.050        13528
+ binary +             0.026         6764
+@end group
+@end example
+
+This shows that most of the runtime was spent executing the function
+@samp{myfib}, and some minor proportion evaluating the listed binary
+operators. Furthermore, it is shown how often the function was called
+and the profiler also records that it is recursive.
+
+@DOCSTRING(profshow)
+
+@node Profiler Example
+@section Profiler Example
+
+Below, we will give a short example of a profiler session. See also
+@ref{Profiling} for the documentation of the profiler functions in
+detail. Consider the code:
+
+@example
+@group
+global N A;
+
+N = 300;
+A = rand (N, N);
+
+function xt = timesteps (steps, x0, expM)
+  global N;
+
+  if (steps == 0)
+    xt = NA (N, 0);
+  else
+    xt = NA (N, steps);
+    x1 = expM * x0;
+    xt(:, 1) = x1;
+    xt(:, 2 : end) = timesteps (steps - 1, x1, expM);
+  endif
+endfunction
+
+function foo ()
+  global N A;
+
+  initial = @@(x) sin (x);
+  x0 = (initial (linspace (0, 2 * pi, N)))';
+
+  expA = expm (A);
+  xt = timesteps (100, x0, expA);
+endfunction
+
+function fib = bar (N)
+  if (N <= 2)
+    fib = 1;
+  else
+    fib = bar (N - 1) + bar (N - 2);
+  endif
+endfunction
+@end group
+@end example
+
+If we execute the two main functions, we get:
+
+@example
+@group
+tic; foo; toc;
+@result{} Elapsed time is 2.37338 seconds.
+
+tic; bar (20); toc;
+@result{} Elapsed time is 2.04952 seconds.
+@end group
+@end example
+
+But this does not give much information about where this time is spent;
+for instance, whether the single call to @code{expm} is more expensive
+or the recursive time-stepping itself. To get a more detailed picture,
+we can use the profiler.
+
+@example
+@group
+profile on;
+foo;
+profile off;
+
+data = profile ('info');
+profshow (data, 10);
+@end group
+@end example
+
+This prints a table like:
+
+@example
+@group
+   #  Function Attr     Time (s)        Calls
+---------------------------------------------
+   7      expm             1.034            1
+   3  binary *             0.823          117
+  41  binary \             0.188            1
+  38  binary ^             0.126            2
+  43 timesteps    R        0.111          101
+  44        NA             0.029          101
+  39  binary +             0.024            8
+  34      norm             0.011            1
+  40  binary -             0.004          101
+  33   balance             0.003            1
+@end group
+@end example
+
+The entries are the individual functions which have been executed (only
+the 10 most important ones), together with some information for each of
+them. The entries like @samp{binary *} denote operators, while other
+entries are ordinary functions. They include both built-ins like
+@code{expm} and our own routines (for instance @code{timesteps}). From
+this profile, we can immediately deduce that @code{expm} uses up the
+largest proportion of the processing time, even though it is only called
+once. The second expensive operation is the matrix-vector product in the
+routine @code{timesteps}. @footnote{We only know it is the binary
+multiplication operator, but fortunately this operator appears only at
+one place in the code and thus we know which occurence takes so much
+time. If there were multiple places, we would have to use the
+hierarchical profile to find out the exact place which uses up the time
+which is not covered in this example.}
+
+Timing, however, is not the only information available from the profile.
+The attribute column shows us that @code{timesteps} calls itself
+recursively. This may not be that remarkable in this example (since it's
+clear anyway), but could be helpful in a more complex setting. As to the
+question of why is there a @samp{binary \} in the output, we can easily
+shed some light on that too. Note that @code{data} is a structure array
+(@ref{Structure Arrays}) which contains the field @code{FunctionTable}.
+This stores the raw data for the profile shown. The number in the first
+column of the table gives the index under which the shown function can
+be found there. Looking up @code{data.FunctionTable(41)} gives:
+
+@example
+@group
+  scalar structure containing the fields:
+
+    FunctionName = binary \
+    TotalTime =  0.18765
+    NumCalls =  1
+    IsRecursive = 0
+    Parents =  7
+    Children = [](1x0)
+@end group
+@end example
+
+Here we see the information from the table again, but have additional
+fields @code{Parents} and @code{Children}. Those are both arrays, which
+contain the indices of functions which have directly called the function
+in question (which is entry 7, @code{expm}, in this case) or been called
+by it (no functions). Hence, the backslash operator has been used
+internally by @code{expm}.
+
+Now let's take a look at @code{bar}. For this, we start a fresh
+profiling session (@code{profile on} does this; the old data is removed
+before the profiler is restarted):
+
+@example
+@group
+profile on;
+bar (20);
+profile off;
+
+profshow (profile ('info'));
+@end group
+@end example
+
+This gives:
+
+@example
+   #            Function Attr     Time (s)        Calls
+-------------------------------------------------------
+   1                 bar    R        2.091        13529
+   2           binary <=             0.062        13529
+   3            binary -             0.042        13528
+   4            binary +             0.023         6764
+   5             profile             0.000            1
+   8               false             0.000            1
+   6              nargin             0.000            1
+   7           binary !=             0.000            1
+   9 __profiler_enable__             0.000            1
+@end example
+
+Unsurprisingly, @code{bar} is also recursive. It has been called 13,529
+times in the course of recursively calculating the Fibonacci number in a
+suboptimal way, and most of the time was spent in @code{bar} itself.
+
+Finally, let's say we want to profile the execution of both @code{foo}
+and @code{bar} together. Since we already have the runtime data
+collected for @code{bar}, we can restart the profiler without clearing
+the existing data and collect the missing statistics about @code{foo}.
+This is done by:
+
+@example
+@group
+profile resume;
+foo;
+profile off;
+
+profshow (profile ('info'), 10);
+@end group
+@end example
+
+As you can see in the table below, now we have both profiles mixed
+together.
+
+@example
+@group
+   #  Function Attr     Time (s)        Calls
+---------------------------------------------
+   1       bar    R        2.091        13529
+  16      expm             1.122            1
+  12  binary *             0.798          117
+  46  binary \             0.185            1
+  45  binary ^             0.124            2
+  48 timesteps    R        0.115          101
+   2 binary <=             0.062        13529
+   3  binary -             0.045        13629
+   4  binary +             0.041         6772
+  49        NA             0.036          101
+@end group
+@end example
deleted file mode 100644
--- a/doc/interpreter/dir
+++ /dev/null
@@ -1,14 +0,0 @@
--*- Text -*-
-This is the file .../info/dir, which contains the topmost node of the
-Info hierarchy.	 The first time you invoke Info you start off
-looking at that node, which is (dir)Top.
-
-File: dir	Node: Top	This is the top of the INFO tree
-  This (the Directory node) gives a menu of major topics. 
-  Typing "d" returns here, "q" exits, "?" lists all INFO commands, "h" 
-  gives a primer for first-timers, "mItem<Return>" visits the menu
-  item named `Item', etc.
-
-* Menu: The list of major topics begins on the next line.
-
-* Octave: (octave).	Interactive language for numerical computations.
--- a/doc/interpreter/doccheck/mk_undocumented_list
+++ b/doc/interpreter/doccheck/mk_undocumented_list
@@ -82,7 +82,6 @@
 comma
 debug
 dbnext
-error_text
 exit
 F_DUPFD
 F_GETFD
deleted file mode 100644
--- a/doc/interpreter/eos.txi
+++ /dev/null
@@ -1,515 +0,0 @@
-@c Copyright (C) 1996-2011 Kurt Hornik
-@c
-@c This file is part of Octave.
-@c
-@c Octave is free software; you can redistribute it and/or modify it
-@c under the terms of the GNU General Public License as published by the
-@c Free Software Foundation; either version 3 of the License, or (at
-@c your option) any later version.
-@c 
-@c Octave is distributed in the hope that it will be useful, but WITHOUT
-@c ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-@c FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-@c for more details.
-@c 
-@c You should have received a copy of the GNU General Public License
-@c along with Octave; see the file COPYING.  If not, see
-@c <http://www.gnu.org/licenses/>.
-
-@c Written by Kurt Hornik <Kurt.Hornik@wu-wien.ac.at> on 1996/05/17.
-@c Last updated by KH on 1997/07/31.
-
-@node Emacs
-@chapter Emacs Octave Support
-
-The development of Octave code can greatly be facilitated using Emacs
-with Octave mode
-automatically indent the code, do some of the typing (with Abbrev mode)
-and show keywords, comments, strings, etc.@: in different faces (with
-Font-lock mode on devices that support it).
-
-It is also possible to run Octave from within Emacs, either by directly
-entering commands at the prompt in a buffer in Inferior Octave mode, or
-by interacting with Octave from within a file with Octave code.  This is
-useful in particular for debugging Octave code.
-
-Finally, you can convince Octave to use the Emacs info reader for
-@kbd{help -i}.
-
-All functionality is provided by the Emacs Lisp package EOS (for ``Emacs
-Octave Support'').  This chapter describes how to set up and use this
-package.
-
-Please contact @email{Kurt.Hornik@@wu-wien.ac.at} if you have any questions
-or suggestions on using EOS.
-
-@menu
-* Installing EOS::              
-* Using Octave Mode::           
-* Running Octave From Within Emacs::  
-* Using the Emacs Info Reader for Octave::  
-@end menu
-
-@node Installing EOS
-@section Installing EOS
-
-The Emacs package EOS consists of the three files @file{octave-mod.el},
-@file{octave-inf.el}, and @file{octave-hlp.el}.  These files, or better
-yet their byte-compiled versions, should be somewhere in your Emacs
-load-path.
-
-If you have GNU Emacs with a version number at least as high as 19.35,
-you are all set up, because EOS is respectively will be part of GNU
-Emacs as of version 19.35.
-
-Otherwise, copy the three files from the @file{emacs} subdirectory of
-the Octave distribution to a place where Emacs can find them (this
-depends on how your Emacs was installed).  Byte-compile them for speed
-if you want.
-
-@node Using Octave Mode
-@section Using Octave Mode
-
-If you are lucky, your sysadmins have already arranged everything so
-that Emacs automatically goes into Octave mode whenever you visit an
-Octave code file as characterized by its extension @file{.m}.  If not,
-proceed as follows.
-
-@enumerate
-@item
-To begin using Octave mode for all @file{.m} files you visit, add the
-following lines to a file loaded by Emacs at startup time, typically
-your @file{~/.emacs} file:
-
-@lisp
-(autoload 'octave-mode "octave-mod" nil t)
-(setq auto-mode-alist
-      (cons '(\"\\\\.m$\" . octave-mode) auto-mode-alist))
-@end lisp
-
-@item
-Finally, to turn on the abbrevs, auto-fill and font-lock features
-automatically, also add the following lines to one of the Emacs startup
-files:
-@lisp
-(add-hook 'octave-mode-hook
-          (lambda ()
-            (abbrev-mode 1)
-            (auto-fill-mode 1)
-            (if (eq window-system 'x)
-                (font-lock-mode 1))))
-@end lisp
-See the Emacs manual for more information about how to customize
-Font-lock mode.
-@end enumerate
-
-In Octave mode, the following special Emacs commands can be used in
-addition to the standard Emacs commands.
-
-@table @kbd
-@item C-h m
-Describe the features of Octave mode.
-
-@item LFD
-Reindent the current Octave line, insert a newline and indent the new
-line (@code{octave-reindent-then-newline-and-indent}).  An abbrev before
-point is expanded if @code{abbrev-mode} is non-@code{nil}.
-
-@item TAB
-Indents current Octave line based on its contents and on previous
-lines (@code{indent-according-to-mode}). 
-
-@item ;
-Insert an ``electric'' semicolon (@code{octave-electric-semi}).  If
-@code{octave-auto-indent} is non-@code{nil}, reindent the current line.
-If @code{octave-auto-newline} is non-@code{nil}, automagically insert a
-newline and indent the new line.
-
-@item `
-Start entering an abbreviation (@code{octave-abbrev-start}).  If Abbrev
-mode is turned on, typing @kbd{`C-h} or @kbd{`?} lists all abbrevs.
-Any other key combination is executed normally.  Note that all Octave
-abbrevs start with a grave accent.
-
-@item M-LFD
-Break line at point and insert continuation marker and alignment
-(@code{octave-split-line}).
-
-@item M-TAB
-Perform completion on Octave symbol preceding point, comparing that
-symbol against Octave's reserved words and built-in variables
-(@code{octave-complete-symbol}). 
-
-@item M-C-a
-Move backward to the beginning of a function
-(@code{octave-beginning-of-defun}).
-With prefix argument @var{N}, do it that many times if @var{N} is
-positive; otherwise, move forward to the @var{N}-th following beginning
-of a function.
-
-@item M-C-e
-Move forward to the end of a function (@code{octave-end-of-defun}).
-With prefix argument @var{N}, do it that many times if @var{N} is
-positive; otherwise, move back to the @var{N}-th preceding end of a
-function.
-
-@item M-C-h
-Puts point at beginning and mark at the end of the current Octave
-function, i.e., the one containing point or following point
-(@code{octave-mark-defun}).
-
-@item M-C-q
-Properly indents the Octave function which contains point
-(@code{octave-indent-defun}).
-
-@item M-;
-If there is no comment already on this line, create a code-level comment
-(started by two comment characters) if the line is empty, or an in-line
-comment (started by one comment character) otherwise
-(@code{octave-indent-for-comment}).
-Point is left after the start of the comment which is properly aligned.
-
-@item C-c ;
-Puts the comment character @samp{#} (more precisely, the string value of
-@code{octave-comment-start}) at the beginning of every line in the
-region (@code{octave-comment-region}).  With just @kbd{C-u} prefix
-argument, uncomment each line in the region.  A numeric prefix argument
-@var{N} means use @var{N} comment characters.
-
-@item C-c :
-Uncomments every line in the region (@code{octave-uncomment-region}).
-
-@item C-c C-p
-Move one line of Octave code backward, skipping empty and comment lines
-(@code{octave-previous-code-line}).  With numeric prefix argument
-@var{N}, move that many code lines backward (forward if @var{N} is
-negative).
-
-@item C-c C-n
-Move one line of Octave code forward, skipping empty and comment lines
-(@code{octave-next-code-line}).  With numeric prefix argument @var{N},
-move that many code lines forward (backward if @var{N} is negative).
-
-@item C-c C-a
-Move to the `real' beginning of the current line
-(@code{octave-beginning-of-line}).  If point is in an empty or comment
-line, simply go to its beginning; otherwise, move backwards to the
-beginning of the first code line which is not inside a continuation
-statement, i.e., which does not follow a code line ending in @samp{...}
-or @samp{\}, or is inside an open parenthesis list.
-
-@item C-c C-e
-Move to the `real' end of the current line (@code{octave-end-of-line}).
-If point is in a code line, move forward to the end of the first Octave
-code line which does not end in @samp{...} or @samp{\} or is inside an
-open parenthesis list.  Otherwise, simply go to the end of the current
-line.
-
-@item C-c M-C-n
-Move forward across one balanced begin-end block of Octave code
-(@code{octave-forward-block}).  With numeric prefix argument @var{N},
-move forward across @var{n} such blocks (backward if @var{N} is
-negative).
-
-@item C-c M-C-p
-Move back across one balanced begin-end block of Octave code
-(@code{octave-backward-block}).  With numeric prefix argument @var{N},
-move backward across @var{N} such blocks (forward if @var{N} is
-negative).
-
-@item C-c M-C-d
-Move forward down one begin-end block level of Octave code
-(@code{octave-down-block}).  With numeric prefix argument, do it that
-many times; a negative argument means move backward, but still go down
-one level.
-
-@item C-c M-C-u
-Move backward out of one begin-end block level of Octave code
-(@code{octave-backward-up-block}).  With numeric prefix argument, do it
-that many times; a negative argument means move forward, but still to a
-less deep spot.
-
-@item C-c M-C-h
-Put point at the beginning of this block, mark at the end
-(@code{octave-mark-block}).
-The block marked is the one that contains point or follows point.
-
-@item C-c ]
-Close the current block on a separate line (@code{octave-close-block}).
-An error is signaled if no block to close is found.
-
-@item C-c f
-Insert a function skeleton, prompting for the function's name, arguments
-and return values which have to be entered without parentheses
-(@code{octave-insert-defun}).
-
-@item C-c C-h
-Search the function, operator and variable indices of all info files
-with documentation for Octave for entries (@code{octave-help}).  If used
-interactively, the entry is prompted for with completion.  If multiple
-matches are found, one can cycle through them using the standard
-@samp{,} (@code{Info-index-next}) command of the Info reader.
-
-The variable @code{octave-help-files} is a list of files to search
-through and defaults to @code{'("octave")}.  If there is also an Octave
-Local Guide with corresponding info file, say, @file{octave-LG}, you can
-have @code{octave-help} search both files by 
-@lisp
-(setq octave-help-files '("octave" "octave-LG"))
-@end lisp
-@noindent
-in one of your Emacs startup files.
-
-@end table
-
-A common problem is that the @key{RET} key does @emph{not} indent the
-line to where the new text should go after inserting the newline.  This
-is because the standard Emacs convention is that @key{RET} (aka
-@kbd{C-m}) just adds a newline, whereas @key{LFD} (aka @kbd{C-j}) adds a
-newline and indents it.  This is particularly inconvenient for users with
-keyboards which do not have a special @key{LFD} key at all; in such
-cases, it is typically more convenient to use @key{RET} as the @key{LFD}
-key (rather than typing @kbd{C-j}).  
-
-You can make @key{RET} do this by adding
-@lisp
-(define-key octave-mode-map "\C-m"
-  'octave-reindent-then-newline-and-indent)
-@end lisp
-@noindent
-to one of your Emacs startup files.  Another, more generally applicable
-solution is
-@lisp
-(defun RET-behaves-as-LFD ()
-  (let ((x (key-binding "\C-j")))
-    (local-set-key "\C-m" x)))
-(add-hook 'octave-mode-hook 'RET-behaves-as-LFD)
-@end lisp
-@noindent
-(this works for all modes by adding to the startup hooks, without having
-to know the particular binding of @key{RET} in that mode!).  Similar
-considerations apply for using @key{M-RET} as @key{M-LFD}.  As Barry
-A. Warsaw @email{bwarsaw@@cnri.reston.va.us} says in the documentation for his
-@code{cc-mode}, ``This is a very common question.  @code{:-)} If you want
-this to be the default behavior, don't lobby me, lobby RMS!''
-
-The following variables can be used to customize Octave mode.
-
-@table @code
-@item octave-auto-indent
-Non-@code{nil} means auto-indent the current line after a semicolon or
-space.  Default is @code{nil}.
-
-@item octave-auto-newline
-Non-@code{nil} means auto-insert a newline and indent after semicolons
-are typed.  The default value is @code{nil}.
-
-@item octave-blink-matching-block
-Non-@code{nil} means show matching begin of block when inserting a space,
-newline or @samp{;} after an else or end keyword.  Default is @code{t}.
-This is an extremely useful feature for automatically verifying that the
-keywords match---if they don't, an error message is displayed.
-
-@item octave-block-offset
-Extra indentation applied to statements in block structures.
-Default is 2.
-
-@item octave-continuation-offset
-Extra indentation applied to Octave continuation lines.
-Default is 4. 
-
-@item octave-continuation-string
-String used for Octave continuation lines.
-Normally @samp{\}.
-
-@item octave-mode-startup-message
-If @code{t} (default), a startup message is displayed when Octave mode
-is called.
-
-@end table
-
-If Font Lock mode is enabled, Octave mode will display
-@itemize @bullet
-@item
-strings in @code{font-lock-string-face}
-
-@item
-comments in @code{font-lock-comment-face}
-
-@item
-the Octave reserved words (such as all block keywords) and the text
-functions (such as @samp{cd} or @samp{who}) which are also reserved
-using @code{font-lock-keyword-face}
-
-@item
-the built-in operators (@samp{&&}, @samp{==}, @dots{}) using
-@code{font-lock-reference-face}
-
-@item
-and the function names in function declarations in
-@code{font-lock-function-name-face}.
-@end itemize
-
-There is also rudimentary support for Imenu (currently, function names
-can be indexed).
-
-Customization of Octave mode can be performed by modification of the
-variable @code{octave-mode-hook}.  It the value of this variable is
-non-@code{nil}, turning on Octave mode calls its value.
-
-If you discover a problem with Octave mode, you can conveniently send a
-bug report using @kbd{C-c C-b} (@code{octave-submit-bug-report}).  This
-automatically sets up a mail buffer with version information already
-added.  You just need to add a description of the problem, including a
-reproducible test case and send the message.
-
-@node Running Octave From Within Emacs
-@section Running Octave From Within Emacs
-
-The package @file{octave} provides commands for running an inferior
-Octave process in a special Emacs buffer.  Use 
-@lisp
-M-x run-octave
-@end lisp
-@noindent
-to directly start an inferior Octave process.  If Emacs does not know
-about this command, add the line
-@lisp
-(autoload 'run-octave "octave-inf" nil t)
-@end lisp
-@noindent
-to your @file{.emacs} file.
-
-This will start Octave in a special buffer the name of which is
-specified by the variable @code{inferior-octave-buffer} and defaults to
-@code{"*Inferior Octave*"}.  From within this buffer, you can
-interact with the inferior Octave process `as usual', i.e., by entering
-Octave commands at the prompt.  The buffer is in Inferior Octave mode,
-which is derived from the standard Comint mode, a major mode for
-interacting with an inferior interpreter.  See the documentation for
-@code{comint-mode} for more details, and use @kbd{C-h b} to find out
-about available special keybindings.
-
-You can also communicate with an inferior Octave process from within
-files with Octave code (i.e., buffers in Octave mode), using the
-following commands.
-
-@table @kbd
-@item C-c i l
-Send the current line to the inferior Octave process
-(@code{octave-send-line}).
-With positive prefix argument @var{N}, send that many lines.
-If @code{octave-send-line-auto-forward} is non-@code{nil}, go to the
-next unsent code line.
-
-@item C-c i b
-Send the current block to the inferior Octave process
-(@code{octave-send-block}).
-
-@item C-c i f
-Send the current function to the inferior Octave process
-(@code{octave-send-defun}).
-
-@item C-c i r
-Send the region to the inferior Octave process
-(@code{octave-send-region}).
-
-@item C-c i s
-Make sure that `inferior-octave-buffer' is displayed
-(@code{octave-show-process-buffer}).
-
-@item C-c i h
-Delete all windows that display the inferior Octave buffer
-(@code{octave-hide-process-buffer}).
-
-@item C-c i k
-Kill the inferior Octave process and its buffer
-(@code{octave-kill-process}).
-@end table
-
-The effect of the commands which send code to the Octave process can be
-customized by the following variables.
-@table @code
-@item octave-send-echo-input
-Non-@code{nil} means echo input sent to the inferior Octave process.
-Default is @code{t}.
-
-@item octave-send-show-buffer
-Non-@code{nil} means display the buffer running the Octave process after
-sending a command (but without selecting it).
-Default is @code{t}.
-@end table
-
-If you send code and there is no inferior Octave process yet, it will be
-started automatically.
-
-The startup of the inferior Octave process is highly customizable.
-The variable @code{inferior-octave-startup-args} can be used for
-specifying command lines arguments to be passed to Octave on startup
-as a list of strings.  For example, to suppress the startup message and
-use `traditional' mode, set this to @code{'("-q" "--traditional")}.
-You can also specify a startup file of Octave commands to be loaded on
-startup; note that these commands will not produce any visible output
-in the process buffer.  Which file to use is controlled by the variable
-@code{inferior-octave-startup-file}.  If this is @code{nil}, the file
-@file{~/.emacs-octave} is used if it exists.
-
-And finally, @code{inferior-octave-mode-hook} is run after starting the
-process and putting its buffer into Inferior Octave mode.  Hence, if you
-like the up and down arrow keys to behave in the interaction buffer as
-in the shell, and you want this buffer to use nice colors, add
-@lisp
-(add-hook 'inferior-octave-mode-hook
-          (lambda ()
-            (turn-on-font-lock)
-            (define-key inferior-octave-mode-map [up]
-              'comint-previous-input)
-            (define-key inferior-octave-mode-map [down]
-              'comint-next-input)))
-@end lisp
-@noindent
-to your @file{.emacs} file.  You could also swap the roles of @kbd{C-a}
-(@code{beginning-of-line}) and @code{C-c C-a} (@code{comint-bol}) using
-this hook.
-
-@quotation
-@strong{Note:}
-If you set your Octave prompts to something different from the defaults,
-make sure that @code{inferior-octave-prompt} matches them.
-Otherwise, @emph{nothing} will work, because Emacs will have no idea
-when Octave is waiting for input, or done sending output.
-@end quotation
-
-@node Using the Emacs Info Reader for Octave
-@section Using the Emacs Info Reader for Octave
-
-You can also set up the Emacs Info reader for dealing with the results
-of Octave's @samp{help -i}.  For this, the package @file{gnuserv} needs
-to be installed, which unfortunately still does not come with GNU Emacs
-(it does with XEmacs).  It can be retrieved from any GNU Emacs Lisp Code
-Directory archive, e.g.@:
-@url{ftp://ftp.cis.ohio-state.edu/pub/gnu/emacs/elisp-archive},
-in the @file{packages} subdirectory.  The alpha version of an enhanced
-version of gnuserv is available at 
-@url{ftp://ftp.wellfleet.com/netman/psmith/emacs/gnuserv-2.1alpha.tar.gz}.
-
-If @file{gnuserv} is installed, add the lines
-@lisp
-(autoload 'octave-help "octave-hlp" nil t)
-(require 'gnuserv)
-(gnuserv-start)
-@end lisp
-@noindent
-to your @file{.emacs} file.
-
-You can use either `plain' Emacs Info or the function @code{octave-help}
-as your Octave info reader (for @samp{help -i}).  In the former case,
-set the Octave variable @w{@env{INFO_PROGRAM}} to @code{"info-emacs-info"}.
-The latter is perhaps more attractive because it allows to look up keys
-in the indices of @emph{several} info files related to Octave (provided
-that the Emacs variable @code{octave-help-files} is set correctly).  In
-this case, set @w{@env{INFO_PROGRAM}} to @code{"info-emacs-octave-help"}.
-
-If you use Octave from within Emacs, these settings are best done in the
-@file{~/.emacs-octave} startup file (or the file pointed to by the Emacs
-variable @code{inferior-octave-startup-file}).
--- a/doc/interpreter/expr.txi
+++ b/doc/interpreter/expr.txi
@@ -1239,51 +1239,62 @@
 any such mistake.
 
 When operators of equal precedence are used together, the leftmost
-operator groups first, except for the assignment and exponentiation
-operators, which group in the opposite order.  Thus, the expression
-@code{a - b + c} groups as @code{(a - b) + c}, but the expression
-@code{a = b = c} groups as @code{a = (b = c)}.
+operator groups first, except for the assignment operators, which group
+in the opposite order.  Thus, the expression @code{a - b + c} groups as
+@code{(a - b) + c}, but the expression @code{a = b = c} groups as
+@code{a = (b = c)}.
 
 The precedence of prefix unary operators is important when another
 operator follows the operand.  For example, @code{-x^2} means
 @code{-(x^2)}, because @samp{-} has lower precedence than @samp{^}.
 
-Here is a table of the operators in Octave, in order of increasing
-precedence.
+Here is a table of the operators in Octave, in order of decreasing
+precedence.  Unless noted, all operators group left to right.
 
 @table @code
-@item statement separators
-@samp{;}, @samp{,}.
+@item function call and array indexing, cell array indexing, and structure element indexing
+@samp{()}  @samp{@{@}} @samp{.}
+
+@item postfix increment, and postfix decrement
+@samp{++}  @samp{--}
+
+These operators group right to left.
+
+@item transpose and exponentiation
+@samp{'} @samp{.'} @samp{^} @samp{**} @samp{.^} @samp{.**}
 
-@item assignment
-@samp{=}, @samp{+=}, @samp{-=}, @samp{*=},@samp{/=}.  This operator
-groups right to left.
+@item unary plus, unary minus, prefix increment, prefix decrement, and logical "not"
+@samp{+} @samp{-} @samp{++}  @samp{--} @samp{~} @samp{!}
+
+@item multiply and divide
+@samp{*} @samp{/} @samp{\} @samp{.\} @samp{.*} @samp{./}
 
-@item logical "or" and "and"
-@samp{||}, @samp{&&}.
+@item add, subtract
+@samp{+} @samp{-}
 
-@item element-wise "or" and "and"
-@samp{|}, @samp{&}.
+@item colon
+@samp{:}
 
 @item relational
-@samp{<}, @samp{<=}, @samp{==}, @samp{>=}, @samp{>}, @samp{!=},
-@samp{~=}.
+@samp{<} @samp{<=} @samp{==} @samp{>=} @samp{>} @samp{!=}
+@samp{~=}
 
-@item colon
-@samp{:}.
+@item element-wise "and"
+@samp{&}
 
-@item add, subtract
-@samp{+}, @samp{-}.
+@item element-wise "or"
+@samp{|}
 
-@item multiply, divide
-@samp{*}, @samp{/}, @samp{\}, @samp{.\}, @samp{.*}, @samp{./}.
+@item logical "and"
+@samp{&&}
 
-@item transpose
-@samp{'}, @samp{.'}
+@item logical "or"
+@samp{||}
 
-@item unary plus, minus, increment, decrement, and ``not''
-@samp{+}, @samp{-}, @samp{++}, @samp{--}, @samp{!}, @samp{~}.
+@item assignment
+@samp{=} @samp{+=} @samp{-=} @samp{*=} @samp{/=} @samp{\=}
+@samp{^=} @samp{.*=} @samp{./=} @samp{.\=} @samp{.^=} @samp{|=}
+@samp{&=}
 
-@item exponentiation
-@samp{^}, @samp{**}, @samp{.^}, @samp{.**}.
+These operators group right to left.
 @end table
--- a/doc/interpreter/install.txi
+++ b/doc/interpreter/install.txi
@@ -32,7 +32,7 @@
 under the terms of the GNU General Public License as published by the
 Free Software Foundation.
 
-@strong{Note:} This file is automatically generated from
+@strong{Note}: This file is automatically generated from
 @file{doc/interpreter/install.txi} in the Octave sources.  To update
 the documentation make changes to the .txi source file rather than this
 derived file.
--- a/doc/interpreter/linalg.txi
+++ b/doc/interpreter/linalg.txi
@@ -187,6 +187,8 @@
 @node Specialized Solvers
 @section Specialized Solvers
 
+@DOCSTRING(bicg)
+
 @DOCSTRING(bicgstab)
 
 @DOCSTRING(cgs)
--- a/doc/interpreter/matrix.txi
+++ b/doc/interpreter/matrix.txi
@@ -257,8 +257,6 @@
 
 @DOCSTRING(rosser)
 
-@DOCSTRING(sylvester_matrix)
-
 @DOCSTRING(toeplitz)
 
 @DOCSTRING(vander)
--- a/doc/interpreter/mkoctfile.1
+++ b/doc/interpreter/mkoctfile.1
@@ -95,28 +95,29 @@
 Print configuration variable \fIVAR\fP.  Recognized variables are:
 .RS
 .Vb
-   ALL_CFLAGS                FFTW3F_LDFLAGS
-   ALL_CXXFLAGS              FFTW3F_LIBS
-   ALL_FFLAGS                FLIBS
-   ALL_LDFLAGS               FPICFLAG
-   BLAS_LIBS                 INCFLAGS
-   CC                        LAPACK_LIBS
-   CFLAGS                    LDFLAGS
-   CPICFLAG                  LD_CXX
-   CPPFLAGS                  LD_STATIC_FLAG
-   CXX                       LFLAGS
-   CXXFLAGS                  LIBCRUFT
-   CXXPICFLAG                LIBOCTAVE
-   DEPEND_EXTRA_SED_PATTERN  LIBOCTINTERP
-   DEPEND_FLAGS              LIBS
-   DL_LD                     OCTAVE_LIBS
-   DL_LDFLAGS                RDYNAMIC_FLAG
-   EXEEXT                    READLINE_LIBS
-   F77                       RLD_FLAG
-   F77_INTEGER_8_FLAG        SED
-   FFLAGS                    XTRA_CFLAGS
-   FFTW3_LDFLAGS             XTRA_CXXFLAGS
-   FFTW3_LIBS
+    ALL_CFLAGS                FFTW3F_LIBS
+    ALL_CXXFLAGS              FLIBS
+    ALL_FFLAGS                FPICFLAG
+    ALL_LDFLAGS               INCFLAGS
+    BLAS_LIBS                 LAPACK_LIBS
+    CC                        LDFLAGS
+    CFLAGS                    LD_CXX
+    CPICFLAG                  LD_STATIC_FLAG
+    CPPFLAGS                  LFLAGS
+    CXX                       LIBCRUFT
+    CXXFLAGS                  LIBOCTAVE
+    CXXPICFLAG                LIBOCTINTERP
+    DEPEND_EXTRA_SED_PATTERN  LIBS
+    DEPEND_FLAGS              OCTAVE_LIBS
+    DL_LD                     OCTAVE_LINK_DEPS
+    DL_LDFLAGS                OCT_LINK_DEPS
+    EXEEXT                    RDYNAMIC_FLAG
+    F77                       READLINE_LIBS
+    F77_INTEGER_8_FLAG        SED
+    FFLAGS                    XTRA_CFLAGS
+    FFTW3_LDFLAGS             XTRA_CXXFLAGS
+    FFTW3_LIBS
+    FFTW3F_LDFLAGS
 .Ve
 .RE
 .TP
--- a/doc/interpreter/plot.txi
+++ b/doc/interpreter/plot.txi
@@ -2396,7 +2396,11 @@
 may override the factory defaults.
 
 Although default values may be set for any object, they are set in
-parent objects and apply to child objects.  For example,
+parent objects and apply to child objects, of the specified object type.
+For example, seeting the default @code{color} property of @code{line}
+objects to "green", for the @code{root} object, will result in all
+@code{line} objects inheriting the @code{color} "green" as the default
+value.
 
 @example
 set (0, "defaultlinecolor", "green");
--- a/doc/interpreter/stats.txi
+++ b/doc/interpreter/stats.txi
@@ -114,7 +114,7 @@
 
 @DOCSTRING(center)
 
-@DOCSTRING(studentize)
+@DOCSTRING(zscore)
 
 @DOCSTRING(histc)
 
@@ -168,9 +168,7 @@
 
 @DOCSTRING(cov)
 
-@DOCSTRING(cor)
-
-@DOCSTRING(corrcoef)
+@DOCSTRING(corr)
 
 @DOCSTRING(spearman)
 
--- a/doc/refcard/refcard.tex
+++ b/doc/refcard/refcard.tex
@@ -863,14 +863,14 @@
 gray2ind ({\it i}, {\it n})&convert gray scale to Octave image\cr
 image ({\it img}, {\it zoom})&display an Octave image matrix\cr
 imagesc ({\it img}, {\it zoom})&display scaled matrix as image\cr
+imread ({\it file})&load an image file\cr
 imshow ({\it img}, {\it map})&display Octave image\cr
 imshow ({\it i}, {\it n})&display gray scale image\cr
 imshow ({\it r}, {\it g}, {\it b})&display RGB image\cr
+imwrite ({\it img}, {\it file})&write images in various file formats\cr
 ind2gray ({\it img}, {\it map})&convert Octave image to gray scale\cr
 ind2rgb ({\it img}, {\it map})&convert indexed image to RGB\cr
-loadimage ({\it file})&load an image file\cr
 rgb2ind ({\it r}, {\it g}, {\it b})&convert RGB to Octave image\cr
-\omit\tt saveimage ({\it file}, {\it img}, {\it fmt}, {\it map})\quad\rm
 save a matrix to {\it file}\span\cr
 \endsec
 
--- a/etc/OLD-ChangeLogs/ChangeLog
+++ b/etc/OLD-ChangeLogs/ChangeLog
@@ -2,6 +2,10 @@
 
 	* NEWS: Add colstyle to list of new functions for 3.4
 
+2011-04-08  Rik  <octave@nomad.inbox5.com>
+
+	* NEWS: Deprecate studentize(), add new function zscore().
+
 2011-04-04  Rik  <octave@nomad.inbox5.com>
 
 	* NEWS: Add perror, strerror to list of functions deprecated in 3.4
@@ -88,6 +92,11 @@
 
 	* NEWS: Use indentation of 2 spaces rather than 3 in code examples.
 
+2011-02-08  John W. Eaton  <jwe@octave.org>
+
+	* NEWS: New section for 3.6.  List deprecated functions that
+	have been removed for 3.6.
+
 2011-02-08  Ben Abbott  <bpabbott@mac.com>
 
 	* README.MacOS: Add detail.
--- a/etc/OLD-ChangeLogs/doc-ChangeLog
+++ b/etc/OLD-ChangeLogs/doc-ChangeLog
@@ -1,3 +1,7 @@
+2011-04-16  Ben Abbott  <bpabbott@mac.com>
+
+	* interpreter/plot.txi: Clarify that inheritance of default property
+	values only applies to the named object type.
 2011-04-14  Rik  <octave@nomad.inbox5.com>
 
 	* interpreter/plot.txi: Add colstyle function to documentation.
@@ -16,6 +20,11 @@
 	* interpreter/func.txi: Add discussion of isargout to Ignoring
 	Arguments section of documentation.
 
+2011-04-08  Rik  <octave@nomad.inbox5.com>
+
+	* interpreter/stats.txi: Deprecate studentize(), replace with
+	zscore().
+
 2011-04-07  Rik  <octave@nomad.inbox5.com>
 
 	* interpreter/Makefile.am: Add spellcheck target to documentation
@@ -42,7 +51,7 @@
 
 2011-04-04  Rik  <octave@nomad.inbox5.com>
 
-	* interpreter/doccheck/aspell-octave.en.pws, interpreter/nonlin.txi, 
+	* interpreter/doccheck/aspell-octave.en.pws, interpreter/nonlin.txi,
 	interpreter/tips.txi: Spellcheck documentation for 3.4.1 release.
 
 2011-04-04  Rik  <octave@nomad.inbox5.com>
--- a/etc/OLD-ChangeLogs/liboctave-ChangeLog
+++ b/etc/OLD-ChangeLogs/liboctave-ChangeLog
@@ -1,3 +1,7 @@
+2011-04-12  Rik  <octave@nomad.inbox5.com>
+
+	* LSODE.cc: Add semicolon to error messages to prevent run-together text.
+
 2011-04-01  Jordi Gutiérrez Hermoso  <jordigh@gmail.com>
 
 	* MatrixType (MatrixType::operator =): Plug memory leak due to
--- a/etc/OLD-ChangeLogs/scripts-ChangeLog
+++ b/etc/OLD-ChangeLogs/scripts-ChangeLog
@@ -1,8 +1,47 @@
+2011-04-18  Paul Boven  <p.boven@xs4all.nl>
+
+	* image/image.m: Fixed naming of variables in texinfo
+
+2011-04-17  Patrick Häcker  <magicmuscleman>
+
+	* strings/mat2str.m: Limit the number of digits to one less than
+	available for double.
+
+2011-04-15  Kai Habel  <kai.habel@gmx.de>
+
+	* general/interp1.m, polynomial/mkpp.m, polynomial/pchip.m,
+	polynomial/ppder.m, polynomial/ppint.m, polynomial/ppjumps.m,
+	polynomial/ppval.m, polynomial/spline.m, polynomial/unmkpp.m:
+	Make functions more compatible with respect to handling of
+	picewise polynoms (pp). Rename pp-struct elements.
+	Handle nD-arguments correctly. Tests added.
+	(bugs #32040, #32045)
+
 2011-04-13  David Bateman  <dbateman@free.fr>
 
 	* plot/colstyle.m : New function.
 	* plot/module.mk plot_FCN_FILES) : Add it here.
 
+2011-04-13  Rik  <octave@nomad.inbox5.com>
+
+	* help/__makeinfo__.m: Simplify function by using regular expressions.
+	Eliminate third input argument see_also function.
+
+2011-04-13  Rik  <octave@nomad.inbox5.com>
+
+	* general/isdir.m, general/isequal.m, general/isequalwithequalnans.m,
+	general/isscalar.m, general/issquare.m, general/isvector.m: Refactor
+	code to put input validation first.
+
+	* general/iscolumn.m, general/isrow.m : Remove useless initialization
+	of output variable.
+
+	* general/isa.m: Add additional tests for various classes.
+
+2011-04-13  Rik  <octave@nomad.inbox5.com>
+
+	* ChangeLog: Remove results of bad merge in ChangeLog.
+
 2011-04-12  Ben Abbott  <bpabbott@mac.com>
 
 	* miscellaneous/getappdata.m: If no property name is provided, return
@@ -20,10 +59,21 @@
 
 2011-04-08  Rik  <octave@nomad.inbox5.com>
 
+	* deprecated/module.mk, statistics/base/center.m,
+	statistics/base/module.mk: Deprecate studentize(), replace with
+	zscore().
+
+2011-04-08  Rik  <octave@nomad.inbox5.com>
+
 	* linear-algebra/cond.m, linear-algebra/expm.m, linear-algebra/logm.m,
 	linear-algebra/null.m, linear-algebra/orth.m, linear-algebra/rank.m,
 	linear-algebra/rref.m: Improve docstrings.
 
+2011-04-08  Rik  <octave@nomad.inbox5.com>
+
+	* statistics/base/mode.m, statistics/base/quantile.m: Return output
+	of same class as input.
+
 2011-04-06  Rik  <octave@nomad.inbox5.com>
 
 	* miscellaneous/pack.m: Improve docstring.
@@ -397,6 +447,25 @@
 
 	* plot/__go_draw_axes__.m: Properly set fontspec for legends.
 
+2011-02-08  John W. Eaton  <jwe@octave.org>
+
+	* deprecated/complement.m, deprecated/create_set.m,
+	deprecated/dmult.m, deprecated/iscommand.m,
+	deprecated/israwcommand.m, deprecated/lchol.m,
+	deprecated/loadimage.m, deprecated/mark_as_command.m,
+	deprecated/mark_as_rawcommand.m, deprecated/spatan2.m,
+	deprecated/spchol2inv.m, deprecated/spcholinv.m,
+	deprecated/spchol.m, deprecated/spcumprod.m,
+	deprecated/spcumsum.m, deprecated/spdet.m, deprecated/spdiag.m,
+	deprecated/spfind.m, deprecated/spinv.m, deprecated/spkron.m,
+	deprecated/splchol.m, deprecated/split.m, deprecated/splu.m,
+	deprecated/spmax.m, deprecated/spmin.m, deprecated/spprod.m,
+	deprecated/spqr.m, deprecated/spsum.m, deprecated/spsumsq.m,
+	deprecated/str2mat.m, deprecated/unmark_command.m,
+	deprecated/unmark_rawcommand.m:
+	Remove functions deprecated in version 3.2.
+	* module.mk (deprecated_FCN_FILES): Remove them from the list.
+
 2011-02-05  David Bateman  <dbateman@free.fr>
 
 	* plot/legend.m: Allow the location and orientation to be set
--- a/etc/OLD-ChangeLogs/src-ChangeLog
+++ b/etc/OLD-ChangeLogs/src-ChangeLog
@@ -1,10 +1,15 @@
+2011-04-19  Kai Habel  <kai.habel@gmx.de>
+
+	* src/DLD-FUNCTIONS/__init_fltk__.cc(plot_window::plot_window):
+	Instantiate canvas before uimenu.
+
 2011-04-13  Rik  <octave@nomad.inbox5.com>
 
 	* help.cc: Add spaces after commas in @seealso blocks.
 
 2011-04-12  Rik  <octave@nomad.inbox5.com>
 
-	* load-path.cc (restoredefaultpath): Correct use of it's -> its in 
+	* load-path.cc (restoredefaultpath): Correct use of it's -> its in
 	documentation.
 
 2011-04-10  John Eaton  <jwe@octave.org>
@@ -90,7 +95,7 @@
 
 	* DLD-FUNCTIONS/inv.cc (inv, inverse), DLD-FUNCTIONS/tril.cc (tril),
 	data.cc (cumsum, szie), file-io.cc (fgets), ov-typeinfo.cc (typeinfo),
-	ov-usr-fcn.cc (nargout), utils.cc (make_absolute_filename), 
+	ov-usr-fcn.cc (nargout), utils.cc (make_absolute_filename),
 	variables.cc (who): Improve docstrings
 
 2011-03-25  John W. Eaton  <jwe@octave.org>
@@ -342,6 +347,10 @@
 
 2011-02-08  John W. Eaton  <jwe@octave.org>
 
+	* DLD-FUNCTIONS/chol.cc: Delete obsolete test of spcholinv.
+
+2011-02-08  John W. Eaton  <jwe@octave.org>
+
 	* oct-parse.yy (parse_fcn_file): Don't warn about coercing
 	nested functions to subfunctions if yyparse failed.
 
--- a/etc/OLD-ChangeLogs/test-ChangeLog
+++ b/etc/OLD-ChangeLogs/test-ChangeLog
@@ -1,3 +1,9 @@
+2011-04-11  Rik  <octave@nomad.inbox5.com>
+
+	* fntests.m: Remove deprecated and private functions from list of 
+	functions requiring tests.  Count functions with %!demo blocks as
+	having tests.
+
 2011-04-03  Rik  <octave@nomad.inbox5.com>
 
 	* test_diag_perm.m: Reverse previous changeset.  Return 3-input form
--- a/etc/README.MacOS
+++ b/etc/README.MacOS
@@ -334,67 +334,83 @@
 includes a port file for octave-devel.  To build and run the most recent
 development snapshots, enter the commands below.
 
-    sudo port selfupdate
-    sudo port install octave-devel
+  sudo port selfupdate
+  sudo port install octave-devel
 
 To build the developers sources in one's own way, or if MacPorts' version is
 outdated, a custom port file can be added.  This requires setting up a local
 port file repository (link below).
 
-    http://guide.macports.org/#development.local-repositories
+  http://guide.macports.org/#development.local-repositories
 
 The octave-devel port file may be used as an initial starting point.  The port
 file is accessible from the web at the link below.
 
-    http://trac.macports.org/browser/trunk/dports/math/octave-devel/Portfile
+  http://trac.macports.org/browser/trunk/dports/math/octave-devel/Portfile
 
 It is also available locally at the location below.  The parameter ${prefix} is
 corresponds to where MacPorts is install, which by default is "/opt/local".
 
-    ${prefix}/var/macports/sources/rsync.macports.org/release/ports/math/octave-devel/Portfile
+  ${prefix}/var/macports/sources/rsync.macports.org/release/ports/math/octave-devel/Portfile
+
+If the Portfile is missing the dependencies, epstools, epstoedit, and transfig,
+those should be installed manually or added to the Portfile. To install
+manually, type the command below.
+
+  sudo port install epstools epstoedit transfig
 
 The local source tarball must be placed in the location below, where ${name}
 and ${distname} are each specified in the port file.
 
-    ${prefix}/var/macports/distfiles/${name}/${disname}.tar.gz
+  ${prefix}/var/macports/distfiles/${name}/${disname}.tar.gz
 
 
 2.4.2 Building for Active Development of Octave
 -----------------------------------------------
 
-To satisfy Octave's dependencies, first install the octave-devel port.
-
-    sudo port selfupdate
-    sudo port install octave-devel
+To satisfy most of Octave's dependencies, first install the octave-devel port.
 
-Next run octave to determine the configure options needed to build Octave
-using MacPorts.  At Octave's prompt type the command below and make note of
-the result, ${config_opts}.
-
-    octave:1> octave_config_info.config_opts
+  sudo port selfupdate
+  sudo port install octave-devel
 
 Now uninstall the Octave port.
 
-    sudo port deactivate octave-devel
+  sudo port deactivate octave-devel
+
+This will remove Octave and leave its dependencies in place. Some additional
+dependencies may be needed.
+
+  sudo port install epstools epstoedit transfig
+
+Octave may now be built from a local mercurial archive by typing the commands
+below (these assume gcc-4.4 is installed by macports).
 
-This will remove Octave and leave its dependencies in place.  Now Octave may
-be built from the local mercurial archive by typing the commands below, where
-the configure options mentioned above are substituted for the parameter
-${config_opts}.  If the sources being built are from the mercurial archive,
-then ./autogen.sh must be run prior to ./configure.
-
-    ./configure ${config_opts}
-    make
+  ./autogen.sh
+  export PREFIX=/opt/local
+  export CC=/opt/local/bin/gcc-mp-4.4
+  export CXX=/opt/local/bin/g++-mp-4.4
+  export CXXCPP="/opt/local/bin/g++-mp-4.4 -E"
+  export F77=/opt/local/bin/gfortran-mp-4.4
+  export FC=/opt/local/bin/gfortran-mp-4.4
+  export CXXFLAGS="-pipe -O2 -m64"
+  export FFLAGS="$CXXFLAGS -D_THREAD_SAFE -pthread"
+  export CFLAGS="$FFLAGS -lstdc++"
+  export LDFLAGS=-L$PREFIX/lib
+  export CPPFLAGS=-I$PREFIX/include
+  export BLAS_LIBS="-lcblas -lf77blas -latlas"
+  export LAPACK_LIBS=-llapack
+  ./configure --prefix="/opt/local" --without-framework-carbon --with-x
+  make
 
 Octave's integrated tests may be run.
 
-    make check
+  make check
 
-However, "make install" should not be run as it may damage or corrupt the
-MacPorts installation.  To run Octave, type the command below from the root of
-the mercurial archive.
+"make install" should not be run as it will bypass the macports package 
+management.  To run Octave, type the command below from the root of the
+mercurial archive.
 
-    ./run-octave
+  ./run-octave
 
 
 John W. Eaton
--- a/libcruft/Makefile.am
+++ b/libcruft/Makefile.am
@@ -34,6 +34,13 @@
   @CRUFT_DLL_DEFS@ \
   $(AM_CPPFLAGS)
 
+include link-deps.mk
+
+libcruft_la_LIBADD = \
+  libranlib.la \
+  ../libgnu/libgnu.la \
+  $(LIBCRUFT_LINK_DEPS)
+
 # Increment these as needed and according to the rules in the libtool
 # manual:
 libcruft_current = 0
@@ -46,13 +53,8 @@
   -version-info $(libcruft_version_info) \
   $(NO_UNDEFINED_LDFLAG) \
   @XTRA_CRUFT_SH_LDFLAGS@ \
-  -bindir $(bindir)
-
-libcruft_la_LIBADD = \
-  ../libgnu/libgnu.la \
-  libranlib.la \
-  $(LAPACK_LIBS) $(BLAS_LIBS) \
-  $(FLIBS)
+  -bindir $(bindir) \
+  $(LIBCRUFT_LINK_OPTS)
 
 libcruft_la_DEPENDENCIES = cruft.def
 
new file mode 100644
--- /dev/null
+++ b/libcruft/link-deps.mk
@@ -0,0 +1,30 @@
+## The following libraries may be needed to satisfy gnulib dependencies:
+##
+##   $(COPYSIGN_LIBM)
+##   $(FLOOR_LIBM)
+##   $(GETHOSTNAME_LIB)
+##   $(LIBSOCKET)
+##   $(LIB_NANOSLEEP)
+##   $(LTLIBINTL)
+##   $(ROUNDF_LIBM)
+##   $(ROUND_LIBM)
+##   $(TRUNCF_LIBM)
+##   $(TRUNC_LIBM)
+
+LIBCRUFT_LINK_DEPS = \
+  $(COPYSIGN_LIBM) \
+  $(FLOOR_LIBM) \
+  $(GETHOSTNAME_LIB) \
+  $(LIBSOCKET) \
+  $(LIB_NANOSLEEP) \
+  $(LTLIBINTL) \
+  $(ROUNDF_LIBM) \
+  $(ROUND_LIBM) \
+  $(TRUNCF_LIBM) \
+  $(TRUNC_LIBM) \
+  $(LAPACK_LIBS) \
+  $(BLAS_LIBS) \
+  $(FLIBS) \
+  $(LIBS)
+
+LIBCRUFT_LINK_OPTS =
--- a/liboctave/LSODE.cc
+++ b/liboctave/LSODE.cc
@@ -292,7 +292,7 @@
     case -2:  // excess accuracy requested (tolerances too small).
     case -3:  // invalid input detected (see printed message).
     case -4:  // repeated error test failures (check all inputs).
-    case -5:  // repeated convergence failures (perhaps bad jacobian
+    case -5:  // repeated convergence failures (perhaps bad Jacobian
               // supplied or wrong choice of mf or tolerances).
     case -6:  // error weight became zero during problem. (solution
               // component i vanished, and atol or atol(i) = 0.)
@@ -349,13 +349,13 @@
 
     case -4:
       retval = std::string ("repeated error test failures (t = ")
-        + t_curr + "check all inputs)";
+        + t_curr + "; check all inputs)";
       break;
 
     case -5:
       retval = std::string ("repeated convergence failures (t = ")
         + t_curr
-        + "perhaps bad jacobian supplied or wrong choice of integration method or tolerances)";
+        + "; perhaps bad Jacobian supplied or wrong choice of integration method or tolerances)";
       break;
 
     case -6:
--- a/liboctave/MArray.cc
+++ b/liboctave/MArray.cc
@@ -339,7 +339,7 @@
   MArray<T> \
   FCN (const MArray<T>& a, const MArray<T>& b) \
   { \
-    return do_mm_binary_op<T, T, T> (a, b, FN, #FCN); \
+    return do_mm_binary_op<T, T, T> (a, b, FN, FN, FN, #FCN); \
   }
 
 MARRAY_NDND_OP (operator +, +, mx_inline_add)
--- a/liboctave/MDiagArray2.cc
+++ b/liboctave/MDiagArray2.cc
@@ -82,7 +82,7 @@
   { \
     if (a.d1 != b.d1 || a.d2 != b.d2) \
       gripe_nonconformant (#FCN, a.d1, a.d2, b.d1, b.d2); \
-    return MDiagArray2<T> (do_mm_binary_op<T, T, T> (a, b, FN, #FCN), a.d1, a.d2); \
+    return MDiagArray2<T> (do_mm_binary_op<T, T, T> (a, b, FN, FN, FN, #FCN), a.d1, a.d2); \
   }
 
 MARRAY_DADA_OP (operator +, +, mx_inline_add)
--- a/liboctave/Makefile.am
+++ b/liboctave/Makefile.am
@@ -188,6 +188,7 @@
   base-dae.h \
   base-de.h \
   base-min.h \
+  bsxfun.h \
   byte-swap.h \
   caseless-str.h \
   cmd-edit.h \
@@ -491,21 +492,6 @@
 
 LIBOCT_READLINE_SOURCES = $(LIBOCT_READLINE_CXX_SOURCES) $(LIBOCT_READLINE_C_SOURCES)
 
-LINK_DEPS = \
-  $(RLD_FLAG) \
-  ../libcruft/libcruft.la \
-  ../libcruft/libranlib.la \
-  ../libgnu/libgnu.la \
-  $(SPARSE_XLIBS) \
-  $(ARPACK_LIBS) \
-  $(QRUPDATE_LIBS) \
-  $(FFTW_XLIBS) \
-  $(LAPACK_LIBS) $(BLAS_LIBS) \
-  $(READLINE_LIBS) $(TERM_LIBS) \
-  $(LIBGLOB) $(REGEX_LIBS) $(DL_LIBS) \
-  $(FLIBS) \
-  $(PTHREAD_LIBS) $(LIBS)
-
 liboctave_la_SOURCES = \
   $(LIBOCTAVE_CXX_SOURCES) \
   $(LIBOCTAVE_C_SOURCES) \
@@ -516,7 +502,11 @@
 nodist_liboctave_la_SOURCES = \
   $(BUILT_LIBOCTAVE_CXX_SOURCES)
 
-liboctave_la_LIBADD = $(LINK_DEPS)
+include link-deps.mk
+
+liboctave_la_LIBADD = \
+  ../libcruft/libcruft.la \
+  $(LIBOCTAVE_LINK_DEPS)
 
 liboctave_la_CPPFLAGS = \
   @OCTAVE_DLL_DEFS@ \
@@ -537,10 +527,7 @@
   -version-info $(liboctave_version_info) \
   $(NO_UNDEFINED_LDFLAG) \
   -bindir $(bindir) \
-  $(SPARSE_XLDFLAGS) \
-  $(ARPACK_LDFLAGS) \
-  $(QRUPDATE_LDFLAGS) \
-  $(FFTW_XLDFLAGS)
+  $(LIBOCTAVE_LINK_OPTS)
 
 octinclude_HEADERS = \
   $(INCS) \
--- a/liboctave/bsxfun-decl.h
+++ b/liboctave/bsxfun-decl.h
@@ -42,6 +42,12 @@
   BSXFUN_OP_DECL (min, ARRAY, API) \
   BSXFUN_OP_DECL (max, ARRAY, API)
 
+#define BSXFUN_MIXED_INT_DECLS(INT_TYPE, API)         \
+  BSXFUN_OP2_DECL (pow, INT_TYPE, INT_TYPE, NDArray, API)       \
+  BSXFUN_OP2_DECL (pow, INT_TYPE, INT_TYPE, FloatNDArray, API)  \
+  BSXFUN_OP2_DECL (pow, INT_TYPE, NDArray, INT_TYPE, API)       \
+  BSXFUN_OP2_DECL (pow, INT_TYPE, FloatNDArray, INT_TYPE, API)
+
 #define BSXFUN_STDREL_DECLS(ARRAY, API) \
   BSXFUN_REL_DECL (eq, ARRAY, API) \
   BSXFUN_REL_DECL (ne, ARRAY, API) \
--- a/liboctave/bsxfun-defs.cc
+++ b/liboctave/bsxfun-defs.cc
@@ -174,4 +174,11 @@
   BSXFUN_REL_DEF_MXLOOP (gt, ARRAY, mx_inline_gt) \
   BSXFUN_REL_DEF_MXLOOP (ge, ARRAY, mx_inline_ge)
 
+//For bsxfun power with mixed integer/float types
+#define BSXFUN_POW_MIXED_MXLOOP(INT_TYPE)                              \
+  BSXFUN_OP2_DEF_MXLOOP (pow, INT_TYPE, INT_TYPE, NDArray, mx_inline_pow) \
+  BSXFUN_OP2_DEF_MXLOOP (pow, INT_TYPE, INT_TYPE, FloatNDArray, mx_inline_pow)\
+  BSXFUN_OP2_DEF_MXLOOP (pow, INT_TYPE, NDArray, INT_TYPE,  mx_inline_pow) \
+  BSXFUN_OP2_DEF_MXLOOP (pow, INT_TYPE, FloatNDArray, INT_TYPE, mx_inline_pow)
+
 #endif
new file mode 100644
--- /dev/null
+++ b/liboctave/bsxfun.h
@@ -0,0 +1,44 @@
+/*
+
+Copyright (C) 2011 Jordi Gutiérrez Hermoso <jordigh@octave.org>
+
+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 (bsxfun_h)
+#define bsxfun_h 1
+
+#include <algorithm>
+
+#include "Array.h"
+#include "dim-vector.h"
+
+inline
+bool
+is_valid_bsxfun (const dim_vector& dx, const dim_vector& dy)
+{
+  for (int i = 0; i < std::min (dx.length (), dy.length ()); i++)
+    {
+      if ( dx(i) > 1 && dy(i) > 1 && dx(i) != dy(i))
+        return false;
+    }
+  return true;
+}
+
+#include "bsxfun-defs.cc"
+
+#endif
--- a/liboctave/chMatrix.cc
+++ b/liboctave/chMatrix.cc
@@ -74,8 +74,8 @@
     elem (0, i) = s[i];
 }
 
-charMatrix::charMatrix (const string_vector& s)
-  : Array<char> (dim_vector (s.length (), s.max_length ()), 0)
+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 ();
 
--- a/liboctave/chMatrix.h
+++ b/liboctave/chMatrix.h
@@ -62,7 +62,7 @@
 
   charMatrix (const std::string& s);
 
-  charMatrix (const string_vector& s);
+  charMatrix (const string_vector& s, char fill_value = '\0');
 
   charMatrix& operator = (const charMatrix& a)
     {
--- a/liboctave/dNDArray.cc
+++ b/liboctave/dNDArray.cc
@@ -925,3 +925,5 @@
 BSXFUN_OP_DEF_MXLOOP (pow, NDArray, mx_inline_pow)
 BSXFUN_OP2_DEF_MXLOOP (pow, ComplexNDArray, ComplexNDArray,
                        NDArray, mx_inline_pow)
+BSXFUN_OP2_DEF_MXLOOP (pow, ComplexNDArray, NDArray,
+                       ComplexNDArray, mx_inline_pow)
--- a/liboctave/dNDArray.h
+++ b/liboctave/dNDArray.h
@@ -185,5 +185,7 @@
 BSXFUN_OP_DECL (pow, NDArray, OCTAVE_API)
 BSXFUN_OP2_DECL (pow, ComplexNDArray, ComplexNDArray,
                  NDArray, OCTAVE_API)
+BSXFUN_OP2_DECL (pow, ComplexNDArray, NDArray,
+                 ComplexNDArray, OCTAVE_API)
 
 #endif
--- a/liboctave/fNDArray.cc
+++ b/liboctave/fNDArray.cc
@@ -885,3 +885,5 @@
 BSXFUN_OP_DEF_MXLOOP (pow, FloatNDArray, mx_inline_pow)
 BSXFUN_OP2_DEF_MXLOOP (pow, FloatComplexNDArray, FloatComplexNDArray,
                        FloatNDArray, mx_inline_pow)
+BSXFUN_OP2_DEF_MXLOOP (pow, FloatComplexNDArray, FloatNDArray,
+                       FloatComplexNDArray, mx_inline_pow)
--- a/liboctave/fNDArray.h
+++ b/liboctave/fNDArray.h
@@ -182,5 +182,7 @@
 BSXFUN_OP_DECL (pow, FloatNDArray, OCTAVE_API)
 BSXFUN_OP2_DECL (pow, FloatComplexNDArray, FloatComplexNDArray,
                  FloatNDArray, OCTAVE_API)
+BSXFUN_OP2_DECL (pow, FloatComplexNDArray, FloatNDArray,
+                 FloatComplexNDArray, OCTAVE_API)
 
 #endif
--- a/liboctave/int16NDArray.cc
+++ b/liboctave/int16NDArray.cc
@@ -54,3 +54,7 @@
 
 BSXFUN_STDOP_DEFS_MXLOOP (int16NDArray)
 BSXFUN_STDREL_DEFS_MXLOOP (int16NDArray)
+
+BSXFUN_OP_DEF_MXLOOP (pow, int16NDArray, mx_inline_pow)
+
+BSXFUN_POW_MIXED_MXLOOP (int16NDArray)
--- a/liboctave/int16NDArray.h
+++ b/liboctave/int16NDArray.h
@@ -44,6 +44,7 @@
 MINMAX_DECLS (int16NDArray, octave_int16, OCTAVE_API)
 
 BSXFUN_STDOP_DECLS (int16NDArray, OCTAVE_API)
+BSXFUN_MIXED_INT_DECLS(int16NDArray, OCTAVE_API)
 BSXFUN_STDREL_DECLS (int16NDArray, OCTAVE_API)
 
 #endif
--- a/liboctave/int32NDArray.cc
+++ b/liboctave/int32NDArray.cc
@@ -54,3 +54,6 @@
 
 BSXFUN_STDOP_DEFS_MXLOOP (int32NDArray)
 BSXFUN_STDREL_DEFS_MXLOOP (int32NDArray)
+
+BSXFUN_OP_DEF_MXLOOP (pow, int32NDArray, mx_inline_pow)
+BSXFUN_POW_MIXED_MXLOOP (int32NDArray)
--- a/liboctave/int32NDArray.h
+++ b/liboctave/int32NDArray.h
@@ -44,6 +44,7 @@
 MINMAX_DECLS (int32NDArray, octave_int32, OCTAVE_API)
 
 BSXFUN_STDOP_DECLS (int32NDArray, OCTAVE_API)
+BSXFUN_MIXED_INT_DECLS(int32NDArray, OCTAVE_API)
 BSXFUN_STDREL_DECLS (int32NDArray, OCTAVE_API)
 
 #endif
--- a/liboctave/int64NDArray.cc
+++ b/liboctave/int64NDArray.cc
@@ -54,3 +54,7 @@
 
 BSXFUN_STDOP_DEFS_MXLOOP (int64NDArray)
 BSXFUN_STDREL_DEFS_MXLOOP (int64NDArray)
+
+BSXFUN_OP_DEF_MXLOOP (pow, int64NDArray, mx_inline_pow)
+
+BSXFUN_POW_MIXED_MXLOOP (int64NDArray)
--- a/liboctave/int64NDArray.h
+++ b/liboctave/int64NDArray.h
@@ -44,6 +44,7 @@
 MINMAX_DECLS (int64NDArray, octave_int64, OCTAVE_API)
 
 BSXFUN_STDOP_DECLS (int64NDArray, OCTAVE_API)
+BSXFUN_MIXED_INT_DECLS(int64NDArray, OCTAVE_API)
 BSXFUN_STDREL_DECLS (int64NDArray, OCTAVE_API)
 
 #endif
--- a/liboctave/int8NDArray.cc
+++ b/liboctave/int8NDArray.cc
@@ -54,3 +54,6 @@
 
 BSXFUN_STDOP_DEFS_MXLOOP (int8NDArray)
 BSXFUN_STDREL_DEFS_MXLOOP (int8NDArray)
+
+BSXFUN_OP_DEF_MXLOOP (pow, int8NDArray, mx_inline_pow)
+BSXFUN_POW_MIXED_MXLOOP (int8NDArray)
--- a/liboctave/int8NDArray.h
+++ b/liboctave/int8NDArray.h
@@ -44,6 +44,7 @@
 MINMAX_DECLS (int8NDArray, octave_int8, OCTAVE_API)
 
 BSXFUN_STDOP_DECLS (int8NDArray, OCTAVE_API)
+BSXFUN_MIXED_INT_DECLS(int8NDArray, OCTAVE_API)
 BSXFUN_STDREL_DECLS (int8NDArray, OCTAVE_API)
 
 #endif
new file mode 100644
--- /dev/null
+++ b/liboctave/link-deps.mk
@@ -0,0 +1,27 @@
+include ../libcruft/link-deps.mk
+
+LIBOCTAVE_LINK_DEPS = \
+  $(SPARSE_XLIBS) \
+  $(ARPACK_LIBS) \
+  $(QRUPDATE_LIBS) \
+  $(FFTW_XLIBS) \
+  $(LAPACK_LIBS) \
+  $(BLAS_LIBS) \
+  $(READLINE_LIBS) \
+  $(TERM_LIBS) \
+  $(LIBGLOB) \
+  $(REGEX_LIBS) \
+  $(DL_LIBS) \
+  $(PTHREAD_LIBS) \
+  $(LIBS)
+
+LIBOCTAVE_LINK_OPTS = \
+  $(SPARSE_XLDFLAGS) \
+  $(ARPACK_LDFLAGS) \
+  $(QRUPDATE_LDFLAGS) \
+  $(FFTW_XLDFLAGS)
+
+if AMCOND_LINK_ALL_DEPS
+  LIBOCTAVE_LINK_DEPS += $(LIBCRUFT_LINK_DEPS)
+  LIBOCTAVE_LINK_OPTS += $(LIBCRUFT_LINK_OPTS)
+endif
--- a/liboctave/lo-utils.cc
+++ b/liboctave/lo-utils.cc
@@ -196,44 +196,57 @@
 }
 
 static inline double
-read_inf_nan_na (std::istream& is, char c, char sign = '+')
+read_inf_nan_na (std::istream& is, char c0, char sign = '+')
 {
   double d = 0.0;
 
-  switch (c)
+  switch (c0)
     {
     case 'i': case 'I':
       {
-        c = is.get ();
-        if (c == 'n' || c == 'N')
+        char c1 = is.get ();
+        if (c1 == 'n' || c1 == 'N')
           {
-            c = is.get ();
-            if (c == 'f' || c == 'F')
+            char c2 = is.get ();
+            if (c2 == 'f' || c2 == 'F')
               d = sign == '-' ? -octave_Inf : octave_Inf;
             else
-              is.putback (c);
+              {
+                is.putback (c2);
+                is.putback (c1);
+                is.putback (c0);
+                is.setstate (std::ios::failbit);
+              }
           }
         else
-          is.putback (c);
+          {
+            is.putback (c1);
+            is.putback (c0);
+            is.setstate (std::ios::failbit);
+          }
       }
       break;
 
     case 'n': case 'N':
       {
-        c = is.get ();
-        if (c == 'a' || c == 'A')
+        char c1 = is.get ();
+        if (c1 == 'a' || c1 == 'A')
           {
-            c = is.get ();
-            if (c == 'n' || c == 'N')
+            char c2 = is.get ();
+            if (c2 == 'n' || c2 == 'N')
               d = octave_NaN;
             else
               {
-                is.putback (c);
+                is.putback (c2);
                 d = octave_NA;
               }
           }
         else
-          is.putback (c);
+          {
+            is.putback (c1);
+            is.putback (c0);
+            is.setstate (std::ios::failbit);
+          }
       }
       break;
 
@@ -244,6 +257,8 @@
   return d;
 }
 
+// Read a double value.  Discard any sign on NaN and NA.
+
 template <>
 double
 octave_read_value (std::istream& is)
@@ -261,7 +276,7 @@
       {
         char c2 = 0;
         c2 = is.get ();
-        if (c2 == 'i' || c2 == 'I')
+        if (c2 == 'i' || c2 == 'I' || c2 == 'n' || c2 == 'N')
           d = read_inf_nan_na (is, c2, c1);
         else
           {
@@ -276,7 +291,7 @@
       {
         char c2 = 0;
         c2 = is.get ();
-        if (c2 == 'i' || c2 == 'I')
+        if (c2 == 'i' || c2 == 'I' || c2 == 'n' || c2 == 'N')
           d = read_inf_nan_na (is, c2, c1);
         else
           {
@@ -344,44 +359,57 @@
 }
 
 static inline float
-read_float_inf_nan_na (std::istream& is, char c, char sign = '+')
+read_float_inf_nan_na (std::istream& is, char c0, char sign = '+')
 {
   float d = 0.0;
 
-  switch (c)
+  switch (c0)
     {
     case 'i': case 'I':
       {
-        c = is.get ();
-        if (c == 'n' || c == 'N')
+        char c1 = is.get ();
+        if (c1 == 'n' || c1 == 'N')
           {
-            c = is.get ();
-            if (c == 'f' || c == 'F')
-              d = sign == '-' ? -octave_Inf : octave_Inf;
+            char c2 = is.get ();
+            if (c2 == 'f' || c2 == 'F')
+              d = sign == '-' ? -octave_Float_Inf : octave_Float_Inf;
             else
-              is.putback (c);
+              {
+                is.putback (c2);
+                is.putback (c1);
+                is.putback (c0);
+                is.setstate (std::ios::failbit);
+              }
           }
         else
-          is.putback (c);
+          {
+            is.putback (c1);
+            is.putback (c0);
+            is.setstate (std::ios::failbit);
+          }
       }
       break;
 
     case 'n': case 'N':
       {
-        c = is.get ();
-        if (c == 'a' || c == 'A')
+        char c1 = is.get ();
+        if (c1 == 'a' || c1 == 'A')
           {
-            c = is.get ();
-            if (c == 'n' || c == 'N')
-              d = octave_NaN;
+            char c2 = is.get ();
+            if (c2 == 'n' || c2 == 'N')
+              d = octave_Float_NaN;
             else
               {
-                is.putback (c);
-                d = octave_NA;
+                is.putback (c2);
+                d = octave_Float_NA;
               }
           }
         else
-          is.putback (c);
+          {
+            is.putback (c1);
+            is.putback (c0);
+            is.setstate (std::ios::failbit);
+          }
       }
       break;
 
@@ -392,6 +420,8 @@
   return d;
 }
 
+// Read a float value.  Discard any sign on NaN and NA.
+
 template <>
 float
 octave_read_value (std::istream& is)
@@ -409,7 +439,7 @@
       {
         char c2 = 0;
         c2 = is.get ();
-        if (c2 == 'i' || c2 == 'I')
+        if (c2 == 'i' || c2 == 'I' || c2 == 'n' || c2 == 'N')
           d = read_float_inf_nan_na (is, c2, c1);
         else
           {
@@ -424,7 +454,7 @@
       {
         char c2 = 0;
         c2 = is.get ();
-        if (c2 == 'i' || c2 == 'I')
+        if (c2 == 'i' || c2 == 'I' || c2 == 'n' || c2 == 'N')
           d = read_float_inf_nan_na (is, c2, c1);
         else
           {
--- a/liboctave/mx-inlines.cc
+++ b/liboctave/mx-inlines.cc
@@ -37,6 +37,8 @@
 #include "Array.h"
 #include "Array-util.h"
 
+#include "bsxfun.h"
+
 // Provides some commonly repeated, basic loop templates.
 
 template <class R, class S>
@@ -286,7 +288,10 @@
 inline void F (size_t n, R *r, X x, const Y *y) throw () \
 { for (size_t i = 0; i < n; i++) r[i] = FUN (x, y[i]); }
 
-DEFMXMAPPER2X (mx_inline_pow, std::pow)
+// Let the compiler decide which pow to use, whichever best matches the
+// arguments provided.
+using std::pow;
+DEFMXMAPPER2X (mx_inline_pow, pow)
 
 // Arbitrary function appliers. The function is a template parameter to enable
 // inlining.
@@ -336,11 +341,12 @@
   return r;
 }
 
-
 template <class R, class X, class Y>
 inline Array<R>
 do_mm_binary_op (const Array<X>& x, const Array<Y>& y,
                  void (*op) (size_t, R *, const X *, const Y *) throw (),
+                 void (*op1) (size_t, R *, X, const Y *) throw (),
+                 void (*op2) (size_t, R *, const X *, Y) throw (),
                  const char *opname)
 {
   dim_vector dx = x.dims (), dy = y.dims ();
@@ -350,6 +356,10 @@
       op (r.length (), r.fortran_vec (), x.data (), y.data ());
       return r;
     }
+  else if (is_valid_bsxfun (dx, dy))
+    {
+      return do_bsxfun_op (x, y, op, op1, op2);
+    }
   else
     {
       gripe_nonconformant (opname, dx, dy);
--- a/liboctave/mx-op-defs.h
+++ b/liboctave/mx-op-defs.h
@@ -72,7 +72,7 @@
   R \
   F (const V1& v1, const V2& v2) \
   { \
-    return do_mm_binary_op<R::element_type, V1::element_type, V2::element_type> (v1, v2, OP, #F); \
+    return do_mm_binary_op<R::element_type, V1::element_type, V2::element_type> (v1, v2, OP, OP, OP, #F); \
   }
 
 #define VV_BIN_OPS(R, V1, V2) \
@@ -173,7 +173,7 @@
   R \
   OP (const M1& m1, const M2& m2) \
   { \
-    return do_mm_binary_op<R::element_type, M1::element_type, M2::element_type> (m1, m2, F, #OP); \
+    return do_mm_binary_op<R::element_type, M1::element_type, M2::element_type> (m1, m2, F, F, F, #OP); \
   }
 
 #define MM_BIN_OPS(R, M1, M2) \
@@ -186,7 +186,7 @@
   boolMatrix \
   F (const M1& m1, const M2& m2) \
   { \
-    return do_mm_binary_op<bool, M1::element_type, M2::element_type> (m1, m2, OP, #F); \
+    return do_mm_binary_op<bool, M1::element_type, M2::element_type> (m1, m2, OP, OP, OP, #F); \
   }
 
 #define MM_CMP_OPS(M1, M2) \
@@ -203,7 +203,7 @@
   { \
     MNANCHK (m1, M1::element_type); \
     MNANCHK (m2, M2::element_type); \
-    return do_mm_binary_op<bool, M1::element_type, M2::element_type> (m1, m2, OP, #F); \
+    return do_mm_binary_op<bool, M1::element_type, M2::element_type> (m1, m2, OP, OP, OP, #F); \
   }
 
 #define MM_BOOL_OPS(M1, M2) \
@@ -310,7 +310,7 @@
   R \
   OP (const ND1& m1, const ND2& m2) \
   { \
-    return do_mm_binary_op<R::element_type, ND1::element_type, ND2::element_type> (m1, m2, F, #OP); \
+    return do_mm_binary_op<R::element_type, ND1::element_type, ND2::element_type> (m1, m2, F, F, F, #OP); \
   }
 
 #define NDND_BIN_OPS(R, ND1, ND2) \
@@ -323,7 +323,7 @@
   boolNDArray \
   F (const ND1& m1, const ND2& m2) \
   { \
-    return do_mm_binary_op<bool, ND1::element_type, ND2::element_type> (m1, m2, OP, #F); \
+    return do_mm_binary_op<bool, ND1::element_type, ND2::element_type> (m1, m2, OP, OP, OP, #F); \
   }
 
 #define NDND_CMP_OPS(ND1, ND2) \
@@ -340,7 +340,7 @@
   { \
     MNANCHK (m1, ND1::element_type); \
     MNANCHK (m2, ND2::element_type); \
-    return do_mm_binary_op<bool, ND1::element_type, ND2::element_type> (m1, m2, OP, #F); \
+    return do_mm_binary_op<bool, ND1::element_type, ND2::element_type> (m1, m2, OP, OP, OP, #F); \
   }
 
 #define NDND_BOOL_OPS(ND1, ND2) \
@@ -583,7 +583,7 @@
 T \
 FCN (const T& a, const T& b) \
 { \
-  return do_mm_binary_op<T::element_type, T::element_type, T::element_type> (a, b, mx_inline_x##FCN, #FCN); \
+  return do_mm_binary_op<T::element_type, T::element_type, T::element_type> (a, b, mx_inline_x##FCN, mx_inline_x##FCN, mx_inline_x##FCN, #FCN); \
 }
 
 #define MINMAX_FCNS(T, S) \
--- a/liboctave/oct-binmap.h
+++ b/liboctave/oct-binmap.h
@@ -27,9 +27,13 @@
 #include "Sparse.h"
 #include "Array-util.h"
 
-// This source implements a general binary maping function for arrays.
-// The syntax is binmap<type> (a, b, f, [name]). type denotes the expected
-// return type of the operation. a, b, should be one of the 6 combinations:
+#include "bsxfun.h"
+
+// This source file implements a general binary maping function for
+// arrays. The syntax is binmap<type> (a, b, f, [name]). type denotes
+// the expected return type of the operation. a, b, should be one of
+// the 6 combinations:
+//
 // Array-Array
 // Array-scalar
 // scalar-Array
@@ -37,11 +41,12 @@
 // Sparse-scalar
 // scalar-Sparse
 //
-// If both operands are nonscalar, name must be supplied. It is used as the base for error message
-// when operands are nonconforming.
+// If both operands are nonscalar, name must be supplied. It is used
+// as the base for error message when operands are nonconforming.
 //
-// The operation needs not be homogeneous, i.e. a, b and the result may be of distinct types.
-// f can have any of the four signatures:
+// The operation needs not be homogeneous, i.e. a, b and the result
+// may be of distinct types. f can have any of the four signatures:
+//
 // U f (T, R)
 // U f (const T&, R)
 // U f (T, const R&)
@@ -49,7 +54,51 @@
 //
 // Additionally, f can be an arbitrary functor object.
 //
-// octave_quit() is called at appropriate places, hence the operation is breakable.
+// octave_quit() is called at appropriate places, hence the operation
+// is breakable.
+
+// The following template wrappers are provided for automatic bsxfun
+// calls (see the function signature for do_bsxfun_op).
+
+template<typename R, typename X, typename Y, typename F>
+class bsxfun_wrapper
+{
+private:
+  static F f;
+
+public:
+  static void
+  set_f (const F& f_in)
+  {
+    f = f_in;
+  }
+
+  static void
+  op_mm (size_t n, R* r, const X* x , const Y* y)
+  {
+    for (size_t i = 0; i < n; i++)
+      r[i] = f (x[i], y[i]);
+  }
+
+  static void
+  op_sm (size_t n, R* r, X x, const Y* y)
+  {
+    for (size_t i = 0; i < n; i++)
+      r[i] = f (x, y[i]);
+  }
+
+  static void
+  op_ms (size_t n , R* r, const X* x, Y y)
+  {
+    for (size_t i = 0; i < n; i++)
+      r[i] = f (x[i], y);
+  }
+};
+
+// Static init
+template<typename R, typename X, typename Y, typename F>
+F bsxfun_wrapper<R, X, Y, F>::f;
+
 
 // scalar-Array
 template <class U, class T, class R, class F>
@@ -118,12 +167,24 @@
 Array<U>
 binmap (const Array<T>& xa, const Array<R>& ya, F fcn, const char *name)
 {
+  dim_vector xad = xa.dims (), yad = ya.dims ();
   if (xa.numel () == 1)
     return binmap<U, T, R, F> (xa(0), ya, fcn);
   else if (ya.numel () == 1)
     return binmap<U, T, R, F> (xa, ya(0), fcn);
-  else if (xa.dims () != ya.dims ())
-    gripe_nonconformant (name, xa.dims (), ya.dims ());
+  else if (xad != yad)
+    {
+      if (is_valid_bsxfun (xad, yad))
+        {
+          bsxfun_wrapper<U, T, R, F>::set_f(fcn);
+          return do_bsxfun_op (xa, ya,
+                               bsxfun_wrapper<U, T, R, F>::op_mm,
+                               bsxfun_wrapper<U, T, R, F>::op_sm,
+                               bsxfun_wrapper<U, T, R, F>::op_ms);
+        }
+      else
+        gripe_nonconformant (name, xad, yad);
+    }
 
   octave_idx_type len = xa.numel ();
 
@@ -273,134 +334,134 @@
                                           fcn, name));
 }
 
-// Overloads for function references.
+// Overloads for function pointers.
 
 // Signature (T, R)
 
 template <class U, class T, class R>
 inline Array<U>
-binmap (const Array<T>& xa, const Array<R>& ya, U (&fcn) (T, R), const char *name)
-{ return binmap<U, T, R, U (&) (T, R)> (xa, ya, fcn, name); }
+binmap (const Array<T>& xa, const Array<R>& ya, U (*fcn) (T, R), const char *name)
+{ return binmap<U, T, R, U (*) (T, R)> (xa, ya, fcn, name); }
 
 template <class U, class T, class R>
 inline Array<U>
-binmap (const T& x, const Array<R>& ya, U (&fcn) (T, R))
-{ return binmap<U, T, R, U (&) (T, R)> (x, ya, fcn); }
+binmap (const T& x, const Array<R>& ya, U (*fcn) (T, R))
+{ return binmap<U, T, R, U (*) (T, R)> (x, ya, fcn); }
 
 template <class U, class T, class R>
 inline Array<U>
-binmap (const Array<T>& xa, const R& y, U (&fcn) (T, R))
-{ return binmap<U, T, R, U (&) (T, R)> (xa, y, fcn); }
+binmap (const Array<T>& xa, const R& y, U (*fcn) (T, R))
+{ return binmap<U, T, R, U (*) (T, R)> (xa, y, fcn); }
 
 template <class U, class T, class R>
 inline Sparse<U>
-binmap (const Sparse<T>& xa, const Sparse<R>& ya, U (&fcn) (T, R), const char *name)
-{ return binmap<U, T, R, U (&) (T, R)> (xa, ya, fcn, name); }
+binmap (const Sparse<T>& xa, const Sparse<R>& ya, U (*fcn) (T, R), const char *name)
+{ return binmap<U, T, R, U (*) (T, R)> (xa, ya, fcn, name); }
 
 template <class U, class T, class R>
 inline Sparse<U>
-binmap (const T& x, const Sparse<R>& ya, U (&fcn) (T, R))
-{ return binmap<U, T, R, U (&) (T, R)> (x, ya, fcn); }
+binmap (const T& x, const Sparse<R>& ya, U (*fcn) (T, R))
+{ return binmap<U, T, R, U (*) (T, R)> (x, ya, fcn); }
 
 template <class U, class T, class R>
 inline Sparse<U>
-binmap (const Sparse<T>& xa, const R& y, U (&fcn) (T, R))
-{ return binmap<U, T, R, U (&) (T, R)> (xa, y, fcn); }
+binmap (const Sparse<T>& xa, const R& y, U (*fcn) (T, R))
+{ return binmap<U, T, R, U (*) (T, R)> (xa, y, fcn); }
 
 // Signature (const T&, const R&)
 
 template <class U, class T, class R>
 inline Array<U>
-binmap (const Array<T>& xa, const Array<R>& ya, U (&fcn) (const T&, const R&), const char *name)
-{ return binmap<U, T, R, U (&) (const T&, const R&)> (xa, ya, fcn, name); }
+binmap (const Array<T>& xa, const Array<R>& ya, U (*fcn) (const T&, const R&), const char *name)
+{ return binmap<U, T, R, U (*) (const T&, const R&)> (xa, ya, fcn, name); }
 
 template <class U, class T, class R>
 inline Array<U>
-binmap (const T& x, const Array<R>& ya, U (&fcn) (const T&, const R&))
-{ return binmap<U, T, R, U (&) (const T&, const R&)> (x, ya, fcn); }
+binmap (const T& x, const Array<R>& ya, U (*fcn) (const T&, const R&))
+{ return binmap<U, T, R, U (*) (const T&, const R&)> (x, ya, fcn); }
 
 template <class U, class T, class R>
 inline Array<U>
-binmap (const Array<T>& xa, const R& y, U (&fcn) (const T&, const R&))
-{ return binmap<U, T, R, U (&) (const T&, const R&)> (xa, y, fcn); }
+binmap (const Array<T>& xa, const R& y, U (*fcn) (const T&, const R&))
+{ return binmap<U, T, R, U (*) (const T&, const R&)> (xa, y, fcn); }
 
 template <class U, class T, class R>
 inline Sparse<U>
-binmap (const Sparse<T>& xa, const Sparse<R>& ya, U (&fcn) (const T&, const R&), const char *name)
-{ return binmap<U, T, R, U (&) (const T&, const R&)> (xa, ya, fcn, name); }
+binmap (const Sparse<T>& xa, const Sparse<R>& ya, U (*fcn) (const T&, const R&), const char *name)
+{ return binmap<U, T, R, U (*) (const T&, const R&)> (xa, ya, fcn, name); }
 
 template <class U, class T, class R>
 inline Sparse<U>
-binmap (const T& x, const Sparse<R>& ya, U (&fcn) (const T&, const R&))
-{ return binmap<U, T, R, U (&) (const T&, const R&)> (x, ya, fcn); }
+binmap (const T& x, const Sparse<R>& ya, U (*fcn) (const T&, const R&))
+{ return binmap<U, T, R, U (*) (const T&, const R&)> (x, ya, fcn); }
 
 template <class U, class T, class R>
 inline Sparse<U>
-binmap (const Sparse<T>& xa, const R& y, U (&fcn) (const T&, const R&))
-{ return binmap<U, T, R, U (&) (const T&, const R&)> (xa, y, fcn); }
+binmap (const Sparse<T>& xa, const R& y, U (*fcn) (const T&, const R&))
+{ return binmap<U, T, R, U (*) (const T&, const R&)> (xa, y, fcn); }
 
 // Signature (const T&, R)
 
 template <class U, class T, class R>
 inline Array<U>
-binmap (const Array<T>& xa, const Array<R>& ya, U (&fcn) (const T&, R), const char *name)
-{ return binmap<U, T, R, U (&) (const T&, R)> (xa, ya, fcn, name); }
+binmap (const Array<T>& xa, const Array<R>& ya, U (*fcn) (const T&, R), const char *name)
+{ return binmap<U, T, R, U (*) (const T&, R)> (xa, ya, fcn, name); }
 
 template <class U, class T, class R>
 inline Array<U>
-binmap (const T& x, const Array<R>& ya, U (&fcn) (const T&, R))
-{ return binmap<U, T, R, U (&) (const T&, R)> (x, ya, fcn); }
+binmap (const T& x, const Array<R>& ya, U (*fcn) (const T&, R))
+{ return binmap<U, T, R, U (*) (const T&, R)> (x, ya, fcn); }
 
 template <class U, class T, class R>
 inline Array<U>
-binmap (const Array<T>& xa, const R& y, U (&fcn) (const T&, R))
-{ return binmap<U, T, R, U (&) (const T&, R)> (xa, y, fcn); }
+binmap (const Array<T>& xa, const R& y, U (*fcn) (const T&, R))
+{ return binmap<U, T, R, U (*) (const T&, R)> (xa, y, fcn); }
 
 template <class U, class T, class R>
 inline Sparse<U>
-binmap (const Sparse<T>& xa, const Sparse<R>& ya, U (&fcn) (const T&, R), const char *name)
-{ return binmap<U, T, R, U (&) (const T&, R)> (xa, ya, fcn, name); }
+binmap (const Sparse<T>& xa, const Sparse<R>& ya, U (*fcn) (const T&, R), const char *name)
+{ return binmap<U, T, R, U (*) (const T&, R)> (xa, ya, fcn, name); }
 
 template <class U, class T, class R>
 inline Sparse<U>
-binmap (const T& x, const Sparse<R>& ya, U (&fcn) (const T&, R))
-{ return binmap<U, T, R, U (&) (const T&, R)> (x, ya, fcn); }
+binmap (const T& x, const Sparse<R>& ya, U (*fcn) (const T&, R))
+{ return binmap<U, T, R, U (*) (const T&, R)> (x, ya, fcn); }
 
 template <class U, class T, class R>
 inline Sparse<U>
-binmap (const Sparse<T>& xa, const R& y, U (&fcn) (const T&, R))
-{ return binmap<U, T, R, U (&) (const T&, R)> (xa, y, fcn); }
+binmap (const Sparse<T>& xa, const R& y, U (*fcn) (const T&, R))
+{ return binmap<U, T, R, U (*) (const T&, R)> (xa, y, fcn); }
 
 // Signature (T, const R&)
 
 template <class U, class T, class R>
 inline Array<U>
-binmap (const Array<T>& xa, const Array<R>& ya, U (&fcn) (T, const R&), const char *name)
-{ return binmap<U, T, R, U (&) (T, const R&)> (xa, ya, fcn, name); }
+binmap (const Array<T>& xa, const Array<R>& ya, U (*fcn) (T, const R&), const char *name)
+{ return binmap<U, T, R, U (*) (T, const R&)> (xa, ya, fcn, name); }
 
 template <class U, class T, class R>
 inline Array<U>
-binmap (const T& x, const Array<R>& ya, U (&fcn) (T, const R&))
-{ return binmap<U, T, R, U (&) (T, const R&)> (x, ya, fcn); }
+binmap (const T& x, const Array<R>& ya, U (*fcn) (T, const R&))
+{ return binmap<U, T, R, U (*) (T, const R&)> (x, ya, fcn); }
 
 template <class U, class T, class R>
 inline Array<U>
-binmap (const Array<T>& xa, const R& y, U (&fcn) (T, const R&))
-{ return binmap<U, T, R, U (&) (T, const R&)> (xa, y, fcn); }
+binmap (const Array<T>& xa, const R& y, U (*fcn) (T, const R&))
+{ return binmap<U, T, R, U (*) (T, const R&)> (xa, y, fcn); }
 
 template <class U, class T, class R>
 inline Sparse<U>
-binmap (const Sparse<T>& xa, const Sparse<R>& ya, U (&fcn) (T, const R&), const char *name)
-{ return binmap<U, T, R, U (&) (T, const R&)> (xa, ya, fcn, name); }
+binmap (const Sparse<T>& xa, const Sparse<R>& ya, U (*fcn) (T, const R&), const char *name)
+{ return binmap<U, T, R, U (*) (T, const R&)> (xa, ya, fcn, name); }
 
 template <class U, class T, class R>
 inline Sparse<U>
-binmap (const T& x, const Sparse<R>& ya, U (&fcn) (T, const R&))
-{ return binmap<U, T, R, U (&) (T, const R&)> (x, ya, fcn); }
+binmap (const T& x, const Sparse<R>& ya, U (*fcn) (T, const R&))
+{ return binmap<U, T, R, U (*) (T, const R&)> (x, ya, fcn); }
 
 template <class U, class T, class R>
 inline Sparse<U>
-binmap (const Sparse<T>& xa, const R& y, U (&fcn) (T, const R&))
-{ return binmap<U, T, R, U (&) (T, const R&)> (xa, y, fcn); }
+binmap (const Sparse<T>& xa, const R& y, U (*fcn) (T, const R&))
+{ return binmap<U, T, R, U (*) (T, const R&)> (xa, y, fcn); }
 
 #endif
--- a/liboctave/oct-inttypes.cc
+++ b/liboctave/oct-inttypes.cc
@@ -578,6 +578,23 @@
 
 template <class T>
 octave_int<T>
+pow (const float& a, const octave_int<T>& b)
+{ return octave_int<T> (pow (a, b.float_value ())); }
+
+template <class T>
+octave_int<T>
+pow (const octave_int<T>& a, const float& b)
+{
+  return ((b >= 0 && b < std::numeric_limits<T>::digits && b == xround (b))
+          ? pow (a, octave_int<T> (static_cast<T> (b)))
+          : octave_int<T> (pow (a.double_value (), static_cast<double> (b))));
+}
+
+// FIXME: Do we really need a differently named single-precision
+//        function integer power function here instead of an overloaded
+//        one?
+template <class T>
+octave_int<T>
 powf (const float& a, const octave_int<T>& b)
 { return octave_int<T> (pow (a, b.float_value ())); }
 
@@ -595,6 +612,8 @@
   template OCTAVE_API octave_int<T> pow (const octave_int<T>&, const octave_int<T>&); \
   template OCTAVE_API octave_int<T> pow (const double&, const octave_int<T>&); \
   template OCTAVE_API octave_int<T> pow (const octave_int<T>&, const double&); \
+  template OCTAVE_API octave_int<T> pow (const float&, const octave_int<T>&);  \
+  template OCTAVE_API octave_int<T> pow (const octave_int<T>&, const float&);  \
   template OCTAVE_API octave_int<T> powf (const float&, const octave_int<T>&); \
   template OCTAVE_API octave_int<T> powf (const octave_int<T>&, const float&); \
   template OCTAVE_API octave_int<T> \
--- a/liboctave/oct-inttypes.h
+++ b/liboctave/oct-inttypes.h
@@ -874,6 +874,17 @@
 
 template <class T>
 extern OCTAVE_API octave_int<T>
+pow (const float& a, const octave_int<T>& b);
+
+template <class T>
+extern OCTAVE_API octave_int<T>
+pow (const octave_int<T>& a, const float& b);
+
+// FIXME: Do we really need a differently named single-precision
+//        function integer power function here instead of an overloaded
+//        one?
+template <class T>
+extern OCTAVE_API octave_int<T>
 powf (const float& a, const octave_int<T>& b);
 
 template <class T>
--- a/liboctave/str-vec.cc
+++ b/liboctave/str-vec.cc
@@ -163,6 +163,26 @@
   return *this;
 }
 
+std::string
+string_vector::join (const std::string& sep) const
+{
+  std::string retval;
+
+  octave_idx_type len = length ();
+
+  if (len > 0)
+    {
+      octave_idx_type i;
+
+      for (i = 0; i < len - 1; i++)
+        retval += elem(i) + sep;
+
+      retval += elem(i);
+    }
+
+  return retval;
+}
+
 char **
 string_vector::c_str_vec (void) const
 {
--- a/liboctave/str-vec.h
+++ b/liboctave/str-vec.h
@@ -105,6 +105,8 @@
 
   string_vector& append (const string_vector& sv);
 
+  std::string join (const std::string& sep = std::string ()) const;
+
   char **c_str_vec (void) const;
 
   static void delete_c_str_vec (const char * const*);
--- a/liboctave/uint16NDArray.cc
+++ b/liboctave/uint16NDArray.cc
@@ -54,3 +54,6 @@
 
 BSXFUN_STDOP_DEFS_MXLOOP (uint16NDArray)
 BSXFUN_STDREL_DEFS_MXLOOP (uint16NDArray)
+
+BSXFUN_OP_DEF_MXLOOP (pow, uint16NDArray, mx_inline_pow)
+BSXFUN_POW_MIXED_MXLOOP (uint16NDArray)
--- a/liboctave/uint16NDArray.h
+++ b/liboctave/uint16NDArray.h
@@ -44,6 +44,7 @@
 MINMAX_DECLS (uint16NDArray, octave_uint16, OCTAVE_API)
 
 BSXFUN_STDOP_DECLS (uint16NDArray, OCTAVE_API)
+BSXFUN_MIXED_INT_DECLS(uint16NDArray, OCTAVE_API)
 BSXFUN_STDREL_DECLS (uint16NDArray, OCTAVE_API)
 
 #endif
--- a/liboctave/uint32NDArray.cc
+++ b/liboctave/uint32NDArray.cc
@@ -54,3 +54,6 @@
 
 BSXFUN_STDOP_DEFS_MXLOOP (uint32NDArray)
 BSXFUN_STDREL_DEFS_MXLOOP (uint32NDArray)
+
+BSXFUN_OP_DEF_MXLOOP (pow, uint32NDArray, mx_inline_pow)
+BSXFUN_POW_MIXED_MXLOOP (uint32NDArray)
--- a/liboctave/uint32NDArray.h
+++ b/liboctave/uint32NDArray.h
@@ -44,6 +44,7 @@
 MINMAX_DECLS (uint32NDArray, octave_uint32, OCTAVE_API)
 
 BSXFUN_STDOP_DECLS (uint32NDArray, OCTAVE_API)
+BSXFUN_MIXED_INT_DECLS(uint32NDArray, OCTAVE_API)
 BSXFUN_STDREL_DECLS (uint32NDArray, OCTAVE_API)
 
 #endif
--- a/liboctave/uint64NDArray.cc
+++ b/liboctave/uint64NDArray.cc
@@ -54,3 +54,7 @@
 
 BSXFUN_STDOP_DEFS_MXLOOP (uint64NDArray)
 BSXFUN_STDREL_DEFS_MXLOOP (uint64NDArray)
+
+BSXFUN_OP_DEF_MXLOOP (pow, uint64NDArray, mx_inline_pow)
+BSXFUN_POW_MIXED_MXLOOP (uint64NDArray)
+
--- a/liboctave/uint64NDArray.h
+++ b/liboctave/uint64NDArray.h
@@ -44,6 +44,7 @@
 MINMAX_DECLS (uint64NDArray, octave_uint64, OCTAVE_API)
 
 BSXFUN_STDOP_DECLS (uint64NDArray, OCTAVE_API)
+BSXFUN_MIXED_INT_DECLS(uint64NDArray, OCTAVE_API)
 BSXFUN_STDREL_DECLS (uint64NDArray, OCTAVE_API)
 
 #endif
--- a/liboctave/uint8NDArray.cc
+++ b/liboctave/uint8NDArray.cc
@@ -54,3 +54,7 @@
 
 BSXFUN_STDOP_DEFS_MXLOOP (uint8NDArray)
 BSXFUN_STDREL_DEFS_MXLOOP (uint8NDArray)
+
+BSXFUN_POW_MIXED_MXLOOP (uint8NDArray)
+BSXFUN_OP_DEF_MXLOOP (pow, uint8NDArray, mx_inline_pow)
+
--- a/liboctave/uint8NDArray.h
+++ b/liboctave/uint8NDArray.h
@@ -44,6 +44,7 @@
 MINMAX_DECLS (uint8NDArray, octave_uint8, OCTAVE_API)
 
 BSXFUN_STDOP_DECLS (uint8NDArray, OCTAVE_API)
+BSXFUN_MIXED_INT_DECLS(uint8NDArray, OCTAVE_API)
 BSXFUN_STDREL_DECLS (uint8NDArray, OCTAVE_API)
 
 #endif
--- a/scripts/audio/playaudio.m
+++ b/scripts/audio/playaudio.m
@@ -47,7 +47,10 @@
       num = fopen (file, "wb");
       c = fwrite (num, X, "uchar");
       fclose (num);
-      system (sprintf ("cat \"%s\" > /dev/dsp", file));
+      [status, out] = system (sprintf ("cat \"%s\" > /dev/dsp", file));
+      if (status != 0)
+        system (sprintf ("paplay --raw \"%s\"", file))
+      endif
     unwind_protect_cleanup
       unlink (file);
     end_unwind_protect
@@ -61,10 +64,16 @@
       print_usage ();
     endif
     if (strcmp (ext, "lin") || strcmp (ext, "raw"))
-      system (sprintf ("cat \"%s\" > /dev/dsp", name));
+      [status, out] = system (sprintf ("cat \"%s\" > /dev/dsp", name));
+      if (status != 0)
+        system (sprintf ("paplay --raw \"%s\"", name))
+      endif
     elseif (strcmp (ext, "mu") || strcmp (ext, "au")
             || strcmp (ext, "snd") || strcmp (ext, "ul"))
-      system (sprintf ("cat \"%s\" > /dev/audio", name));
+      [status, out] = system (sprintf ("cat \"%s\" > /dev/audio", name));
+      if (status != 0)
+        system (sprintf ("paplay \"%s\"", name))
+      endif
     else
       error ("playaudio: unsupported extension");
     endif
--- a/scripts/audio/wavread.m
+++ b/scripts/audio/wavread.m
@@ -55,135 +55,139 @@
     error ("wavread: FILENAME must be a character string");
   endif
 
-  # Open file for binary reading.
-  [fid, msg] = fopen (filename, "rb");
-  if (fid < 0)
-    error ("wavread: %s", msg);
-  endif
+  fid = -1;
+
+  unwind_protect
 
-  ## Get file size.
-  fseek (fid, 0, "eof");
-  file_size = ftell (fid);
-  fseek (fid, 0, "bof");
+    [fid, msg] = fopen (filename, "rb");
+
+    if (fid < 0)
+      error ("wavread: %s", msg);
+    endif
 
-  ## Find RIFF chunk.
-  riff_size = find_chunk (fid, "RIFF", file_size);
-  riff_pos = ftell (fid);
-  if (riff_size == -1)
-    fclose (fid);
-    error ("wavread: file contains no RIFF chunk");
-  endif
+    ## Get file size.
+    fseek (fid, 0, "eof");
+    file_size = ftell (fid);
+    fseek (fid, 0, "bof");
 
-  riff_type = char (fread (fid, 4))';
-  if (! strcmp (riff_type, "WAVE"))
-    fclose (fid);
-    error ("wavread: file contains no WAVE signature");
-  endif
-  riff_pos = riff_pos + 4;
-  riff_size = riff_size - 4;
+    ## Find RIFF chunk.
+    riff_size = find_chunk (fid, "RIFF", file_size);
+    riff_pos = ftell (fid);
+    if (riff_size == -1)
+      error ("wavread: file contains no RIFF chunk");
+    endif
+
+    riff_type = char (fread (fid, 4))';
+    if (! strcmp (riff_type, "WAVE"))
+      error ("wavread: file contains no WAVE signature");
+    endif
+    riff_pos = riff_pos + 4;
+    riff_size = riff_size - 4;
 
-  ## Find format chunk inside the RIFF chunk.
-  fseek (fid, riff_pos, "bof");
-  fmt_size = find_chunk (fid, "fmt ", riff_size);
-  fmt_pos = ftell(fid);
-  if (fmt_size == -1)
-    fclose (fid);
-    error ("wavread: file contains no format chunk");
-  endif
+    ## Find format chunk inside the RIFF chunk.
+    fseek (fid, riff_pos, "bof");
+    fmt_size = find_chunk (fid, "fmt ", riff_size);
+    fmt_pos = ftell(fid);
+    if (fmt_size == -1)
+      error ("wavread: file contains no format chunk");
+    endif
+
+    ## Find data chunk inside the RIFF chunk.
+    ## We don't assume that it comes after the format chunk.
+    fseek (fid, riff_pos, "bof");
+    data_size = find_chunk (fid, "data", riff_size);
+    data_pos = ftell (fid);
+    if (data_size == -1)
+      error ("wavread: file contains no data chunk");
+    endif
 
-  ## Find data chunk inside the RIFF chunk.
-  ## We don't assume that it comes after the format chunk.
-  fseek (fid, riff_pos, "bof");
-  data_size = find_chunk (fid, "data", riff_size);
-  data_pos = ftell (fid);
-  if (data_size == -1)
-    fclose (fid);
-    error ("wavread: file contains no data chunk");
-  endif
+    ### Read format chunk.
+    fseek (fid, fmt_pos, "bof");
 
-  ### Read format chunk.
-  fseek (fid, fmt_pos, "bof");
+    ## Sample format code.
+    format_tag = fread (fid, 1, "uint16", 0, BYTEORDER);
+    if (format_tag != FORMAT_PCM && format_tag != FORMAT_IEEE_FLOAT)
+      error ("wavread: sample format %#x is not supported", format_tag);
+    endif
 
-  ## Sample format code.
-  format_tag = fread (fid, 1, "uint16", 0, BYTEORDER);
-  if (format_tag != FORMAT_PCM && format_tag != FORMAT_IEEE_FLOAT)
-    fclose (fid);
-    error ("wavread: sample format %#x is not supported", format_tag);
-  endif
+    ## Number of interleaved channels.
+    channels = fread (fid, 1, "uint16", 0, BYTEORDER);
 
-  ## Number of interleaved channels.
-  channels = fread (fid, 1, "uint16", 0, BYTEORDER);
+    ## Sample rate.
+    samples_per_sec = fread (fid, 1, "uint32", 0, BYTEORDER);
 
-  ## Sample rate.
-  samples_per_sec = fread (fid, 1, "uint32", 0, BYTEORDER);
+    ## Bits per sample.
+    fseek (fid, 6, "cof");
+    bits_per_sample = fread (fid, 1, "uint16", 0, BYTEORDER);
 
-  ## Bits per sample.
-  fseek (fid, 6, "cof");
-  bits_per_sample = fread (fid, 1, "uint16", 0, BYTEORDER);
+    ### Read data chunk.
+    fseek (fid, data_pos, "bof");
 
-  ### Read data chunk.
-  fseek (fid, data_pos, "bof");
+    ## Determine sample data type.
+    if (format_tag == FORMAT_PCM)
+      switch (bits_per_sample)
+        case 8
+          format = "uint8";
+        case 16
+          format = "int16";
+        case 24
+          format = "uint8";
+        case 32
+          format = "int32";
+        otherwise
+          error ("wavread: %d bits sample resolution is not supported with PCM",
+                 bits_per_sample);
+      endswitch
+    else
+      switch (bits_per_sample)
+        case 32
+          format = "float32";
+        case 64
+          format = "float64";
+        otherwise
+          error ("wavread: %d bits sample resolution is not supported with IEEE float",
+                 bits_per_sample);
+      endswitch
+    endif
 
-  ## Determine sample data type.
-  if (format_tag == FORMAT_PCM)
-    switch (bits_per_sample)
-      case 8
-        format = "uint8";
-      case 16
-        format = "int16";
-      case 24
-        format = "uint8";
-      case 32
-        format = "int32";
-      otherwise
-        fclose (fid);
-        error ("wavread: %d bits sample resolution is not supported with PCM",
-               bits_per_sample);
-    endswitch
-  else
-    switch (bits_per_sample)
-      case 32
-        format = "float32";
-      case 64
-        format = "float64";
-      otherwise
-        fclose (fid);
-        error ("wavread: %d bits sample resolution is not supported with IEEE float",
-               bits_per_sample);
-    endswitch
-  endif
+    ## Parse arguments.
+    if (nargin == 1)
+      length = idivide (8 * data_size, bits_per_sample);
+    else
+      nparams = numel (param);
+      if (nparams == 1)
+        ## Number of samples is given.
+        length = param * channels;
+      elseif (nparams == 2)
+        ## Sample range is given.
+        if (fseek (fid, (param(1)-1) * channels * (bits_per_sample/8), "cof") < 0)
+          warning ("wavread: seeking failed");
+        endif
+        length = (param(2)-param(1)+1) * channels;
+      elseif (nparams == 4 && char (param) == "size")
+        ## Size of the file is requested.
+        tmp = idivide (8 * data_size, channels * bits_per_sample);
+        y = [tmp, channels];
+        return;
+      else
+        error ("wavread: invalid PARAM argument");
+      endif
+    endif
 
-  ## Parse arguments.
-  if (nargin == 1)
-    length = 8 * data_size / bits_per_sample;
-  else
-    nparams = numel (param);
-    if (nparams == 1)
-      ## Number of samples is given.
-      length = param * channels;
-    elseif (nparams == 2)
-      ## Sample range is given.
-      if (fseek (fid, (param(1)-1) * channels * (bits_per_sample/8), "cof") < 0)
-        warning ("wavread: seeking failed");
-      endif
-      length = (param(2)-param(1)+1) * channels;
-    elseif (nparams == 4 && char (param) == "size")
-      ## Size of the file is requested.
+    ## Read samples and close file.
+    if (bits_per_sample == 24)
+      length *= 3;
+    endif
+
+    [yi, n] = fread (fid, length, format, 0, BYTEORDER);
+
+  unwind_protect_cleanup
+
+    if (fid >= 0)
       fclose (fid);
-      y = [data_size/channels/(bits_per_sample/8), channels];
-      return;
-    else
-      fclose (fid);
-      error ("wavread: invalid PARAM argument");
     endif
-  endif
 
-  ## Read samples and close file.
-  if (bits_per_sample == 24)
-    length *= 3;
-  endif
-  [yi, n] = fread (fid, length, format, 0, BYTEORDER);
-  fclose (fid);
+  end_unwind_protect
 
   ## Check data.
   if (mod (numel (yi), channels) != 0)
@@ -240,7 +244,6 @@
   endif
 endfunction
 
-
-%% Tests for wavread/wavwrite pair are in wavrite.m
-%!assert(1)  # stop fntests.m from reporting no tests for wavread
-
+## Mark file as being tested.  Tests for wavread/wavwrite pair are in
+## wavwrite.m
+%!assert(1)
new file mode 100644
--- /dev/null
+++ b/scripts/deprecated/__error_text__.m
@@ -0,0 +1,36 @@
+## Copyright (C) 2011 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{msg}, @var{msgid}] =} __error_text__ (@var{msg}, @var{msgid})
+## This function has been deprecated.  Use @code{lasterr} instead.
+## @seealso{lasterr}
+## @end deftypefn
+
+function [msg, msgid] = __error_text__ (varargin)
+
+  persistent warned = false;
+  if (! warned)
+    warned = true;
+    warning ("Octave:deprecated-function",
+             "__error_text__ is obsolete and will be removed from a future version of Octave, please use lasterr instead");
+  endif
+
+  [msg, msgid] = lasterr (varargin{:});
+
+endfunction
deleted file mode 100644
--- a/scripts/deprecated/complement.m
+++ /dev/null
@@ -1,78 +0,0 @@
-## Copyright (C) 1994-2011 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} {} complement (@var{x}, @var{y})
-## Return the elements of set @var{y} that are not in set @var{x}.  For
-## example:
-##
-## @example
-## @group
-## complement ([ 1, 2, 3 ], [ 2, 3, 5 ])
-##      @result{} 5
-## @end group
-## @end example
-## @seealso{union, intersect, unique}
-## @end deftypefn
-
-## Author: jwe
-
-## Deprecated in version 3.2
-
-function y = complement (a, b)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "complement is obsolete and will be removed from a future version of Octave, please use setdiff instead");
-  endif
-
-  if (nargin != 2)
-    print_usage ();
-  endif
-
-  if (isempty (a))
-    y = unique (b);
-  elseif (isempty (b))
-    y = [];
-  else
-    a = unique (a);
-    b = unique (b);
-    yindex = 1;
-    y = zeros (1, length (b));
-    for index = 1:length (b)
-      if (all (a != b (index)))
-        y(yindex++) = b(index);
-      endif
-    endfor
-    y = y(1:(yindex-1));
-  endif
-
-endfunction
-
-%!assert(all (all (complement ([1, 2, 3], [3; 4; 5; 6]) == [4, 5, 6])));
-
-%!assert(all (all (complement ([1, 2, 3], [3, 4, 5, 6]) == [4, 5, 6])));
-
-%!assert(isempty (complement ([1, 2, 3], [3, 2, 1])));
-
-%!error complement (1);
-
-%!error complement (1, 2, 3);
-
rename from scripts/statistics/base/cor.m
rename to scripts/deprecated/cor.m
--- a/scripts/statistics/base/cor.m
+++ b/scripts/deprecated/cor.m
@@ -27,6 +27,13 @@
 
 function retval = cor (x, y = x)
 
+  persistent warned = false;
+  if (! warned)
+    warned = true;
+    warning ("Octave:deprecated-function",
+             "cor is obsolete and will be removed from a future version of Octave; please use corr instead");
+  endif
+
   if (nargin < 1 || nargin > 2)
     print_usage ();
   endif
@@ -35,6 +42,7 @@
 
 endfunction
 
+
 %!test
 %! x = rand (10, 2);
 %! assert (cor (x), corrcoef (x), 5*eps);
rename from scripts/statistics/base/corrcoef.m
rename to scripts/deprecated/corrcoef.m
--- a/scripts/statistics/base/corrcoef.m
+++ b/scripts/deprecated/corrcoef.m
@@ -48,20 +48,26 @@
 
 function retval = corrcoef (x, y = [])
 
+  persistent warned = false;
+  if (! warned)
+    warned = true;
+    warning ("Octave:deprecated-function",
+             "corrcoef is not equivalent to Matlab and will be removed from a future version of Octave; for similar functionality see corr");
+  endif
+
   if (nargin < 1 || nargin > 2)
     print_usage ();
   endif
 
-  if (! (isnumeric (x) && isnumeric (y)))
-    error ("corrcoef: X and Y must be numeric matrices or vectors");
-  endif
+  ## Input validation is done by cov.m.  Don't repeat tests here
 
-  if (ndims (x) != 2 || ndims (y) != 2)
-    error ("corrcoef: X and Y must be 2-D matrices or vectors");
-  endif
-
+  ## Special case, scalar is always 100% correlated with itself
   if (isscalar (x))
-    retval = 1;
+    if (isa (x, 'single'))
+      retval = single (1);
+    else
+      retval = 1;
+    endif
     return;
   endif
 
@@ -79,20 +85,35 @@
 
 endfunction
 
+
 %!test
 %! x = rand (10);
 %! cc1 = corrcoef (x);
 %! cc2 = corrcoef (x, x);
-%! assert((size (cc1) == [10, 10] && size (cc2) == [10, 10]
-%! && abs (cc1 - cc2) < sqrt (eps)));
+%! assert (size (cc1) == [10, 10] && size (cc2) == [10, 10]);
+%! assert (cc1, cc2, sqrt (eps));
+
+%!test
+%! x = [1:3]';
+%! y = [3:-1:1]';
+%! assert (corrcoef (x,y), -1, 5*eps)
+%! assert (corrcoef (x,flipud (y)), 1, 5*eps)
+%! assert (corrcoef ([x, y]), [1 -1; -1 1], 5*eps)
 
-%!assert(corrcoef (5), 1);
+%!test
+%! x = single ([1:3]');
+%! y = single ([3:-1:1]');
+%! assert (corrcoef (x,y), single (-1), 5*eps)
+%! assert (corrcoef (x,flipud (y)), single (1), 5*eps)
+%! assert (corrcoef ([x, y]), single ([1 -1; -1 1]), 5*eps)
+
+%!assert (corrcoef (5), 1);
+%!assert (corrcoef (single(5)), single(1));
 
 %% Test input validation
 %!error corrcoef ();
 %!error corrcoef (1, 2, 3);
-%!error corrcoef ([true, true]);
-%!error corrcoef ([1, 2], [true, true]);
+%!error corrcoef ([1; 2], ["A", "B"]);
 %!error corrcoef (ones (2,2,2));
 %!error corrcoef (ones (2,2), ones (2,2,2));
 
deleted file mode 100644
--- a/scripts/deprecated/create_set.m
+++ /dev/null
@@ -1,79 +0,0 @@
-## Copyright (C) 1994-2011 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} {} create_set (@var{x})
-## @deftypefnx {Function File} {} create_set (@var{x}, "rows")
-## This function has been deprecated.  Use unique instead.
-## @end deftypefn
-
-## Return a row vector containing the unique values in @var{x}, sorted in
-## ascending order.  For example,
-##
-## @example
-## @group
-## create_set ([ 1, 2; 3, 4; 4, 2; 1, 2 ])
-##      @result{} [ 1, 2, 3, 4 ]
-## @end group
-## @end example
-##
-## If the optional second input argument is the string "rows" each row of
-## the matrix @var{x} will be considered an element of set.  For example,
-## @example
-## @group
-## create_set ([ 1, 2; 3, 4; 4, 2; 1, 2 ], "rows")
-##      @result{}  1   2
-##     3   4
-##     4   2
-## @end group
-## @end example
-## @seealso{union, intersect, complement, unique}
-
-## Author: jwe
-
-## Deprecated in version 3.2
-
-function y = create_set (x, rows_opt)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "create_set is obsolete and will be removed from a future version of Octave, please use unique instead");
-  endif
-
-  if (nargin < 1 || nargin > 2)
-    print_usage ();
-  endif
-
-  if (nargin == 1)
-    y = unique (x)(:)';
-  elseif (strcmpi (rows_opt, "rows"))
-    y = unique (x, "rows");
-  else
-    error ("create_set: expecting \"rows\" as second argument");
-  endif
-
-endfunction
-
-%!assert(all (all (create_set ([1, 2, 3, 4, 2, 4]) == [1, 2, 3, 4])));
-%!assert(all (all (create_set ([1, 2; 3, 4; 2, 4]) == [1, 2, 3, 4])));
-%!assert(all (all (create_set ([1; 2; 3; 4; 2; 4]) == [1, 2, 3, 4])));
-%!assert(isempty (create_set ([])));
-%!error create_set (1, 2);
-
rename from scripts/statistics/base/cut.m
rename to scripts/deprecated/cut.m
--- a/scripts/statistics/base/cut.m
+++ b/scripts/deprecated/cut.m
@@ -37,6 +37,13 @@
 
 function group = cut (x, breaks)
 
+  persistent warned = false;
+  if (! warned)
+    warned = true;
+    warning ("Octave:deprecated-function",
+             "cut is obsolete and will be removed from a future version of Octave; please use histc instead");
+  endif
+
   if (nargin != 2)
     print_usage ();
   endif
deleted file mode 100644
--- a/scripts/deprecated/dmult.m
+++ /dev/null
@@ -1,49 +0,0 @@
-## Copyright (C) 1995-2011 Kurt Hornik
-##
-## 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} {} dmult (@var{a}, @var{b})
-## This function has been deprecated.  Use the direct syntax @code{diag(A)*B}
-## which is more readable and now also more efficient.
-## @end deftypefn
-
-## Author: KH <Kurt.Hornik@wu-wien.ac.at>
-## Description: Rescale the rows of a matrix
-
-## Deprecated in version 3.2
-
-function M = dmult (a, B)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "dmult is obsolete and will be removed from a future version of Octave; please use the straightforward (and now efficient) syntax \"diag(A)*B\"");
-  endif
-
-  if (nargin != 2)
-    print_usage ();
-  endif
- if (! isvector (a))
-    error ("dmult: a must be a vector of length rows (B)");
-  endif
-  a = a(:);
-  sb = size (B);
-  sb(1) = 1;
-  M = repmat (a(:), sb) .* B;
-endfunction
new file mode 100644
--- /dev/null
+++ b/scripts/deprecated/error_text.m
@@ -0,0 +1,36 @@
+## Copyright (C) 2011 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{msg}, @var{msgid}] =} error_text (@var{msg}, @var{msgid})
+## This function has been deprecated.  Use @code{lasterr} instead.
+## @seealso{lasterr}
+## @end deftypefn
+
+function [msg, msgid] = error_text (varargin)
+
+  persistent warned = false;
+  if (! warned)
+    warned = true;
+    warning ("Octave:deprecated-function",
+             "error_text is obsolete and will be removed from a future version of Octave, please use lasterr instead");
+  endif
+
+  [msg, msgid] = lasterr (varargin{:});
+
+endfunction
deleted file mode 100644
--- a/scripts/deprecated/iscommand.m
+++ /dev/null
@@ -1,44 +0,0 @@
-## Copyright (C) 2009-2011 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} {} iscommand (@var{name})
-## This function is obsolete and will be removed from a future
-## version of Octave.
-## @end deftypefn
-
-## Author: jwe
-
-## Deprecated in version 3.2
-
-function retval = iscommand ()
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "iscommand is obsolete and will be removed from a future version of Octave");
-  endif
-
-  if (nargin == 0)
-    retval = {};
-  else
-    retval = true;
-  endif
-
-endfunction
deleted file mode 100644
--- a/scripts/deprecated/israwcommand.m
+++ /dev/null
@@ -1,44 +0,0 @@
-## Copyright (C) 2009-2011 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} {} israwcommand (@var{name})
-## This function is obsolete and will be removed from a future
-## version of Octave.
-## @end deftypefn
-
-## Author: jwe
-
-## Deprecated in version 3.2
-
-function retval = israwcommand ()
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "israwcommand is obsolete and will be removed from a future version of Octave");
-  endif
-
-  if (nargin == 0)
-    retval = {};
-  else
-    retval = true;
-  endif
-
-endfunction
deleted file mode 100644
--- a/scripts/deprecated/lchol.m
+++ /dev/null
@@ -1,39 +0,0 @@
-## Copyright (C) 2008-2011 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  {Loadable Function} {@var{l} =} lchol (@var{a})
-## @deftypefnx {Loadable Function} {[@var{l}, @var{p}] =} lchol (@var{a})
-## This function has been deprecated.  Use @code{chol (@dots{},'lower')}
-## instead.
-## @end deftypefn
-
-## Deprecated in version 3.2
-
-function varargout = lchol (varargin)
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "spfind is obsolete and will be removed from a future version of Octave; please use find instead");
-  endif
-
-  varargout = cell (nargout, 1);
-  [ varargout{:} ] = chol (varargin{:}, "lower");
-
-endfunction
deleted file mode 100644
--- a/scripts/deprecated/loadimage.m
+++ /dev/null
@@ -1,43 +0,0 @@
-## Copyright (C) 1994-2011 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{x}, @var{map}] =} loadimage (@var{file})
-## Load an image file and its associated color map from the specified
-## @var{file}.  The image must be stored in Octave's image format.
-## @seealso{saveimage, load, save}
-## @end deftypefn
-
-## Author: Tony Richardson <arichard@stark.cc.oh.us>
-## Created: July 1994
-## Adapted-By: jwe
-
-## Deprecated in version 3.2
-
-function [img_retval, map_retval] = loadimage (varargin)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "loadimage is obsolete and will be removed from a future version of Octave; please use imread instead");
-  endif
-
-  [img_retval, map_retval] = imread (varargin{:});
-
-endfunction
deleted file mode 100644
--- a/scripts/deprecated/mark_as_command.m
+++ /dev/null
@@ -1,38 +0,0 @@
-## Copyright (C) 2009-2011 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} {} mark_as_command (@var{name})
-## This function is obsolete and will be removed from a future
-## version of Octave.
-## @end deftypefn
-
-## Author: jwe
-
-## Deprecated in version 3.2
-
-function mark_as_command ()
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "mark_as_command is obsolete and will be removed from a future version of Octave");
-  endif
-
-endfunction
deleted file mode 100644
--- a/scripts/deprecated/mark_as_rawcommand.m
+++ /dev/null
@@ -1,38 +0,0 @@
-## Copyright (C) 2009-2011 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} {} mark_as_rawcommand (@var{name})
-## This function is obsolete and will be removed from a future
-## version of Octave.
-## @end deftypefn
-
-## Author: jwe
-
-## Deprecated in version 3.2
-
-function mark_as_rawcommand ()
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "mark_as_rawcommand is obsolete and will be removed from a future version of Octave");
-  endif
-
-endfunction
--- a/scripts/deprecated/module.mk
+++ b/scripts/deprecated/module.mk
@@ -6,55 +6,29 @@
   deprecated/betai.m \
   deprecated/cellidx.m \
   deprecated/clg.m \
-  deprecated/complement.m \
-  deprecated/create_set.m \
+  deprecated/cor.m \
+  deprecated/corrcoef.m \
   deprecated/cquad.m \
+  deprecated/cut.m \
   deprecated/dispatch.m \
-  deprecated/dmult.m \
   deprecated/fstat.m \
   deprecated/gammai.m \
   deprecated/glpkmex.m \
   deprecated/intwarning.m \
-  deprecated/iscommand.m \
   deprecated/is_duplicate_entry.m \
   deprecated/is_global.m \
-  deprecated/israwcommand.m \
   deprecated/isstr.m \
-  deprecated/lchol.m \
-  deprecated/loadimage.m \
   deprecated/krylovb.m \
-  deprecated/mark_as_command.m \
-  deprecated/mark_as_rawcommand.m \
   deprecated/perror.m \
+  deprecated/polyderiv.m \
   deprecated/replot.m \
   deprecated/saveimage.m \
   deprecated/setstr.m \
-  deprecated/spatan2.m \
-  deprecated/spchol2inv.m \
-  deprecated/spcholinv.m \
-  deprecated/spchol.m \
-  deprecated/spcumprod.m \
-  deprecated/spcumsum.m \
-  deprecated/spdet.m \
-  deprecated/spdiag.m \
-  deprecated/spfind.m \
   deprecated/sphcat.m \
-  deprecated/spinv.m \
-  deprecated/spkron.m \
-  deprecated/splchol.m \
-  deprecated/split.m \
-  deprecated/splu.m \
-  deprecated/spmax.m \
-  deprecated/spmin.m \
-  deprecated/spprod.m \
-  deprecated/spqr.m \
-  deprecated/spsum.m \
-  deprecated/spsumsq.m \
   deprecated/spvcat.m \
-  deprecated/str2mat.m \
   deprecated/strerror.m \
-  deprecated/unmark_command.m \
-  deprecated/unmark_rawcommand.m \
+  deprecated/studentize.m \
+  deprecated/sylvester_matrix.m \
   deprecated/values.m \
   deprecated/weibcdf.m \
   deprecated/weibinv.m \
rename from scripts/polynomial/polyderiv.m
rename to scripts/deprecated/polyderiv.m
--- a/scripts/polynomial/polyderiv.m
+++ b/scripts/deprecated/polyderiv.m
@@ -36,6 +36,13 @@
 
 function [q, d] = polyderiv (p, a)
 
+  persistent warned = false;
+  if (! warned)
+    warned = true;
+    warning ("Octave:deprecated-function",
+             "polyderiv is obsolete and will be removed from a future version of Octave; please use polyder instead");
+  endif
+
   if (nargin == 1 || nargin == 2)
     if (! isvector (p))
       error ("polyderiv: argument must be a vector");
--- a/scripts/deprecated/saveimage.m
+++ b/scripts/deprecated/saveimage.m
@@ -30,8 +30,7 @@
 ## Portable pixmap format.
 ##
 ## @item "ps"
-## PostScript format.  Note that images saved in PostScript format cannot
-## be read back into Octave with loadimage.
+## PostScript format.
 ## @end table
 ##
 ## If the fourth argument is supplied, the specified colormap will also be
@@ -42,7 +41,7 @@
 ## image is a gray scale image (the entries within each row of the colormap
 ## are equal) the gray scale ppm and PostScript image formats are used,
 ## otherwise the full color formats are used.
-## @seealso{loadimage, save, load, colormap}
+## @seealso{imread, save, load, colormap}
 ## @end deftypefn
 
 ## The conversion to PostScript is based on pbmtolps.c, which was
deleted file mode 100644
--- a/scripts/deprecated/spatan2.m
+++ /dev/null
@@ -1,36 +0,0 @@
-## Copyright (C) 2008-2011 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} {} spatan2 (@var{y}, @var{x})
-## This function has been deprecated.  Use @code{atan2} instead.
-## @end deftypefn
-
-## Deprecated in version 3.2
-
-function retval = spatan2 (varargin)
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "spatan2 is obsolete and will be removed from a future version of Octave; please use atan2 instead");
-  endif
-
-  retval = atan2 (varargin{:});
-
-endfunction
deleted file mode 100644
--- a/scripts/deprecated/spchol.m
+++ /dev/null
@@ -1,39 +0,0 @@
-## Copyright (C) 2008-2011 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  {Loadable Function} {@var{r} =} spchol (@var{a})
-## @deftypefnx {Loadable Function} {[@var{r}, @var{p}] =} spchol (@var{a})
-## @deftypefnx {Loadable Function} {[@var{r}, @var{p}, @var{q}] =} spchol (@var{a})
-## This function has been deprecated.  Use @code{chol} instead.
-## @end deftypefn
-
-## Deprecated in version 3.2
-
-function varargout = spchol (varargin)
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "spchol is obsolete and will be removed from a future version of Octave; please use chol instead");
-  endif
-
-  varargout = cell (nargout, 1);
-  [ varargout{:} ] = chol (varargin{:});
-
-endfunction
deleted file mode 100644
--- a/scripts/deprecated/spchol2inv.m
+++ /dev/null
@@ -1,36 +0,0 @@
-## Copyright (C) 2008-2011 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} {} spchol2inv (@var{u})
-## This function has been deprecated.  Use @code{chol2inv} instead.
-## @end deftypefn
-
-## Deprecated in version 3.2
-
-function retval = spchol2inv (varargin)
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "spchol2inv is obsolete and will be removed from a future version of Octave; please use chol2inv instead");
-  endif
-
-  retval = chol2inv (varargin{:});
-
-endfunction
deleted file mode 100644
--- a/scripts/deprecated/spcholinv.m
+++ /dev/null
@@ -1,35 +0,0 @@
-## Copyright (C) 2008-2011 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} {} spcholinv (@var{u})
-## This function has been deprecated.  Use @code{cholinv} instead.
-## @end deftypefn
-
-## Deprecated in version 3.2
-
-function retval = spcholinv (varargin)
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "spcholinv is obsolete and will be removed from a future version of Octave; please use cholinv instead");
-  endif
-  retval = cholinv (varargin{:});
-
-endfunction
deleted file mode 100644
--- a/scripts/deprecated/spcumprod.m
+++ /dev/null
@@ -1,36 +0,0 @@
-## Copyright (C) 2008-2011 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} {} spcumprod (@var{x}, @var{dim})
-## This function has been deprecated.  Use @code{cumprod} instead.
-## @end deftypefn
-
-## Deprecated in version 3.2
-
-function retval = spcumprod (varargin)
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "spcumprod is obsolete and will be removed from a future version of Octave; please use cumprod instead");
-  endif
-
-  retval = cumprod (varargin{:});
-
-endfunction
deleted file mode 100644
--- a/scripts/deprecated/spcumsum.m
+++ /dev/null
@@ -1,36 +0,0 @@
-## Copyright (C) 2008-2011 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} {} spcumsum (@var{x}, @var{dim})
-## This function has been deprecated.  Use @code{cumsum} instead.
-## @end deftypefn
-
-## Deprecated in version 3.2
-
-function retval = spcumsum (varargin)
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "spcumsum is obsolete and will be removed from a future version of Octave; please use cumsum instead");
-  endif
-
-  retval = cumsum (varargin{:});
-
-endfunction
deleted file mode 100644
--- a/scripts/deprecated/spdet.m
+++ /dev/null
@@ -1,37 +0,0 @@
-## Copyright (C) 2008-2011 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 {Loadable Function} {[@var{d}, @var{rcond}] =} spdet (@var{a})
-## This function has been deprecated.  Use @code{det} instead.
-## @end deftypefn
-
-## Deprecated in version 3.2
-
-function varargout = spdet (varargin)
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "spdet is obsolete and will be removed from a future version of Octave; please use det instead");
-  endif
-
-  varargout = cell (nargout, 1);
-  [ varargout{:} ] = det (varargin{:});
-
-endfunction
deleted file mode 100644
--- a/scripts/deprecated/spdiag.m
+++ /dev/null
@@ -1,37 +0,0 @@
-## Copyright (C) 2008-2011 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} {} spdiag (@var{v}, @var{k})
-## This function has been deprecated.  Use @code{sparse (diag (@dots{}))}
-## instead.
-## @end deftypefn
-
-## Deprecated in version 3.2
-
-function retval = spdiag (varargin)
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "spdiag is obsolete and will be removed from a future version of Octave; please use sparse (diag (...)) instead");
-  endif
-
-  retval = sparse (diag (varargin{:}));
-
-endfunction
deleted file mode 100644
--- a/scripts/deprecated/spfind.m
+++ /dev/null
@@ -1,40 +0,0 @@
-## Copyright (C) 2008-2011 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  {Loadable Function} {} spfind (@var{x})
-## @deftypefnx {Loadable Function} {} spfind (@var{x}, @var{n})
-## @deftypefnx {Loadable Function} {} spfind (@var{x}, @var{n}, @var{direction})
-## @deftypefnx {Loadable Function} {[@var{i}, @var{j}, @var{v}} spfind (@dots{})
-## This function has been deprecated.  Use @code{find} instead.
-## @end deftypefn
-
-## Deprecated in version 3.2
-
-function varargout = spfind (varargin)
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "spfind is obsolete and will be removed from a future version of Octave; please use find instead");
-  endif
-
-  varargout = cell (nargout, 1);
-  [ varargout{:} ] = find (varargin{:});
-
-endfunction
deleted file mode 100644
--- a/scripts/deprecated/spinv.m
+++ /dev/null
@@ -1,37 +0,0 @@
-## Copyright (C) 2008-2011 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{x}, @var{rcond}] =} spinv (@var{a})
-## This function has been deprecated.  Use @code{inv} instead.
-## @end deftypefn
-
-## Deprecated in version 3.2
-
-function varargout = spinv (varargin)
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "spinv is obsolete and will be removed from a future version of Octave; please use inv instead");
-  endif
-
-  varargout = cell (nargout, 1);
-  [ varargout{:} ] = inv (varargin{:});
-
-endfunction
deleted file mode 100644
--- a/scripts/deprecated/spkron.m
+++ /dev/null
@@ -1,38 +0,0 @@
-## Copyright (C) 2008-2011 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} {} spkron (@var{a}, @var{b})
-## This function has been deprecated.  Use @code{kron} instead.
-## @end deftypefn
-
-## Author: jwe
-
-## Deprecated in version 3.2
-
-function retval = spkron (varargin)
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "spkron is obsolete and will be removed from a future version of Octave; please use kron instead");
-  endif
-
-  retval = kron (varargin{:});
-
-endfunction
deleted file mode 100644
--- a/scripts/deprecated/splchol.m
+++ /dev/null
@@ -1,40 +0,0 @@
-## Copyright (C) 2008-2011 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  {Loadable Function} {@var{l} =} splchol (@var{a})
-## @deftypefnx {Loadable Function} {[@var{l}, @var{p}] =} splchol (@var{a})
-## @deftypefnx {Loadable Function} {[@var{l}, @var{p}, @var{q}] =} splchol (@var{a})
-## This function has been deprecated.  Use @code{chol (@dots{},'lower')}
-## instead.
-## @end deftypefn
-
-## Deprecated in version 3.2
-
-function varargout = splchol (varargin)
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "splchol is obsolete and will be removed from a future version of Octave; please use chol instead");
-  endif
-
-  varargout = cell (nargout, 1);
-  [ varargout{:} ] = chol (varargin{:}, "lower");
-
-endfunction
deleted file mode 100644
--- a/scripts/deprecated/split.m
+++ /dev/null
@@ -1,130 +0,0 @@
-## Copyright (C) 1996-2011 Kurt Hornik
-##
-## 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} {} split (@var{s}, @var{t}, @var{n})
-## This function has been deprecated.  Use @code{char (strsplit (s, t))}
-## instead.
-## @end deftypefn
-
-## Divides the string @var{s} into pieces separated by @var{t}, returning
-## the result in a string array (padded with blanks to form a valid
-## matrix).  If the optional input @var{n} is supplied, split @var{s}
-## into at most @var{n} different pieces.
-##
-## For example,
-##
-## @example
-## split ("Test string", "t")
-##      @result{}
-##         "Tes "
-##         " s  "
-##         "ring"
-## @end example
-##
-## @example
-## split ("Test string", "t s", 2)
-##      @result{}
-##         "Tes  "
-##         "tring"
-## @end example
-## @seealso{strtok, index}
-## @end deftypefn
-
-## Author: Kurt Hornik <Kurt.Hornik@wu-wien.ac.at>
-## Adapted-By: jwe
-
-## Deprecated in version 3.2
-
-function m = split (s, t, n)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "split is obsolete and will be removed from a future version of Octave; please use strsplit instead");
-  endif
-
-  if (nargin == 2 || nargin == 3)
-    if (nargin == 2)
-      n = length (s);
-    endif
-
-    if (ischar (s) && ischar (t))
-
-      l_s = length (s);
-      l_t = length (t);
-
-      if (l_s == 0)
-        m = "";
-        return;
-      elseif (l_t == 0)
-        m = s';
-        return;
-      elseif (l_s < l_t)
-        error ("split: S must not be shorter than T");
-      endif
-
-      if (min (size (s)) != 1 || min (size (t)) != 1)
-        error("split: multi-line strings are not supported");
-      endif
-
-      ind = findstr (s, t, 0);
-      if (length (ind) == 0)
-        m = s;
-        return;
-      elseif (n - 1 < length(ind))
-        ind = ind(1:n-1);
-      endif
-      ind2 = [1, ind+l_t];
-      ind  = [ind, l_s+1];
-
-      ind_diff = ind-ind2;
-
-      ## Create a matrix of the correct size that's filled with spaces.
-      m_rows = length (ind);
-      m_cols = max (ind_diff);
-      m = repmat (" ", m_rows, m_cols);
-
-      ## Copy the strings to the matrix.
-      for i = 1:length (ind)
-        tmp = ind2(i):(ind(i)-1);
-        m(i,1:length(tmp)) = s(tmp);
-      endfor
-    else
-      error ("split: both S and T must be strings");
-    endif
-  else
-    print_usage ();
-  endif
-
-endfunction
-
-%!assert(all (all (split ("Test string", "t") == ["Tes "; " s  "; "ring"])));
-
-%!error split ();
-
-%!assert(all (strcmp (split ("foo bar baz", " ", 2), ["foo"; "bar baz"])));
-
-%!error split ("foo", "bar", 3, 4);
-
-%!assert (all (strcmp (split("road//to/hell","/"), ["road"; "    "; "to  "; "hell"])))
-
-%!assert (all (strcmp (split("/road/to/hell/","/"), ["    "; "road"; "to  "; "hell"; "    "])))
-
-
deleted file mode 100644
--- a/scripts/deprecated/splu.m
+++ /dev/null
@@ -1,48 +0,0 @@
-## Copyright (C) 2008-2011 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  {Loadable Function} {[@var{l}, @var{u}] =} splu (@var{a})
-## @deftypefnx {Loadable Function} {[@var{l}, @var{u}, @var{P}] =} splu (@var{a})
-## @deftypefnx {Loadable Function} {[@var{l}, @var{u}, @var{P}, @var{Q}] =} splu (@var{a})
-## @deftypefnx {Loadable Function} {[@var{l}, @var{u}, @var{P}, @var{Q}] =} splu (@dots{}, @var{thres})
-## @deftypefnx {Loadable Function} {[@var{l}, @var{u}, @var{P}] =} splu (@dots{}, @var{Q})
-## This function has been deprecated.  Use @code{lu} instead.
-## @end deftypefn
-
-## Deprecated in version 3.2
-
-function varargout = splu (varargin)
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "splu is obsolete and will be removed from a future version of Octave; please use lu instead");
-  endif
-
-  for i = 2 : nargin
-    arg = varargin {i};
-    if (! isscalar (arg))
-      error ("splu: Can no longer treat input column permutations");
-    endif
-  endfor
-
-  varargout = cell (nargout, 1);
-  [ varargout{:} ] = lu (varargin{:});
-
-endfunction
deleted file mode 100644
--- a/scripts/deprecated/spmax.m
+++ /dev/null
@@ -1,38 +0,0 @@
-## Copyright (C) 2008-2011 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  {Mapping Function} {} spmax (@var{x}, @var{y}, @var{dim})
-## @deftypefnx {Mapping Function} {[@var{w}, @var{iw}] =} spmax (@var{x})
-## This function has been deprecated.  Use @code{max} instead.
-## @end deftypefn
-
-## Deprecated in version 3.2
-
-function varargout = spmax (varargin)
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "spmax is obsolete and will be removed from a future version of Octave; please use max instead");
-  endif
-
-  varargout = cell (nargout, 1);
-  [ varargout{:} ] = max (varargin{:});
-
-endfunction
deleted file mode 100644
--- a/scripts/deprecated/spmin.m
+++ /dev/null
@@ -1,38 +0,0 @@
-## Copyright (C) 2008-2011 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  {Mapping Function} {} spmin (@var{x}, @var{y}, @var{dim})
-## @deftypefnx {Mapping Function} {[@var{w}, @var{iw}] =} spmin (@var{x})
-## This function has been deprecated.  Use @code{min} instead.
-## @end deftypefn
-
-## Deprecated in version 3.2
-
-function varargout = spmin (varargin)
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "spmin is obsolete and will be removed from a future version of Octave; please use min instead");
-  endif
-
-  varargout = cell (nargout, 1);
-  [ varargout{:} ] = min (varargin{:});
-
-endfunction
deleted file mode 100644
--- a/scripts/deprecated/spprod.m
+++ /dev/null
@@ -1,36 +0,0 @@
-## Copyright (C) 2008-2011 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} {} spprod (@var{x}, @var{dim})
-## This function has been deprecated.  Use @code{prod} instead.
-## @end deftypefn
-
-## Deprecated in version 3.2
-
-function retval = spprod (varargin)
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "spprod is obsolete and will be removed from a future version of Octave; please use prod instead");
-  endif
-
-  retval = prod (varargin{:});
-
-endfunction
deleted file mode 100644
--- a/scripts/deprecated/spqr.m
+++ /dev/null
@@ -1,40 +0,0 @@
-## Copyright (C) 2008-2011 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  {Loadable Function} {@var{r} =} spqr (@var{a})
-## @deftypefnx {Loadable Function} {@var{r} =} spqr (@var{a}, 0)
-## @deftypefnx {Loadable Function} {[@var{c}, @var{r}] =} spqr (@var{a}, @var{b})
-## @deftypefnx {Loadable Function} {[@var{c}, @var{r}] =} spqr (@var{a}, @var{b}, 0)
-## This function has been deprecated.  Use @code{qr} instead.
-## @end deftypefn
-
-## Deprecated in version 3.2
-
-function varargout = spqr (varargin)
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "spqr is obsolete and will be removed from a future version of Octave; please use qr instead");
-  endif
-
-  varargout = cell (nargout, 1);
-  [ varargout{:} ] = qr (varargin{:});
-
-endfunction
deleted file mode 100644
--- a/scripts/deprecated/spsum.m
+++ /dev/null
@@ -1,36 +0,0 @@
-## Copyright (C) 2008-2011 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} {} spsum (@var{x}, @var{dim})
-## This function has been deprecated.  Use @code{sum} instead.
-## @end deftypefn
-
-## Deprecated in version 3.2
-
-function retval = spsum (varargin)
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "spsum is obsolete and will be removed from a future version of Octave; please use sum instead");
-  endif
-
-  retval = sum (varargin{:});
-
-endfunction
deleted file mode 100644
--- a/scripts/deprecated/spsumsq.m
+++ /dev/null
@@ -1,35 +0,0 @@
-## Copyright (C) 2008-2011 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} {} spsumsq (@var{x}, @var{dim})
-## This function has been deprecated.  Use @code{sumsq} instead.
-## @end deftypefn
-
-## Deprecated in version 3.2
-
-function retval = spsumsq (varargin)
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "spsumsq is obsolete and will be removed from a future version of Octave; please use sumsq instead");
-  endif
-  retval = sumsq (varargin{:});
-
-endfunction
deleted file mode 100644
--- a/scripts/deprecated/str2mat.m
+++ /dev/null
@@ -1,45 +0,0 @@
-## Copyright (C) 1996-2011 Kurt Hornik
-##
-## 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} {} str2mat (@var{s_1}, @dots{}, @var{s_n})
-## Return a matrix containing the strings @var{s_1}, @dots{}, @var{s_n} as
-## its rows.  Each string is padded with blanks in order to form a valid
-## matrix.
-##
-## This function is modelled after @sc{matlab}.  In Octave, you can create
-## a matrix of strings by @code{[@var{s_1}; @dots{}; @var{s_n}]} even if
-## the strings are not all the same length.
-## @end deftypefn
-
-## Author: Kurt Hornik <Kurt.Hornik@wu-wien.ac.at>
-## Adapted-By: jwe
-
-## Deprecated in version 3.2
-
-function retval = str2mat (varargin)
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "str2mat is obsolete and will be removed from a future version of Octave; please use char instead");
-  endif
-
-  retval = char (varargin{:});
-
-endfunction
rename from scripts/statistics/base/studentize.m
rename to scripts/deprecated/studentize.m
--- a/scripts/statistics/base/studentize.m
+++ b/scripts/deprecated/studentize.m
@@ -32,6 +32,12 @@
 ## Description: Subtract mean and divide by standard deviation
 
 function t = studentize (x, dim)
+  persistent warned = false;
+  if (! warned)
+    warned = true;
+    warning ("Octave:deprecated-function",
+             "studentize is obsolete and will be removed from a future version of Octave; please use zscore instead");
+  endif
 
   if (nargin != 1 && nargin != 2)
     print_usage ();
rename from scripts/special-matrix/sylvester_matrix.m
rename to scripts/deprecated/sylvester_matrix.m
--- a/scripts/special-matrix/sylvester_matrix.m
+++ b/scripts/deprecated/sylvester_matrix.m
@@ -33,6 +33,13 @@
 
 function retval = sylvester_matrix (k)
 
+  persistent warned = false;
+  if (! warned)
+    warned = true;
+    warning ("Octave:deprecated-function",
+             "sylvester_matrix is obsolete and will be removed from a future version of Octave; please use hadamard(2^k) instead");
+  endif
+
   if (nargin != 1)
     print_usage ();
   endif
deleted file mode 100644
--- a/scripts/deprecated/unmark_command.m
+++ /dev/null
@@ -1,38 +0,0 @@
-## Copyright (C) 2009-2011 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} {} unmark_command (@var{name})
-## This function is obsolete and will be removed from a future
-## version of Octave.
-## @end deftypefn
-
-## Author: jwe
-
-## Deprecated in version 3.2
-
-function unmark_command ()
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "unmark_command is obsolete and will be removed from a future version of Octave");
-  endif
-
-endfunction
deleted file mode 100644
--- a/scripts/deprecated/unmark_rawcommand.m
+++ /dev/null
@@ -1,38 +0,0 @@
-## Copyright (C) 2009-2011 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} {} unmark_rawcommand (@var{name})
-## This function is obsolete and will be removed from a future
-## version of Octave.
-## @end deftypefn
-
-## Author: jwe
-
-## Deprecated in version 3.2
-
-function unmark_rawcommand ()
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "unmark_rawcommand is obsolete and will be removed from a future version of Octave");
-  endif
-
-endfunction
--- a/scripts/elfun/module.mk
+++ b/scripts/elfun/module.mk
@@ -20,7 +20,6 @@
   elfun/csc.m \
   elfun/cscd.m \
   elfun/csch.m \
-  elfun/lcm.m \
   elfun/sec.m \
   elfun/secd.m \
   elfun/sech.m \
--- a/scripts/general/accumarray.m
+++ b/scripts/general/accumarray.m
@@ -72,7 +72,7 @@
   endif
 
   if (iscell (subs))
-    subs = cellfun (@vec, subs, "uniformoutput", false);
+    subs = cellfun ("vec", subs, "uniformoutput", false);
     ndims = numel (subs);
     if (ndims == 1)
       subs = subs{1};
@@ -149,7 +149,7 @@
     if (ndims > 1)
       if (isempty (sz))
         if (iscell (subs))
-          sz = cellfun (@max, subs);
+          sz = cellfun ("max", subs);
         else
           sz = max (subs, [], 1);
         endif
--- a/scripts/general/accumdim.m
+++ b/scripts/general/accumdim.m
@@ -42,12 +42,12 @@
 ##
 ## An example of the use of @code{accumdim} is:
 ##
-## @example
+## @smallexample
 ## @group
 ## accumdim ([1, 2, 1, 2, 1], [7,-10,4;-5,-12,8;-12,2,8;-10,9,-3;-5,-3,-13])
 ## @result{} ans = [-10,-11,-1;-15,-3,5]
 ## @end group
-## @end example
+## @end smallexample
 ##
 ## @seealso{accumarray}
 ## @end deftypefn
--- a/scripts/general/arrayfun.m
+++ b/scripts/general/arrayfun.m
@@ -154,7 +154,7 @@
   args = varargin(1:nargs);
   opts = varargin(nargs+1:end);
 
-  args = cellfun (@num2cell, args, "UniformOutput", false,
+  args = cellfun ("num2cell", args, "UniformOutput", false,
   "ErrorHandler",  @arg_class_error);
 
   [varargout{1:max(1, nargout)}] = cellfun (func, args{:}, opts{:});
--- a/scripts/general/bitget.m
+++ b/scripts/general/bitget.m
@@ -79,3 +79,31 @@
   C = bitand (A, bitshift (_conv (1), uint8 (n) - uint8 (1))) != _conv (0);
 
 endfunction
+
+%!error bitget (1);
+%!error bitget (1, 2, 3);
+
+%!test
+%! assert (bitget ([4, 14], [3, 3]), logical ([1, 1]));
+%! pfx = {"", "u"};
+%! for i = 1:2
+%!   for prec = [8, 16, 32, 64]
+%!     fcn = str2func (sprintf ("%sint%d", pfx{i}, prec));
+%!     assert (bitget (fcn ([4, 14]), [3, 3]), logical ([1, 1]));
+%!   endfor
+%! endfor
+
+%!error bitget (0, 0);
+%!error bitget (0, 55);
+
+%!error bitget (int8 (0), 9);
+%!error bitget (uint8 (0), 9);
+
+%!error bitget (int16 (0), 17);
+%!error bitget (uint16 (0), 17);
+
+%!error bitget (int32 (0), 33);
+%!error bitget (uint32 (0), 33);
+
+%!error bitget (int64 (0), 65);
+%!error bitget (uint64 (0), 65);
--- a/scripts/general/bitset.m
+++ b/scripts/general/bitset.m
@@ -92,3 +92,31 @@
   endif
 
 endfunction
+
+%!error bitset (1);
+%!error bitset (1, 2, 3, 4);
+
+%!test
+%! assert (bitset ([0, 10], [3, 3]), [4, 14]);
+%! pfx = {"", "u"};
+%! for i = 1:2
+%!   for prec = [8, 16, 32, 64]
+%!     fcn = str2func (sprintf ("%sint%d", pfx{i}, prec));
+%!     assert (bitset (fcn ([0, 10]), [3, 3]), fcn ([4, 14]));
+%!   endfor
+%! endfor
+
+%!error bitset (0, 0);
+%!error bitset (0, 55);
+
+%!error bitset (int8 (0), 9);
+%!error bitset (uint8 (0), 9);
+
+%!error bitset (int16 (0), 17);
+%!error bitset (uint16 (0), 17);
+
+%!error bitset (int32 (0), 33);
+%!error bitset (uint32 (0), 33);
+
+%!error bitset (int64 (0), 65);
+%!error bitset (uint64 (0), 65);
--- a/scripts/general/blkdiag.m
+++ b/scripts/general/blkdiag.m
@@ -33,7 +33,7 @@
     print_usage ();
   endif
 
-  if (! all (cellfun (@isnumeric, varargin)))
+  if (! all (cellfun ("isnumeric", varargin)))
     error ("blkdiag: all arguments must be numeric");
   endif
 
--- a/scripts/general/cell2mat.m
+++ b/scripts/general/cell2mat.m
@@ -43,11 +43,11 @@
   else
 
     ## We only want numeric, logical, and char matrices.
-    valid = cellfun (@isnumeric, c);
-    valid |= cellfun (@islogical, c);
-    valid |= cellfun (@ischar, c);
-    validc = cellfun (@iscell, c);
-    valids = cellfun (@isstruct, c);
+    valid = cellfun ("isnumeric", c);
+    valid |= cellfun ("islogical", c);
+    valid |= cellfun ("isclass", c, "char");
+    validc = cellfun ("isclass", c, "cell");
+    valids = cellfun ("isclass", c, "struct");
 
     if (! all (valid(:)) && ! all (validc(:)) && ! all (valids(:)))
       error ("cell2mat: wrong type elements or mixed cells, structs and matrices");
@@ -71,7 +71,7 @@
       endif
       xdim = [1:idim-1, idim+1:nd];
       cc = num2cell (c, xdim);
-      c = cellfun (@cat, {idim}, cc{:}, "uniformoutput", false);
+      c = cellfun ("cat", {idim}, cc{:}, "uniformoutput", false);
     endfor
     m = c{1};
   endif
--- a/scripts/general/colon.m
+++ b/scripts/general/colon.m
@@ -38,3 +38,7 @@
     error ("colon: not defined for class \"%s\"", class(varargin{1}));
   endif
 endfunction
+
+%!error colon (1)
+
+## FIXME -- what does colon () mean since it doesn't set a return value?
--- a/scripts/general/common_size.m
+++ b/scripts/general/common_size.m
@@ -52,7 +52,7 @@
   endif
 
   ## Find scalar args.
-  nscal = cellfun (@numel, varargin) != 1;
+  nscal = cellfun ("numel", varargin) != 1;
 
   i = find (nscal, 1);
 
@@ -60,7 +60,7 @@
     errorcode = 0;
     varargout = varargin;
   else
-    match = cellfun (@size_equal, varargin, varargin(i));
+    match = cellfun ("size_equal", varargin, varargin(i));
     if (any (nscal &! match))
       errorcode = 1;
       varargout = varargin;
@@ -78,3 +78,13 @@
     endif
   endif
 endfunction
+
+%!error common_size ();
+
+%!test
+%! m = [1,2;3,4];
+%! [err, a, b, c] = common_size (m, 3, 5);
+%! assert (err, 0);
+%! assert (a, m);
+%! assert (b, [3,3;3,3]);
+%! assert (c, [5,5;5,5]);
--- a/scripts/general/dblquad.m
+++ b/scripts/general/dblquad.m
@@ -37,22 +37,23 @@
 ##
 ## The optional argument @var{quadf} specifies which underlying integrator
 ## function to use.  Any choice but @code{quad} is available and the default
-## is @code{quadgk}.
+## is @code{quadcc}.
 ##
 ## Additional arguments, are passed directly to @var{f}.  To use the default
-## value for @var{tol} or @var{quadf} one may pass an empty matrix ([]).
+## value for @var{tol} or @var{quadf} one may pass ':' or an empty matrix ([]).
 ## @seealso{triplequad, quad, quadv, quadl, quadgk, quadcc, trapz}
 ## @end deftypefn
 
-function q = dblquad(f, xa, xb, ya, yb, tol, quadf, varargin)
+function q = dblquad (f, xa, xb, ya, yb, tol = 1e-6, quadf = @quadcc, varargin)
+
   if (nargin < 5)
     print_usage ();
   endif
-  if (nargin < 6 || isempty (tol))
+  if (isempty (tol))
     tol = 1e-6;
   endif
-  if (nargin < 7 || isempty (quadf))
-    quadf = @quadgk;
+  if (isempty (quadf))
+    quadf = @quadcc;
   endif
 
   inner = @__dblquad_inner__;
@@ -72,10 +73,10 @@
   endfor
 endfunction
 
-%% Nasty integrand to show quadgk off
+%% Nasty integrand to show quadcc off
 %!assert (dblquad (@(x,y) 1 ./ (x+y), 0, 1, 0, 1), 2*log(2), 1e-6)
 
-%!assert (dblquad (@(x,y) exp(-x.^2 - y.^2) , -1, 1, -1, 1, [],  @quadgk), pi * erf(1).^2, 1e-6)
-%!assert (dblquad (@(x,y) exp(-x.^2 - y.^2) , -1, 1, -1, 1, [],  @quadl), pi * erf(1).^2, 1e-6)
-%!assert (dblquad (@(x,y) exp(-x.^2 - y.^2) , -1, 1, -1, 1, [],  @quadv), pi * erf(1).^2, 1e-6)
+%!assert (dblquad (@(x,y) exp(-x.^2 - y.^2) , -1, 1, -1, 1, 1e-6, @quadgk), pi * erf(1).^2, 1e-6)
+%!assert (dblquad (@(x,y) exp(-x.^2 - y.^2) , -1, 1, -1, 1, 1e-6, @quadl), pi * erf(1).^2, 1e-6)
+%!assert (dblquad (@(x,y) exp(-x.^2 - y.^2) , -1, 1, -1, 1, 1e-6, @quadv), pi * erf(1).^2, 1e-6)
 
--- a/scripts/general/flipdim.m
+++ b/scripts/general/flipdim.m
@@ -43,9 +43,10 @@
   endif
 
   nd = ndims (x);
+  sz = size (x);
   if (nargin == 1)
     ## Find the first non-singleton dimension.
-    [~, dim] = min (size (x) != 1);
+    (dim = find (sz > 1, 1)) || (dim = 1);
   elseif (! (isscalar (dim) && isindex (dim)))
     error ("flipdim: DIM must be a positive integer");
   endif
@@ -55,3 +56,12 @@
   y = x(idx{:});
 
 endfunction
+
+%!error flipdim ();
+%!error flipdim (1, 2, 3);
+
+%!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]);
+
+## FIXME -- we need tests for multidimensional arrays.
--- a/scripts/general/int2str.m
+++ b/scripts/general/int2str.m
@@ -49,31 +49,33 @@
 
 function retval = int2str (n)
 
-  if (nargin == 1)
-    n = round (real(n));
-    sz = size(n);
-    nd = ndims (n);
-    nc = columns (n);
-    if (nc > 1)
-      idx = cell ();
-      for i = 1:nd
-        idx{i} = 1:sz(i);
-      endfor
-      idx(2) = 1;
-      ifmt = get_fmt (n(idx{:}), 0);
-      idx(2) = 2:sz(2);
-      rfmt = get_fmt (n(idx{:}), 2);
-      fmt = cstrcat (ifmt, repmat (rfmt, 1, nc-1), "\n");
-    else
-      fmt = cstrcat (get_fmt (n, 0), "\n");
-    endif
-    tmp = sprintf (fmt, permute (n, [2, 1, 3 : nd]));
-    tmp(end) = "";
-    retval = char (strsplit (tmp, "\n"));
-  else
+  if (nargin != 1)
     print_usage ();
   endif
 
+  if (isempty (n))
+    retval = '';
+    return;
+  endif
+
+  n = round (real(n));
+  sz = size(n);
+  nd = ndims (n);
+  nc = columns (n);
+  if (nc > 1)
+    idx = repmat ({':'}, nd, 1);
+    idx(2) = 1;
+    ifmt = get_fmt (n(idx{:}), 0);
+    idx(2) = 2:sz(2);
+    rfmt = get_fmt (n(idx{:}), 2);
+    fmt = cstrcat (ifmt, repmat (rfmt, 1, nc-1), "\n");
+  else
+    fmt = cstrcat (get_fmt (n, 0), "\n");
+  endif
+  tmp = sprintf (fmt, permute (n, [2, 1, 3 : nd]));
+  tmp(end) = "";
+  retval = char (strsplit (tmp, "\n"));
+
 endfunction
 
 function fmt = get_fmt (x, sep)
@@ -112,8 +114,10 @@
 
 endfunction
 
-%!assert(strcmp (int2str (-123), "-123") && strcmp (int2str (1.2), "1"));
+%!assert (strcmp (int2str (-123), "-123") && strcmp (int2str (1.2), "1"));
 %!assert (all (int2str ([1, 2, 3; 4, 5, 6]) == ["1  2  3";"4  5  6"]));
+%!assert (int2str([]), "");
+
 %!error int2str ();
 %!error int2str (1, 2);
 
--- a/scripts/general/interp1.m
+++ b/scripts/general/interp1.m
@@ -43,7 +43,7 @@
 ## Piecewise cubic Hermite interpolating polynomial
 ##
 ## @item 'cubic'
-## Cubic interpolation from four nearest neighbors
+## Cubic interpolation (same as @code{pchip})
 ##
 ## @item 'spline'
 ## Cubic spline interpolation---smooth first and second derivatives
@@ -112,7 +112,7 @@
   method = "linear";
   extrap = NA;
   xi = [];
-  pp = false;
+  ispp = false;
   firstnumeric = true;
 
   if (nargin > 2)
@@ -123,7 +123,7 @@
         if (strcmp ("extrap", arg))
           extrap = "extrap";
         elseif (strcmp ("pp", arg))
-          pp = true;
+          ispp = true;
         else
           method = arg;
         endif
@@ -138,7 +138,7 @@
     endfor
   endif
 
-  if (isempty (xi) && firstnumeric && ! pp)
+  if (isempty (xi) && firstnumeric && ! ispp)
     xi = y;
     y = x;
     x = 1:numel(y);
@@ -150,9 +150,8 @@
   szx = size (xi);
   if (isvector (y))
     y = y(:);
-  elseif (isvector (xi))
-    szx = length (xi);
   endif
+  
   szy = size (y);
   y = y(:,:);
   [ny, nc] = size (y);
@@ -191,147 +190,85 @@
 
   switch (method)
   case "nearest"
-    if (pp)
-      yi = mkpp ([x(1); (x(1:nx-1)+x(2:nx))/2; x(nx)], y, szy(2:end));
+    pp = mkpp ([x(1); (x(1:nx-1)+x(2:nx))/2; x(nx)], shiftdim (y, 1), szy(2:end));
+    pp.orient = "first";
+    
+    if (ispp)
+      yi = pp;
     else
-      idx = lookup (0.5*(x(1:nx-1)+x(2:nx)), xi) + 1;
-      yi = y(idx,:);
+      yi = ppval (pp, reshape (xi, szx));
     endif
   case "*nearest"
-    if (pp)
-      yi = mkpp ([x(1); x(1)+[0.5:(nx-1)]'*dx; x(nx)], y, szy(2:end));
+    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
-      idx = max (1, min (ny, floor((xi-x(1))/dx+1.5)));
-      yi = y(idx,:);
+      yi = ppval(pp, reshape (xi, szx));
     endif
   case "linear"
     dy = diff (y);
-    dx = diff (x);
-    if (pp)
-      coefs = [dy./dx, y(1:nx-1)];
-      xx = x;
-      if (have_jumps)
-        ## Omit zero-size intervals.
-        coefs(jumps) = [];
-        xx(jumps) = [];
-      endif
-      yi = mkpp (xx, coefs, szy(2:end));
+    dx = diff (x);    
+    dx = repmat (dx, [1 size(dy)(2:end)]);
+    coefs = [(dy./dx).'(:), y(1:nx-1, :).'(:)];
+    xx = x;
+
+    if (have_jumps)
+      ## Omit zero-size intervals.
+      coefs(jumps, :) = [];
+      xx(jumps) = [];
+    endif
+
+    pp = mkpp (xx, coefs, szy(2:end));
+    pp.orient = "first";
+
+    if (ispp)
+      yi = pp;
     else
-      ## find the interval containing the test point
-      idx = lookup (x, xi, "lr");
-      ## use the endpoints of the interval to define a line
-      s = (xi - x(idx))./dx(idx);
-      yi = bsxfun (@times, s, dy(idx,:)) + y(idx,:);
-      if (have_jumps)
-        ## Fix the corner cases of discontinuities at boundaries.
-        ## Internal discontinuities already handled correctly.
-        if (jumps (1))
-          mask = xi < x(1);
-          yi(mask,:) = y(1*ones (1, sum (mask)),:);
-        endif
-        if (jumps(nx-1))
-          mask = xi >= x(nx);
-          yi(mask,:) = y(nx*ones (1, sum (mask)),:);
-        endif
-      endif
+      yi = ppval(pp, reshape (xi, szx));
     endif
+
   case "*linear"
     dy = diff (y);
-    if (pp)
-      yi = mkpp (x(1) + [0:ny-1]*dx, [dy./dx, y(1:end-1)], szy(2:end));
+    coefs = [(dy/dx).'(:), y(1:nx-1, :).'(:)];
+    pp = mkpp (x, coefs, szy(2:end));
+    pp.orient = "first";
+
+    if (ispp)
+      yi = pp;
     else
-      ## find the interval containing the test point
-      t = (xi - x(1))/dx + 1;
-      idx = max (1, min (ny - 1, floor (t)));
+      yi = ppval(pp, reshape (xi, szx));
+    endif
 
-      ## use the endpoints of the interval to define a line
-      s = t - idx;
-      yi = bsxfun (@times, s, dy(idx,:)) + y(idx,:);
-    endif
-  case {"pchip", "*pchip"}
+  case {"pchip", "*pchip", "cubic", "*cubic"}
     if (nx == 2 || starmethod)
       x = linspace (x(1), x(nx), ny);
     endif
-    ## Note that pchip's arguments are transposed relative to interp1
-    if (pp)
-      yi = pchip (x.', y.');
-      yi.d = szy(2:end);
-    else
-      yi = pchip (x.', y.', xi.').';
-    endif
-
-  case {"cubic", "*cubic"}
-    if (nx < 4 || ny < 4)
-      error ("interp1: table too short");
-    endif
-
-    ## FIXME Is there a better way to treat pp return and *cubic
-    if (starmethod && ! pp)
-      ## From: Miloje Makivic
-      ## http://www.npac.syr.edu/projects/nasa/MILOJE/final/node36.html
-      t = (xi - x(1))/dx + 1;
-      idx = max (min (floor (t), ny-2), 2);
-      t = t - idx;
-      t2 = t.*t;
-      tp = 1 - 0.5*t;
-      a = (1 - t2).*tp;
-      b = (t2 + t).*tp;
-      c = (t2 - t).*tp/3;
-      d = (t2 - 1).*t/6;
-      J = ones (1, nc);
-
-      yi = a(:,J) .* y(idx,:) + b(:,J) .* y(idx+1,:) ...
-      + c(:,J) .* y(idx-1,:) + d(:,J) .* y(idx+2,:);
+    
+    if (ispp)
+      y = shiftdim (reshape (y, szy), 1);
+      yi = pchip (x, y);
     else
-      if (starmethod)
-        x = linspace (x(1), x(nx), ny).';
-        nx = ny;
-      endif
-
-      idx = lookup (x(2:nx-1), xi, "lr");
-
-      ## Construct cubic equations for each interval using divided
-      ## differences (computation of c and d don't use divided differences
-      ## but instead solve 2 equations for 2 unknowns). Perhaps
-      ## reformulating this as a lagrange polynomial would be more efficient.
-      i = 1:nx-3;
-      J = ones (1, nc);
-      dx = diff (x);
-      dx2 = x(i+1).^2 - x(i).^2;
-      dx3 = x(i+1).^3 - x(i).^3;
-      a = diff (y, 3)./dx(i,J).^3/6;
-      b = (diff (y(1:nx-1,:), 2)./dx(i,J).^2 - 6*a.*x(i+1,J))/2;
-      c = (diff (y(1:nx-2,:), 1) - a.*dx3(:,J) - b.*dx2(:,J))./dx(i,J);
-      d = y(i,:) - ((a.*x(i,J) + b).*x(i,J) + c).*x(i,J);
-
-      if (pp)
-        xs = [x(1);x(3:nx-2)];
-        yi = mkpp ([x(1);x(3:nx-2);x(nx)],
-                   [a(:), (b(:) + 3.*xs(:,J).*a(:)), ...
-                    (c(:) + 2.*xs(:,J).*b(:) + 3.*xs(:,J)(:).^2.*a(:)), ...
-                    (d(:) + xs(:,J).*c(:) + xs(:,J).^2.*b(:) + ...
-                     xs(:,J).^3.*a(:))], szy(2:end));
-      else
-        yi = ((a(idx,:).*xi(:,J) + b(idx,:)).*xi(:,J) ...
-              + c(idx,:)).*xi(:,J) + d(idx,:);
-      endif
+      y = shiftdim (y, 1);
+      yi = pchip (x, y, reshape (xi, szx));
     endif
   case {"spline", "*spline"}
     if (nx == 2 || starmethod)
       x = linspace(x(1), x(nx), ny);
     endif
-    ## Note that spline's arguments are transposed relative to interp1
-    if (pp)
-      yi = spline (x.', y.');
-      yi.d = szy(2:end);
+    
+    if (ispp)
+      y = shiftdim (reshape (y, szy), 1);
+      yi = spline (x, y);
     else
-      yi = spline (x.', y.', xi.').';
+      y = shiftdim (y, 1);
+      yi = spline (x, y, reshape (xi, szx));
     endif
   otherwise
     error ("interp1: invalid method '%s'", method);
   endswitch
 
-  if (! pp)
+  if (! ispp)
     if (! ischar (extrap))
       ## determine which values are out of range and set them to extrap,
       ## unless extrap == "extrap".
@@ -339,10 +276,24 @@
       maxx = max (x(1), x(nx));
 
       outliers = xi < minx | ! (xi <= maxx); # this catches even NaNs
-      yi(outliers, :) = extrap;
+      if (size_equal (outliers, yi))
+        yi(outliers) = extrap;
+        yi = reshape (yi, szx);
+      elseif (!isvector (yi))
+        if (strcmp (method, "pchip") || strcmp (method, "*pchip")
+          ||strcmp (method, "cubic") || strcmp (method, "*cubic")
+          ||strcmp (method, "spline") || strcmp (method, "*spline"))
+          yi(:, outliers) = extrap;
+          yi = shiftdim(yi, 1);
+        else
+          yi(outliers, :) = extrap;
+        endif
+      else
+        yi(outliers.') = extrap;
+      endif
     endif
-
-    yi = reshape (yi, [szx, szy(2:end)]);
+  else
+    yi.orient = "first";
   endif
 
 endfunction
@@ -394,6 +345,7 @@
 %! %--------------------------------------------------------
 %! % confirm that interpolated function matches the original
 
+##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
@@ -595,7 +547,6 @@
 %!assert (interp1(1:2,1:2,1.4,"nearest"),1);
 %!error interp1(1,1,1, "linear");
 %!assert (interp1(1:2,1:2,1.4,"linear"),1.4);
-%!error interp1(1:3,1:3,1, "cubic");
 %!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);
@@ -604,7 +555,6 @@
 %!assert (interp1(1:2:4,1:2:4,1.4,"*nearest"),1);
 %!error interp1(1,1,1, "*linear");
 %!assert (interp1(1:2:4,1:2:4,[0,1,1.4,3,4],"*linear"),[NA,1,1.4,3,NA]);
-%!error interp1(1:3,1:3,1, "*cubic");
 %!assert (interp1(1:2:8,1:2:8,1.4,"*cubic"),1.4);
 %!assert (interp1(1:2,1:2,1.3, "*spline"), 1.3);
 %!assert (interp1(1:2:6,1:2:6,1.4,"*spline"),1.4);
@@ -612,5 +562,5 @@
 %!assert (interp1([3,2,1],[3,2,2],2.5),2.5)
 
 %!assert (interp1 ([1,2,2,3,4],[0,1,4,2,1],[-1,1.5,2,2.5,3.5], "linear", "extrap"), [-2,0.5,4,3,1.5])
-%!assert (interp1 ([4,4,3,2,0],[0,1,4,2,1],[1.5,4,4.5], "linear"), [0,1,NA])
+%!assert (interp1 ([4,4,3,2,0],[0,1,4,2,1],[1.5,4,4.5], "linear"), [1.75,1,NA])
 %!assert (interp1 (0:4, 2.5), 1.5)
--- a/scripts/general/interp3.m
+++ b/scripts/general/interp3.m
@@ -92,7 +92,7 @@
       error ("interp3: expect 3-dimensional array of values");
     endif
     x = varargin (2:4);
-    if (any (! cellfun (@isvector, x)))
+    if (any (! cellfun ("isvector", x)))
       for i = 2 : 3
         if (! size_equal (x{1}, x{i}))
           error ("interp3: dimensional mismatch");
@@ -109,7 +109,7 @@
       error ("interp3: expect 3-dimensional array of values");
     endif
     x = varargin (1:3);
-    if (any (! cellfun (@isvector, x)))
+    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");
@@ -119,7 +119,7 @@
       x{1} = permute (x{1}, [2, 1, 3]);
     endif
     y = varargin (5:7);
-    if (any (! cellfun (@isvector, y)))
+    if (any (! cellfun ("isvector", y)))
       for i = 2 : 3
         if (! size_equal (y{1}, y{i}))
           error ("interp3: dimensional mismatch");
--- a/scripts/general/interpft.m
+++ b/scripts/general/interpft.m
@@ -76,10 +76,8 @@
   k = floor (m / 2);
   sz = size (x);
   sz(1) = n * inc - m;
-  idx = cell (nd, 1);
-  for i = 2:nd
-    idx{i} = 1:sz(i);
-  endfor
+
+  idx = repmat ({':'}, nd, 1);
   idx{1} = 1:k;
   z = cat (1, y(idx{:}), zeros (sz));
   idx{1} = k+1:m;
--- a/scripts/general/interpn.m
+++ b/scripts/general/interpn.m
@@ -124,7 +124,7 @@
     error ("interpn: wrong number or incorrectly formatted input arguments");
   endif
 
-  if (any (! cellfun (@isvector, x)))
+  if (any (! cellfun ("isvector", x)))
     for i = 2 : nd
       if (! size_equal (x{1}, x{i}) || ! size_equal (x{i}, v))
         error ("interpn: dimensional mismatch");
@@ -140,8 +140,8 @@
 
   method = tolower (method);
 
-  all_vectors = all (cellfun (@isvector, y));
-  different_lengths = numel (unique (cellfun (@numel, y))) > 1;
+  all_vectors = all (cellfun ("isvector", y));
+  different_lengths = numel (unique (cellfun ("numel", y))) > 1;
   if (all_vectors && different_lengths)
     [foobar(1:numel(y)).y] = ndgrid (y{:});
     y = {foobar.y};
@@ -169,7 +169,7 @@
     vi(idx) = extrapval;
     vi = reshape (vi, yshape);
   elseif (strcmp (method, "spline"))
-    if (any (! cellfun (@isvector, y)))
+    if (any (! cellfun ("isvector", y)))
       for i = 2 : nd
         if (! size_equal (y{1}, y{i}))
           error ("interpn: dimensional mismatch");
--- a/scripts/general/isa.m
+++ b/scripts/general/isa.m
@@ -75,3 +75,22 @@
 %!assert (isa (uint16 (13), "numeric"), true)
 %!assert (isa (uint32 (13), "numeric"), true)
 %!assert (isa (uint64 (13), "numeric"), true)
+
+%!assert (isa (double (13), "double"));
+%!assert (isa (single (13), "single"));
+%!assert (isa (int8 (13), "int8"));
+%!assert (isa (int16 (13), "int16"));
+%!assert (isa (int32 (13), "int32"));
+%!assert (isa (int64 (13), "int64"));
+%!assert (isa (uint8 (13), "uint8"));
+%!assert (isa (uint16 (13), "uint16"));
+%!assert (isa (uint32 (13), "uint32"));
+%!assert (isa (uint64 (13), "uint64"));
+%!assert (isa ("string", "char"));
+%!assert (isa (true, "logical"));
+%!assert (isa (false, "logical"));
+%!assert (isa ({1, 2}, "cell"));
+%!test
+%! a.b = 1;
+%! assert (isa (a, "struct"));
+
--- a/scripts/general/iscolumn.m
+++ b/scripts/general/iscolumn.m
@@ -26,8 +26,6 @@
 
 function retval = iscolumn (x)
 
-  retval = false;
-
   if (nargin != 1)
     print_usage ();
   endif
--- a/scripts/general/isdir.m
+++ b/scripts/general/isdir.m
@@ -23,10 +23,17 @@
 ## @end deftypefn
 
 function retval = isdir (f)
-  if (nargin == 1)
-    ## Exist returns an integer but isdir should return a logical.
-    retval = (exist (f, "dir") == 7);
-  else
+  if (nargin != 1)
     print_usage ("isdir");
   endif
+
+  ## Exist returns an integer but isdir should return a logical.
+  retval = (exist (f, "dir") == 7);
+
 endfunction
+
+%!error isdir ();
+%!error isdir (1, 2);
+
+%!assert (isdir (pwd ()));
+%!assert (! isdir ("this is highly unlikely to be a directory name"));
--- a/scripts/general/isequal.m
+++ b/scripts/general/isequal.m
@@ -24,12 +24,12 @@
 
 function retval = isequal (x1, varargin)
 
-  if (nargin > 1)
-    retval = __isequal__ (false, x1, varargin{:});
-  else
+  if (nargin < 2)
     print_usage ();
   endif
 
+  retval = __isequal__ (false, x1, varargin{:});
+
 endfunction
 
 ## test size and shape
--- a/scripts/general/isequalwithequalnans.m
+++ b/scripts/general/isequalwithequalnans.m
@@ -25,12 +25,12 @@
 
 function retval = isequalwithequalnans (x1, varargin)
 
-  if (nargin > 1)
-    retval = __isequal__ (true, x1, varargin{:});
-  else
+  if (nargin < 2)
     print_usage ();
   endif
 
+  retval = __isequal__ (true, x1, varargin{:});
+
 endfunction
 
 ## test for equality
--- a/scripts/general/isrow.m
+++ b/scripts/general/isrow.m
@@ -26,8 +26,6 @@
 
 function retval = isrow (x)
 
-  retval = false;
-
   if (nargin != 1)
     print_usage ();
   endif
--- a/scripts/general/isscalar.m
+++ b/scripts/general/isscalar.m
@@ -26,12 +26,12 @@
 
 function retval = isscalar (x)
 
-  if (nargin == 1)
-    retval = numel (x) == 1;
-  else
+  if (nargin != 1)
     print_usage ();
   endif
 
+  retval = numel (x) == 1;
+
 endfunction
 
 %!assert(isscalar (1));
--- a/scripts/general/issquare.m
+++ b/scripts/general/issquare.m
@@ -28,42 +28,35 @@
 
 function retval = issquare (x)
 
-  if (nargin == 1)
-    if (ndims (x) == 2)
-      [r, c] = size (x);
-      retval = r == c;
-    else
-      retval = false;
-    endif
+  if (nargin != 1)
+    print_usage ();
+  endif
+
+  if (ndims (x) == 2)
+    [r, c] = size (x);
+    retval = r == c;
   else
-    print_usage ();
+    retval = false;
   endif
 
 endfunction
 
+%!assert(issquare ([]));
 %!assert(issquare (1));
-
 %!assert(!(issquare ([1, 2])));
-
-%!assert(issquare ([]));
-
 %!assert(issquare ([1, 2; 3, 4]));
-
-%!test
-%! assert(issquare ("t"));
-
+%!assert(!(issquare ([1, 2; 3, 4; 5, 6])));
+%!assert(!(issquare (ones (3,3,3))));
+%!assert(issquare ("t"));
 %!assert(!(issquare ("test")));
-
-%!test
-%! assert(issquare (["test"; "ing"; "1"; "2"]));
-
+%!assert(issquare (["test"; "ing"; "1"; "2"]));
 %!test
 %! s.a = 1;
 %! assert(issquare (s));
-
-%!assert(!(issquare ([1, 2; 3, 4; 5, 6])));
+%!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
+++ b/scripts/general/isvector.m
@@ -28,15 +28,13 @@
 
 function retval = isvector (x)
 
-  retval = 0;
-
-  if (nargin == 1)
-    sz = size (x);
-    retval = (ndims (x) == 2 && (sz(1) == 1 || sz(2) == 1));
-  else
+  if (nargin != 1)
     print_usage ();
   endif
 
+  sz = size (x);
+  retval = (ndims (x) == 2 && (sz(1) == 1 || sz(2) == 1));
+
 endfunction
 
 %!assert(isvector (1));
--- a/scripts/general/module.mk
+++ b/scripts/general/module.mk
@@ -61,6 +61,8 @@
   general/polyarea.m \
   general/postpad.m \
   general/prepad.m \
+  general/profile.m \
+  general/profshow.m \
   general/quadgk.m \
   general/quadl.m \
   general/quadv.m \
--- a/scripts/general/nargchk.m
+++ b/scripts/general/nargchk.m
@@ -30,16 +30,14 @@
 
 ## Author: Bill Denney <bill@denney.ws>
 
-function msg = nargchk (minargs, maxargs, nargs, outtype)
+function msg = nargchk (minargs, maxargs, nargs, outtype = "string")
 
   if (nargin < 3 || nargin > 4)
     print_usage ();
   elseif (minargs > maxargs)
     error ("nargchk: MINARGS must be <= MAXARGS");
-  elseif (nargin == 3)
-    outtype = "string";
   elseif (! any (strcmpi (outtype, {"string", "struct"})))
-    error ("nargchk: output type must be either string or struct");
+    error ('nargchk: output type must be either "string" or "struct"');
   elseif (! (isscalar (minargs) && isscalar (maxargs) && isscalar (nargs)))
     error ("nargchk: MINARGS, MAXARGS, and NARGS must be scalars");
   endif
@@ -56,13 +54,16 @@
   if (strcmpi (outtype, "string"))
     msg = msg.message;
   elseif (isempty (msg.message))
-    msg = struct ([]);
+    ## Compatability: Matlab returns a 0x1 empty struct when nargchk passes
+    msg = resize (msg, 0, 1);
   endif
 
 endfunction
 
+
 ## Tests
-%!shared stmin, stmax
+%!shared stnul, stmin, stmax
+%!  stnul = resize (struct ("message", "", "identifier", ""), 0, 1);
 %!  stmin = struct ("message", "not enough input arguments",
 %!                  "identifier", "Octave:nargchk:not-enough-inputs");
 %!  stmax = struct ("message", "too many input arguments",
@@ -73,7 +74,7 @@
 %!assert (nargchk (0, 1, 2), "too many input arguments")
 %!assert (nargchk (0, 1, 2, "string"), "too many input arguments")
 ## Struct outputs
-%!assert (nargchk (0, 1, 0, "struct"), struct([]))
-%!assert (nargchk (0, 1, 1, "struct"), struct([]))
+%!assert (isequal (nargchk (0, 1, 0, "struct"), stnul))
+%!assert (isequal (nargchk (0, 1, 1, "struct"), stnul))
 %!assert (nargchk (1, 1, 0, "struct"), stmin)
 %!assert (nargchk (0, 1, 2, "struct"), stmax)
--- a/scripts/general/nargoutchk.m
+++ b/scripts/general/nargoutchk.m
@@ -55,19 +55,17 @@
 
   if (strcmpi (outtype, "string"))
     msg = msg.message;
-  else
-    if (isempty (msg.message))
-      msg = struct ([]);
-    endif
-    ## FIXME: remove the error below if error is modified to accept
-    ## struct inputs
-    error ("nargoutchk: error does not yet support struct inputs");
+  elseif (isempty (msg.message))
+    ## Compatability: Matlab returns a 0x1 empty struct when nargchk passes
+    msg = resize (msg, 0, 1);
   endif
 
 endfunction
 
+
 ## Tests
-%!shared stmin, stmax
+%!shared stnul, stmin, stmax
+%!  stnul = resize (struct ("message", "", "identifier", ""), 0, 1);
 %!  stmin = struct ("message", "not enough output arguments",
 %!                  "identifier", "Octave:nargoutchk:not-enough-outputs");
 %!  stmax = struct ("message", "too many output arguments",
@@ -78,7 +76,8 @@
 %!assert (nargoutchk (0, 1, 2), "too many output arguments")
 %!assert (nargoutchk (0, 1, 2, "string"), "too many output arguments")
 ## Struct outputs
-#%!assert (nargoutchk (0, 1, 0, "struct"), struct([]))
-#%!assert (nargoutchk (0, 1, 1, "struct"), struct([]))
-#%!assert (nargoutchk (1, 1, 0, "struct"), stmin)
-#%!assert (nargoutchk (0, 1, 2, "struct"), stmax)
+%!assert (isequal (nargoutchk (0, 1, 0, "struct"), stnul))
+%!assert (isequal (nargoutchk (0, 1, 1, "struct"), stnul))
+%!assert (nargoutchk (1, 1, 0, "struct"), stmin)
+%!assert (nargoutchk (0, 1, 2, "struct"), stmax)
+
--- a/scripts/general/nextpow2.m
+++ b/scripts/general/nextpow2.m
@@ -55,3 +55,14 @@
   endif
 
 endfunction
+
+%!error nexpow2 ();
+%!error nexpow2 (1, 2);
+
+%!assert (nextpow2 (16), 4);
+%!assert (nextpow2 (17), 5);
+%!assert (nextpow2 (31), 5);
+%!assert (nextpow2 (-16), 4);
+%!assert (nextpow2 (-17), 5);
+%!assert (nextpow2 (-31), 5);
+%!assert (nextpow2 (1:17), 5);
--- a/scripts/general/num2str.m
+++ b/scripts/general/num2str.m
@@ -111,10 +111,7 @@
     nd = ndims (x);
     perm = fix ([1:0.5:nc+0.5]);
     perm(2:2:2*nc) = perm(2:2:2*nc) + nc;
-    idx = cell ();
-    for i = 1:nd
-      idx{i} = 1:sz(i);
-    endfor
+    idx = repmat ({':'}, nd, 1);
     idx{2} = perm;
     x = horzcat (real (x), imag (x));
     x = x(idx{:});
--- a/scripts/general/postpad.m
+++ b/scripts/general/postpad.m
@@ -53,11 +53,8 @@
   nd = ndims (x);
   sz = size (x);
   if (nargin < 4)
-    ## Find the first non-singleton dimension
-    dim = find (sz > 1, 1);
-    if (isempty (dim))
-      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))
@@ -76,10 +73,7 @@
   d = sz (dim);
 
   if (d >= l)
-    idx = cell ();
-    for i = 1:nd
-      idx{i} = 1:sz(i);
-    endfor
+    idx = repmat ({':'}, nd, 1);
     idx{dim} = 1:l;
     y = x(idx{:});
   else
@@ -88,3 +82,16 @@
   endif
 
 endfunction
+
+%!error postpad ();
+%!error postpad (1);
+%!error postpad (1,2,3,4,5);
+%!error postpad ([1,2], 2, 2,3);
+
+%!assert (postpad ([1,2], 4), [1,2,0,0]);
+%!assert (postpad ([1;2], 4), [1;2;0;0]);
+
+%!assert (postpad ([1,2], 4, 2), [1,2,2,2]);
+%!assert (postpad ([1;2], 4, 2), [1;2;2;2]);
+
+%!assert (postpad ([1,2], 2, 2, 1), [1,2;2,2]);
--- a/scripts/general/prepad.m
+++ b/scripts/general/prepad.m
@@ -53,11 +53,8 @@
   nd = ndims (x);
   sz = size (x);
   if (nargin < 4)
-    ## Find the first non-singleton dimension
-    dim = find (sz > 1, 1);
-    if (isempty (dim))
-      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))
@@ -76,10 +73,7 @@
   d = sz (dim);
 
   if (d >= l)
-    idx = cell ();
-    for i = 1:nd
-      idx{i} = 1:sz(i);
-    endfor
+    idx = repmat ({':'}, nd, 1);
     idx{dim} = d-l+1:d;
     y = x(idx{:});
   else
@@ -88,3 +82,18 @@
   endif
 
 endfunction
+
+%!error prepad ();
+%!error prepad (1);
+%!error prepad (1,2,3,4,5);
+%!error prepad ([1,2], 2, 2,3);
+
+%!assert (prepad ([1,2], 4), [0,0,1,2]);
+%!assert (prepad ([1;2], 4), [0;0;1;2]);
+
+%!assert (prepad ([1,2], 4, 2), [2,2,1,2]);
+%!assert (prepad ([1;2], 4, 2), [2;2;1;2]);
+
+%!assert (prepad ([1,2], 2, 2, 1), [2,2;1,2]);
+
+## FIXME -- we need tests for multidimensional arrays.
--- a/scripts/general/private/__isequal__.m
+++ b/scripts/general/private/__isequal__.m
@@ -59,16 +59,16 @@
   ## All arguments must either be of the same class or they must be
   ## numeric values.
   t = (all (strcmp (class(x),
-                    cellfun (@class, varargin, "uniformoutput", false)))
+                    cellfun ("class", varargin, "uniformoutput", false)))
        || ((isnumeric (x) || islogical (x))
-           && all (cellfun (@isnumeric, varargin)
-                   | cellfun (@islogical, varargin))));
+           && all (cellfun ("isnumeric", varargin)
+                   | cellfun ("islogical", 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 (length (s_x) == cellfun ("length", s_v));
   endif
 
   if (t)
@@ -96,8 +96,8 @@
       ## Test the number of fields.
       fn_x = fieldnames (x);
       l_fn_x = length (fn_x);
-      fn_v = cellfun (@fieldnames, varargin, "uniformoutput", false);
-      t = all (l_fn_x == cellfun (@length, fn_v));
+      fn_v = cellfun ("fieldnames", varargin, "uniformoutput", false);
+      t = all (l_fn_x == cellfun ("length", fn_v));
 
       ## Test that all the names are equal.
       idx = 0;
@@ -146,7 +146,7 @@
     elseif (isa (x, "function_handle"))
 
       ## The == operator is overloaded for handles.
-      t = all (cellfun (@eq, {x}, varargin));
+      t = all (cellfun ("eq", {x}, varargin));
 
     else
       ## Check the numeric types.
new file mode 100644
--- /dev/null
+++ b/scripts/general/profile.m
@@ -0,0 +1,115 @@
+## Copyright (C) 2011 Daniel Kraft
+##
+## 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} {} profile on
+## @deftypefnx {Function File} {} profile off
+## @deftypefnx {Function File} {} profile resume
+## @deftypefnx {Function File} {} profile clear
+## @deftypefnx {Function File} {@var{S} =} profile ('status')
+## @deftypefnx {Function File} {@var{T} =} profile ('info')
+## Control the built-in profiler.
+##
+## @table @code
+## @item profile on
+## Start the profiler, clearing all previously collected data if there
+## is any.
+##
+## @item profile off
+## Stop profiling.  The collected data can later be retrieved and examined
+## with calls like @code{S = profile ('info')}.
+##
+## @item profile clear
+## Clear all collected profiler data.
+##
+## @item profile resume
+## Restart profiling without cleaning up the old data and instead
+## all newly collected statistics are added to the already existing ones.
+##
+## @item @var{S} = profile ('status')
+## Return a structure filled with certain information about the current status
+## of the profiler.  At the moment, the only field is @code{ProfilerStatus}
+## which is either 'on' or 'off'.
+##
+## @item @var{T} = profile ('info')
+## Return the collected profiling statistics in the structure @var{T}.
+## The flat profile is returned in the field @code{FunctionTable} which is an
+## array of structures, each entry corresponding to a function which was called
+## and for which profiling statistics are present.  Furthermore, the field
+## @code{Hierarchical} contains the hierarchical call-tree.  Each node
+## has an index into the @code{FunctionTable} identifying the function it
+## corresponds to as well as data fields for number of calls and time spent
+## at this level in the call-tree.
+## @end table
+## @end deftypefn
+
+## Built-in profiler.
+## Author: Daniel Kraft <d@domob.eu>
+
+function retval = profile (option)
+
+  if (nargin != 1)
+    print_usage ();
+  endif
+
+  switch (option)
+    case 'on'
+      __profiler_reset__ ();
+      __profiler_enable__ (true);
+
+    case 'off'
+      __profiler_enable__ (false);
+
+    case 'clear'
+      __profiler_reset__ ();
+
+    case 'resume'
+      __profiler_enable__ (true);
+
+    case 'status'
+      enabled = __profiler_enable__ ();
+      if (enabled)
+        enabled = 'on';
+      else
+        enabled = 'off';
+      endif
+      retval = struct ('ProfilerStatus', enabled);
+
+    case 'info'
+      [flat, tree] = __profiler_data__ ();
+      retval = struct ('FunctionTable', flat, 'Hierarchical', tree);
+
+    otherwise
+      warning ("profile: Unrecognized option '%s'", option);
+      print_usage ();
+
+  endswitch
+
+endfunction
+
+
+%!demo
+%! profile ('on');
+%! A = rand (100);
+%! B = expm (A);
+%! profile ('off');
+%! profile ('resume');
+%! C = sqrtm (A);
+%! profile ('off');
+%! T = profile ('info');
+%! profshow (T);
new file mode 100644
--- /dev/null
+++ b/scripts/general/profshow.m
@@ -0,0 +1,102 @@
+## Copyright (C) 2011 Daniel Kraft
+##
+## 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} {} profshow (@var{data})
+## @deftypefnx {Function File} {} profshow (@var{data}, @var{n})
+## Show flat 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}
+## defaults to 20.
+##
+## The attribute column shows @samp{R} for recursive functions and nothing
+## otherwise.
+## @end deftypefn
+
+## Built-in profiler.
+## Author: Daniel Kraft <d@domob.eu>
+
+function profshow (data, n = 20)
+
+  if (nargin < 1 || nargin > 2)
+    print_usage ();
+  endif
+
+  n = fix (n);
+  if (! isscalar (n) || ! isreal (n) || ! (n > 0))
+    error ("profile: N must be a positive integer"); 
+  endif
+
+  m = length (data.FunctionTable);
+  n = min (n, m);
+
+  ## 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 ];
+
+  [~, p] = sort (times);
+
+  ## 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);
+
+  printf (headerFormat, "#", "Function", "Attr", "Time (s)", "Calls");
+  printf ("%s\n", repmat ("-", 1, nameLen + 2 * 5 + 2 * 13));
+  for i = 1 : n
+    row = data.FunctionTable(p(i));
+    attr = "";
+    if (row.IsRecursive)
+      attr = "R";
+    endif
+    printf (rowFormat, p(i), row.FunctionName, attr, ...
+            row.TotalTime, row.NumCalls);
+  endfor
+
+endfunction
+
+%!demo
+%! profile ("on");
+%! A = rand (100);
+%! B = expm (A);
+%! profile ("off");
+%! T = profile ("info");
+%! profshow (T, 10);
+
+%!demo
+%! function f = myfib (n)
+%!   if (n <= 2)
+%!     f = 1;
+%!   else
+%!     f = myfib (n - 1) + myfib (n - 2);
+%!   endif
+%! endfunction
+%! profile ("on");
+%! myfib (20);
+%! profile ("off");
+%! profshow (profile ("info"), 5);
--- a/scripts/general/quadl.m
+++ b/scripts/general/quadl.m
@@ -62,14 +62,12 @@
 ##   * replace global variable terminate2 with local function need_warning
 ##   * add paper ref to docs
 
-function q = quadl (f, a, b, tol, trace, varargin)
-  need_warning (1);
-  if (nargin < 4)
-    tol = [];
+function q = quadl (f, a, b, tol = [], trace = false, varargin)
+
+  if (nargin < 3)
+    print_usage ();
   endif
-  if (nargin < 5)
-    trace = [];
-  endif
+
   if (isa (a, "single") || isa (b, "single"))
     myeps = eps ("single");
   else
@@ -79,16 +77,23 @@
     tol = myeps;
   endif
   if (isempty (trace))
-    trace = 0;
+    trace = false;
   endif
   if (tol < myeps)
     tol = myeps;
   endif
 
+  ## Track whether recursion has occurred
+  global __quadl_recurse_done__;
+  __quadl_recurse_done__ = false;
+  ## Track whether warning about machine precision has been issued
+  global __quadl_need_warning__;
+  __quadl_need_warning__ = true;
+
   m = (a+b)/2;
   h = (b-a)/2;
-  alpha = sqrt(2/3);
-  beta = 1/sqrt(5);
+  alpha = sqrt (2/3);
+  beta = 1/sqrt (5);
 
   x1 = .942882415695480;
   x2 = .641853342345781;
@@ -104,12 +109,12 @@
 
   i2 = (h/6)*(y(1) + y(13) + 5*(y(5)+y(9)));
 
-  i1 = (h/1470)*(77*(y(1)+y(13))
+  i1 = (h/1470)*(   77*(y(1)+y(13))
                  + 432*(y(3)+y(11))
                  + 625*(y(5)+y(9))
                  + 672*y(7));
 
-  is = h*(.0158271919734802*(y(1)+y(13))
+  is = h*( .0158271919734802*(y(1)+y(13))
           +.0942738402188500*(y(2)+y(12))
           + .155071987336585*(y(3)+y(11))
           + .188821573960182*(y(4)+y(10))
@@ -117,80 +122,96 @@
           + .224926465333340*(y(6)+y(8))
           + .242611071901408*y(7));
 
-  s = sign(is);
-
+  s = sign (is);
   if (s == 0)
     s = 1;
   endif
-  erri1 = abs(i1-is);
-  erri2 = abs(i2-is);
-  R = 1;
+  erri1 = abs (i1-is);
+  erri2 = abs (i2-is);
   if (erri2 != 0)
     R = erri1/erri2;
+  else
+    R = 1;
   endif
   if (R > 0 && R < 1)
     tol = tol/R;
   endif
-  is = s*abs(is)*tol/myeps;
+  is = s * abs(is) * tol/myeps;
   if (is == 0)
     is = b-a;
   endif
+
   q = adaptlobstp (f, a, b, fa, fb, is, trace, varargin{:});
+
 endfunction
 
 ## ADAPTLOBSTP  Recursive function used by QUADL.
 ##
 ##   Q = ADAPTLOBSTP('F', A, B, FA, FB, IS, TRACE) tries to
 ##   approximate the integral of F(X) from A to B to
-##   an appropriate relative error. The argument 'F' is
+##   an appropriate relative error.  The argument 'F' is
 ##   a string containing the name of f.  The remaining
 ##   arguments are generated by ADAPTLOB or by recursion.
 ##
 ##   Walter Gautschi, 08/03/98
 
 function q = adaptlobstp (f, a, b, fa, fb, is, trace, varargin)
+  global __quadl_recurse_done__;
+  global __quadl_need_warning__;
+
   h = (b-a)/2;
   m = (a+b)/2;
-  alpha = sqrt(2/3);
-  beta = 1/sqrt(5);
+  alpha = sqrt (2/3);
+  beta = 1 / sqrt(5);
   mll = m-alpha*h;
-  ml = m-beta*h;
-  mr = m+beta*h;
+  ml  = m-beta*h;
+  mr  = m+beta*h;
   mrr = m+alpha*h;
   x = [mll, ml, m, mr, mrr];
-  y = feval(f, x, varargin{:});
+  y = feval (f, x, varargin{:});
   fmll = y(1);
-  fml = y(2);
-  fm = y(3);
-  fmr = y(4);
+  fml  = y(2);
+  fm   = y(3);
+  fmr  = y(4);
   fmrr = y(5);
   i2 = (h/6)*(fa + fb + 5*(fml+fmr));
   i1 = (h/1470)*(77*(fa+fb) + 432*(fmll+fmrr) + 625*(fml+fmr) + 672*fm);
-  if (is+(i1-i2) == is || mll <= a || b <= mrr)
-    if ((m <= a || b <= m) && need_warning ())
+  if ((is+(i1-i2) == is || mll <= a || b <= mrr) && __quadl_recurse_done__)
+    if ((m <= a || b <= m) && __quadl_need_warning__)
       warning ("quadl: interval contains no more machine number");
       warning ("quadl: required tolerance may not be met");
-      need_warning (0);
+      __quadl_need_warning__ = false;
     endif
     q = i1;
     if (trace)
       disp ([a, b-a, q]);
     endif
   else
-    q = (adaptlobstp (f, a, mll, fa, fmll, is, trace, varargin{:})
-         + adaptlobstp (f, mll, ml, fmll, fml, is, trace, varargin{:})
-         + adaptlobstp (f, ml, m, fml, fm, is, trace, varargin{:})
-         + adaptlobstp (f, m, mr, fm, fmr, is, trace, varargin{:})
-         + adaptlobstp (f, mr, mrr, fmr, fmrr, is, trace, varargin{:})
-         + adaptlobstp (f, mrr, b, fmrr, fb, is, trace, varargin{:}));
+    __quadl_recurse_done__ = true;
+    q = (  adaptlobstp (f, a  , mll, fa  , fmll, is, trace, varargin{:})
+         + adaptlobstp (f, mll, ml , fmll, fml , is, trace, varargin{:})
+         + adaptlobstp (f, ml , m  , fml , fm  , is, trace, varargin{:})
+         + adaptlobstp (f, m  , mr , fm  , fmr , is, trace, varargin{:})
+         + adaptlobstp (f, mr , mrr, fmr , fmrr, is, trace, varargin{:})
+         + adaptlobstp (f, mrr, b  , fmrr, fb  , is, trace, varargin{:}));
   endif
 endfunction
 
-function r = need_warning (v)
-  persistent w = [];
-  if (nargin == 0)
-    r = w;
-  else
-    w = v;
-  endif
-endfunction
+
+## basic functionality
+%!assert (quadl (@(x) sin (x), 0, pi, [], []), 2, -3e-16)
+
+## the values here are very high so it may be unavoidable that this fails
+%!assert (quadl (@(x) sin (3*x).*cosh (x).*sinh (x),10,15),
+%!         2.588424538641647e+10, -9e-15)
+
+## extra parameters
+%!assert (quadl (@(x,a,b) sin (a + b*x), 0, 1, [], [], 2, 3),
+%!        cos(2)/3 - cos(5)/3, - 3e-16)
+
+## test different tolerances. 
+%!assert (quadl (@(x) sin (2 + 3*x).^2, 0, 10, 0.3, []),
+%!        (60 + sin(4) - sin(64))/12, -0.3)
+%!assert (quadl (@(x) sin (2 + 3*x).^2, 0, 10, 0.1, []),
+%!        (60 + sin(4) - sin(64))/12, -0.1)
+
--- a/scripts/general/rat.m
+++ b/scripts/general/rat.m
@@ -150,3 +150,11 @@
   endif
 
 endfunction
+
+%!error rat ();
+%!error rat (1, 2, 3);
+
+%!test
+%! [n, d] = rat ([0.5, 0.3, 1/3]);
+%! assert (n, [1, 3, 1]);
+%! assert (d, [2, 10, 3]);
--- a/scripts/general/rot90.m
+++ b/scripts/general/rot90.m
@@ -52,44 +52,41 @@
 
 ## Author: jwe
 
-function B = rot90 (A, k)
-
-  if (nargin == 1 || nargin == 2)
-    if (nargin < 2)
-      k = 1;
-    endif
-
-    if (ndims (A) > 2)
-      error ("rot90: Only works with 2-D arrays");
-    endif
-
-    if (imag (k) != 0 || fix (k) != k)
-      error ("rot90: K must be an integer");
-    endif
-
-    k = rem (k, 4);
+function B = rot90 (A, k = 1)
 
-    if (k < 0)
-      k = k + 4;
-    endif
-
-    if (k == 0)
-      B = A;
-    elseif (k == 1)
-      B = flipud (A.');
-    elseif (k == 2)
-      B = flipud (fliplr (A));
-    elseif (k == 3)
-      B = (flipud (A)).';
-    else
-      error ("rot90: internal error!");
-    endif
-  else
+  if (nargin < 1 || nargin > 2)
     print_usage ();
   endif
 
+  if (ndims (A) > 2)
+    error ("rot90: A must be a 2-D array");
+  endif
+
+  if (! (isscalar (k) && isreal (k) && fix (k) == k))
+    error ("rot90: K must be a single real integer");
+  endif
+
+  k = rem (k, 4);
+
+  if (k < 0)
+    k = k + 4;
+  endif
+
+  if (k == 0)
+    B = A;
+  elseif (k == 1)
+    B = flipud (A.');
+  elseif (k == 2)
+    B = flipud (fliplr (A));
+  elseif (k == 3)
+    B = (flipud (A)).';
+  else
+    error ("rot90: internal error!");
+  endif
+
 endfunction
 
+
 %!test
 %! x1 = [1, 2; 3, 4];
 %! x2 = [2, 4; 1, 3];
@@ -106,4 +103,6 @@
 %% Test input validation
 %!error rot90 ();
 %!error rot90 (1, 2, 3);
-
+%!error rot90 (1, ones(2));
+%!error rot90 (1, 1.5);
+%!error rot90 (1, 1+i);
--- a/scripts/general/rotdim.m
+++ b/scripts/general/rotdim.m
@@ -71,22 +71,26 @@
   nd = ndims (x);
   sz = size (x);
   if (nargin < 3)
-    ## Find the first two non-singleton dimension.
-    plane = [];
-    dim = 0;
-    while (dim < nd)
-      dim = dim + 1;
-      if (sz (dim) != 1)
-        plane = [plane, dim];
-        if (length (plane) == 2)
-          break;
+    if (nd > 2)
+      ## Find the first two non-singleton dimension.
+      plane = [];
+      dim = 0;
+      while (dim < nd)
+        dim = dim + 1;
+        if (sz (dim) != 1)
+          plane = [plane, dim];
+          if (length (plane) == 2)
+            break;
+          endif
         endif
+      endwhile
+      if (length (plane) < 1)
+        plane = [1, 2];
+      elseif (length (plane) < 2)
+        plane = [1, plane];
       endif
-    endwhile
-    if (length (plane) < 1)
+    else
       plane = [1, 2];
-    elseif (length (plane) < 2)
-      plane = [1, plane];
     endif
   else
     if (! (isvector (plane) && length (plane) == 2
@@ -119,3 +123,36 @@
   endif
 
 endfunction
+
+%!error rotdim ();
+%!error rotdim (1, 2, 3, 4);
+
+%!shared r, rr
+%! r = [1,2,3]; rr = [3,2,1];
+%!assert (rotdim (r, 0), r);
+%!assert (rotdim (r, 1), rr');
+%!assert (rotdim (r, 2), rr);
+%!assert (rotdim (r, 3), r');
+%!assert (rotdim (r, 3), rotdim (r, -1));
+%!assert (rotdim (r, 1), rotdim (r));
+
+%!shared c, cr
+%! c = [1;2;3]; cr = [3;2;1];
+%!assert (rotdim (c, 0), c);
+%!assert (rotdim (c, 1), c');
+%!assert (rotdim (c, 2), cr);
+%!assert (rotdim (c, 3), cr');
+%!assert (rotdim (c, 3), rotdim (c, -1));
+%!assert (rotdim (c, 1), rotdim (c));
+
+%!shared m
+%! m = [1,2;3,4];
+%!assert (rotdim (m, 0), m);
+%!assert (rotdim (m, 1), [2,4;1,3]);
+%!assert (rotdim (m, 2), [4,3;2,1]);
+%!assert (rotdim (m, 3), [3,1;4,2]);
+%!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.
--- a/scripts/general/shift.m
+++ b/scripts/general/shift.m
@@ -51,10 +51,7 @@
     endif
   else
     ## Find the first non-singleton dimension.
-    dim = find (sz > 1, 1);
-    if (isempty (dim))
-      dim = 1;
-    endif
+    (dim = find (sz > 1, 1)) || (dim = 1);
   endif
 
   if (numel (x) < 1)
@@ -63,10 +60,7 @@
 
   d = sz (dim);
 
-  idx = cell ();
-  for i = 1:nd
-    idx{i} = 1:sz(i);
-  endfor
+  idx = repmat ({':'}, nd, 1);
   if (b >= 0)
     b = rem (b, d);
     idx{dim} = [d-b+1:d, 1:d-b];
--- a/scripts/general/shiftdim.m
+++ b/scripts/general/shiftdim.m
@@ -57,14 +57,9 @@
   orig_dims = size (x);
 
   if (nargin == 1)
-    ## Find the first singleton dimension.
-    n = 0;
-    while (n < nd && orig_dims(n+1) == 1)
-      n++;
-    endwhile
-  endif
-
-  if (! isscalar (n) || floor (n) != n)
+    ## Find the first non-singleton dimension.
+    (n = find (orig_dims != 1, 1) - 1) || (n = nd);
+  elseif (! (isscalar (n) && n == fix (n)))
     error ("shiftdim: N must be a scalar integer");
   endif
 
@@ -78,7 +73,7 @@
   elseif (n > 0)
     ## We need permute here instead of reshape to shift values in a
     ## compatible way.
-    y = permute (x, [n+1:ndims(x) 1:n]);
+    y = permute (x, [n+1:nd 1:n]);
   else
     y = x;
   endif
@@ -86,3 +81,20 @@
   ns = n;
 
 endfunction
+
+
+%!test
+%! x = rand (1, 1, 4, 2);
+%! [y, ns] = shiftdim (x);
+%! assert (size (y), [4 2]);
+%! assert (ns, 2);
+%! assert (shiftdim (y, -2), x);
+%! assert (size (shiftdim (x, 2)), [4 2]);
+%!assert (size (shiftdim (rand (0, 1, 2))), [0 1 2]);
+
+%% Test input validation
+%!error(shiftdim ());
+%!error(shiftdim (1,2,3));
+%!error(shiftdim (1, ones (2)));
+%!error(shiftdim (1, 1.5));
+
--- a/scripts/general/structfun.m
+++ b/scripts/general/structfun.m
@@ -106,7 +106,7 @@
   [varargout{:}] = cellfun (func, struct2cell (S), varargin{:});
 
   if (! uniform_output)
-    varargout = cellfun (@cell2struct, varargout, {fieldnames(S)}, {1}, uo_str, false);
+    varargout = cellfun ("cell2struct", varargout, {fieldnames(S)}, {1}, uo_str, false);
   endif
 endfunction
 
--- a/scripts/general/triplequad.m
+++ b/scripts/general/triplequad.m
@@ -37,22 +37,25 @@
 ##
 ## The optional argument @var{quadf} specifies which underlying integrator
 ## function to use.  Any choice but @code{quad} is available and the default
-## is @code{quadgk}.
+## is @code{quadcc}.
 ##
 ## Additional arguments, are passed directly to @var{f}.  To use the default
-## value for @var{tol} or @var{quadf} one may pass an empty matrix ([]).
+## value for @var{tol} or @var{quadf} one may pass ':' or an empty matrix ([]).
 ## @seealso{dblquad, quad, quadv, quadl, quadgk, quadcc, trapz}
 ## @end deftypefn
 
-function q = triplequad(f, xa, xb, ya, yb, za, zb, tol, quadf, varargin)
+function q = triplequad (f, xa, xb, ya, yb, za, zb, tol = 1e-6, quadf = @quadcc, varargin)
+
   if (nargin < 7)
     print_usage ();
   endif
-  if (nargin < 8 || isempty (tol))
+
+  ## Allow use of empty matrix ([]) to indicate default 
+  if (isempty (tol))
     tol = 1e-6;
   endif
-  if (nargin < 9 || isempty (quadf))
-    quadf = @quadgk;
+  if (isempty (quadf))
+    quadf = @quadcc;
   endif
 
   inner = @__triplequad_inner__;
@@ -61,7 +64,8 @@
     varargin = {};
   endif
 
-  q = dblquad(@(y, z) inner (y, z, f, xa, xb, tol, quadf, varargin{:}),ya, yb, za, zb, tol);
+  q = dblquad (@(y, z) inner (y, z, f, xa, xb, tol, quadf, varargin{:}), ya, yb, za, zb, tol);
+
 endfunction
 
 function q = __triplequad_inner__ (y, z, f, xa, xb, tol, quadf, varargin)
@@ -71,8 +75,11 @@
   endfor
 endfunction
 
-%% These tests are too expensive to run normally. Disable them
-% !#assert (triplequad (@(x,y,z) exp(-x.^2 - y.^2 - z.^2) , -1, 1, -1, 1, -1, 1, [],  @quadgk), pi ^ (3/2) * erf(1).^3, 1e-6)
-% !#assert (triplequad (@(x,y,z) exp(-x.^2 - y.^2 - z.^2) , -1, 1, -1, 1, -1, 1, [],  @quadl), pi ^ (3/2) * erf(1).^3, 1e-6)
-% !#assert (triplequad (@(x,y,z) exp(-x.^2 - y.^2 - z.^2) , -1, 1, -1, 1, -1, 1, [],  @quadv), pi ^ (3/2) * erf(1).^3, 1e-6)
+ 
+%!assert (triplequad (@(x,y,z) exp(-x.^2 - y.^2 - z.^2) , -1, 1, -1, 1, -1, 1, [],  @quadcc), pi ^ (3/2) * erf(1).^3, 1e-6)
 
+%% These tests are too expensive to run normally (~30 sec each).  Disable them
+#%!assert (triplequad (@(x,y,z) exp(-x.^2 - y.^2 - z.^2) , -1, 1, -1, 1, -1, 1, [],  @quadgk), pi ^ (3/2) * erf(1).^3, 1e-6)
+#%!#assert (triplequad (@(x,y,z) exp(-x.^2 - y.^2 - z.^2) , -1, 1, -1, 1, -1, 1, [],  @quadl), pi ^ (3/2) * erf(1).^3, 1e-6)
+#%!#assert (triplequad (@(x,y,z) exp(-x.^2 - y.^2 - z.^2) , -1, 1, -1, 1, -1, 1, [],  @quadv), pi ^ (3/2) * erf(1).^3, 1e-6)
+
--- a/scripts/geometry/module.mk
+++ b/scripts/geometry/module.mk
@@ -12,9 +12,6 @@
   geometry/griddatan.m \
   geometry/inpolygon.m \
   geometry/rectint.m \
-  geometry/trimesh.m \
-  geometry/triplot.m \
-  geometry/trisurf.m \
   geometry/tsearchn.m \
   geometry/voronoi.m \
   geometry/voronoin.m
--- a/scripts/geometry/voronoi.m
+++ b/scripts/geometry/voronoi.m
@@ -129,7 +129,7 @@
   idx = find (!infi);
   ll = length (idx);
   c = c(idx).';
-  k = sum (cellfun ('length', c));
+  k = sum (cellfun ("length", c));
   edges = cell2mat(cellfun (@(x) [x ; [x(end), x(1:end-1)]], c,
                             "uniformoutput", false));
 
@@ -166,3 +166,13 @@
   endif
 
 endfunction
+
+%!testif HAVE_QHULL
+%! phi=linspace(-pi,3/4*pi,8);
+%! [x,y]=pol2cart(phi,1);
+%! [vx,vy]=voronoi(x,y);
+%! assert(vx(2,:),zeros(1,size(vx,2)),eps);
+%! assert(vy(2,:),zeros(1,size(vy,2)),eps);
+
+%!demo
+%! voronoi (rand(10,1), rand(10,1));
--- a/scripts/help/__makeinfo__.m
+++ b/scripts/help/__makeinfo__.m
@@ -17,8 +17,8 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {[@var{retval}, @var{status}] =} __makeinfo__ (@var{text}, @var{output_type})
-## @deftypefnx {Function File} {[@var{retval}, @var{status}] =} __makeinfo__ (@var{text}, @var{output_type}, @var{see_also})
+## @deftypefn  {Function File} {[@var{retval}, @var{status}] =} __makeinfo__ (@var{text})
+## @deftypefnx {Function File} {[@var{retval}, @var{status}] =} __makeinfo__ (@var{text}, @var{output_type})
 ## Undocumented internal function.
 ## @end deftypefn
 
@@ -33,13 +33,6 @@
 ## @t{"plain text"}. If @var{output_type} is @t{"texinfo"}, the @t{@@seealso}
 ## macro is expanded, but otherwise the text is unaltered.
 ##
-## If the optional argument @var{see_also} is present, it is used to expand the
-## Octave specific @t{@@seealso} macro. This argument must be a function handle,
-## that accepts a cell array of strings as input argument (each elements of the
-## array corresponds to the arguments to the @t{@@seealso} macro), and return
-## the expanded string. If this argument is not given, the @t{@@seealso} macro
-## will be expanded to the text
-##
 ## @example
 ## See also: arg1, arg2@, ...
 ## @end example
@@ -60,7 +53,7 @@
 function [retval, status] = __makeinfo__ (text, output_type = "plain text", see_also = [])
 
   ## Check input
-  if (nargin == 0)
+  if (nargin < 1 || nargin > 2)
     print_usage ();
   endif
 
@@ -72,72 +65,18 @@
     error ("__makeinfo__: second input argument must be a string");
   endif
 
-  ## Define the function which expands @seealso macro
-  if (isempty (see_also))
-    if (strcmpi (output_type, "plain text"))
-      see_also = @simple_see_also;
-    else
-      see_also = @simple_see_also_with_refs;
-    endif
-  endif
-
-  if (!isa (see_also, "function_handle"))
-    error ("__makeinfo__: third input argument must be the empty matrix, or a function handle");
-  endif
-
   ## It seems like makeinfo sometimes gets angry if the first character
   ## on a line is a space, so we remove these.
   text = strrep (text, "\n ", "\n");
 
   ## Handle @seealso macro
-  SEE_ALSO = "@seealso";
-  starts = strfind (text, SEE_ALSO);
-  for start = fliplr (starts)
-    if (start == 1 || (text (start-1) != "@"))
-      bracket_start = find (text (start:end) == "{", 1);
-      stop = find (text (start:end) == "}", 1);
-      if (!isempty (stop) && !isempty (bracket_start))
-        stop += start - 1;
-        bracket_start += start - 1;
-      else
-        bracket_start = start + length (SEE_ALSO);
-        stop = find (text (start:end) == "\n", 1);
-        if (isempty (stop))
-          stop = length (text);
-        else
-          stop += start - 1;
-        endif
-      endif
-      see_also_args = text (bracket_start+1:(stop-1));
-      see_also_args = strtrim (strsplit (see_also_args, ","));
-      expanded = see_also (see_also_args);
-      text = strcat (text (1:start-1), expanded, text (stop+1:end));
-    endif
-  endfor
-
+  if (strcmpi (output_type, "plain text")) 
+    text = regexprep (text, '@seealso *\{([^}]*)\}', "\nSee also: $1.\n\n");
+  else
+    text = regexprep (text, '@seealso *\{([^}]*)\}', "\nSee also: @ref{$1}.\n\n");
+  endif
   ## Handle @nospell macro
-  NOSPELL = "@nospell";
-  starts = strfind (text, NOSPELL);
-  for start = fliplr (starts)
-    if (start == 1 || (text (start-1) != "@"))
-      bracket_start = find (text (start:end) == "{", 1);
-      stop = find (text (start:end) == "}", 1);
-      if (!isempty (stop) && !isempty (bracket_start))
-        stop += start - 1;
-        bracket_start += start - 1;
-      else
-        bracket_start = start + length (NOSPELL);
-        stop = find (text (start:end) == "\n", 1);
-        if (isempty (stop))
-          stop = length (text);
-        else
-          stop += start - 1;
-        endif
-      endif
-      text(stop) = [];
-      text(start:bracket_start) = [];
-    endif
-  endfor
+  text = regexprep (text, '@nospell *\{([^}]*)\}', "$1");
 
   if (strcmpi (output_type, "texinfo"))
     status = 0;
@@ -180,12 +119,3 @@
   end_unwind_protect
 endfunction
 
-function expanded = simple_see_also (args)
-  expanded = strcat ("\nSee also:", sprintf (" %s,", args {:}));
-  expanded = strcat (expanded (1:end-1), "\n\n");
-endfunction
-
-function expanded = simple_see_also_with_refs (args)
-  expanded = strcat ("\nSee also:", sprintf (" @ref{%s},", args {:}));
-  expanded = strcat (expanded (1:end-1), "\n\n");
-endfunction
--- a/scripts/help/module.mk
+++ b/scripts/help/module.mk
@@ -1,11 +1,11 @@
 FCN_FILE_DIRS += help
 
 help_PRIVATE_FCN_FILES = \
-  help/private/__additional_help_message__.m
+  help/private/__additional_help_message__.m \
+  help/private/__strip_html_tags__.m
 
 help_FCN_FILES = \
   help/__makeinfo__.m \
-  help/__strip_html_tags__.m \
   help/doc.m \
   help/gen_doc_cache.m \
   help/get_first_help_sentence.m \
@@ -13,6 +13,7 @@
   help/lookfor.m \
   help/print_usage.m \
   help/type.m \
+  help/unimplemented.m \
   help/which.m \
   $(help_PRIVATE_FCN_FILES)
 
--- a/scripts/help/print_usage.m
+++ b/scripts/help/print_usage.m
@@ -136,3 +136,7 @@
   retval = get_usage_plain_text (help_text, max_len);
 endfunction
 
+
+## Stop reporting function as missing tests.  No good tests possible.
+%!assert (1)
+
rename from scripts/help/__strip_html_tags__.m
rename to scripts/help/private/__strip_html_tags__.m
--- a/scripts/help/type.m
+++ b/scripts/help/type.m
@@ -111,4 +111,14 @@
   endfor
 endfunction
 
+%!test
+%! var = 1;
+%! typestr = type ("var");
+%! typestr = typestr{1}(1:17);
+%! assert (typestr, "var is a variable");
 
+%!assert (type ('dot'){1}, "dot is a dynamically-linked function")
+%!assert (type ('cat'){1}, "cat is a built-in function")
+%!assert (type ('+'){1}, "+ is an operator")
+%!assert (type ('end'){1}, "end is a keyword")
+%!error (type ('NO_NAME'))
rename from scripts/miscellaneous/unimplemented.m
rename to scripts/help/unimplemented.m
--- a/scripts/miscellaneous/unimplemented.m
+++ b/scripts/help/unimplemented.m
@@ -333,13 +333,11 @@
   "reducepatch",
   "reducevolume",
   "resample",
-  "reset",
   "rgbplot",
   "rmpref",
   "root",
   "rotate",
   "rotate3d",
-  "rsf2csf",
   "selectmoveresize",
   "sendmail",
   "serial",
@@ -428,3 +426,14 @@
   "zoom",
   };
 endfunction
+
+
+%!test
+%! str = unimplemented ("no_name_function");
+%! assert (isempty (str));
+%! str = unimplemented ("quad2d");
+%! assert (str(1:51), "quad2d is not implemented.  Consider using dblquad.");
+%! str = unimplemented ("MException");
+%! assert (str(1:58), "the `MException' function is not yet implemented in Octave");
+
+
--- a/scripts/help/which.m
+++ b/scripts/help/which.m
@@ -53,3 +53,13 @@
   endif
 
 endfunction
+
+
+%!test
+%! str = which ("ls");
+%! assert (str(end-17:end), strcat ("miscellaneous", filesep(), "ls.m"));
+%!test
+%! str = which ("dot");
+%! assert (str(end-6:end), "dot.oct");
+
+%!assert (which ("NO_NAME"), "");
--- a/scripts/image/image.m
+++ b/scripts/image/image.m
@@ -19,9 +19,9 @@
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {} image (@var{img})
 ## @deftypefnx {Function File} {} image (@var{x}, @var{y}, @var{img})
-## Display a matrix as a color image.  The elements of @var{x} are indices
+## Display a matrix as a color image.  The elements of @var{img} are indices
 ## into the current colormap, and the colormap will be scaled so that the
-## extremes of @var{x} are mapped to the extremes of the colormap.
+## extremes of @var{img} are mapped to the extremes of the colormap.
 ##
 ## The axis values corresponding to the matrix elements are specified in
 ## @var{x} and @var{y}.  If you're not using gnuplot 4.2 or later, these
--- a/scripts/io/strread.m
+++ b/scripts/io/strread.m
@@ -19,15 +19,16 @@
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {[@var{a}, @dots{}] =} strread (@var{str})
 ## @deftypefnx {Function File} {[@var{a}, @dots{}] =} strread (@var{str}, @var{format})
+## @deftypefnx {Function File} {[@var{a}, @dots{}] =} strread (@var{str}, @var{format}, @var{format_repeat})
 ## @deftypefnx {Function File} {[@var{a}, @dots{}] =} strread (@var{str}, @var{format}, @var{prop1}, @var{value1}, @dots{})
+## @deftypefnx {Function File} {[@var{a}, @dots{}] =} strread (@var{str}, @var{format}, @var{format_repeat}, @var{prop1}, @var{value1}, @dots{})
 ## Read data from a string.
 ##
 ## The string @var{str} is split into words that are repeatedly matched to the
 ## specifiers in @var{format}.  The first word is matched to the first
-## specifier,
-## the second to the second specifier and so forth.  If there are more words
-## than
-## specifiers, the process is repeated until all words have been processed.
+## specifier, the second to the second specifier and so forth.  If there are
+## more words than specifiers, the process is repeated until all words have
+## been processed.
 ##
 ## The string @var{format} describes how the words in @var{str} should be
 ## parsed.
@@ -36,19 +37,31 @@
 ## @item %s
 ## The word is parsed as a string.
 ##
-## @item %d
 ## @itemx %f
-## The word is parsed as a number.
+## @itemx %n
+## The word is parsed as a number and converted to double.
+##
+## @item  %d
+## @itemx %u
+## The word is parsed as a number and converted to int32.
 ##
-## @item %*
+## @item %*', '%*f', '%*s
 ## The word is skipped.
+##
+## For %s and %d, %f, %n, %u and the associated %*s @dots{} specifiers an
+## optional width can be specified as %Ns, etc. where N is an integer > 1.
+## For %f, format specifiers like %N.Mf are allowed.
+##
+## @item literals
+## In addition the format may contain literal character strings; these will be
+## skipped during reading.
 ## @end table
 ##
 ## Parsed word corresponding to the first specifier are returned in the first
 ## output argument and likewise for the rest of the specifiers.
 ##
 ## By default, @var{format} is @t{"%f"}, meaning that numbers are read from
-## @var{str}.
+## @var{str}.  This will do if @var{str} contains only numeric fields.
 ##
 ## For example, the string
 ##
@@ -68,6 +81,18 @@
 ## [@var{a}, @var{b}, @var{c}] = strread (@var{str}, "%s %s %f");
 ## @end example
 ##
+## Optional numeric argument @var{format_repeat} can be used for
+## limiting the number of items read:
+## @table @asis
+## @item -1
+## (default) read all of the string until the end.
+##
+## @item N
+## Read N times @var{nargout} items.  0 (zero) is an acceptable
+## value for @var{format_repeat}.
+##
+## @end table
+##
 ## The behavior of @code{strread} can be changed via property-value
 ## pairs.  The following properties are recognized:
 ##
@@ -77,94 +102,202 @@
 ## @var{value} is the comment style and can be any of the following.
 ## @itemize
 ## @item "shell"
-## Everything from @code{#} characters to the nearest end-line is skipped.
+## Everything from @code{#} characters to the nearest end-of-line is skipped.
 ##
 ## @item "c"
 ## Everything between @code{/*} and @code{*/} is skipped.
 ##
 ## @item "c++"
-## Everything from @code{//} characters to the nearest end-line is skipped.
+## Everything from @code{//} characters to the nearest end-of-line is skipped.
 ##
 ## @item "matlab"
-## Everything from @code{%} characters to the nearest end-line is skipped.
+## Everything from @code{%} characters to the nearest end-of-line is skipped.
+##
+## @item user-supplied.  Two options:
+## (1) One string, or 1x1 cell string: Skip everything to the right of it;
+## (2) 2x1 cell string array: Everything between the left and right strings
+## is skipped.
 ## @end itemize
 ##
 ## @item "delimiter"
-## Any character in @var{value} will be used to split @var{str} into words.
+## Any character in @var{value} will be used to split @var{str} into words 
+## (default value = any whitespace).
 ##
 ## @item "emptyvalue"
 ## Parts of the output where no word is available is filled with @var{value}.
+##
+## @item "multipledelimsasone"
+## Treat a series of consecutive delimiters, without whitespace in between,
+## as a single delimiter.  Consecutive delimiter series need not be vertically 
+## "aligned".
+##
+## @item "treatasempty"
+## Treat single occurrences (surrounded by delimiters or whitespace) of the
+## string(s) in @var{value} as missing values.
+##
+## @item "returnonerror"
+## If @var{value} true (1, default), ignore read errors and return normally.
+## If false (0), return an error.
+##
+## @item "whitespace"
+## Any character in @var{value} will be interpreted as whitespace and
+## trimmed; the string defining whitespace must be enclosed in double
+## quotes for proper processing of special characters like \t.
+## The default value for whitespace = " \b\r\n\t" (note the space).
+## 
 ## @end table
 ##
-## @seealso{textread, load, dlmread, fscanf}
+## @seealso{textscan, textread, load, dlmread, fscanf}
 ## @end deftypefn
 
 function varargout = strread (str, format = "%f", varargin)
+
   ## Check input
   if (nargin < 1)
     print_usage ();
   endif
 
-  if (!ischar (str) || !ischar (format))
+  if (isempty (format))
+    format = "%f";
+  endif
+
+  if (! ischar (str) || ! ischar (format))
     error ("strread: STR and FORMAT arguments must be strings");
   endif
 
-  ## Parse options
+  ## Parse format string to compare number of conversion fields and nargout
+  nfields = length (strfind (format, "%")) - length (strfind (format, "%*"));
+  ## If str only has numeric fields, a (default) format ("%f") will do.
+  ## Otherwise:
+  if ((max (nargout, 1) != nfields) && ! strcmp (format, "%f"))
+    error ("strread: the number of output variables must match that specified by FORMAT");
+  endif
+
+  ## Check for format string repeat count
+  format_repeat_count = -1;
+  if (nargin > 2 && isnumeric (varargin{1}))
+    if (varargin{1} >= 0)
+      format_repeat_count = varargin{1};
+    endif
+    if (nargin > 3)
+      varargin = varargin(2:end);
+    else
+      varargin = {};
+    endif
+  endif
+
+  ## Parse options.  First initialize defaults
   comment_flag = false;
-  numeric_fill_value = 0;
-  white_spaces = " \n\r\t\b";
   delimiter_str = "";
+  empty_str = "";
+  eol_char = "";
+  err_action = 0;
+  mult_dlms_s1 = false;
+  numeric_fill_value = NaN;
+  white_spaces = " \b\r\n\t";
   for n = 1:2:length (varargin)
-    switch (lower (varargin {n}))
+    switch (lower (varargin{n}))
+      case "bufsize"
+        ## We could synthesize this, but that just seems weird...
+        warning ('strread: property "bufsize" is not implemented');
       case "commentstyle"
         comment_flag = true;
-        switch (lower (varargin {n+1}))
+        switch (lower (varargin{n+1}))
           case "c"
-            comment_specif = {"/*", "*/"};
+            [comment_start, comment_end] = deal ("/*", "*/");
           case "c++"
-            comment_specif = {"//", "\n"};
+            [comment_start, comment_end] = deal ("//", "eol_char");
           case "shell"
-            comment_specif = {"#", "\n"};
+            [comment_start, comment_end] = deal ("#" , "eol_char");
           case "matlab"
-            comment_specif = {"%", "\n"};
+            [comment_start, comment_end] = deal ("%" , "eol_char");
           otherwise
-            warning ("strread: unknown comment style '%s'", val);
+            if (ischar (varargin{n+1}) ||
+               (numel (varargin{n+1}) == 1 && iscellstr (varargin{n+1})))
+              [comment_start, comment_end] = deal (char (varargin{n+1}), "eol_char");
+            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
+              error ("strread: unknown or unrecognized comment style '%s'", 
+                      varargin{n+1});
+            endif
         endswitch
       case "delimiter"
-        delimiter_str = varargin {n+1};
+        delimiter_str = varargin{n+1};
       case "emptyvalue"
-        numeric_fill_value = varargin {n+1};
-      case "bufsize"
-        ## XXX: We could synthesize this, but that just seems weird...
-        warning ("strread: property \"bufsize\" is not implemented");
+        numeric_fill_value = varargin{n+1};
+      case "expchars"
+        warning ('strread: property "expchars" is not implemented');
       case "whitespace"
-        white_spaces = varargin {n+1};
-      case "expchars"
-        warning ("strread: property \"expchars\" is not implemented");
+        white_spaces = varargin{n+1};
+      ## The following parameters are specific to textscan and textread
+      case "endofline"
+        eol_char = varargin{n+1};
+      case "returnonerror"
+        err_action = varargin{n+1};
+      case "multipledelimsasone"
+        mult_dlms_s1 = varargin{n+1};
+      case "treatasempty"
+        if (iscellstr (varargin{n+1}))
+          empty_str = varargin{n+1};
+        elseif (ischar (varargin{n+1}))
+          empty_str = varargin(n+1);
+        else
+          error ('strread: "treatasempty" value must be string or cellstr');
+        endif
       otherwise
-        warning ("strread: unknown property \"%s\"", varargin {n});
+        warning ('strread: unknown property "%s"', varargin{n});
     endswitch
   endfor
-  if (isempty (delimiter_str))
-    delimiter_str = white_spaces;
+
+  ## First parse of FORMAT
+  if (strcmpi (strtrim (format), "%f"))
+    ## Default format specified.  Expand it (to desired nargout)
+    fmt_words = cell (nargout, 1);
+    fmt_words (1:nargout) = format;
+  else
+    ## Determine the number of words per line as a first guess.  Forms
+    ## like %f<literal>) (w/o delimiter in between) are fixed further on
+    format = strrep (format, "%", " %");
+    fmt_words = regexp (format, '[^ ]+', 'match');
+    ## Format conversion specifiers following literals w/o space/delim
+    ## in between are separate now.  Separate those w trailing literals
+    idy2 = find (! cellfun ("isempty", strfind (fmt_words, "%")));
+    a = strfind (fmt_words(idy2), "%");
+    b = regexp (fmt_words(idy2), '[nfdus]', 'end');
+    for jj = 1:numel (a)
+      ii = numel (a) - jj + 1;
+      if (! (length (fmt_words{idy2(ii)}) == b{ii}(1)))
+        ## Fix format_words
+        fmt_words(idy2(ii)+1 : end+1) = fmt_words(idy2(ii) : end);
+        fmt_words{idy2(ii)} = fmt_words{idy2(ii)}(a{ii} : b{ii}(1));
+        fmt_words{idy2(ii)+1} = fmt_words{idy2(ii)+1}(b{ii}+1:end);
+      endif
+    endfor
+  endif
+  num_words_per_line = numel (fmt_words);
+
+  ## Special handling for CRLF EOL character in str
+  if (! isempty (eol_char) && strcmp (eol_char, "\r\n"))
+    ## Strip CR from CRLF sequences
+    str = strrep (str, "\r\n", "\n");
+    ## CR serves no further purpose in function
+    eol_char = "\n";
   endif
 
-  ## Parse format string
-  idx = strfind (format, "%")';
-  specif = format ([idx, idx+1]);
-  nspecif = length (idx);
-  idx_star = strfind (format, "%*");
-  nfields = length (idx) - length (idx_star);
-
-  if (max (nargout, 1) != nfields)
-    error ("strread: the number of output variables must match that specified byFORMAT");
-  endif
-
-  ## Remove comments
+  ## Remove comments in str
   if (comment_flag)
-    cstart = strfind (str, comment_specif{1});
-    cstop  = strfind (str, comment_specif{2});
-    if (length (cstart) > 0)
+    ## Expand 'eol_char' here, after option processing which may have set value
+    comment_end = regexprep (comment_end, 'eol_char', eol_char); 
+    cstart = strfind (str, comment_start);
+    cstop  = strfind (str, comment_end);
+    ## Treat end of string as additional comment stop
+    if (isempty (cstop) || cstop(end) != length (str))
+      cstop(end+1) = length (str);
+    endif
+    if (! isempty (cstart))
       ## Ignore nested openers.
       [idx, cidx] = unique (lookup (cstop, cstart), "first");
       if (idx(end) == length (cstop))
@@ -172,7 +305,7 @@
       endif
       cstart = cstart(cidx);
     endif
-    if (length (cstop) > 0)
+    if (! isempty (cstop))
       ## Ignore nested closers.
       [idx, cidx] = unique (lookup (cstart, cstop), "first");
       if (idx(1) == 0)
@@ -181,101 +314,406 @@
       cstop = cstop(cidx);
     endif
     len = length (str);
-    c2len = length (comment_specif{2});
+    c2len = length (comment_end);
     str = cellslices (str, [1, cstop + c2len], [cstart - 1, len]);
     str = [str{:}];
   endif
 
-  ## Determine the number of words per line
-  format = strrep (format, "%", " %");
-  [~, ~, ~, fmt_words] = regexp (format, '[^ ]+');
+  if (! isempty (white_spaces))
+    ## Remove any delimiter chars from white_spaces list
+    white_spaces = setdiff (white_spaces, delimiter_str);
+  endif
+  if (isempty (delimiter_str))
+    delimiter_str = " ";
+  endif
+  if (! isempty (eol_char))
+    ## Add eol_char to delimiter collection
+    delimiter_str = unique ([delimiter_str eol_char]);
+    ## .. and remove it from whitespace collection
+    white_spaces = strrep (white_spaces, eol_char, '');
+  endif
 
-  num_words_per_line = numel (fmt_words);
-  for m = 1:numel(fmt_words)
-    ## Convert formats such as "%Ns" to "%s" (see the FIXME below)
-    if (length (fmt_words{m}) > 2)
-      if (strcmp (fmt_words{m}(1:2), "%*"))
-        fmt_words{m} = "%*";
-      elseif (fmt_words{m}(1) == "%")
-        fmt_words{m} = fmt_words{m}([1, end]);
-      endif
+  pad_out = 0;
+  ## Trim whitespace if needed
+  ## FIXME: This is very complicated.  Can this be simplified with regexprep?
+  if (! isempty (white_spaces))
+    ## Check if trailing "\n" might signal padding output arrays to equal size
+    ## before it is trimmed away below
+    if ((str(end) == 10) && (nargout > 1)) 
+      pad_out = 1;
     endif
-  endfor
+    ## Remove repeated white_space chars.  First find white_space positions
+    idx = strchr (str, white_spaces);
+    ## Find repeated white_spaces
+    idx2 = ! (idx(2:end) - idx(1:end-1) - 1);
+    ## Set all whitespace chars to spaces
+    ## FIXME: this implies real spaces are always part of white_spaces
+    str(idx) = ' ';
+    ## Set all repeated white_space to \0
+    str(idx(idx2)) = "\0";
+    str = strsplit (str, "\0");
+    ## Reconstruct trimmed str
+    str = cell2mat (str);
+    ## Remove leading & trailing space, but preserve delimiters.
+    str = strtrim (str);
+    ## FIXME: Double strrep on str is enormously expensive of CPU time.
+    ## Can this be eliminated
+    ## Wipe leading and trailing whitespace on each line (it may be delimiter too)
+    if (! isempty (eol_char))
+      str = strrep (str, [eol_char " "], eol_char);
+      str = strrep (str, [" " eol_char], eol_char);
+    endif
+  endif
 
   ## Split 'str' into words
-  words = split_by (str, delimiter_str);
+  words = split_by (str, delimiter_str, mult_dlms_s1, eol_char);
+  if (! isempty (white_spaces))
+    ## Trim leading and trailing white_spaces
+    ## FIXME: Is this correct?  strtrim clears what matches isspace(), not
+    ## necessarily what is in white_spaces.
+    words = strtrim (words);
+  endif
   num_words = numel (words);
+  ## First guess at number of lines in file (ignoring leading/trailing literals)
   num_lines = ceil (num_words / num_words_per_line);
 
-  ## For each specifier
+  ## Replace TreatAsEmpty char sequences by empty strings
+  if (! isempty (empty_str))
+    for ii = 1:numel (empty_str)
+      idz = strmatch (empty_str{ii}, words, "exact");
+      words(idz) = {""};
+    endfor
+  endif
+  
+  ## We now may have to cope with 3 cases:
+  ## A: Trailing literals (%f<literal>) w/o delimiter in between.
+  ## B: Leading literals (<literal>%f) w/o delimiter in between.
+  ## C. Skipping leftover parts of specified skip fields (%*N )
+  ## fmt_words has been split properly now, but words{} has only been split on
+  ## delimiter positions.  Some words columns may have to be split further.
+  ## We also don't know the number of lines (as EndOfLine may have been set to
+  ## "" (empty) by the caller).
+
+  ## Find indices and pointers to possible literals in fmt_words
+  idf = cellfun ("isempty", strfind (fmt_words, "%"));
+  ## Find indices and pointers to conversion specifiers with fixed width
+  idg = ! cellfun ("isempty", regexp (fmt_words, '%\*?\d'));
+  idy = find (idf | idg); 
+
+  ## If needed, split up columns in three steps:
+  if (! isempty (idy))
+    ## Try-catch because complexity of strings to read can be infinite    
+    #try
+
+      ## 1. Assess "period" in the split-up words array ( < num_words_per_line).
+      ## Could be done using EndOfLine but that prohibits EndOfLine = "" option.
+      ## Alternative below goes by simply parsing a first grab of words
+      ## and counting words until the fmt_words array is exhausted:
+      iwrd = 1; iwrdp = 0; iwrdl = length (words{iwrd});
+      for ii = 1:numel (fmt_words)
+
+        if (idf(ii))
+          ## Literal expected
+          if (isempty (strfind (fmt_words{ii}, words(iwrd))))
+            ## Not found in current word; supposed to be in next word
+            ++iwrd; iwrdp = 0;
+            if (ii < numel (fmt_words))
+              iwrdl = length (words{iwrd});
+            endif
+          else
+            ## Found it in current word.  Subtract literal length
+            iwrdp += length (fmt_words{ii});
+            if (iwrdp > iwrdl)
+              ## Parse error.  Literal extends beyond delimiter (word boundary)
+              error ("strread: Literal '%s' (fmt spec # %d) does not match data", fmt_words{ii}, ii);
+            elseif (iwrdp == iwrdl)
+              ## Word completely "used up". Next word
+              ++iwrd; iwrdp = 0;
+              if (ii < numel (fmt_words))
+                iwrdl = length (words{iwrd});
+              endif
+            endif
+          endif
+
+        elseif (idg(ii))
+          ## Fixed width specifier (%N or %*N): read just a part of word
+            iwrdp += floor ...
+             (str2double (fmt_words{ii}(regexp(fmt_words{ii}, '\d') : end-1)));
+            if (iwrdp > iwrdl)
+              ## Error. Field extends beyond word boundary.
+              error ("strread: Field width '%s' (fmt spec # %d) extends beyond word limit", fmt_words{ii}, ii);
+            elseif (iwrdp == iwrdl)
+              ## Word completely "used up".  Next word
+              ++iwrd; iwrdp = 0; iwrdl = length (words{iwrd});
+            endif
+   
+        else
+          ## A simple format conv. specifier. Either (1) uses rest of word, or
+          ## (2) is squeezed between current iwrdp and next literal, or (3) uses
+          ## next word. (3) is already taken care of.  So just check (1) & (2)
+          if (ii < numel (fmt_words) && idf(ii+1))
+            ## Next fmt_word is a literal...
+            if (! index (words{iwrd}(iwrdp+1:end), fmt_words{ii+1}))
+              ## ...but not found in current word => field uses rest of word
+              ++iwrd; iwrdp = 0; iwrdl = length (words{iwrd});
+            else
+              ## ..or it IS found.  Add inferred width of current conversion field
+              iwrdp += index (words{iwrd}(iwrdp+1:end), fmt_words{ii+1}) - 1;
+            endif
+          elseif (iwrdp < iwrdl)
+            ## No bordering literal to the right => field occupies (rest of) word
+            ++iwrd; iwrdp = 0; 
+            if (ii < numel (fmt_words))
+              iwrdl = length (words{iwrd});
+            endif
+          endif
+
+        endif
+      endfor
+      ## Done
+      words_period = max (iwrd - 1, 1);
+      num_lines = ceil (num_words / words_period);
+
+      ## 2. Pad words array so that it can be reshaped
+      tmp_lines = ceil (num_words / words_period);
+      num_words_padded = tmp_lines * words_period - num_words;
+      if (num_words_padded)
+        words = [words'; cell(num_words_padded, 1)]; 
+      endif
+      words = reshape (words, words_period, tmp_lines);
+
+      ## 3. Do the column splitting on rectangular words array
+      icol = 1; ii = 1;    # icol = current column, ii = current fmt_word
+      while (ii <= num_words_per_line)
+
+        ## Check if fmt_words(ii) contains a literal or fixed-width
+        if ((idf(ii) || idg(ii)) && (rows(words) < num_words_per_line))
+          if (idf(ii))
+            s = strfind (words(icol, 1), fmt_words{ii});
+            if (isempty (s{:}))
+              error ("strread: Literal '%s' not found in column %d", fmt_words{ii}, icol);
+            endif
+            s = s{:}(1);
+            e = s(1) + length (fmt_words{ii}) - 1;
+          endif
+          if (! strcmp (fmt_words{ii}, words{icol, 1}))
+            ## Column doesn't exactly match literal => split needed.  Insert a column
+            words(icol+1:end+1, :) = words(icol:end, :); 
+            ## Watch out for empty cells
+            jptr = find (! cellfun ("isempty", words(icol, :)));
+
+            ## Distinguish leading or trailing literals
+            if (! idg(ii) && ! isempty (s) && s(1) == 1)
+              ## Leading literal.  Assign literal to icol, paste rest in icol + 1
+              ## Apply only to those cells that do have something beyond literal
+              jptr = find (cellfun("length", words(icol+1, jptr), ...
+                            "UniformOutput", false) > e(1));
+              words(icol+1, :) = {""};
+              words(icol+1, jptr) = cellfun ...
+                (@(x) substr(x, e(1)+1, length(x)-e(1)), words(icol, jptr), ...
+                "UniformOutput", false);
+              words(icol, jptr) = fmt_words{ii};
+
+            else
+              if (! idg(ii) && ! isempty (strfind (fmt_words{ii-1}, "%s")))
+                ## Trailing literal.  If preceding format == '%s' this is an error
+                warning ("Ambiguous '%s' specifier next to literal in column %d", icol);
+              elseif (idg(ii))
+                ## Current field = fixed width. Strip into icol, rest in icol+1
+                wdth = floor (str2double (fmt_words{ii}(regexp(fmt_words{ii}, ...
+                              '\d') : end-1)));
+                words(icol+1, jptr) = cellfun (@(x) x(wdth+1:end),
+                     words(icol,jptr), "UniformOutput", false);                 
+                words(icol, jptr) = strtrunc (words(icol, jptr), wdth);
+              else
+                ## FIXME: this assumes char(254)/char(255) won't occur in input!
+                clear wrds;
+                wrds(1:2:2*numel (words(icol, jptr))) = ...
+                     strrep (words(icol, jptr), fmt_words{ii}, ...
+                     [char(255) char(254)]);
+                wrds(2:2:2*numel (words(icol, jptr))-1) = char(255);
+                wrds = strsplit ([wrds{:}], char(255));
+                words(icol, jptr) = ...
+                  wrds(find (cellfun ("isempty", strfind (wrds, char(254)))));
+                wrds(find (cellfun ("isempty", strfind (wrds, char(254))))) ...
+                   = char(255);
+                words(icol+1, jptr) = strsplit (strrep ([wrds{2:end}], ...
+                   char(254), fmt_words{ii}), char(255));
+                ## Former trailing literal may now be leading for next specifier
+                --ii;
+              endif
+            endif
+          endif
+
+        else
+          ## Conv. specifier.  Peek if next fmt_word needs split from current column
+          if (ii < num_words_per_line && idf(ii+1))
+            if (! isempty (strfind (words{icol, 1}, fmt_words{ii+1})))
+              --icol;
+            endif
+          endif
+        endif
+        ## Next fmt_word, next column
+        ++ii; ++icol;
+      endwhile
+
+      ## Done.  Reshape words back into 1 long vector and strip padded empty words
+      words = reshape (words, 1, numel (words))(1 : end-num_words_padded);
+
+    #catch
+    #  warning ("strread: unable to parse text or file with given format string");
+    #  return;
+
+    #end_try_catch
+  endif
+  
+  ## For each specifier, process corresponding column
   k = 1;
   for m = 1:num_words_per_line
-    data = words (m:num_words_per_line:end);
-    ## Map to format
-    ## FIXME - add support for formats like "%4s" or "<%s>", "%[a-zA-Z]"
-    ##         Someone with regexp experience is needed.
-    switch fmt_words{m}
-      case "%s"
-        data (end+1:num_lines) = {""};
-        varargout {k} = data';
-        k++;
-      case {"%d", "%f"}
-        n = cellfun (@isempty, data);
-        data = str2double (data);
-        data(n) = numeric_fill_value;
-        data (end+1:num_lines) = numeric_fill_value;
-        varargout {k} = data.';
-        k++;
-      case {"%*", "%*s"}
-        ## skip the word
-      otherwise
-        ## Ensure descriptive content is consistent
-        if (numel (unique (data)) > 1
-            || ! strcmpi (unique (data), fmt_words{m}))
-          error ("strread: FORMAT does not match data");
-        endif
-    endswitch
+    try
+      if (format_repeat_count < 0)
+        data = words(m:num_words_per_line:end);
+      elseif (format_repeat_count == 0)
+        data = {};
+      else
+        lastline = ...
+          min (num_words_per_line * format_repeat_count + m - 1, numel (words));
+        data = words(m:num_words_per_line:lastline);
+      endif
+
+      ## Map to format
+      ## 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)
+            data(end+1:num_lines) = {""}; 
+          endif
+          varargout{k} = data';
+          k++;
+        case {"%d", "%u", "%f", "%n"}
+          n = cellfun ("isempty", data);
+          ### FIXME - erroneously formatted data lead to NaN, not an error
+          data = str2double (data);
+          if (! isempty (regexp (fmt_words{m}, "%[du]")))
+            ## Cast to integer 
+            ## FIXME: NaNs will be transformed into zeros
+            data = int32 (data);
+          end
+          data(n) = numeric_fill_value;
+          if (pad_out)
+            data(end+1:num_lines) = numeric_fill_value;
+          endif
+          varargout{k} = data.';
+          k++;
+        case {"%0", "%1", "%2", "%3", "%4", "%5", "%6", "%7", "%8", "%9"}
+          nfmt = strsplit (fmt_words{m}(2:end-1), '.');
+          swidth = str2double (nfmt{1});
+          switch fmt_words{m}(end)
+            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
+              data = str2double (strtrunc (data, swidth));
+              data(n) = numeric_fill_value;
+              if (pad_out)
+                data(end+1:num_lines) = numeric_fill_value;
+              endif
+              if (numel (nfmt) > 1)
+                sprec = str2double (nfmt{2});
+                data = 10^-sprec * round (10^sprec * data);
+              elseif (! isempty (regexp (fmt_words{m}, "[du]")))
+                ## Cast to integer 
+                ## FIXME: NaNs will be transformed into zeros
+                data = int32 (data);
+              end
+              varargout{k} = data.';
+              k++;
+            case "s"
+              if (pad_out)
+                data(end+1:num_lines) = {""}
+              endif
+              varargout{k} = strtrunc (data, swidth)';
+              k++;
+            otherwise
+          endswitch
+        case {"%*", "%*s"}
+          ## skip the word
+        otherwise
+          ## Ensure descriptive content is consistent.
+          ## Test made a bit lax to accomodate for incomplete last lines
+          n = find (! cellfun ("isempty", data));
+          if (numel (unique (data(n))) > 1
+              || ! strcmpi (unique (data), fmt_words{m}))
+            error ("strread: FORMAT does not match data");
+          endif
+      endswitch
+    catch
+      ## As strread processes columnwise, ML-compatible error processing
+      ## (row after row) is not feasible. In addition Octave sets unrecognizable
+      ## numbers to NaN w/o error.  But maybe Octave is better in this respect.
+      if (err_action)
+        ## Just try the next column where ML bails out
+      else
+        rethrow (lasterror);
+      endif
+    end_try_catch
   endfor
+
 endfunction
 
-function out = split_by (text, sep)
-  sep = union (sep, "\n");
-  pat = sprintf ('[^%s]+', sep);
-  [~, ~, ~, out] = regexp (text, pat);
-  out(cellfun (@isempty, out)) = {""};
-  out = strtrim (out);
+function out = split_by (text, sep, mult_dlms_s1, eol_char)
+
+  ## Check & if needed, process MultipleDelimsAsOne parameter
+  if (mult_dlms_s1)
+    mult_dlms_s1 = true;
+    ## FIXME: Should re-implement strsplit() function here in order
+    ## to avoid strrep on megabytes of data.
+    ## If \n is in sep collection we need to enclose it in spaces in text
+    ## to avoid it being included in consecutive delim series
+    text = strrep (text, eol_char, [" " eol_char " "]);
+  else
+    mult_dlms_s1 = false;
+  endif
+
+  ## Split text string along delimiters
+  out = strsplit (text, sep, mult_dlms_s1);
+  ## In case of trailing delimiter, strip stray last empty word
+  if (!isempty (out) && any (sep == text(end)))
+    out(end) = [];
+  endif
+  
+  ## Empty cells converted to empty cellstrings.
+  out(cellfun ("isempty", out)) = {""};
+
 endfunction
 
+
 %!test
 %! [a, b] = strread ("1 2", "%f%f");
-%! assert (a == 1 && b == 2);
-
-%!test
-%! str = "# comment\n# comment\n1 2 3";
-%! [a, b] = strread (str, '%d %s', 'commentstyle', 'shell');
-%! assert (a, [1; 3]);
-%! assert (b, {"2"; ""});
+%! assert (a, 1);
+%! assert (b, 2);
 
 %!test
 %! str = '';
 %! a = rand (10, 1);
-%! b = char (round (65 + 20 * rand (10, 1)));
+%! b = char (randi ([65, 85], 10, 1));
 %! for k = 1:10
-%!   str = sprintf ('%s %.6f %s\n', str, a (k), b (k));
+%!   str = sprintf ('%s %.6f %s\n', str, a(k), b(k));
 %! endfor
 %! [aa, bb] = strread (str, '%f %s');
-%! assert (a, aa, 1e-5);
+%! assert (a, aa, 1e-6);
 %! assert (cellstr (b), bb);
 
 %!test
 %! str = '';
 %! a = rand (10, 1);
-%! b = char (round (65 + 20 * rand (10, 1)));
+%! b = char (randi ([65, 85], 10, 1));
 %! for k = 1:10
-%!   str = sprintf ('%s %.6f %s\n', str, a (k), b (k));
+%!   str = sprintf ('%s %.6f %s\n', str, a(k), b(k));
 %! endfor
 %! aa = strread (str, '%f %*s');
-%! assert (a, aa, 1e-5);
+%! assert (a, aa, 1e-6);
 
 %!test
 %! str = sprintf ('/* this is\nacomment*/ 1 2 3');
@@ -283,6 +721,12 @@
 %! assert (a, [1; 2; 3]);
 
 %!test
+%! str = "# comment\n# comment\n1 2 3";
+%! [a, b] = strread (str, '%n %s', 'commentstyle', 'shell', 'endofline', "\n");
+%! assert (a, [1; 3]);
+%! assert (b, {"2"});
+
+%!test
 %! str = sprintf ("Tom 100 miles/hr\nDick 90 miles/hr\nHarry 80 miles/hr");
 %! fmt = "%s %f miles/hr";
 %! c = cell (1, 2);
@@ -294,3 +738,65 @@
 %! a = strread ("a b c, d e, , f", "%s", "delimiter", ",");
 %! assert (a, {"a b c"; "d e"; ""; "f"});
 
+%!test
+%! # Bug #33536
+%! [a, b, c] = strread ("1,,2", "%s%s%s", "delimiter", ",");
+%! assert (a{1}, '1');
+%! assert (b{1}, '');
+%! assert (c{1}, '2');
+
+%!test
+%! # Bug #33536
+%! a = strread ("[SomeText]", "[%s", "delimiter", "]");
+%! assert (a{1}, "SomeText");
+
+%!test
+%! dat = "Data file.\r\n=  =  =  =  =\r\nCOMPANY    : <Company name>\r\n";
+%! a = strread (dat, "%s", 'delimiter', "\n", 'whitespace', '', 'endofline', "\r\n");
+%! assert (a{2}, "=  =  =  =  =");
+%! assert (double (a{3}(end-5:end)), [32 110 97 109 101 62]);
+
+%!test
+%! [a, b, c, d] = strread ("1,2,3,,5,6", "%d%f%d%f", 'delimiter', ',');
+%! assert (c, int32 (3));
+%! assert (d, NaN);
+
+%!test
+%! [a, b, c, d] = strread ("1,2,3,,5,6\n", "%d%d%f%d", 'delimiter', ',');
+%! assert (c, [3; NaN]);
+%! assert (d, int32 ([0; 0]));
+
+%!test
+%! # Default format (= %f)
+%1 [a, b, c] = strread ("0.12 0.234 0.3567");
+%1 assert (a, 0.12);
+%1 assert (b, 0.234);
+%1 assert (c, 0.3567);
+
+%!test
+%! [a, b] = strread('0.41 8.24 3.57 6.24 9.27', "%f%f", 2, 'delimiter', ' ');
+%1 assert (a, [0.41; 3.57]);
+
+%!test
+%! # TreatAsEmpty
+%! [a, b, c, d] = strread ("1,2,3,NN,5,6\n", "%d%d%d%f", 'delimiter', ',', 'TreatAsEmpty', 'NN');
+%! assert (c, int32 ([3; 0]));
+%! assert (d, [NaN; NaN]);
+
+%!test
+%! # No delimiters at all besides EOL.  Plain reading numbers & strings
+%! str = "Text1Text2Text\nText398Text4Text\nText57Text";
+%! c = textscan (str, "Text%dText%1sText");
+%! assert (c{1}, int32 ([1; 398; 57]));
+%! assert (c{2}(1:2), {'2'; '4'});
+%! assert (isempty (c{2}{3}), true);
+
+%% MultipleDelimsAsOne
+%!test
+%! str = "11, 12, 13,, 15\n21,, 23, 24, 25\n,, 33, 34, 35";
+%! [a b c d] = strread (str, "%f %f %f %f", 'delimiter', ',', 'multipledelimsasone', 1, 'endofline', "\n");
+%! assert (a', [11, 21, NaN]);
+%! assert (b', [12, 23, 33]);
+%! assert (c', [13, 24, 34]);
+%! assert (d', [15, 25, 35]);
+
--- a/scripts/io/textread.m
+++ b/scripts/io/textread.m
@@ -19,30 +19,43 @@
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {[@var{a}, @dots{}] =} textread (@var{filename})
 ## @deftypefnx {Function File} {[@var{a}, @dots{}] =} textread (@var{filename}, @var{format})
+## @deftypefnx {Function File} {[@var{a}, @dots{}] =} textread (@var{filename}, @var{format}, @var{n})
 ## @deftypefnx {Function File} {[@var{a}, @dots{}] =} textread (@var{filename}, @var{format}, @var{prop1}, @var{value1}, @dots{})
+## @deftypefnx {Function File} {[@var{a}, @dots{}] =} textread (@var{filename}, @var{format}, @var{n}, @var{prop1}, @var{value1}, @dots{})
 ## Read data from a text file.
 ##
 ## The file @var{filename} is read and parsed according to @var{format}.  The
 ## function behaves like @code{strread} except it works by parsing a file
-## instead
-## of a string.  See the documentation of @code{strread} for details.
+## instead of a string.  See the documentation of @code{strread} for details.
+##
 ## In addition to the options supported by @code{strread}, this function
-## supports one more:
+## supports two more:
+##
 ## @itemize
 ## @item "headerlines":
+## The first @var{value} number of lines of @var{filename} are skipped.
+##
+## @item "endofline":
+## Specify a single character or "\r\n".  If no value is given, it will be
+## inferred from the file.  If set to "" (empty string) EOLs are ignored as
+## delimiters.
 ## @end itemize
-## The first @var{value} number of lines of @var{str} are skipped.
-## @seealso{strread, load, dlmread, fscanf}
+##
+## The optional input @var{n} specifes the number of times to use 
+## @var{format} when parsing, i.e., the format repeat count.
+##
+## @seealso{strread, load, dlmread, fscanf, textscan}
 ## @end deftypefn
 
 function varargout = textread (filename, format = "%f", varargin)
+
   ## Check input
   if (nargin < 1)
     print_usage ();
   endif
 
-  if (!ischar (filename) || !ischar (format))
-    error ("textread: first and second input arguments must be strings");
+  if (! ischar (filename) || ! ischar (format))
+    error ("textread: FILENAME and FORMAT arguments must be strings");
   endif
 
   ## Read file
@@ -51,21 +64,85 @@
     error ("textread: could not open '%s' for reading", filename);
   endif
 
-  ## Maybe skip header lines
+  ## Skip header lines if requested
   headerlines = find (strcmpi (varargin, "headerlines"), 1);
-  if (! isempty (headerlines))
-    hdr_lines = floor (varargin{headerlines + 1});
-    ## Beware of zero valued headerline, fskipl will count lines to EOF then
-    if (hdr_lines > 0)
-      fskipl (fid, hdr_lines);
-    endif
+  ## Beware of zero valued headerline, fskipl would skip to EOF
+  if (! isempty (headerlines) && (varargin{headerlines + 1} > 0))
+    fskipl (fid, varargin{headerlines + 1});
     varargin(headerlines:headerlines+1) = [];
   endif
 
-  str = fread (fid, "char=>char").';
+  if (nargin > 2 && isnumeric (varargin{1}))
+    nlines = varargin{1};
+  else
+    nlines = Inf;
+  endif
+
+  if (isfinite (nlines) && (nlines >= 0))
+    str = tmp_str = "";
+    n = 0;
+    ## FIXME: Can this be done without slow loop?
+    while (ischar (tmp_str) && n++ <= nlines)
+      str = strcat (str, tmp_str);
+      tmp_str = fgets (fid);
+    endwhile
+  else
+    str = fread (fid, "char=>char").';
+  endif
   fclose (fid);
 
+  if (isempty (str))
+    warning ("textread: empty file");
+    return;
+  endif
+
+  endofline = find (strcmpi (varargin, "endofline"), 1);
+  if (! isempty (endofline))
+    ## 'endofline' option set by user.  
+    if (! ischar (varargin{endofline + 1})); 
+      error ("textread: character value required for EndOfLine"); 
+    endif
+  else
+    ## Determine EOL from file.  Search for EOL candidates in first 3000 chars
+    eol_srch_len = min (length (str), 3000);
+    ## First try DOS (CRLF)
+    if (! isempty (findstr ("\r\n", str(1 : eol_srch_len))))
+      eol_char = "\r\n";
+    ## Perhaps old Macintosh? (CR)
+    elseif (! isempty (findstr ("\r", str(1 : eol_srch_len))))
+      eol_char = "\r";
+    ## Otherwise, use plain UNIX (LF)
+    else
+      eol_char = "\n";
+    endif
+    ## Set up default endofline param value
+    varargin(end+1:end+2) = {'endofline', eol_char};
+  endif
+
+  ## Set up default whitespace param value if needed
+  if (isempty (find (strcmpi ('whitespace', varargin))))
+    varargin(end+1:end+2) = {'whitespace', " \b\t"};
+  endif
+
   ## Call strread to make it do the real work
   [varargout{1:max (nargout, 1)}] = strread (str, format, varargin {:});
 
 endfunction
+
+
+%!test
+%! f = tmpnam();
+%! d = rand (5, 3);
+%! dlmwrite (f, d, 'precision', '%5.2f');
+%! [a, b, c] = textread (f, "%f %f %f", "delimiter", ",", "headerlines", 3);
+%! unlink(f);
+%! assert (a, d(4:5, 1), 1e-2);
+%! assert (b, d(4:5, 2), 1e-2);
+%! assert (c, d(4:5, 3), 1e-2);
+
+%% Test input validation
+%!error textread ()
+%!error textread (1)
+%!error <arguments must be strings> textread (1, '%f')
+%!error <arguments must be strings> textread ("fname", 1)
+
--- a/scripts/io/textscan.m
+++ b/scripts/io/textscan.m
@@ -22,23 +22,40 @@
 ## @deftypefnx {Function File} {@var{C} =} textscan (@var{fid}, @var{format}, @var{param}, @var{value}, @dots{})
 ## @deftypefnx {Function File} {@var{C} =} textscan (@var{fid}, @var{format}, @var{n}, @var{param}, @var{value}, @dots{})
 ## @deftypefnx {Function File} {@var{C} =} textscan (@var{str}, @dots{})
-## @deftypefnx {Function File} {[@var{C}, @var{position}] =} textscan (@dots{})
-## Read data from a text file.
+## @deftypefnx {Function File} {[@var{C}, @var{position}] =} textscan (@var{fid}, @dots{})
+## Read data from a text file or string.
 ##
 ## The file associated with @var{fid} is read and parsed according to
 ## @var{format}.  The function behaves like @code{strread} except it works by
 ## parsing a file instead of a string.  See the documentation of
-## @code{strread} for details.  In addition to the options supported by
-## @code{strread}, this function supports one more:
+## @code{strread} for details.  
+##
+## In addition to the options supported by
+## @code{strread}, this function supports a few more:
+##
 ## @itemize
+## @item "collectoutput":
+## A value of 1 or true instructs textscan to concatenate consecutive columns
+## of the same class in the output cell array.  A value of 0 or false (default)
+## leaves output in distinct columns.
+##
+## @item "endofline":
+## Specify "\r", "\n" or "\r\n" (for CR, LF, or CRLF).  If no value is given,
+## it will be inferred from the file.  If set to "" (empty string) EOLs are
+## ignored as delimiters and added to whitespace.
+##
 ## @item "headerlines":
+## The first @var{value} number of lines of @var{fid} are skipped.
+##
+## @item "returnonerror":
+## If set to numerical 1 or true (default), return normally when read errors
+## have been encountered.  If set to 0 or false, return an error and no data.
 ## @end itemize
-## The first @var{value} number of lines of @var{str} are skipped.
 ##
-## The optional input, @var{n}, specifes the number of lines to be read from
-## the file, associated with @var{fid}.
+## The optional input @var{n} specifes the number of times to use 
+## @var{format} when parsing, i.e., the format repeat count.
 ##
-## The output, @var{C}, is a cell array whose length is given by the number
+## The output @var{C} is a cell array whose length is given by the number
 ## of format specifiers.
 ##
 ## The second output, @var{position}, provides the position, in characters,
@@ -47,89 +64,208 @@
 ## @seealso{dlmread, fscanf, load, strread, textread}
 ## @end deftypefn
 
-function [C, p] = textscan (fid, format, varargin)
+function [C, position] = textscan (fid, format = "%f", varargin)
 
   ## Check input
   if (nargin < 1)
     print_usage ();
-  elseif (nargin == 1 || isempty (format))
+  endif
+
+  if (isempty (format))
     format = "%f";
   endif
 
-  if (nargin > 2 && isnumeric (varargin{1}))
-    nlines = varargin{1};
-    args = varargin(2:end);
+  if (! (isa (fid, "double") && fid > 0) && ! ischar (fid))
+    error ("textscan: first argument must be a file id or character string");
+  endif
+
+  if (! ischar (format))
+    error ("textscan: FORMAT must be a string");
+  endif
+
+  args = varargin;
+  if (nargin > 2 && isnumeric (args{1}))
+    nlines = args{1};
   else
     nlines = Inf;
-    args = varargin;
   endif
 
   if (! any (strcmpi (args, "emptyvalue")))
     ## Matlab returns NaNs for missing values
-    args{end+1} = "emptyvalue";
-    args{end+1} = NaN;
+    args(end+1:end+2) = {'emptyvalue', NaN};
+  endif
+
+  ## Check default parameter values that differ for strread & textread
+
+  ipos = find (strcmpi (args, "whitespace"));
+  if (isempty (ipos))
+    ## Matlab default whitespace = " \b\t"
+    args(end+1:end+2) = {'whitespace', " \b\t"};
+    whitespace = " \b\t";
+  else
+    ## Check if there's at least one string format specifier
+    fmt = strrep (format, "%", " %");
+    fmt = regexp (fmt, '[^ ]+', 'match');
+    fmt = strtrim (fmt(strmatch ("%", fmt)))
+    has_str_fmt = all (cellfun ("isempty", strfind (strtrim (fmt(strmatch ("%", fmt))), 's')));
+    ## If there is a format, AND whitespace value = empty, 
+    ## don't add a space (char(32)) to whitespace
+    if (! (isempty (args{ipos+1}) &&  has_str_fmt))
+      args{ipos+1} = unique ([" ", whitespace]);
+    endif
+  endif
+
+  if (! any (strcmpi (args, "delimiter")))
+    ## Matlab says default delimiter = whitespace.  
+    ## strread() will pick this up further
+    args(end+1:end+2) = {'delimiter', ""};
+  endif
+
+  collop = false;
+  ipos = find (strcmpi (args, "collectoutput"));
+  if (! isempty (ipos))
+    ## Search & concatenate consecutive columns of same class requested
+    if (isscalar (args{ipos+1})
+        && (islogical (args{ipos+1}) || isnumeric (args{ipos+1})))
+      collop = args{ipos+1};
+    else
+      warning ("textscan: illegal value for CollectOutput parameter - ignored");
+    endif
+    ## Remove argument before call to strread() below
+    args(ipos:ipos+1) = [];
+  endif
+
+  if (any (strcmpi (args, "returnonerror")))
+    ## Because of the way strread() reads data (columnwise) this parameter
+    ## can't be neatly implemented.  strread() will pick it up anyway
+    warning ('textscan: ReturnOnError is not fully implemented');
+  else
+    ## Set default value (=true)
+    args(end+1:end+2) = {"returnonerror", 1};
+  endif
+
+  if (ischar (fid))
+    ## Read from a text string
+    if (nargout == 2)
+      error ("textscan: cannot provide position information for character input");
+    endif
+    str = fid;
+  else
+    ## Skip header lines if requested
+    headerlines = find (strcmpi (args, "headerlines"), 1);
+    ## Beware of zero valued headerline, fskipl would skip to EOF
+    if (! isempty (headerlines) && (args{headerlines + 1} > 0))
+      fskipl (fid, varargin{headerlines + 1});
+      args(headerlines:headerlines+1) = []; 
+    endif
+    if (isfinite (nlines) && (nlines >= 0))
+      str = tmp_str = "";
+      n = 0;
+      ## FIXME: Can this be done without slow loop?
+      while (ischar (tmp_str) && n++ < nlines)
+        tmp_str = fgets (fid);
+        if (ischar (tmp_str))
+          str = strcat (str, tmp_str);
+        endif
+      endwhile
+    else
+      str = fread (fid, "char=>char").';
+    endif
   endif
 
-  if (isa (fid, "double") && fid > 0 || ischar (fid))
-    if (ischar (format))
-      if (ischar (fid))
-        if (nargout == 2)
-          error ("textscan: cannot provide position information for character input");
-        endif
-        str = fid;
-      else
-        ## Maybe skip header lines
-        headerlines = find (strcmpi (args, "headerlines"), 1);
-        if (! isempty (headerlines))
-          hdr_lines = floor (varargin{headerlines + 1});
-          ## Beware of zero valued headerline, fskipl will count lines to EOF
-          if (hdr_lines > 0)
-            fskipl (fid, hdr_lines);
-          endif
-        endif
-        if (isfinite (nlines))
-          str = "";
-          for n = 1:nlines
-            str = strcat (str, fgets (fid));
-          endfor
-            else
-          str = fread (fid, "char=>char").';
-        endif
+  ## Check for empty result
+  if (isempty (str))
+    warning ("textscan: no data read");
+    C = [];
+    return;
+  endif
+
+  ## Check value of 'endofline'.  String or file doesn't seem to matter
+  endofline = find (strcmpi (args, "endofline"), 1);
+  if (! isempty (endofline))
+    if (ischar (args{endofline + 1})) 
+      eol_char = args{endofline + 1};
+      if (isempty (strmatch (eol_char, {"", "\n", "\r", "\r\n"}, 'exact')))
+        error ("textscan: illegal EndOfLine character value specified");
       endif
-
-      ## Determine the number of data fields
-      num_fields = numel (strfind (format, "%")) - ...
-                   numel (idx_star = strfind (format, "%*"));
-
-      ## Call strread to make it do the real work
-      C = cell (1, num_fields);
-      [C{:}] = strread (str, format, args{:});
-
-      if (ischar (fid) && isfinite (nlines))
-        C = cellfun (@(x) x(1:nlines), C, "uniformoutput", false);
-      endif
-
-      if (nargout == 2)
-        p = ftell (fid);
-      endif
-
     else
-      error ("textscan: FORMAT must be a valid specification");
+      error ("textscan: character value required for EndOfLine"); 
     endif
   else
-    error ("textscan: first argument must be a file id or character string");
+    ## Determine EOL from file.  Search for EOL candidates in first 3000 chars
+    eol_srch_len = min (length (str), 3000);
+    ## First try DOS (CRLF)
+    if (! isempty (findstr ("\r\n", str(1 : eol_srch_len))))
+      eol_char = "\r\n";
+    ## Perhaps old Macintosh? (CR)
+    elseif (! isempty (findstr ("\r", str(1 : eol_srch_len))))
+      eol_char = "\r";
+    ## Otherwise, use plain UNIX (LF)
+    else
+      eol_char = "\n";
+    endif
+    ## Set up the default endofline param value
+    args(end+1:end+2) = {'endofline', eol_char};
+  endif
+
+  ## Determine the number of data fields
+  num_fields = numel (strfind (format, "%")) - numel (strfind (format, "%*"));
+
+  ## Strip trailing EOL to avoid returning stray missing values (f. strread)
+  if (strcmp (str(end-length (eol_char) + 1 : end), eol_char));
+    str(end-length (eol_char) + 1 : end) = "";
+  endif
+
+  ## Call strread to make it do the real work
+  C = cell (1, num_fields);
+  [C{:}] = strread (str, format, args{:});
+  
+  ## If requested, collect output columns of same class
+  if (collop)
+    C = colloutp (C);
   endif
 
+  if (nargout == 2)
+    position = ftell (fid);
+  endif
+
+endfunction
+
+
+## Collect consecutive columns of same class into one cell column
+function C = colloutp (C)
+
+  ## Start at rightmost column and work backwards to avoid ptr mixup
+  ii = numel (C);
+  while ii > 1
+    clss1 = class (C{ii});
+    jj = ii;
+    while  (jj > 1 && strcmp (clss1, class (C{jj - 1})))
+      ## Column to the left is still same class; check next column to the left
+      --jj;
+    endwhile
+    if (jj < ii)
+      ## Concatenate columns into current column
+      C{jj} = [C{jj : ii}];
+      ## Wipe concatenated columns to the right, resume search to the left
+      C(jj+1 : ii) = [];
+      ii = jj - 1;
+    else
+      ## No similar class in column to the left, search from there
+      --ii;
+    endif
+  endwhile
+
 endfunction
 
 %!test
 %! str = "1,  2,  3,  4\n 5,  ,  ,  8\n 9, 10, 11, 12";
 %! fmtstr = "%f %d %f %s";
 %! c = textscan (str, fmtstr, 2, "delimiter", ",", "emptyvalue", -Inf);
-%! assert (isequal (c{1}, [1;5]))
+%! assert (isequal (c{1}, [1;5]));
 %! assert (length (c{1}), 2);
-%! assert (iscellstr (c{4}))
-%! assert (isequal (c{3}, [3; -Inf]))
+%! assert (iscellstr (c{4}));
+%! assert (isequal (c{3}, [3; -Inf]));
 
 %!test
 %! b = [10:10:100];
@@ -137,7 +273,60 @@
 %! str = sprintf ("%g miles/hr = %g kilometers/hr\n", b);
 %! fmt = "%f miles/hr = %f kilometers/hr";
 %! c = textscan (str, fmt);
-%! assert (b(1,:)', c{1})
-%! assert (b(2,:)', c{2})
+%! assert (b(1,:)', c{1}, 1e-5);
+%! assert (b(2,:)', c{2}, 1e-5);
+
+#%!test
+#%! str = "13, 72, NA, str1, 25\r\n// Middle line\r\n36, na, 05, str3, 6";
+#%! a = textscan(str, '%d %n %f %s %n', 'delimiter', ',','treatAsEmpty', {'NA', 'na'},'commentStyle', '//');
+#%! assert (a{1}, int32([13; 36]));
+#%! assert (a{2}, [72; NaN]);
+#%! assert (a{3}, [NaN; 5]);
+#%! assert (a{4}, {"str1"; "str3"});
+#%! assert (a{5}, [25; 6]);
+
+%!test
+%! str = "Km:10 = hhhBjjj miles16hour\r\n";
+%! str = [str "Km:15 = hhhJjjj miles241hour\r\n"];
+%! str = [str "Km:2 = hhhRjjj miles3hour\r\n"];
+%! str = [str "Km:25 = hhhZ\r\n"];
+%! fmt = "Km:%d = hhh%1sjjj miles%dhour";
+%! a = textscan (str, fmt, 'delimiter', ' ');
+%! assert (a{1}', int32([10 15 2 25]));
+%! assert (a{2}', {'B' 'J' 'R' 'Z'});
+%! assert (a{3}', int32([16 241 3 0]));
+
+%% Test with default endofline parameter
+%!test
+%! c = textscan ("L1\nL2", "%s");
+%! assert (c{:}, {"L1"; "L2"});
 
+%% Test with endofline parameter set to '' (empty) - newline should be in word
+%!test
+%! c = textscan ("L1\nL2", "%s", 'endofline', '');
+%! assert (int8(c{:}{:}), int8([ 76,  49,  10,  76,  50 ]));
 
+%!test
+%! # No delimiters at all besides EOL.  Skip fields, even empty fields
+%! str = "Text1Text2Text\nTextText4Text\nText57Text";
+%! c = textscan (str, "Text%*dText%dText");
+%! assert (c{1}, int32 ([2; 4; 0]));
+
+%!test
+%% CollectOutput test
+%! b = [10:10:100];
+%! b = [b; 8*b/5; 8*b*1000/5];
+%! str = sprintf ("%g miles/hr = %g (%g) kilometers (meters)/hr\n", b);
+%! fmt = "%f miles%s %s %f (%f) kilometers %*s";
+%! c = textscan (str, fmt, 'collectoutput', 1);
+%! assert (size(c{3}), [10, 2]);
+%! assert (size(c{2}), [10, 2]);
+
+%% Test input validation
+%!error textscan ()
+%!error textscan (single (4))
+%!error textscan ({4})
+%!error <must be a string> textscan ("Hello World", 2)
+%!error <cannot provide position information> [C, pos] = textscan ("Hello World")
+%!error <character value required> textscan ("Hello World", '%s', 'EndOfLine', 3)
+
new file mode 100644
--- /dev/null
+++ b/scripts/linear-algebra/bicg.m
@@ -0,0 +1,249 @@
+## Copyright (C) 2006   Sylvain Pelissier   <sylvain.pelissier@gmail.com>
+## Copyright (C) 2011   Carlo de Falco
+##
+## 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 2 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} =} bicg (@var{A}, @var{b}, @var{rtol}, @var{maxit}, @var{M1}, @var{M2}, @var{x0})
+## @deftypefnx {Function File} {@var{x} =} bicg (@var{A}, @var{b}, @var{rtol}, @var{maxit}, @var{P})
+## @deftypefnx {Function File} {[@var{x}, @var{flag}, @var{relres}, @var{iter}, @var{resvec}] =} bicg (@var{A}, @var{b}, ...)
+##
+##   Solve @code{A x = b} using the Bi-conjugate gradient iterative method.
+##
+##   @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 colled 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 relative residual at each iteration.
+##   @end itemize
+##
+##   @seealso{pcg,cgs,bigcstab,gmres}
+##
+## @end deftypefn
+
+
+function [x, flag, res1, k, resvec] = bicg (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 (ismatrix (A))
+      Ax  = @(x) A  * x;
+      Atx = @(x) A' * x;
+    elseif (isa (A, "function_handle"))
+      Ax  = @(x) feval (A, x, "notransp");
+      Atx = @(x) feval (A, x, "transp");
+    else
+      error (["bicg: 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 (ismatrix (M1))
+      M1m1x  = @(x) M1  \ x;
+      M1tm1x = @(x) M1' \ x;
+    elseif (isa (M1, "function_handle"))
+      M1m1x  = @(x) feval (M1, x, "notransp");
+      M1tm1x = @(x) feval (M1, x, "transp");
+    else
+      error (["bicg: 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 (ismatrix (M2))
+      M2m1x  = @(x) M2  \ x;
+      M2tm1x = @(x) M2' \ x;
+    elseif (isa (M2, "function_handle"))
+      M2m1x  = @(x) feval (M2, x, "notransp");
+      M2tm1x = @(x) feval (M2, x, "transp");
+    else
+      error (["bicg: preconditioner is expected to " ...
+              "be a function or matrix"]);
+    endif
+
+    Pm1x  = @(x) M2m1x  (M1m1x (x));
+    Ptm1x = @(x) M1tm1x (M2tm1x (x));
+
+    if ((nargin < 7) || (isempty (x0)))
+      x0 = zeros (size (b));
+    endif
+
+    y = x = x0;
+    c = b;
+
+    r0 = b - Ax (x);
+    s0 = c - Atx (y);
+
+    d = Pm1x (r0);
+    f = Ptm1x (s0);
+
+    bnorm = norm (b);
+    res0  = Inf;
+
+    if (any (r0 != 0))
+      
+      for k = 1:maxit
+
+	a  = (s0' * Pm1x (r0)) ./ (f' * Ax (d));
+
+	x += a * d;
+	y += conj (a) * f;
+
+	r1 = r0 - a * Ax (d);
+	s1 = s0 - conj (a) * Atx (f);
+
+	beta = (s1' * Pm1x (r1)) ./ (s0' * Pm1x (r0));
+
+	d = Pm1x (r1) + beta * d;
+	f = Ptm1x (s1) + conj (beta) * f;
+
+	r0 = r1;
+	s0 = s1;
+
+	res1 = norm (b - Ax (x)) / bnorm;
+	if (res1 < tol)
+          flag = 0;
+          if (nargout < 2)
+	    printf ("bicg converged at iteration %i ", k);
+            printf ("to a solution with relative residual %e\n", res1);
+          endif
+	  break;
+	endif
+	
+	if (res0 <= res1)
+          flag = 3;
+	  printf ("bicg stopped at iteration %i ", k);
+          printf ("without converging to the desired tolerance %e\n", tol);
+          printf ("because the method stagnated.\n");
+          printf ("The iterate returned (number %i) ", k-1);
+          printf ("has relative residual %e\n", res0);
+	  break
+	endif
+        res0 = res1;
+        if (nargout > 4)
+          resvec(k) = res0;
+        endif
+      endfor
+
+      if (k == maxit)
+        flag = 1;
+	printf ("bicg stopped at iteration %i ", maxit);
+        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
+
+    else
+      flag = 0;
+      if (nargout < 2)
+        printf ("bicg converged after 0 interations\n");
+      endif
+    endif
+  
+  else
+    print_usage ();
+  endif
+  
+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] = bicg (A, b, tol, maxit, M1, M2);
+%! assert (x, ones (size (b)), 1e-7);
+%!
+%!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); 
+%!
+%! function y = afun (x, t, a)
+%!  switch t
+%!   case "notransp"
+%!     y = a * x;
+%!   case "transp"
+%!     y = a' * x;
+%!  endswitch
+%! endfunction
+%!
+%! [x, flag, relres, iter, resvec] = bicg (@(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] = bicg (A, b, tol, [], diag (diag (A)));
+%! assert (x, ones (size (b)), 1e-7);
--- a/scripts/linear-algebra/commutation_matrix.m
+++ b/scripts/linear-algebra/commutation_matrix.m
@@ -95,3 +95,25 @@
   endfor
 
 endfunction
+
+%!test
+%! c = commutation_matrix(1,1);
+%! assert(c,1);
+
+%!test
+%! A = rand(3,5);
+%! vc = vec(A);
+%! vr = vec(A');
+%! c = commutation_matrix(3,5);
+%! assert(c*vc,vr);
+
+%!test
+%! A = rand(4,6);
+%! vc = vec(A);
+%! vr = vec(A');
+%! c = commutation_matrix(4,6);
+%! assert(c*vc,vr);
+
+%!error commutation_matrix(0,0);
+%!error commutation_matrix(1,0);
+%!error commutation_matrix(0,1);
--- a/scripts/linear-algebra/isdefinite.m
+++ b/scripts/linear-algebra/isdefinite.m
@@ -63,3 +63,22 @@
   endif
 
 endfunction
+
+%!test
+%! A = [-1 0; 0 -1];
+%! assert (isdefinite (A), -1)
+
+%!test
+%! A = [1 0; 0 1];
+%! assert (isdefinite (A), 1)
+
+%!test
+%! A = [2 -1 0; -1 2 -1; 0 -1 2];
+%! assert (isdefinite (A), 1)
+
+%!test
+%! A = [1 0; 0 0];
+%! assert (isdefinite (A), 0)
+
+%!error isdefinite ()
+%!error isdefinite ([1 2; 3 4])
\ No newline at end of file
--- a/scripts/linear-algebra/module.mk
+++ b/scripts/linear-algebra/module.mk
@@ -7,7 +7,6 @@
   linear-algebra/cross.m \
   linear-algebra/duplication_matrix.m \
   linear-algebra/expm.m \
-  linear-algebra/gmres.m \
   linear-algebra/housh.m \
   linear-algebra/isdefinite.m \
   linear-algebra/ishermitian.m \
--- a/scripts/linear-algebra/null.m
+++ b/scripts/linear-algebra/null.m
@@ -77,3 +77,35 @@
   endif
 
 endfunction
+
+%!test
+%! A = 0;
+%! assert(null(A), 1);
+
+%!test
+%! A = 1;
+%! assert(null(A), zeros(1,0))
+
+%!test
+%! A = [1 0; 0 1];
+%! assert(null(A), zeros(2,0));
+
+%!test
+%! A = [1 0; 1 0];
+%! assert(null(A), [0 1]')
+
+%!test
+%! A = [1 1; 0 0];
+%! assert(null(A), [-1/sqrt(2) 1/sqrt(2)]', eps)
+
+%!test
+%! tol = 1e-4;
+%! A = [1 0; 0 tol-eps];
+%! assert(null(A,tol), [0 1]')
+
+%!test
+%! tol = 1e-4;
+%! A = [1 0; 0 tol+eps];
+%! assert(null(A,tol), zeros(2,0));
+
+%!error null()
--- a/scripts/linear-algebra/orth.m
+++ b/scripts/linear-algebra/orth.m
@@ -39,6 +39,11 @@
 
   if (nargin == 1 || nargin == 2)
 
+    if (isempty (A))
+      retval = [];
+      return;
+    endif
+
     [U, S, V] = svd (A);
 
     [rows, cols] = size (A);
--- a/scripts/linear-algebra/rank.m
+++ b/scripts/linear-algebra/rank.m
@@ -58,3 +58,54 @@
   retval = sum (sigma > tolerance);
 
 endfunction
+
+%!test
+%! A = [1 2 3 4 5 6 7; 
+%!      4 5 6 7 8 9 12; 
+%!      1 2 3.1 4 5 6 7; 
+%!      2 3 4 5 6 7 8; 
+%!      3 4 5 6 7 8 9; 
+%!      4 5 6 7 8 9 10; 
+%!      5 6 7 8 9 10 11];
+%! assert(rank(A),4);
+
+%!test
+%! A = [1 2 3 4 5 6 7; 
+%!      4 5 6 7 8 9 12; 
+%!      1 2 3.0000001 4 5 6 7; 
+%!      4 5 6 7 8 9 12.00001; 
+%!      3 4 5 6 7 8 9; 
+%!      4 5 6 7 8 9 10; 
+%!      5 6 7 8 9 10 11];
+%! assert(rank(A),4);
+
+%!test
+%! A = [1 2 3 4 5 6 7; 
+%!      4 5 6 7 8 9 12; 
+%!      1 2 3 4 5 6 7; 
+%!      4 5 6 7 8 9 12.00001; 
+%!      3 4 5 6 7 8 9;
+%!      4 5 6 7 8 9 10; 
+%!      5 6 7 8 9 10 11];
+%! assert(rank(A),3);
+
+%!test
+%! A = [1 2 3 4 5 6 7; 
+%!      4 5 6 7 8 9 12;
+%!      1 2 3 4 5 6 7;
+%!      4 5 6 7 8 9 12; 
+%!      3 4 5 6 7 8 9; 
+%!      4 5 6 7 8 9 10; 
+%!      5 6 7 8 9 10 11];
+%! assert(rank(A),3);
+
+%!test
+%! A = eye(100);
+%! assert(rank(A),100);
+
+%!test
+%! A = [1, 2, 3; 1, 2.001, 3; 1, 2, 3.0000001];
+%! assert(rank(A),3)
+%! assert(rank(A,0.0009),1)
+%! assert(rank(A,0.0006),2)
+%! assert(rank(A,0.00000002),3)
\ No newline at end of file
--- a/scripts/miscellaneous/ans.m
+++ b/scripts/miscellaneous/ans.m
@@ -28,3 +28,7 @@
 ## @noindent
 ## is evaluated, the value returned by @code{ans} is 25.
 ## @end defvr
+
+## Mark file as being tested.  No real test needed for a documentation .m file
+%!assert (1)
+
--- a/scripts/miscellaneous/bug_report.m
+++ b/scripts/miscellaneous/bug_report.m
@@ -43,3 +43,6 @@
   puts ("\n");
 
 endfunction
+
+## Mark file as being tested.  No real test needed for this function.
+%!assert (1)
--- a/scripts/miscellaneous/comma.m
+++ b/scripts/miscellaneous/comma.m
@@ -21,3 +21,7 @@
 ## Array index, function argument, or command separator.
 ## @seealso{semicolon}
 ## @end deftypefn
+
+## Mark file as being tested.  No real test needed for a documentation .m file
+%!assert (1)
+
--- a/scripts/miscellaneous/edit.m
+++ b/scripts/miscellaneous/edit.m
@@ -54,7 +54,7 @@
 ## filename.  If @file{name.ext} is not modifiable, it will be copied to
 ## @env{HOME} before editing.
 ##
-## @strong{WARNING!} You may need to clear name before the new definition
+## @strong{Warning:} You may need to clear name before the new definition
 ## is available.  If you are editing a .cc file, you will need
 ## to mkoctfile @file{name.cc} before the definition will be available.
 ## @end itemize
--- a/scripts/miscellaneous/fullfile.m
+++ b/scripts/miscellaneous/fullfile.m
@@ -26,7 +26,7 @@
 
   if (nargin > 0)
     ## Discard all empty arguments
-    varargin(cellfun (@isempty, varargin)) = [];
+    varargin(cellfun ("isempty", varargin)) = [];
     nargs = numel (varargin);
     if (nargs > 1)
       filename = varargin{1};
--- a/scripts/miscellaneous/getfield.m
+++ b/scripts/miscellaneous/getfield.m
@@ -50,8 +50,8 @@
     print_usage ();
   endif
   subs = varargin;
-  flds = cellfun (@ischar, subs);
-  idxs = cellfun (@iscell, subs);
+  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));
--- a/scripts/miscellaneous/info.m
+++ b/scripts/miscellaneous/info.m
@@ -43,3 +43,6 @@
   http://www.octave.org/bugs.html\n");
 
 endfunction
+
+## Mark file as being tested.  No real test needed for this function.
+%! assert (1)
--- a/scripts/miscellaneous/ismac.m
+++ b/scripts/miscellaneous/ismac.m
@@ -32,3 +32,5 @@
 
 endfunction
 
+%!error ismac (1);
+%!assert (islogical (ismac ()));
--- a/scripts/miscellaneous/ispc.m
+++ b/scripts/miscellaneous/ispc.m
@@ -31,3 +31,6 @@
   endif
 
 endfunction
+
+%!error ispc (1);
+%!assert (islogical (ispc ()));
--- a/scripts/miscellaneous/isunix.m
+++ b/scripts/miscellaneous/isunix.m
@@ -31,3 +31,6 @@
   endif
 
 endfunction
+
+%!error isunix (1);
+%!assert (islogical (isunix ()));
--- a/scripts/miscellaneous/list_primes.m
+++ b/scripts/miscellaneous/list_primes.m
@@ -83,3 +83,9 @@
   endwhile
 
 endfunction
+
+%!test
+%! 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]);
+
--- a/scripts/miscellaneous/ls.m
+++ b/scripts/miscellaneous/ls.m
@@ -63,7 +63,7 @@
           retval = strvcat (regexp (output, '\S+', 'match'){:});
         endif
       else
-        error ("ls: command exited abnormally with status %d", status);
+        error ("ls: command exited abnormally with status %d\n", status);
       endif
 
     else
--- a/scripts/miscellaneous/mkoctfile.m
+++ b/scripts/miscellaneous/mkoctfile.m
@@ -75,26 +75,30 @@
 ## Print the configuration variable VAR@.  Recognized variables are:
 ##
 ## @example
-##    ALL_CFLAGS                FFTW_LIBS
+##    ALL_CFLAGS                FFTW3F_LIBS
 ##    ALL_CXXFLAGS              FLIBS
 ##    ALL_FFLAGS                FPICFLAG
 ##    ALL_LDFLAGS               INCFLAGS
-##    BLAS_LIBS                 LDFLAGS
-##    CC                        LD_CXX
-##    CFLAGS                    LD_STATIC_FLAG
-##    CPICFLAG                  LFLAGS
-##    CPPFLAGS                  LIBCRUFT
-##    CXX                       LIBOCTAVE
-##    CXXFLAGS                  LIBOCTINTERP
-##    CXXPICFLAG                LIBREADLINE
+##    BLAS_LIBS                 LAPACK_LIBS
+##    CC                        LDFLAGS
+##    CFLAGS                    LD_CXX
+##    CPICFLAG                  LD_STATIC_FLAG
+##    CPPFLAGS                  LFLAGS
+##    CXX                       LIBCRUFT
+##    CXXFLAGS                  LIBOCTAVE
+##    CXXPICFLAG                LIBOCTINTERP
 ##    DEPEND_EXTRA_SED_PATTERN  LIBS
 ##    DEPEND_FLAGS              OCTAVE_LIBS
-##    DL_LD                     RDYNAMIC_FLAG
-##    DL_LDFLAGS                RLD_FLAG
-##    F2C                       SED
-##    F2CFLAGS                  XTRA_CFLAGS
-##    F77                       XTRA_CXXFLAGS
-##    FFLAGS
+##    DL_LD                     OCTAVE_LINK_DEPS
+##    DL_LDFLAGS                OCT_LINK_DEPS
+##    EXEEXT                    RDYNAMIC_FLAG
+##    F77                       READLINE_LIBS
+##    F77_INTEGER_8_FLAG        SED
+##    FFLAGS                    XTRA_CFLAGS
+##    FFTW3_LDFLAGS             XTRA_CXXFLAGS
+##    FFTW3_LIBS
+##    FFTW3F_LDFLAGS
+##
 ## @end example
 ##
 ## @item --link-stand-alone
--- a/scripts/miscellaneous/module.mk
+++ b/scripts/miscellaneous/module.mk
@@ -61,7 +61,6 @@
   miscellaneous/tar.m \
   miscellaneous/tempdir.m \
   miscellaneous/tempname.m \
-  miscellaneous/unimplemented.m \
   miscellaneous/unix.m \
   miscellaneous/unpack.m \
   miscellaneous/untar.m \
--- a/scripts/miscellaneous/news.m
+++ b/scripts/miscellaneous/news.m
@@ -36,3 +36,7 @@
   endif
 
 endfunction
+
+
+## Remove from test statistics.  No real tests possible
+%!assert (1)
--- a/scripts/miscellaneous/paren.m
+++ b/scripts/miscellaneous/paren.m
@@ -21,3 +21,7 @@
 ## @deftypefnx {Operator} {} )
 ## Array index or function argument delimeter.
 ## @end deftypefn
+
+## Mark file as being tested.  No real test needed for a documentation .m file
+%!assert (1)
+
--- a/scripts/miscellaneous/private/__xzip__.m
+++ b/scripts/miscellaneous/private/__xzip__.m
@@ -112,10 +112,10 @@
 endfunction
 
 function [d, f] = myfileparts (files)
-  [d, f, ext] = cellfun (@(x) fileparts (x), files, "uniformoutput", false);
+  [d, f, ext] = cellfun ("fileparts", files, "uniformoutput", false);
   f = cellfun (@(x, y) sprintf ("%s%s", x, y), f, ext,
                "uniformoutput", false);
-  idx = cellfun (@isdir, files);
+  idx = cellfun ("isdir", files);
   d(idx) = "";
   f(idx) = files(idx);
 endfunction
--- a/scripts/miscellaneous/semicolon.m
+++ b/scripts/miscellaneous/semicolon.m
@@ -21,3 +21,7 @@
 ## Array row or command separator.
 ## @seealso{comma}
 ## @end deftypefn
+
+## Mark file as being tested.  No real test needed for a documentation .m file
+%!assert (1)
+
--- a/scripts/miscellaneous/setfield.m
+++ b/scripts/miscellaneous/setfield.m
@@ -50,8 +50,8 @@
   endif
   subs = varargin(1:end-1);
   rhs = varargin{end};
-  flds = cellfun (@ischar, subs);
-  idxs = cellfun (@iscell, subs);
+  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);
--- a/scripts/miscellaneous/swapbytes.m
+++ b/scripts/miscellaneous/swapbytes.m
@@ -32,6 +32,7 @@
 ## @end deftypefn
 
 function y = swapbytes (x)
+
   if (nargin != 1)
     print_usage ();
   endif
@@ -53,4 +54,11 @@
     y = reshape (typecast (reshape (typecast (x(:), "uint8"), nb, numel (x))
                            ([nb : -1 : 1], :) (:), clx), size(x));
   endif
+
 endfunction
+
+
+%!assert (double (swapbytes (uint16 (1:4))), [256 512 768 1024])
+%!error (swapbytes ())
+%!error (swapbytes (1, 2))
+
--- a/scripts/miscellaneous/symvar.m
+++ b/scripts/miscellaneous/symvar.m
@@ -28,3 +28,6 @@
 function args = symvar (s)
   args = argnames (inline (s));
 endfunction
+
+## This function is tested by the tests for argnames().
+%!assert (1)
--- a/scripts/miscellaneous/warning_ids.m
+++ b/scripts/miscellaneous/warning_ids.m
@@ -284,3 +284,6 @@
 function warning_ids ()
   help ("warning_ids");
 endfunction
+
+## Remove from test statistics.  No real tests possible
+%!assert (1)
--- a/scripts/miscellaneous/what.m
+++ b/scripts/miscellaneous/what.m
@@ -90,7 +90,7 @@
   if (length (f) > 0)
     printf ("%s %s:\n\n", msg, p);
 
-    maxlen = max (cellfun (@length, f));
+    maxlen = max (cellfun ("length", f));
     ncols = max (1, floor (terminal_size()(2) / (maxlen + 3)));
     fmt = "";
     for i = 1: ncols
--- a/scripts/miscellaneous/xor.m
+++ b/scripts/miscellaneous/xor.m
@@ -48,7 +48,11 @@
       ## Typecast to logicals is necessary for other numeric types.
       z = logical (x) != logical (y);
     else
-      error ("xor: X and Y must be of common size or scalars");
+      try
+        z = bsxfun (@xor, x, y);
+      catch
+        error ("xor: X and Y must be of compatible size or scalars");
+      end_try_catch
     endif
   else
     print_usage ();
--- a/scripts/optimization/fminbnd.m
+++ b/scripts/optimization/fminbnd.m
@@ -49,7 +49,8 @@
 ## This is patterned after opt/fmin.f from Netlib, which in turn is taken from
 ## Richard Brent: Algorithms For Minimization Without Derivatives, Prentice-Hall (1973)
 
-## PKG_ADD: __all_opts__ ("fminbnd");
+## PKG_ADD: ## Discard result to avoid polluting workspace with ans at startup.
+## PKG_ADD: [~] = __all_opts__ ("fminbnd");
 
 function [x, fval, info, output] = fminbnd (fun, xmin, xmax, options = struct ())
 
--- a/scripts/optimization/fminunc.m
+++ b/scripts/optimization/fminunc.m
@@ -77,7 +77,8 @@
 ## @seealso{fminbnd, optimset}
 ## @end deftypefn
 
-## PKG_ADD: __all_opts__ ("fminunc");
+## PKG_ADD: ## Discard result to avoid polluting workspace with ans at startup.
+## PKG_ADD: [~] = __all_opts__ ("fminunc");
 
 function [x, fval, info, output, grad, hess] = fminunc (fcn, x0, options = struct ())
 
--- a/scripts/optimization/fsolve.m
+++ b/scripts/optimization/fsolve.m
@@ -127,7 +127,8 @@
 ## @end example
 ## @end deftypefn
 
-## PKG_ADD: __all_opts__ ("fsolve");
+## PKG_ADD: ## Discard result to avoid polluting workspace with ans at startup.
+## PKG_ADD: [~] = __all_opts__ ("fsolve");
 
 function [x, fvec, info, output, fjac] = fsolve (fcn, x0, options = struct ())
 
--- a/scripts/optimization/fzero.m
+++ b/scripts/optimization/fzero.m
@@ -93,7 +93,8 @@
 ## the need for external functions and error handling. The algorithm has
 ## also been slightly modified.
 
-## PKG_ADD: __all_opts__ ("fzero");
+## PKG_ADD: ## Discard result to avoid polluting workspace with ans at startup.
+## PKG_ADD: [~] = __all_opts__ ("fzero");
 
 function [x, fval, info, output] = fzero (fun, x0, options = struct ())
 
--- a/scripts/optimization/lsqnonneg.m
+++ b/scripts/optimization/lsqnonneg.m
@@ -63,7 +63,8 @@
 ## @seealso{optimset, pqpnonneg}
 ## @end deftypefn
 
-## PKG_ADD: __all_opts__ ("lsqnonneg");
+## PKG_ADD: ## Discard result to avoid polluting workspace with ans at startup.
+## PKG_ADD: [~] = __all_opts__ ("lsqnonneg");
 
 ## This is implemented from Lawson and Hanson's 1973 algorithm on page
 ## 161 of Solving Least Squares Problems.
--- a/scripts/optimization/pqpnonneg.m
+++ b/scripts/optimization/pqpnonneg.m
@@ -58,7 +58,8 @@
 ## @seealso{optimset, lsqnonneg, qp}
 ## @end deftypefn
 
-## PKG_ADD: __all_opts__ ("pqpnonneg");
+## PKG_ADD: ## Discard result to avoid polluting workspace with ans at startup.
+## PKG_ADD: [~] = __all_opts__ ("pqpnonneg");
 
 ## This is analogical to the lsqnonneg implementation, which is
 ## implemented from Lawson and Hanson's 1973 algorithm on page
--- a/scripts/optimization/qp.m
+++ b/scripts/optimization/qp.m
@@ -108,7 +108,8 @@
 ## @end table
 ## @end deftypefn
 
-## PKG_ADD: __all_opts__ ("qp");
+## PKG_ADD: ## Discard result to avoid polluting workspace with ans at startup.
+## PKG_ADD: [~] = __all_opts__ ("qp");
 
 function [x, obj, INFO, lambda] = qp (x0, H, varargin)
 
--- a/scripts/path/matlabroot.m
+++ b/scripts/path/matlabroot.m
@@ -31,5 +31,5 @@
 
 endfunction
 
+%!assert (matlabroot(), OCTAVE_HOME())
 
-
--- a/scripts/pkg/pkg.m
+++ b/scripts/pkg/pkg.m
@@ -20,8 +20,10 @@
 ## -*- texinfo -*-
 ## @deftypefn  {Command} {} pkg @var{command} @var{pkg_name}
 ## @deftypefnx {Command} {} pkg @var{command} @var{option} @var{pkg_name}
-## This command interacts with the package manager.  Different actions will
-## be taken 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:
 ##
 ## @table @samp
 ##
@@ -40,34 +42,44 @@
 ##
 ## @table @code
 ## @item -nodeps
-## The package manager will disable the dependency checking.  That way it
-## is possible to install a package even if it depends on another package
-## that's not installed on the system.  @strong{Use this option with care.}
+## The package manager will disable dependency checking.  With this option it
+## is possible to install a package even when it depends on another package
+## which is not installed on the system.  @strong{Use this option with care.}
 ##
 ## @item -noauto
 ## The package manager will not automatically load the installed package
-## when starting Octave, even if the package requests that it is.
+## when starting Octave.  This overrides any setting within the package.
 ##
 ## @item -auto
 ## The package manager will automatically load the installed package when
-## starting Octave, even if the package requests that it isn't.
+## starting Octave.  This overrides any setting within the package.
 ##
 ## @item -local
-## A local installation is forced, even if the user has system privileges.
+## A local installation (package available only to current user) is forced, 
+## even if the user has system privileges.
 ##
 ## @item -global
-## A global installation is forced, even if the user doesn't normally have
-## system privileges
+## A global installation (package available to all users) is forced, even if
+## the user doesn't normally have system privileges.
 ##
 ## @item -forge
 ## Install a package directly from the Octave-Forge repository.  This
 ## requires an internet connection and the cURL library.
 ##
 ## @item -verbose
-## The package manager will print the output of all of the commands that are
-## performed.
+## The package manager will print the output of all commands as
+## they are performed.
 ## @end table
 ##
+## @item update
+## Check installed Octave-Forge pacakages against repository and update any
+## outdated items.  This requires an internet connection and the cURL library.
+## Usage:
+##
+## @example
+## pkg update
+## @end example
+##
 ## @item uninstall
 ## Uninstall named packages.  For example,
 ##
@@ -90,47 +102,53 @@
 ##
 ## @noindent
 ## adds the @code{image} package to the path.  It is possible to load all
-## installed packages at once with the command
+## installed packages at once with the keyword @samp{all}.  Usage:
 ##
 ## @example
 ## pkg load all
 ## @end example
 ##
 ## @item unload
-## Removes named packages from the path.  After unloading a package it is
-## no longer possible to use the functions provided by the package.
-## This command behaves like the @code{load} command.
+## Remove named packages from the path.  After unloading a package it is
+## no longer possible to use the functions provided by the package.  It is
+## possible to unload all installed packages at once with the keyword
+## @samp{all}.  Usage:
+##
+## @example
+## pkg unload all
+## @end example
 ##
 ## @item list
-## Show a list of the currently installed packages.  By requesting one or two
-## output argument it is possible to get a list of the currently installed
-## packages.  For example,
+## Show the list of currently installed packages.  For example,
 ##
 ## @example
-## installed_packages = pkg list;
+## installed_packages = pkg ("list")
 ## @end example
 ##
 ## @noindent
 ## returns a cell array containing a structure for each installed package.
-## The command
 ##
+## If two output arguments are requested @code{pkg} splits the list of
+## installed packages into those which were installed by the current user,
+## and those which were installed by the system administrator.
+## 
 ## @example
-## [@var{user_packages}, @var{system_packages}] = pkg list
+## [user_packages, system_packages] = pkg ("list")
 ## @end example
 ##
-## @noindent
-## splits the list of installed packages into those who are installed by
-## the current user, and those installed by the system administrator.
+## The option '-forge' lists packages available at the Octave-Forge repository.
+## This requires an internet connection and the cURL library.  For example:
 ##
-## The option '-forge' lists packages available at the Octave-Forge repository.
-## This requires an internet connection and the cURL library.
+## @example
+## oct_forge_pkgs = pkg ("list", "-forge")
+## @end example
 ##
 ## @item describe
 ## Show a short description of the named installed packages, with the option
-## '-verbose' also list functions provided by the package, e.g.:
+## '-verbose' also list functions provided by the package.  For example,
 ##
 ## @example
-##  pkg describe -verbose all
+## pkg describe -verbose all
 ## @end example
 ##
 ## @noindent
@@ -140,7 +158,7 @@
 ## output rather than printed on screen:
 ##
 ## @example
-##  desc = pkg ("describe", "secs1d", "image")
+## desc = pkg ("describe", "secs1d", "image")
 ## @end example
 ##
 ## @noindent
@@ -148,7 +166,7 @@
 ## error, unless a second output is requested:
 ##
 ## @example
-##  [ desc, flag] = pkg ("describe", "secs1d", "image")
+## [desc, flag] = pkg ("describe", "secs1d", "image")
 ## @end example
 ##
 ## @noindent
@@ -170,20 +188,20 @@
 ## output argument.  For example:
 ##
 ## @example
-## p = pkg prefix
+## pfx = pkg ("prefix")
 ## @end example
 ##
 ## The location in which to install the architecture dependent files can be
-## independent specified with an addition argument.  For example:
+## independently specified with an addition argument.  For example:
 ##
 ## @example
 ## pkg prefix ~/my_octave_packages ~/my_arch_dep_pkgs
 ## @end example
 ##
 ## @item local_list
-## Set the file in which to look for information on the locally
+## Set the file in which to look for information on locally
 ## installed packages.  Locally installed packages are those that are
-## typically available only to the current user.  For example:
+## available only to the current user.  For example:
 ##
 ## @example
 ## pkg local_list ~/.octave_packages
@@ -196,9 +214,9 @@
 ## @end example
 ##
 ## @item global_list
-## Set the file in which to look for, for information on the globally
+## Set the file in which to look for information on globally
 ## installed packages.  Globally installed packages are those that are
-## typically available to all users.  For example:
+## available to all users.  For example:
 ##
 ## @example
 ## pkg global_list /usr/share/octave/octave_packages
@@ -210,21 +228,8 @@
 ## pkg global_list
 ## @end example
 ##
-## @item rebuild
-## Rebuilds the package database from the installed directories.  This can
-## be used in cases where for some reason the package database is corrupted.
-## It can also take the @option{-auto} and @option{-noauto} options to allow the
-## autoloading state of a package to be changed.  For example,
-##
-## @example
-## pkg rebuild -noauto image
-## @end example
-##
-## @noindent
-## will remove the autoloading status of the image package.
-##
 ## @item build
-## Builds a binary form of a package or packages.  The binary file produced
+## Build a binary form of a package or packages.  The binary file produced
 ## will itself be an Octave package that can be installed normally with
 ## @code{pkg}.  The form of the command to build a binary package is
 ##
@@ -236,7 +241,21 @@
 ## where @code{builddir} is the name of a directory where the temporary
 ## installation will be produced and the binary packages will be found.
 ## The options @option{-verbose} and @option{-nodeps} are respected, while
-## the other options are ignored.
+## all other options are ignored.
+##
+## @item rebuild
+## Rebuild the package database from the installed directories.  This can
+## be used in cases where the package database has been corrupted.
+## It can also take the @option{-auto} and @option{-noauto} options to allow the
+## autoloading state of a package to be changed.  For example,
+##
+## @example
+## pkg rebuild -noauto image
+## @end example
+##
+## @noindent
+## will remove the autoloading status of the image package.
+##
 ## @end table
 ## @end deftypefn
 
@@ -267,7 +286,8 @@
 
   available_actions = {"list", "install", "uninstall", "load", ...
                        "unload", "prefix", "local_list", ...
-                       "global_list", "rebuild", "build","describe"};
+                       "global_list", "rebuild", "build", ...
+                       "describe", "update"};
   ## Handle input
   if (length (varargin) == 0 || ! iscellstr (varargin))
     print_usage ();
@@ -349,8 +369,8 @@
       unwind_protect
 
         if (octave_forge)
-          [urls, local_files] = cellfun (@get_forge_download, files, "uniformoutput", false);
-          [files, succ] = cellfun (@urlwrite, urls, local_files, "uniformoutput", false);
+          [urls, local_files] = cellfun ("get_forge_download", files, "uniformoutput", false);
+          [files, succ] = cellfun ("urlwrite", urls, local_files, "uniformoutput", false);
           succ = [succ{:}];
           if (! all (succ))
             i = find (! succ, 1);
@@ -362,7 +382,7 @@
                  global_list, global_install);
 
       unwind_protect_cleanup
-        cellfun (@unlink, local_files);
+        cellfun ("unlink", local_files);
       end_unwind_protect
 
     case "uninstall"
@@ -492,6 +512,21 @@
           error ("you can request at most two outputs when calling 'pkg describe'");
       endswitch
 
+    case "update"
+      if (nargout == 0)
+        installed_pkgs_lst = installed_packages (local_list, global_list);
+        for i = 1:length (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);
+          if (compare_versions (forge_pkg_version, installed_pkg_version, ">"))
+            feval (@pkg, "install", "-forge", installed_pkg_name);
+          endif
+        endfor
+      else
+        error ("no output arguments available");
+      endif
+
     otherwise
       error ("you must specify a valid action for 'pkg'. See 'help pkg' for details");
   endswitch
@@ -1383,7 +1418,7 @@
     if (isempty (filenames))
       idx = [];
     else
-      idx = cellfun (@is_architecture_dependent, filenames);
+      idx = cellfun ("is_architecture_dependent", filenames);
     endif
     archdependent = filenames (idx);
     archindependent = filenames (!idx);
--- a/scripts/plot/axis.m
+++ b/scripts/plot/axis.m
@@ -323,10 +323,10 @@
       data(data<=0) = NaN;
     end
     if (iscell (data))
-      data = data (find (! cellfun (@isempty, data)));
+      data = data (find (! cellfun ("isempty", data)));
       if (! isempty (data))
-        lims_min = min (cellfun (@min, cellfun (@min, data, 'uniformoutput', false)(:)));
-        lims_max = max (cellfun (@max, cellfun (@max, data, 'uniformoutput', false)(:)));
+        lims_min = min (cellfun ("min", cellfun ("min", data, 'uniformoutput', false)(:)));
+        lims_max = max (cellfun ("max", cellfun ("max", data, 'uniformoutput', false)(:)));
         lims = [lims_min, lims_max];
       else
         lims = [0, 1];
--- a/scripts/plot/isonormals.m
+++ b/scripts/plot/isonormals.m
@@ -46,47 +46,49 @@
 ##
 ## For example:
 ##
-## @example
+## @c Set example in small font to prevent overfull line
+## @smallexample
 ## function [] = isofinish (p)
-##   set (gca, "PlotBoxAspectRatioMode","manual","PlotBoxAspectRatio",[1 1 1]);
-##   set (p, "VertexNormals", -get(p,"VertexNormals")); ## Revert normals
+##   set (gca, "PlotBoxAspectRatioMode", "manual", ...
+##             "PlotBoxAspectRatio",[1 1 1]);
+##   set (p, "VertexNormals", -get(p,"VertexNormals")); # Revert normals
 ##   set (p, "FaceColor", "interp");
 ##   ## set (p, "FaceLighting", "phong");
-##   ## light ("Position", [1 1 5]); ## Available with JHandles
+##   ## light ("Position", [1 1 5]); # Available with JHandles
 ## endfunction
 ##
-## N = 15;    ## Increase number of vertices in each direction
-## iso = .4;  ## Change isovalue to .1 to display a sphere
+## N = 15;    # Increase number of vertices in each direction
+## iso = .4;  # Change isovalue to .1 to display a sphere
 ## lin = linspace (0, 2, N);
 ## [x, y, z] = meshgrid (lin, lin, lin);
 ## c = abs ((x-.5).^2 + (y-.5).^2 + (z-.5).^2);
-## figure (); ## Open another figure window
+## figure (); # Open another figure window
 ##
 ## subplot (2, 2, 1); view (-38, 20);
 ## [f, v, cdat] = isosurface (x, y, z, c, iso, y);
 ## p = patch ("Faces", f, "Vertices", v, "FaceVertexCData", cdat, \
-##         "FaceColor", "interp", "EdgeColor", "none");
+##            "FaceColor", "interp", "EdgeColor", "none");
 ## isofinish (p); ## Call user function isofinish
 ##
 ## subplot (2, 2, 2); view (-38, 20);
 ## p = patch ("Faces", f, "Vertices", v, "FaceVertexCData", cdat, \
-##         "FaceColor", "interp", "EdgeColor", "none");
-## isonormals (x, y, z, c, p); ## Directly modify patch
+##            "FaceColor", "interp", "EdgeColor", "none");
+## isonormals (x, y, z, c, p); # Directly modify patch
 ## isofinish (p);
 ##
 ## subplot (2, 2, 3); view (-38, 20);
 ## p = patch ("Faces", f, "Vertices", v, "FaceVertexCData", cdat, \
-##         "FaceColor", "interp", "EdgeColor", "none");
-## n = isonormals (x, y, z, c, v); ## Compute normals of isosurface
-## set (p, "VertexNormals", n);    ## Manually set vertex normals
+##            "FaceColor", "interp", "EdgeColor", "none");
+## n = isonormals (x, y, z, c, v); # Compute normals of isosurface
+## set (p, "VertexNormals", n);    # Manually set vertex normals
 ## isofinish (p);
 ##
 ## subplot (2, 2, 4); view (-38, 20);
 ## p = patch ("Faces", f, "Vertices", v, "FaceVertexCData", cdat, \
-##         "FaceColor", "interp", "EdgeColor", "none");
-## isonormals (x, y, z, c, v, "negate"); ## Use reverse directly
+##            "FaceColor", "interp", "EdgeColor", "none");
+## isonormals (x, y, z, c, v, "negate"); # Use reverse directly
 ## isofinish (p);
-## @end example
+## @end smallexample
 ##
 ## @seealso{isosurface, isocolors}
 ## @end deftypefn
--- a/scripts/plot/isosurface.m
+++ b/scripts/plot/isosurface.m
@@ -71,24 +71,27 @@
 ## Another example for an isosurface geometry with different additional
 ## coloring
 ##
-## @example
-## N = 15;    ## Increase number of vertices in each direction
-## iso = .4;  ## Change isovalue to .1 to display a sphere
+## @c Set example in small font to prevent overfull line
+## @smallexample
+## N = 15;    # Increase number of vertices in each direction
+## iso = .4;  # Change isovalue to .1 to display a sphere
 ## lin = linspace (0, 2, N);
 ## [x, y, z] = meshgrid (lin, lin, lin);
 ## c = abs ((x-.5).^2 + (y-.5).^2 + (z-.5).^2);
-## figure (); ## Open another figure window
+## figure (); # Open another figure window
 ##
 ## subplot (2, 2, 1); view (-38, 20);
 ## [f, v] = isosurface (x, y, z, c, iso);
 ## p = patch ("Faces", f, "Vertices", v, "EdgeColor", "none");
-## set (gca, "PlotBoxAspectRatioMode","manual", "PlotBoxAspectRatio", [1 1 1]);
+## set (gca, "PlotBoxAspectRatioMode","manual", ...
+##           "PlotBoxAspectRatio", [1 1 1]);
 ## # set (p, "FaceColor", "green", "FaceLighting", "phong");
-## # light ("Position", [1 1 5]); ## Available with the JHandles package
+## # light ("Position", [1 1 5]); # Available with the JHandles package
 ##
 ## subplot (2, 2, 2); view (-38, 20);
 ## p = patch ("Faces", f, "Vertices", v, "EdgeColor", "blue");
-## set (gca, "PlotBoxAspectRatioMode","manual", "PlotBoxAspectRatio", [1 1 1]);
+## set (gca, "PlotBoxAspectRatioMode","manual", ...
+##           "PlotBoxAspectRatio", [1 1 1]);
 ## # set (p, "FaceColor", "none", "FaceLighting", "phong");
 ## # light ("Position", [1 1 5]);
 ##
@@ -96,17 +99,19 @@
 ## [f, v, c] = isosurface (x, y, z, c, iso, y);
 ## p = patch ("Faces", f, "Vertices", v, "FaceVertexCData", c, \
 ##            "FaceColor", "interp", "EdgeColor", "none");
-## set (gca, "PlotBoxAspectRatioMode","manual", "PlotBoxAspectRatio", [1 1 1]);
+## set (gca, "PlotBoxAspectRatioMode","manual", ...
+##           "PlotBoxAspectRatio", [1 1 1]);
 ## # set (p, "FaceLighting", "phong");
 ## # light ("Position", [1 1 5]);
 ##
 ## subplot (2, 2, 4); view (-38, 20);
 ## p = patch ("Faces", f, "Vertices", v, "FaceVertexCData", c, \
 ##            "FaceColor", "interp", "EdgeColor", "blue");
-## set (gca, "PlotBoxAspectRatioMode","manual", "PlotBoxAspectRatio", [1 1 1]);
+## set (gca, "PlotBoxAspectRatioMode","manual", ...
+##           "PlotBoxAspectRatio", [1 1 1]);
 ## # set (p, "FaceLighting", "phong");
 ## # light ("Position", [1 1 5]);
-## @end example
+## @end smallexample
 ##
 ## @seealso{isonormals, isocolors}
 ## @end deftypefn
--- a/scripts/plot/module.mk
+++ b/scripts/plot/module.mk
@@ -20,38 +20,38 @@
   plot/private/__errplot__.m \
   plot/private/__ezplot__.m \
   plot/private/__fltk_file_filter__.m \
-  plot/private/__ghostscript__.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/__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_FCN_FILES = \
-  plot/__fltk_ginput__.m \
-  plot/__fltk_print__.m \
   plot/__gnuplot_drawnow__.m \
-  plot/__gnuplot_get_var__.m \
-  plot/__gnuplot_ginput__.m \
-  plot/__gnuplot_has_feature__.m \
-  plot/__gnuplot_open_stream__.m \
-  plot/__gnuplot_print__.m \
-  plot/__gnuplot_version__.m \
   plot/__go_close_all__.m \
-  plot/__go_draw_axes__.m \
-  plot/__go_draw_figure__.m \
-  plot/__marching_cube__.m \
-  plot/__next_line_color__.m \
-  plot/__next_line_style__.m \
   plot/__plt_get_axis_arg__.m \
-  plot/__print_parse_opts__.m \
   plot/allchild.m \
   plot/ancestor.m \
   plot/area.m \
@@ -171,6 +171,9 @@
   plot/surfnorm.m \
   plot/text.m \
   plot/title.m \
+  plot/trimesh.m \
+  plot/triplot.m \
+  plot/trisurf.m \
   plot/uigetdir.m \
   plot/uigetfile.m \
   plot/uimenu.m \
--- a/scripts/plot/pareto.m
+++ b/scripts/plot/pareto.m
@@ -66,11 +66,11 @@
       if (ischar (y))
         y = cellstr (y);
       else
-        y = cellfun (@num2str, num2cell (y), "uniformoutput", false);
+        y = cellfun ("num2str", num2cell (y), "uniformoutput", false);
       endif
     endif
   else
-    y = cellfun (@int2str, num2cell (1 : numel(x)),
+    y = cellfun ("int2str", num2cell (1 : numel(x)),
                  "uniformoutput", false);
   endif
 
--- a/scripts/plot/pcolor.m
+++ b/scripts/plot/pcolor.m
@@ -80,3 +80,14 @@
   endif
 
 endfunction
+
+%!demo
+%! clf
+%! [~,~,Z]=peaks;
+%! pcolor(Z);
+
+%!demo
+%! [X,Y,Z]=sombrero;
+%! [Fx,Fy] = gradient(Z);
+%! pcolor(X,Y,Fx+Fy);
+%! shading interp;
--- a/scripts/plot/plotyy.m
+++ b/scripts/plot/plotyy.m
@@ -78,7 +78,7 @@
     ca = get (f, "currentaxes");
     if (isempty (ca))
       ax = [];
-    elseif (strcmp (get (ca, "tag"), "plotyy"));
+    elseif (strcmp (get (ca, "tag"), "plotyy"))
       ax = get (ca, "__plotyy_axes__");
     else
       ax = ca;
@@ -113,8 +113,6 @@
     endif
   end_unwind_protect
 
-  set (ax, "activepositionproperty", "position");
-
   if (nargout > 0)
     Ax = ax;
     H1 = h1;
@@ -162,10 +160,24 @@
   colors = get (ax(1), "colororder");
   set (ax(2), "colororder", [colors(2:end,:); colors(1,:)]);
 
+  if (strcmp (get (ax(1), "autopos_tag"), "subplot"))
+    set (ax(2), "autopos_tag", "subplot");
+  else
+    set (ax, "activepositionproperty", "position");
+  endif
+
   h2 = feval (fun2, x2, y2);
   set (ax(2), "yaxislocation", "right");
   set (ax(2), "ycolor", getcolor (h2(1)));
-  set (ax(2), "position", get (ax(1), "position"));
+
+
+  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"));
+  endif
+
   set (ax(2), "xlim", xlim);
   set (ax(2), "color", "none");
   set (ax(2), "box", "off");
@@ -184,6 +196,10 @@
 
   addlistener (ax(1), "position", {@update_position, ax(2)});
   addlistener (ax(2), "position", {@update_position, ax(1)});
+  addlistener (ax(1), "outerposition", {@update_position, ax(2)});
+  addlistener (ax(2), "outerposition", {@update_position, ax(1)});
+  addlistener (ax(1), "looseinset", {@update_position, ax(2)});
+  addlistener (ax(2), "looseinset", {@update_position, ax(1)});
   addlistener (ax(1), "view", {@update_position, ax(2)});
   addlistener (ax(2), "view", {@update_position, ax(1)});
   addlistener (ax(1), "plotboxaspectratio", {@update_position, ax(2)});
@@ -257,17 +273,27 @@
   if (! recursion)
     unwind_protect
       recursion = true;
-      position = get (h, "position");
       view = get (h, "view");
-      plotboxaspectratio = get (h, "plotboxaspectratio");
-      plotboxaspectratiomode = get (h, "plotboxaspectratiomode");
-      oldposition = get (ax2, "position");
       oldview = get (ax2, "view");
+      plotboxaspectratio = get (h, "plotboxaspectratio");
       oldplotboxaspectratio = get (ax2, "plotboxaspectratio");
+      plotboxaspectratiomode = get (h, "plotboxaspectratiomode");
       oldplotboxaspectratiomode = get (ax2, "plotboxaspectratiomode");
-      if (! (isequal (position, oldposition) && isequal (view, oldview)))
-        set (ax2, "position", position, "view", view);
+
+      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);
--- a/scripts/plot/polar.m
+++ b/scripts/plot/polar.m
@@ -211,3 +211,15 @@
   endif
 
 endfunction
+
+
+%!demo
+%! theta = linspace (0, 2*pi, 1000);
+%! rho = sin (7*theta);
+%! polar (theta, rho);
+
+%!demo
+%! theta = linspace (0, 10*pi, 1000);
+%! rho = sin (5/4*theta);
+%! polar (theta, rho);
+
old mode 100755
new mode 100644
--- a/scripts/plot/private/__axis_label__.m
+++ b/scripts/plot/private/__axis_label__.m
@@ -25,24 +25,20 @@
 
 function retval = __axis_label__ (caller, txt, varargin)
 
-  if (ischar (txt))
-    ca = gca ();
+  ca = gca ();
 
-    h = get (gca (), caller);
+  h = get (gca (), caller);
 
-    set (h, "fontangle", get (ca, "fontangle"),
-         "fontname", get (ca, "fontname"),
-         "fontsize", get (ca, "fontsize"),
-         "fontunits", get (ca, "fontunits"),
-         "fontweight", get (ca, "fontweight"),
-         "string", txt,
-         varargin{:});
+  set (h, "fontangle", get (ca, "fontangle"),
+       "fontname", get (ca, "fontname"),
+       "fontsize", get (ca, "fontsize"),
+       "fontunits", get (ca, "fontunits"),
+       "fontweight", get (ca, "fontweight"),
+       "string", txt,
+       varargin{:});
 
-    if (nargout > 0)
-      retval = h;
-    endif
-  else
-    error ("%s: expecting first argument to be character string", caller);
+  if (nargout > 0)
+    retval = h;
   endif
 
 endfunction
old mode 100755
new mode 100644
rename from scripts/plot/__fltk_ginput__.m
rename to scripts/plot/private/__fltk_ginput__.m
rename from scripts/plot/__fltk_print__.m
rename to scripts/plot/private/__fltk_print__.m
--- a/scripts/plot/private/__ghostscript__.m
+++ b/scripts/plot/private/__ghostscript__.m
@@ -44,7 +44,7 @@
   cleanup_cmd = "";
 
   args = varargin;
-  n = find (cellfun (@isstruct, args));
+  n = find (cellfun ("isclass", args, "struct"));
   if (! isempty (n))
     f = fieldnames (args{n});
     for m = 1:numel(f)
rename from scripts/plot/__gnuplot_get_var__.m
rename to scripts/plot/private/__gnuplot_get_var__.m
rename from scripts/plot/__gnuplot_ginput__.m
rename to scripts/plot/private/__gnuplot_ginput__.m
rename from scripts/plot/__gnuplot_has_feature__.m
rename to scripts/plot/private/__gnuplot_has_feature__.m
rename from scripts/plot/__gnuplot_open_stream__.m
rename to scripts/plot/private/__gnuplot_open_stream__.m
rename from scripts/plot/__gnuplot_print__.m
rename to scripts/plot/private/__gnuplot_print__.m
rename from scripts/plot/__gnuplot_version__.m
rename to scripts/plot/private/__gnuplot_version__.m
rename from scripts/plot/__go_draw_axes__.m
rename to scripts/plot/private/__go_draw_axes__.m
--- a/scripts/plot/__go_draw_axes__.m
+++ b/scripts/plot/private/__go_draw_axes__.m
@@ -1250,6 +1250,11 @@
             colorspec = get_text_colorspec (color, mono);
           endif
 
+          if (ischar (obj.string))
+            num_lines = size (obj.string, 1);
+          else
+            num_lines = numel (obj.string);
+          endif
           switch valign
             ## Text offset in characters. This relies on gnuplot for font metrics.
             case "top"
@@ -1257,17 +1262,18 @@
             case "cap"
               dy = -0.5;
             case "middle"
-              dy = 0;
+              dy = 0.5 * (num_lines - 1);
             case "baseline"
-              dy = 0.5;
+              dy = 0.5 + (num_lines - 1);
             case "bottom"
-              dy = 0.5;
+              dy = 0.5 + (num_lines - 1);
           endswitch
           ## Gnuplot's Character units are different for x/y and vary with fontsize. The aspect ratio
           ## of 1:1.7 was determined by experiment to work for eps/ps/etc. For the MacOS aqua terminal
           ## a value of 2.5 is needed. However, the difference is barely noticable.
           dx_and_dy = [(-dy * sind (angle)), (dy * cosd(angle))] .* [1.7 1];
 
+          ## FIXME - Multiline text produced the gnuplot "warning: ft_render: skipping glyph"
           if (nd == 3)
             ## This produces the desired vertical alignment in 3D.
             fprintf (plot_stream,
@@ -1312,7 +1318,7 @@
       fputs (plot_stream, "unset hidden3d;\n");
     endif
 
-    have_data = (! (isempty (data) || all (cellfun (@isempty, data))));
+    have_data = (! (isempty (data) || all (cellfun ("isempty", data))));
 
     ## Note we don't use the [xy]2range of gnuplot as we don't use the
     ## dual axis plotting features of gnuplot.
@@ -2129,10 +2135,31 @@
     bld = false;
   endif
 
+  ## The text object maybe multiline, and may be of any class
   str = getfield (obj, fld);
+  if (ischar (str) && size (str, 1) > 1)
+    str = cellstr (str);
+  elseif (isnumeric (str))
+    str = cellstr (num2str (str(:)));
+  endif
+  if (iscellstr (str))
+    for n = 1:numel(str)
+      if (isnumeric (str{n}))
+        str{n} = num2str (str{n});
+      endif
+    endfor
+    str = sprintf ("%s\n", str{:})(1:end-1);
+  endif
+
   if (enhanced)
     if (strcmpi (obj.interpreter, "tex"))
-      str = __tex2enhanced__ (str, fnt, it, bld);
+      if (iscellstr (str))
+        for n = 1:numel(str)
+          str{n} = __tex2enhanced__ (str{n}, fnt, it, bld);
+        endfor
+      else
+        str = __tex2enhanced__ (str, fnt, it, bld);
+      endif
     elseif (strcmpi (obj.interpreter, "latex"))
       if (! warned_latex)
         warning ("latex markup not supported for text objects");
@@ -2328,7 +2355,7 @@
   l = length (s) - length (strfind(s,'{')) - length (strfind(s,'}'));
   m = regexp (s, '/([\w-]+|[\w-]+=\d+)', 'matches');
   if (!isempty (m))
-    l = l - sum (cellfun (@length, m));
+    l = l - sum (cellfun ("length", m));
   endif
 endfunction
 
rename from scripts/plot/__go_draw_figure__.m
rename to scripts/plot/private/__go_draw_figure__.m
rename from scripts/plot/__marching_cube__.m
rename to scripts/plot/private/__marching_cube__.m
rename from scripts/plot/__next_line_color__.m
rename to scripts/plot/private/__next_line_color__.m
rename from scripts/plot/__next_line_style__.m
rename to scripts/plot/private/__next_line_style__.m
--- a/scripts/plot/private/__patch__.m
+++ b/scripts/plot/private/__patch__.m
@@ -134,7 +134,7 @@
     endif
   else
     args = varargin;
-    if (any(cellfun (@(x) strcmpi(x,"faces") || strcmpi(x, "vertices"), args)))
+    if (any (strcmpi (args, "faces") | strcmpi (args, "vertices")))
       args = setdata (args);
     else
       args = setvertexdata (args);
rename from scripts/plot/__print_parse_opts__.m
rename to scripts/plot/private/__print_parse_opts__.m
--- a/scripts/plot/__print_parse_opts__.m
+++ b/scripts/plot/private/__print_parse_opts__.m
@@ -361,7 +361,8 @@
 
 endfunction
 
-%!test
+## Test blocks are not allowed (and not needed) for private functions
+#%!test
 %! opts = __print_parse_opts__ ();
 %! assert (opts.devopt, "pswrite");
 %! assert (opts.use_color, 1);
@@ -369,11 +370,11 @@
 %! assert (opts.canvas_size, [576, 432]);
 %! assert (opts.ghostscript.device, "pswrite")
 
-%!test
+#%!test
 %! opts = __print_parse_opts__ ("test.pdf", "-S640,480");
 %! assert (opts.canvas_size, [307.2, 230.4], 0.1);
 
-%!test
+#%!test
 %! opts = __print_parse_opts__ ("-dpsc", "-append", "-loose");
 %! assert (opts.devopt, "pswrite");
 %! assert (opts.send_to_printer, true);
@@ -382,14 +383,14 @@
 %! assert (opts.ghostscript.device, "pswrite")
 %! assert (opts.ghostscript.epscrop, false);
 
-%!test
+#%!test
 %! opts = __print_parse_opts__ ("-deps", "-tight");
 %! assert (opts.tight_flag, true);
 %! assert (opts.send_to_printer, true);
 %! assert (opts.use_color, -1);
 %! assert (opts.ghostscript.device, "")
 
-%!test
+#%!test
 %! opts = __print_parse_opts__ ("-djpg", "foobar", "-mono", "-loose");
 %! assert (opts.devopt, "jpeg")
 %! assert (opts.name, "foobar.jpg")
@@ -401,7 +402,7 @@
 %! assert (opts.printer, "");
 %! assert (opts.use_color, -1);
 
-%!test
+#%!test
 %! opts = __print_parse_opts__ ("-ddeskjet", "foobar", "-mono", "-Pmyprinter");
 %! assert (opts.ghostscript.output, "foobar.deskjet")
 %! assert (opts.ghostscript.device, "deskjet")
@@ -410,7 +411,7 @@
 %! assert (opts.printer, "-Pmyprinter");
 %! assert (opts.use_color, -1);
 
-%!test
+#%!test
 %! opts = __print_parse_opts__ ("-f5", "-dljet3");
 %! assert (opts.ghostscript.device, "ljet3")
 %! assert (strfind (opts.ghostscript.output, ".ljet3"))
--- a/scripts/plot/rectangle.m
+++ b/scripts/plot/rectangle.m
@@ -25,8 +25,8 @@
 ## @deftypefnx {Function File} {@var{h} =} rectangle (@dots{})
 ##
 ## Draw rectangular patch defined by @var{pos} and @var{curv}.  The variable
-## @code{@var{pos}(1 : 2)} defines the lower left-hand corner of the patch
-## and @code{@var{pos}(3 : 4)} defines its width and height.  By default, the
+## @code{@var{pos}(1:2)} defines the lower left-hand corner of the patch
+## and @code{@var{pos}(3:4)} defines its width and height.  By default, the
 ## value of @var{pos} is @code{[0, 0, 1, 1]}.
 ##
 ## The variable @var{curv} defines the curvature of the sides of the rectangle
@@ -41,7 +41,7 @@
 ## by
 ##
 ## @example
-## min (pos (1: 2)) / max (pos (1:2)) * curv
+## min (pos (1:2)) / max (pos (1:2)) * curv
 ## @end example
 ##
 ## Other properties are passed to the underlying patch command.  If called 
--- a/scripts/plot/refreshdata.m
+++ b/scripts/plot/refreshdata.m
@@ -83,7 +83,7 @@
     obj = get (h (i));
     fldnames = fieldnames (obj);
     m = regexpi (fieldnames(obj), '^.+datasource$', "match");
-    idx = cellfun (@(x) !isempty(x), m);
+    idx = ! cellfun ("isempty", m);
     if (any (idx))
       tmp = m(idx);
       props = [props; {vertcat(tmp{:})}];
--- a/scripts/plot/subplot.m
+++ b/scripts/plot/subplot.m
@@ -124,7 +124,22 @@
     units = "normalized";
     set (0, "defaultaxesunits", units);
     set (cf, "units", "pixels");
-    pos = subplot_position (rows, cols, index, "position");
+
+    ## FIXME: At the moment we force gnuplot to use the aligned mode
+    ##        which will set "activepositionproperty" to "position".
+    ##        Τhis can yield to text overlap between labels and titles
+    ##        see bug #31610
+    if (strcmp (get (cf, "__graphics_toolkit__"), "gnuplot"))
+      align_axes = true;
+    endif
+
+    if (align_axes)
+      pos = subplot_position (rows, cols, index, "position");
+    elseif (strcmp (get (cf, "__graphics_toolkit__"), "gnuplot"))
+      pos = subplot_position (rows, cols, index, "outerpositiontight");
+    else
+      pos = subplot_position (rows, cols, index, "outerposition");
+    endif
 
     set (cf, "nextplot", "add");
 
@@ -144,7 +159,11 @@
             || strcmp (get (child, "tag"), "colorbar"))
           continue;
         endif
-        objpos = get (child, "position");
+        if (align_axes)
+          objpos = get (child, "position");
+        else
+          objpos = get (child, "outerposition");
+        endif
         if (all (objpos == pos) && ! replace_axes)
           ## If the new axes are in exactly the same position as an
           ## existing axes object, use the existing axes.
@@ -170,14 +189,13 @@
 
     if (found)
       set (cf, "currentaxes", tmp);
+    elseif (align_axes)
+      tmp = axes ("box", "off", "position", pos);
+    elseif (strcmp (get (cf, "__graphics_toolkit__"), "gnuplot"))
+      tmp = axes ("box", "off", "outerposition", pos);
     else
-      outpos = subplot_position (rows, cols, index, "outerposition");
-      tmp = axes ("looseinset", [0 0 0 0], "box", "off",
-                  "outerposition", outpos, "position", pos);
-    endif
-
-    if (align_axes || strcmp (get (cf, "__graphics_toolkit__"), "gnuplot"))
-      set (tmp, "activepositionproperty", "position");
+      tmp = axes ("looseinset", [0 0 0 0], "box", "off", "outerposition", pos,
+                  "autopos_tag", "subplot");
     endif
 
   unwind_protect_cleanup
@@ -193,67 +211,55 @@
 
 function pos = subplot_position (rows, cols, index, position_property)
 
-  defaultaxesposition = get (0, "defaultaxesposition");
-  defaultaxesouterposition = get (0, "defaultaxesouterposition");
-
   if (rows == 1 && cols == 1)
     ## Trivial result for subplot (1,1,1)
     if (strcmpi (position_property, "position"))
-      pos = defaultaxesposition;
+      pos = get (0, "defaultaxesposition");
     else
-      pos = defaultaxesouterposition;
+      pos = get (0, "defaultaxesouterposition");
     endif
     return
   endif
 
-  ## The outer margins surrounding all subplot "positions" are independent of
-  ## the number of rows and/or columns
-  margins.left   = defaultaxesposition(1);
-  margins.bottom = defaultaxesposition(2);
-  margins.right  = 1.0 - margins.left - defaultaxesposition(3);
-  margins.top    = 1.0 - margins.bottom - defaultaxesposition(4);
-
-  ## Fit from Matlab experiments
-  pc = 1 ./ [0.1860, (margins.left + margins.right - 1)];
-  margins.column = 1 ./ polyval (pc , cols);
-  pr = 1 ./ [0.2282, (margins.top + margins.bottom - 1)];
-  margins.row    = 1 ./ polyval (pr , rows);
-
-  ## Calculate the width/height of the subplot axes "position".
-  ## This is also consistent with Matlab
-  width = 1 - margins.left - margins.right - (cols-1)*margins.column;
-  width = width / cols;
-  height = 1 - margins.top - margins.bottom - (rows-1)*margins.row;
-  height = height / rows;
+  if (strcmp (position_property, "outerposition")
+      || strcmp (position_property, "outerpositiontight"))
+    margins.left   = 0.05;
+    margins.bottom = 0.05;
+    margins.right  = 0.05;
+    margins.top    = 0.05;
+    if (strcmp (position_property, "outerpositiontight"))
+      margins.column = 0.;
+      margins.row = 0.;
+    else
+      margins.column = 0.04 / cols;
+      margins.row = 0.04 / rows;
+    endif
+    width = 1 - margins.left - margins.right - (cols-1)*margins.column;
+    width = width / cols;
+    height = 1 - margins.top - margins.bottom - (rows-1)*margins.row;
+    height = height / rows;
+  else
+    defaultaxesposition = get (0, "defaultaxesposition");
 
-  if (strcmp (position_property, "outerposition") )
-    ## Calculate the inset of the position relative to the outerposition
-    ## The outerpositions are assumed to be tiled. Matlab's implementation
-    ## has outerposition overlap.
-    if (rows > 1)
-      ## Title on top and xlabel & xticks on bottom
-      inset.top = margins.row * (1/3);
-      inset.bottom = margins.row * (2/3);
-      ## Matlab behavior is approximately ...
-      % inset.bottom = margins.row;
-    else
-      inset.bottom = margins.bottom;
-      inset.top = margins.top;
-    endif
-    if (cols > 1)
-      ## ylabel & yticks on left and some overhang for xticks on right
-      x = 0.1;
-      inset.right = x * margins.column;
-      inset.left = (1 - x) * margins.column;
-    else
-      inset.left  = margins.left;
-      inset.right = margins.right;
-    endif
-    ## Apply the inset to the geometries for the "position" property.
-    margins.column = margins.column - inset.right - inset.left;
-    margins.row = margins.row - inset.top - inset.bottom;
-    width = width + inset.right + inset.left;
-    height = height + inset.top + inset.bottom;
+    ## The outer margins surrounding all subplot "positions" are independent
+    ## of the number of rows and/or columns
+    margins.left   = defaultaxesposition(1);
+    margins.bottom = defaultaxesposition(2);
+    margins.right  = 1.0 - margins.left - defaultaxesposition(3);
+    margins.top    = 1.0 - margins.bottom - defaultaxesposition(4);
+
+    ## Fit from Matlab experiments
+    pc = 1 ./ [0.1860, (margins.left + margins.right - 1)];
+    margins.column = 1 ./ polyval (pc , cols);
+    pr = 1 ./ [0.2282, (margins.top + margins.bottom - 1)];
+    margins.row    = 1 ./ polyval (pr , rows);
+
+    ## Calculate the width/height of the subplot axes "position".
+    ## This is also consistent with Matlab
+    width = 1 - margins.left - margins.right - (cols-1)*margins.column;
+    width = width / cols;
+    height = 1 - margins.top - margins.bottom - (rows-1)*margins.row;
+    height = height / rows;
   endif
 
   ## Index offsets from the lower left subplot
@@ -265,12 +271,6 @@
   x0 = xi .* (width + margins.column) + margins.left;
   y0 = yi .* (height + margins.row) + margins.bottom;
 
-  if (strcmp (position_property, "outerposition") )
-    ## Shift from position(1:2) to outerposition(1:2)
-    x0 = x0 - inset.left;
-    y0 = y0 - inset.bottom;
-  endif
-
   if (numel(x0) > 1)
     ## subplot (row, col, m:n)
     x1 = max (x0(:)) + width;
--- a/scripts/plot/surface.m
+++ b/scripts/plot/surface.m
@@ -155,3 +155,7 @@
   endif
 
 endfunction
+
+## Mark file as being tested.  Tests for surface are in
+## surf.m, surfc.m, surfl.m, and pcolor.m
+%!assert(1)
--- a/scripts/plot/surfc.m
+++ b/scripts/plot/surfc.m
@@ -45,7 +45,26 @@
   drawnow ();
   zmin = get (ax, "zlim")(1);
 
-  [c, tmp2] = __contour__ (ax, zmin, varargin{:});
+  # don't pass axis handle and/or string arguments to __contour__()
+  stop_idx = nargin;
+  for i = 2 : nargin
+    if (ischar (varargin{i}))
+      stop_idx = i - 1;
+      break;
+    endif
+  endfor
+
+  start_idx = 1;
+  if (ishandle (varargin{1}))
+    start_idx = 2;
+  endif
+
+  if (stop_idx - start_idx == 1 || stop_idx - start_idx == 3)
+    #don't pass a color matrix c to __contour__
+    stop_idx -= 1;
+  endif
+
+  [c, tmp2] = __contour__ (ax, zmin, varargin{start_idx:stop_idx});
 
   tmp = [tmp; tmp2];
 
--- a/scripts/plot/text.m
+++ b/scripts/plot/text.m
@@ -47,15 +47,33 @@
     endif
 
     label = varargin{offset};
-    if (ischar (label) || iscellstr (label))
-      varargin(1:offset) = [];
-      if (ischar (label))
+    varargin(1:offset) = [];
+
+    nx = numel (x);
+    ny = numel (y);
+    nz = numel (z);
+    if (ischar (label) || isnumeric (label))
+      nt = size (label, 1);
+      if (nx > 1 && nt == 1)
+        ## Mutiple text objects with same string
+        label = repmat ({label}, [nx, 1]);
+        nt = nx;
+      elseif (nx > 1 && nt == nx)
+        ## Mutiple text objects with different strings
         label = cellstr (label);
+      elseif (ischar (label))
+        ## Single text object with one or more lines
+        label = {label};
       endif
-      n = numel (label);
-      nx = numel (x);
-      ny = numel (y);
-      nz = numel (z);
+    elseif (iscell (label))
+      nt = numel (label);
+      if (nx > 1 && nt == 1)
+        label = repmat ({label}, [nx, 1]);
+        nt = nx;
+      elseif (! (nx > 1 && nt == nx))
+        label = {label};
+        nt = 1;
+      endif
     else
       error ("text: expecting LABEL to be a character string or cell array of character strings");
     endif
@@ -63,35 +81,35 @@
     x = y = z = 0;
     nx = ny = nz = 1;
     label = {""};
-    n = 1;
+    nt = 1;
   endif
 
   if (rem (numel (varargin), 2) == 0)
 
-    if (nx == ny && nx == nz)
+    if (nx == ny && nx == nz && (nt == nx || nt == 1 || nx == 1))
       pos = [x(:), y(:), z(:)];
       ca = gca ();
-      tmp = zeros (n, 1);
-      if (n == 1)
-        label = label{1};
-        for i = 1:nx
-          tmp(i) = __go_text__ (ca, "string", label,
+      tmp = zeros (nt, 1);
+      if (nx == 1)
+        ## TODO - Modify __go_text__() to accept cell-strings
+        tmp = __go_text__ (ca, "string", "foobar",
+                           varargin{:},
+                           "position", pos);
+        set (tmp, "string", label{1});
+      elseif (nt == nx)
+        for n = 1:nt
+          tmp(n) = __go_text__ (ca, "string", label{n},
                                 varargin{:},
-                                "position", pos(i,:));
-        endfor
-        __request_drawnow__ ();
-      elseif (n == nx)
-        for i = 1:nx
-          tmp(i) = __go_text__ (ca, "string", label{i},
-                                varargin{:},
-                                "position", pos(i,:));
+                                "position", pos(n,:));
         endfor
         __request_drawnow__ ();
       else
         error ("text: dimension mismatch for coordinates and LABEL");
       endif
+    elseif (nt == nx || nt == 1 || nx == 1)
+      error ("text: dimension mismatch for coordinates");
     else
-      error ("text: dimension mismatch for coordinates");
+      error ("text: mismatch betwween coordinates and strings");
     endif
 
     if (nargout > 0)
@@ -142,3 +160,61 @@
 %! endfor
 %! caxis ([-100 100])
 %! title ("Vertically Aligned at Bottom")
+
+%!demo
+%! clf
+%! axis ([0 8 0 8])
+%! title (["First title";"Second title"])
+%! xlabel (["First xlabel";"Second xlabel"])
+%! ylabel (["First ylabel";"Second ylabel"])
+%! text (4, 4, {"Hello", "World"}, ...
+%!       "horizontalalignment", "center", ...
+%!       "verticalalignment", "middle")
+%! grid on
+
+%!demo
+%! clf
+%! h = mesh (peaks, "edgecolor", 0.7 * [1 1 1], ...
+%!                  "facecolor", "none", ...
+%!                  "facealpha", 0);
+%! title (["First title";"Second title"])
+%! xlabel (["First xlabel";"Second xlabel"])
+%! ylabel (["First ylabel";"Second ylabel"])
+%! zlabel (["First zlabel";"Second zlabel"])
+%! text (0, 0, 5, {"Hello", "World"}, ...
+%!       "horizontalalignment", "center", ...
+%!       "verticalalignment", "middle")
+%! hold on
+%! plot3 (0, 0, 5, "+k")
+%!
+
+%!demo
+%! clf
+%! h = text (0.5, 0.3, "char");
+%! assert ("char", class (get (h, "string")))
+%! h = text (0.5, 0.4, ["char row 1"; "char row 2"]);
+%! assert ("char", class (get (h, "string")))
+%! h = text (0.5, 0.6, {"cell2str (1,1)", "cell2str (1,2)"; "cell2str (2,1)", "cell2str (2,2)"});
+%! assert ("cell", class (get (h, "string")))
+%! h = text (0.5, 0.8, "foobar");
+%! set (h, "string", 1:3)
+%! h = text ([0.1, 0.1], [0.3, 0.4], "one string & two objects");
+%! assert ("char", class (get (h(1), "string")))
+%! assert ("char", class (get (h(2), "string")))
+%! h = text ([0.1, 0.1], [0.5, 0.6], {"one cellstr & two objects"});
+%! assert ("cell", class (get (h(1), "string")))
+%! assert ("cell", class (get (h(2), "string")))
+%! h = text ([0.1, 0.1], [0.7, 0.8], {"cellstr 1 object 1", "cellstr 2 object 2"});
+%! assert ("char", class (get (h(1), "string")))
+%! assert ("char", class (get (h(2), "string")))
+%! h = text ([0.1, 0.1], [0.1, 0.2], ["1st string & 1st object"; "2nd string & 2nd object"]);
+%! assert ("char", class (get (h(1), "string")))
+%! assert ("char", class (get (h(2), "string")))
+%! h = text (0.7, 0.6, "single string");
+%! assert ("char", class (get (h, "string")))
+%! h = text (0.7, 0.5, {"single cell-string"});
+%! assert ("cell", class (get (h, "string")))
+%! xlabel (1:2)
+%! ylabel (1:2)
+%! title (1:2)
+
rename from scripts/geometry/trimesh.m
rename to scripts/plot/trimesh.m
rename from scripts/geometry/triplot.m
rename to scripts/plot/triplot.m
rename from scripts/geometry/trisurf.m
rename to scripts/plot/trisurf.m
--- a/scripts/plot/uimenu.m
+++ b/scripts/plot/uimenu.m
@@ -66,8 +66,10 @@
 ## @group
 ## f = uimenu("label", "&File", "accelerator", "f");
 ## e = uimenu("label", "&Edit", "accelerator", "e");
-## uimenu(f, "label", "Close", "accelerator", "q", "callback", "close (gcf)");
-## uimenu(e, "label", "Toggle &Grid", "accelerator", "g", "callback", "grid (gca)");
+## uimenu(f, "label", "Close", "accelerator", "q", ...
+##           "callback", "close (gcf)");
+## uimenu(e, "label", "Toggle &Grid", "accelerator", "g", ...
+##           "callback", "grid (gca)");
 ## @end group
 ## @end example
 ## @seealso{figure}
--- a/scripts/plot/whitebg.m
+++ b/scripts/plot/whitebg.m
@@ -74,7 +74,7 @@
     if (isroot)
       fac = get (0, "factory");
       fields = fieldnames (fac);
-      fieldindex = intersect (find (!cellfun (@isempty, regexp(fields, 'color'))), union (find (!cellfun (@isempty, regexp(fields, 'factoryaxes.*'))), find (!cellfun (@isempty, regexp(fields, 'factoryfigure.*')))));
+      fieldindex = intersect (find (!cellfun ("isempty", regexp(fields, 'color'))), union (find (!cellfun ("isempty", regexp(fields, 'factoryaxes.*'))), find (!cellfun ("isempty", regexp(fields, 'factoryfigure.*')))));
 
       ## Check whether the factory value has been replaced
       for nf = 1 : numel (fieldindex);
@@ -104,7 +104,7 @@
     for nh = 1 : numel(h)
       p = get (h (nh));
       fields = fieldnames (p);
-      fieldindex = find (!cellfun (@isempty, regexp(fields, 'color')));
+      fieldindex = find (!cellfun ("isempty", regexp(fields, 'color')));
       if (numel (fieldindex))
         for nf = 1 : numel (fieldindex);
           field = fields {fieldindex (nf)};
@@ -121,7 +121,7 @@
         def = get (h (nh), "default");
         fields = fieldnames (def);
         if (! isempty (fields))
-          fieldindex = find (!cellfun (@isempty, regexp(fields, 'color')));
+          fieldindex = find (!cellfun ("isempty", regexp(fields, 'color')));
           for nf = 1 : numel (fieldindex)
             defaultfield = fields {fieldindex (nf)};
             defaultvalue = 1 - subsref (def, struct ("type", ".", "subs", defaultfield));
--- a/scripts/polynomial/mkpp.m
+++ b/scripts/polynomial/mkpp.m
@@ -17,50 +17,66 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {@var{pp} =} mkpp (@var{x}, @var{p})
-## @deftypefnx {Function File} {@var{pp} =} mkpp (@var{x}, @var{p}, @var{d})
+## @deftypefn  {Function File} {@var{pp} =} mkpp (@var{breaks}, @var{coefs})
+## @deftypefnx {Function File} {@var{pp} =} mkpp (@var{breaks}, @var{coefs}, @var{d})
+##
+## Construct a piece-wise polynomial (pp) structure from sample points
+## @var{breaks} and coefficients @var{coefs}.  @var{breaks} must be a vector of
+## strictly increasing values. The number of intervals is given by 
+## @code{@var{ni} = length (@var{breaks}) - 1}.
+## When @var{m} is the polynomial order @var{coefs} must be of 
+## size: @var{ni} x @var{m} + 1.
 ##
-## Construct a piecewise polynomial structure from sample points
-## @var{x} and coefficients @var{p}.  The i-th row of @var{p},
-## @code{@var{p} (@var{i},:)}, contains the coefficients for the polynomial
-## over the @var{i}-th interval, ordered from highest to
-## lowest.  There must be one row for each interval in @var{x}, so
-## @code{rows (@var{p}) == length (@var{x}) - 1}.
+## The i-th row of @var{coefs},
+## @code{@var{coefs} (@var{i},:)}, contains the coefficients for the polynomial
+## over the @var{i}-th interval, ordered from highest (@var{m}) to 
+## lowest (@var{0}).
 ##
-## @var{p} may also be a multi-dimensional array, specifying a vector-valued
-## or array-valued polynomial.  The shape is determined by @var{d}.  If @var{d}
-## is
-## not given, the default is @code{size (p)(1:end-2)}.  If @var{d} is given, the
-## leading dimensions of @var{p} are reshaped to conform to @var{d}.
+## @var{coefs} may also be a multi-dimensional array, specifying a vector-valued
+## or array-valued polynomial. In that case the polynomial order is defined
+## by the length of the last dimension of @var{coefs}.
+## The size of first dimension(s) are given by the scalar or
+## vector @var{d}. If @var{d} is not given it is set to @code{1}. 
+## In any case @var{coefs} is reshaped to a 2d matrix of
+## size @code{[@var{ni}*prod(@var{d} @var{m})] }
 ##
 ## @seealso{unmkpp, ppval, spline}
 ## @end deftypefn
 
 function pp = mkpp (x, P, d)
+
+  # check number of arguments
   if (nargin < 2 || nargin > 3)
     print_usage ();
   endif
-  pp.x = x(:);
-  n = length (x) - 1;
-  if (n < 1)
+
+  # check x
+  if (length (x) < 2)
     error ("mkpp: at least one interval is needed");
   endif
-  nd = ndims (P);
-  k = size (P, nd);
-  if (nargin < 3)
-    if (nd == 2)
-      d = 1;
-    else
-      d = prod (size (P)(1:nd-1));
-    endif
+
+  if (!isvector (x))
+    error ("mkpp: x must be a vector");
   endif
-  pp.d = d;
-  pp.P = P = reshape (P, prod (d), [], k);
-  pp.orient = 0;
+
+  len = length (x) - 1;
+  dP = length (size (P));
 
-  if (size (P, 2) != n)
-    error ("mkpp: num intervals in X doesn't match num polynomials in P");
-  endif
+  pp = struct ("form", "pp",
+               "breaks", x(:).',
+               "coefs", [],
+               "pieces", len,
+               "order", prod (size (P)) / len,
+               "dim", 1);
+
+  if (nargin == 3)
+    pp.dim = d;
+    pp.order /= prod (d);
+  endif 
+
+  dim_vec = [pp.pieces * prod(pp.dim), pp.order];
+  pp.coefs = reshape (P, dim_vec);
+
 endfunction
 
 %!demo # linear interpolation
@@ -72,3 +88,25 @@
 %! xi=linspace(0,pi,50);
 %! plot(x,t,"x",xi,ppval(pp,xi));
 %! legend("control","interp");
+
+%!shared b,c,pp
+%! b = 1:3; c = 1:24; pp=mkpp(b,c);
+%!assert (pp.pieces,2);
+%!assert (pp.order,12);
+%!assert (pp.dim,1);
+%!assert (size(pp.coefs),[2,12]);
+%! pp=mkpp(b,c,2);
+%!assert (pp.pieces,2);
+%!assert (pp.order,6);
+%!assert (pp.dim,2);
+%!assert (size(pp.coefs),[4,6]);
+%! pp=mkpp(b,c,3);
+%!assert (pp.pieces,2);
+%!assert (pp.order,4);
+%!assert (pp.dim,3);
+%!assert (size(pp.coefs),[6,4]);
+%! pp=mkpp(b,c,[2,3]);
+%!assert (pp.pieces,2);
+%!assert (pp.order,2);
+%!assert (pp.dim,[2,3]);
+%!assert (size(pp.coefs),[12,2]);
--- a/scripts/polynomial/module.mk
+++ b/scripts/polynomial/module.mk
@@ -10,7 +10,6 @@
   polynomial/poly.m \
   polynomial/polyaffine.m \
   polynomial/polyder.m \
-  polynomial/polyderiv.m \
   polynomial/polyfit.m \
   polynomial/polygcd.m \
   polynomial/polyint.m \
--- a/scripts/polynomial/pchip.m
+++ b/scripts/polynomial/pchip.m
@@ -27,8 +27,8 @@
 ##
 ## The variable @var{x} must be a strictly monotonic vector (either
 ## increasing or decreasing).  While @var{y} can be either a vector or
-## array.  In the case where @var{y} is a vector, it must have a length
-## of @var{n}.  If @var{y} is an array, then the size of @var{y} must
+## an array.  In the case where @var{y} is a vector, it must have the
+## length @var{n}.  If @var{y} is an array, then the size of @var{y} must
 ## have the form
 ## @tex
 ## $$[s_1, s_2, \cdots, s_k, n]$$
@@ -73,15 +73,22 @@
     print_usage ();
   endif
 
+  ## make row vector
   x = x(:).';
   n = length (x);
 
   ## Check the size and shape of y
   if (isvector (y))
-    y = y(:).';
+    y = y(:).'; ##row vector
     szy = size (y);
+    if !(size_equal (x, y))
+      error ("pchip: length of X and Y must match")
+    endif
   else
     szy = size (y);
+    if (n != szy(end))
+      error ("pchip: length of X and last dimension of Y must match")
+    endif
     y = reshape (y, [prod(szy(1:end-1)), szy(end)]);
   endif
 
@@ -94,16 +101,12 @@
     error("pchip: X must be strictly monotonic");
   endif
 
-  if (columns (y) != n)
-    error("pchip: size of X and Y must match");
-  endif
-
-  f1 = y(:,1:n-1);
+  f1 = y(:, 1:n-1);
 
   ## Compute derivatives.
   d = __pchip_deriv__ (x, y, 2);
-  d1 = d(:,1:n-1);
-  d2 = d(:,2:n);
+  d1 = d(:, 1:n-1);
+  d2 = d(:, 2:n);
 
   ## This is taken from SLATEC.
   h = diag (h);
@@ -114,14 +117,12 @@
   c3 = del1 + del2;
   c2 = -c3 - del1;
   c3 = c3 / h;
-
   coeffs = cat (3, c3, c2, d1, f1);
-  pp = mkpp (x, coeffs, szy(1:end-1));
 
-  if (nargin == 2)
-    ret = pp;
-  else
-    ret = ppval (pp, xi);
+  ret = mkpp (x, coeffs, szy(1:end-1));
+
+  if (nargin == 3)
+    ret = ppval (ret, xi);
   endif
 
 endfunction
@@ -138,7 +139,7 @@
 %! %-------------------------------------------------------------------
 %! % confirm that pchip agreed better to discontinuous data than spline
 
-%!shared x,y
+%!shared x,y,y2,pp,yi1,yi2,yi3
 %! x = 0:8;
 %! y = [1, 1, 1, 1, 0.5, 0, 0, 0, 0];
 %!assert (pchip(x,y,x), y);
@@ -148,3 +149,23 @@
 %!assert (isempty(pchip(x',y',[])));
 %!assert (isempty(pchip(x,y,[])));
 %!assert (pchip(x,[y;y],x), [pchip(x,y,x);pchip(x,y,x)])
+%!assert (pchip(x,[y;y],x'), [pchip(x,y,x);pchip(x,y,x)])
+%!assert (pchip(x',[y;y],x), [pchip(x,y,x);pchip(x,y,x)])
+%!assert (pchip(x',[y;y],x'), [pchip(x,y,x);pchip(x,y,x)])
+%!test
+%! x=(0:8)*pi/4;y=[sin(x);cos(x)];
+%! y2(:,:,1)=y;y2(:,:,2)=y+1;y2(:,:,3)=y-1;
+%! pp=pchip(x,shiftdim(y2,2));
+%! yi1=ppval(pp,(1:4)*pi/4);
+%! yi2=ppval(pp,repmat((1:4)*pi/4,[5,1]));
+%! yi3=ppval(pp,[pi/2,pi]);
+%!assert(size(pp.coefs),[48,4]);
+%!assert(pp.pieces,8);
+%!assert(pp.order,4);
+%!assert(pp.dim,[3,2]);
+%!assert(ppval(pp,pi),[0,-1;1,0;-1,-2],1e-14);
+%!assert(yi3(:,:,2),ppval(pp,pi),1e-14);
+%!assert(yi3(:,:,1),[1,0;2,1;0,-1],1e-14);
+%!assert(squeeze(yi1(1,2,:)),[1/sqrt(2); 0; -1/sqrt(2);-1],1e-14);
+%!assert(size(yi2),[3,2,5,4]);
+%!assert(squeeze(yi2(1,2,3,:)),[1/sqrt(2); 0; -1/sqrt(2);-1],1e-14);
\ No newline at end of file
--- a/scripts/polynomial/polyder.m
+++ b/scripts/polynomial/polyder.m
@@ -1,4 +1,4 @@
-## Copyright (C) 1995-2011 John W. Eaton
+## Copyright (C) 1994-2011 John W. Eaton
 ##
 ## This file is part of Octave.
 ##
@@ -17,27 +17,84 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} polyderiv (@var{p})
-## @deftypefnx {Function File} {[@var{k}] =} polyderiv (@var{a}, @var{b})
-## @deftypefnx {Function File} {[@var{q}, @var{d}] =} polyderiv (@var{b}, @var{a})
-## An alias for @code{polyderiv}.
-## @seealso{polyderiv}
+## @deftypefn  {Function File} {} polyder (@var{p})
+## @deftypefnx {Function File} {[@var{k}] =} polyder (@var{a}, @var{b})
+## @deftypefnx {Function File} {[@var{q}, @var{d}] =} polyder (@var{b}, @var{a})
+## Return the coefficients of the derivative of the polynomial whose
+## coefficients are given by the vector @var{p}.  If a pair of polynomials
+## is given, return the derivative of the product @math{@var{a}*@var{b}}.
+## If two inputs and two outputs are given, return the derivative of the
+## polynomial quotient @math{@var{b}/@var{a}}.  The quotient numerator is
+## in @var{q} and the denominator in @var{d}.
+## @seealso{poly, polyint, polyreduce, roots, conv, deconv, residue,
+## filter, polygcd, polyval, polyvalm}
 ## @end deftypefn
 
-## Author: John W. Eaton
+## Author: Tony Richardson <arichard@stark.cc.oh.us>
+## Created: June 1994
+## Adapted-By: jwe
 
 function [q, d] = polyder (p, a)
 
-  if (nargin == 1)
-    q = polyderiv (p);
-  elseif (nargin == 2)
-    if (nargout == 2)
-      [q, d] = polyderiv (p, a);
+  if (nargin == 1 || nargin == 2)
+    if (! isvector (p))
+      error ("polyder: argument must be a vector");
+    endif
+    if (nargin == 2)
+      if (! isvector (a))
+        error ("polyder: argument must be a vector");
+      endif
+      if (nargout == 1)
+        ## derivative of p*a returns a single polynomial
+        q = polyder (conv (p, a));
+      else
+        ## derivative of p/a returns numerator and denominator
+        d = conv (a, a);
+        if (numel (p) == 1)
+          q = -p * polyder (a);
+        elseif (numel (a) == 1)
+          q = a * polyder (p);
+        else
+          q = conv (polyder (p), a) - conv (p, polyder (a));
+          q = polyreduce (q);
+        endif
+
+        ## remove common factors from numerator and denominator
+        x = polygcd (q, d);
+        if (length(x) != 1)
+          q = deconv (q, x);
+          d = deconv (d, x);
+        endif
+
+        ## move all the gain into the numerator
+        q = q/d(1);
+        d = d/d(1);
+      endif
     else
-      q = polyderiv (p, a);
+      lp = numel (p);
+      if (lp == 1)
+        q = 0;
+        return;
+      elseif (lp == 0)
+        q = [];
+        return;
+      endif
+
+      ## Force P to be a row vector.
+      p = p(:).';
+
+      q = p(1:(lp-1)) .* [(lp-1):-1:1];
     endif
   else
     print_usage ();
   endif
 
 endfunction
+
+
+%!assert(all (all (polyder ([1, 2, 3]) == [2, 2])));
+%!assert(polyder (13) == 0);
+
+%!error polyder ([]);
+%!error polyder ([1, 2; 3, 4]);
+
--- a/scripts/polynomial/polyint.m
+++ b/scripts/polynomial/polyint.m
@@ -61,3 +61,18 @@
   retval = [(p ./ [lp:-1:1]), k];
 
 endfunction
+
+%!test
+%! A = [3, 2, 1];
+%! assert (polyint(A),polyint(A,0));
+%! assert (polyint(A),polyint(A'));
+%! assert (polyint(A),[1, 1, 1, 0]);
+%! assert (polyint(A,1),ones(1,4));
+
+%!test
+%! A = ones(1,8);
+%! B = [length(A):-1:1];
+%! assert (polyint(A),[1./B, 0]);
+
+%!error polyint()
+%!error polyint(ones(2,2))
--- a/scripts/polynomial/polyout.m
+++ b/scripts/polynomial/polyout.m
@@ -97,3 +97,9 @@
     str = num2str (c, 5);
   endif
 endfunction
+
+%!assert (polyout ([3 2 1]), '3*s^2 + 2*s^1 + 1')
+%!assert (polyout ([3 2 1], 'x'), '3*x^2 + 2*x^1 + 1')
+%!assert (polyout ([3 2 1], 'wxyz'), '3*wxyz^2 + 2*wxyz^1 + 1')
+%!assert (polyout ([5 4 3 2 1], '1'),'5*1^4 + 4*1^3 + 3*1^2 + 2*1^1 + 1')
+%!error polyout ([])
--- a/scripts/polynomial/polyval.m
+++ b/scripts/polynomial/polyval.m
@@ -20,7 +20,7 @@
 ## @deftypefn  {Function File} {@var{y} =} polyval (@var{p}, @var{x})
 ## @deftypefnx {Function File} {@var{y} =} polyval (@var{p}, @var{x}, [], @var{mu})
 ## Evaluate the polynomial @var{p} at the specified values of @var{x}.  When
-## @var{mu} is present evaluate the polynomial for
+## @var{mu} is present, evaluate the polynomial for
 ## (@var{x}-@var{mu}(1))/@var{mu}(2).
 ## If @var{x} is a vector or matrix, the polynomial is evaluated for each of
 ## the elements of @var{x}.
@@ -39,17 +39,19 @@
 ## Created: June 1994
 ## Adapted-By: jwe
 
-function [y, dy] = polyval (p, x, s, mu)
+function [y, dy] = polyval (p, x, s = [], mu)
 
   if (nargin < 2 || nargin > 4 || (nargout == 2 && nargin < 3))
     print_usage ();
   endif
 
-  if (nargin < 3)
-    s = [];
-  endif
-
-  if (! (isvector (p) || isempty (p)))
+  if (isempty (x))
+    y = [];
+    return;
+  elseif (isempty (p))
+    y = zeros (size (x));
+    return;
+  elseif (! isvector (p))
     error ("polyval: first argument must be a vector");
   endif
 
@@ -57,16 +59,6 @@
     x = (x - mu(1)) / mu(2);
   endif
 
-  if (isempty (x))
-    y = [];
-    return;
-  endif
-
-  if (length (p) == 0)
-    y = p;
-    return;
-  endif
-
   n = length (p) - 1;
   y = p(1) * ones (size (x));
   for i = 2:n+1
@@ -80,10 +72,23 @@
     ##   dy = t * sqrt (1 + sumsq (A/s.R, 2)) * s.normr / sqrt (s.df)
     ## If my inference is correct, then t must equal 1 for polyval.
     ## This is because finv (0.5, n, n) = 1.0 for any n.
-    k = numel (x);
-    A = (x(:) * ones (1, n+1)) .^ (ones (k, 1) * (n:-1:0));
-    dy = sqrt (1 + sumsq (A/s.R, 2)) * s.normr / sqrt (s.df);
-    dy = reshape (dy, size (x));
+    try
+      k = numel (x);
+      A = (x(:) * ones (1, n+1)) .^ (ones (k, 1) * (n:-1:0));
+      dy = sqrt (1 + sumsq (A/s.R, 2)) * s.normr / sqrt (s.df);
+      dy = reshape (dy, size (x));
+    catch
+      if (isempty (s))
+        error ("polyval: third input is required.")
+      elseif (isstruct (s)
+              && all (ismember ({"R", "normr", "df"}, fieldnames (s))))
+        error (lasterr ())
+      elseif (isstruct (s))
+        error ("polyval: third input is missing the required fields.");
+      else
+        error ("polyval: third input is not a structure.");
+      endif
+    end_try_catch
   endif
 
 endfunction
@@ -142,3 +147,6 @@
 %! assert (y, polyval(p,x), eps)
 %! x = reshape(x, [1, 1, 5, 2]);
 
+%!assert (zeros (1, 10), polyval ([], 1:10))
+%!assert ([], polyval (1, []))
+%!assert ([], polyval ([], []))
--- a/scripts/polynomial/ppder.m
+++ b/scripts/polynomial/ppder.m
@@ -17,28 +17,54 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {@var{ppd} =} ppder (@var{pp})
-## Compute the piecewise derivative of the piecewise polynomial struct @var{pp}.
+## @deftypefn {Function File} {ppd =} ppder (pp, m)
+## Computes the piecewise @var{m}-th derivative of a piecewise polynomial
+## struct @var{pp}. If @var{m} is omitted the first derivate is
+## calculated.
 ## @seealso{mkpp, ppval, ppint}
 ## @end deftypefn
 
-function ppd = ppder (pp)
-  if (nargin != 1)
+function ppd = ppder (pp, m)
+
+  if ((nargin < 1) || (nargin > 2))
     print_usage ();
+  elseif (nargin == 1)
+    m = 1;
   endif
-  if (! isstruct (pp))
+
+  if !(isstruct (pp) && strcmp (pp.form, "pp"))
     error ("ppder: PP must be a structure");
   endif
 
   [x, p, n, k, d] = unmkpp (pp);
-  p = reshape (p, [], k);
-  if (k <= 1)
-    pd = zeros (rows (p), 1);
-    k = 1;
+
+  if (k - m <= 0)
+    x = [x(1) x(end)];
+    pd = zeros (prod (d), 1);
   else
-    k -= 1;
-    pd = p(:,1:k) * diag (k:-1:1);
+    f = k : -1 : 1;
+    ff = bincoeff (f, m + 1) .* factorial (m + 1) ./ f;
+    k -= m;
+    pd = p(:,1:k) * diag (ff(1:k));
   endif
+
   ppd = mkpp (x, pd, d);
 endfunction
 
+%!shared x,y,pp,ppd
+%! x=0:8;y=[x.^2;x.^3+1];pp=spline(x,y);
+%! ppd=ppder(pp);
+%!assert(ppval(ppd,x),[2*x;3*x.^2],1e-14)
+%!assert(ppd.order,3)
+%! ppd=ppder(pp,2);
+%!assert(ppval(ppd,x),[2*ones(size(x));6*x],1e-14)
+%!assert(ppd.order,2)
+%! ppd=ppder(pp,3);
+%!assert(ppd.order,1)
+%!assert(ppd.pieces,8)
+%!assert(size(ppd.coefs),[16,1])
+%! ppd=ppder(pp,4);
+%!assert(ppd.order,1)
+%!assert(ppd.pieces,1)
+%!assert(size(ppd.coefs),[2,1])
+%!assert(ppval(ppd,x),zeros(size(y)),1e-14)
--- a/scripts/polynomial/ppint.m
+++ b/scripts/polynomial/ppint.m
@@ -28,7 +28,7 @@
   if (nargin < 1 || nargin > 2)
     print_usage ();
   endif
-  if (! isstruct (pp))
+  if (! isstruct (pp) && strcmp (pp.form, "pp"))
     error ("ppint: PP must be a structure");
   endif
 
@@ -39,17 +39,20 @@
   pi = p / diag (k:-1:1);
   k += 1;
   if (nargin == 1)
-    pi(:,k) = 0;
+    pi(:, k) = 0;
   else
-    pi(:,k) = repmat (c(:), n, 1);
+    pi(:, k) = repmat (c(:), n, 1);
   endif
 
   ppi = mkpp (x, pi, d);
 
-  ## Adjust constants so the the result is continuous.
-
-  jumps = reshape (ppjumps (ppi), prod (d), n-1);
-  ppi.P(:,2:n,k) -= cumsum (jumps, 2);
-
+  tmp = -cumsum (ppjumps (ppi), length (d) + 1);
+  ppi.coefs(prod(d)+1:end, k) = tmp(:);
+  
 endfunction
 
+%!shared x,y,pp,ppi
+%! x=0:8;y=[ones(size(x));x+1];pp=spline(x,y);
+%! ppi=ppint(pp);
+%!assert(ppval(ppi,x),[x;0.5*x.^2+x],1e-14)
+%!assert(ppi.order,5)
--- a/scripts/polynomial/ppjumps.m
+++ b/scripts/polynomial/ppjumps.m
@@ -28,29 +28,31 @@
   if (nargin != 1)
     print_usage ();
   endif
-  if (! isstruct (pp))
+  
+  if (! isstruct (pp) && strcmp (pp.form, "pp"))
     error ("ppjumps: PP must be a structure");
   endif
 
   ## Extract info.
-  x = pp.x;
-  P = pp.P;
-  d = pp.d;
-  [nd, n, k] = size (P);
+  [x, P, n, k, d] = unmkpp(pp);
+  nd = length (d) + 1;
 
   ## Offsets.
-  dx = diff (x(1:n)).';
-  dx = dx(ones (1, nd), :); # spread (do nothing in 1D)
+  dx = diff(x(1:n));
+  dx = repmat (dx, [prod(d), 1]);
+  dx = reshape (dx, [d, n-1]);
+  dx = shiftdim (dx, nd - 1);
 
-  ## Use Horner scheme to get limits from the left.
-  llim = P(:,1:n-1,1);
-  for i = 2:k;
+  ## Use Horner scheme.
+  if (k>1)
+    llim = shiftdim (reshape (P(1:(n-1) * prod(d), 1), [d, n-1]), nd - 1);
+  endif
+
+  for i = 2 : k;
     llim .*= dx;
-    llim += P(:,1:n-1,i);
+    llim += shiftdim (reshape (P(1:(n-1) * prod (d), i), [d, n-1]), nd - 1);
   endfor
-
-  rlim = P(:,2:n,k); # limits from the right
-  jumps = reshape (rlim - llim, [d, n-1]);
-
+  
+  rlim = shiftdim (ppval (pp, x(2:end-1)), nd - 1);
+  jumps = shiftdim (rlim - llim, 1);
 endfunction
-
--- a/scripts/polynomial/ppval.m
+++ b/scripts/polynomial/ppval.m
@@ -18,16 +18,18 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {@var{yi} =} ppval (@var{pp}, @var{xi})
-## Evaluate piecewise polynomial @var{pp} at the points @var{xi}.
-## If @var{pp} is scalar-valued, the result is an array of the same shape as
-## @var{xi}.
-## Otherwise, the size of the result is @code{[pp.d, length(@var{xi})]} if
-## @var{xi} is a vector, or @code{[pp.d, size(@var{xi})]} if it is a
-## multi-dimensional array.  If pp.orient is 1, the dimensions are permuted as
+## Evaluate piece-wise polynomial structure @var{pp} at the points @var{xi}.  
+## If @var{pp} describes a scalar polynomial function, the result is an
+## array of the same shape as @var{xi}.
+## Otherwise, the size of the result is @code{[pp.dim, length(@var{xi})]} if
+## @var{xi} is a vector, or @code{[pp.dim, size(@var{xi})]} if it is a
+## multi-dimensional array.  
+##
+##, the dimensions are permuted as
 ## in interp1, to
 ## @code{[pp.d, length(@var{xi})]} and @code{[pp.d, size(@var{xi})]}
 ## respectively.
-## @seealso{mkpp, unmkpp, spline}
+## @seealso{mkpp, unmkpp, spline, pchip, interp1}
 ## @end deftypefn
 
 function yi = ppval (pp, xi)
@@ -35,48 +37,85 @@
   if (nargin != 2)
     print_usage ();
   endif
-  if (! isstruct (pp))
-    error ("ppval: PP must be a structure");
+  if (! isstruct (pp) && strcmp (pp.form, "pp"))
+    error ("ppval: expects a pp-form structure");
   endif
 
   ## Extract info.
-  x = pp.x;
-  P = pp.P;
-  d = pp.d;
-  k = size (P, 3);
-  nd = size (P, 1);
-
-  ## Determine resulting shape.
-  if (d == 1) # scalar case
-    yisz = size (xi);
-  elseif (isvector (xi)) # this is special
-    yisz = [d, length(xi)];
-  else # general
-    yisz = [d, size(xi)];
+  [x, P, n, k, d] = unmkpp (pp);
+  
+  ## dimension checks
+  sxi = size (xi);
+  if (isvector (xi))
+    xi = xi(:).';
   endif
+  
+  nd = length (d);
 
   ## Determine intervals.
-  xi = xi(:);
   xn = numel (xi);
-
   idx = lookup (x, xi, "lr");
 
+  P = reshape (P, [d, n * k]);
+  P = shiftdim (P, nd);
+  P = reshape (P, [n, k, d]);
+  Pidx = P(idx(:), :);#2d matrix size x: coefs*prod(d) y: prod(sxi)
+  
+  if (isvector(xi))
+    Pidx = reshape (Pidx, [xn, k, d]);
+    Pidx = shiftdim (Pidx, 1);
+    dimvec = [d, xn];
+  else
+    Pidx = reshape (Pidx, [sxi, k, d]);
+    Pidx = shiftdim (Pidx, length (sxi));
+    dimvec = [d, sxi];
+  end
+  ndv = length (dimvec);
+
   ## Offsets.
-  dx = (xi - x(idx)).';
-  dx = dx(ones (1, nd), :); # spread (do nothing in 1D)
+  dx = (xi - x(idx));
+  dx = repmat (dx, [prod(d), 1]);
+  dx = reshape (dx, dimvec);
+  dx = shiftdim (dx, ndv - 1);
 
   ## Use Horner scheme.
-  yi = P(:,idx,1);
-  for i = 2:k;
+  yi = Pidx;
+  if (k > 1)
+    yi = shiftdim (reshape (Pidx(1,:), dimvec), ndv - 1);
+  endif
+  
+  for i = 2 : k;
     yi .*= dx;
-    yi += P(:,idx,i);
+    yi += shiftdim (reshape (Pidx(i,:), dimvec), ndv - 1);
   endfor
-
+  
   ## Adjust shape.
-  yi = reshape (yi, yisz);
-  if (d != 1 && pp.orient == 1)
-    ## Switch dimensions to match interp1 order.
-    yi = shiftdim (yi, length (d));
+  if ((numel (xi) > 1) || (length (d) == 1))
+    yi = reshape (shiftdim (yi, 1), dimvec);
   endif
 
+  if (isvector (xi) && (d == 1))
+    yi = reshape (yi, sxi);
+  elseif (isfield (pp, "orient") && strcmp (pp.orient, "first"))
+    yi = shiftdim(yi, nd);
+  endif
+
+  ##
+  #if (d == 1)
+  #  yi = reshape (yi, sxi);
+  #endif
+  
 endfunction
+
+%!shared b,c,pp,pp2,xi,abserr
+%! b = 1:3; c = ones(2); pp=mkpp(b,c);abserr = 1e-14;pp2=mkpp(b,[c;c],2);
+%! xi = [1.1 1.3 1.9 2.1];
+%!assert (ppval(pp,1.1), 1.1, abserr);
+%!assert (ppval(pp,2.1), 1.1, abserr);
+%!assert (ppval(pp,xi), [1.1 1.3 1.9 1.1], abserr);
+%!assert (ppval(pp,xi.'), [1.1 1.3 1.9 1.1].', abserr);
+%!assert (ppval(pp2,1.1), [1.1;1.1], abserr);
+%!assert (ppval(pp2,2.1), [1.1;1.1], abserr);
+%!assert (ppval(pp2,xi), [1.1 1.3 1.9 1.1;1.1 1.3 1.9 1.1], abserr);
+%!assert (ppval(pp2,xi'), [1.1 1.3 1.9 1.1;1.1 1.3 1.9 1.1], abserr);
+%!assert (size(ppval(pp2,[xi;xi])), [2 2 4]);
--- a/scripts/polynomial/spline.m
+++ b/scripts/polynomial/spline.m
@@ -83,15 +83,15 @@
   ## Check the size and shape of y
   ndy = ndims (y);
   szy = size (y);
-  if (ndy == 2 && (szy(1) == 1 || szy(2) == 1))
-    if (szy(1) == 1)
+  if (ndy == 2 && (szy(1) == n || szy(2) == n))
+    if (szy(2) == n)
       a = y.';
     else
       a = y;
       szy = fliplr (szy);
     endif
   else
-    a = reshape (y, [prod(szy(1:end-1)), szy(end)]).';
+    a = shiftdim (reshape (y, [prod(szy(1:end-1)), szy(end)]), 1);
   endif
 
   for k = (1:columns (a))(any (isnan (a)))
@@ -120,9 +120,9 @@
 
     if (n == 2)
       d = (dfs + dfe) / (x(2) - x(1)) ^ 2 + ...
-	2 * (a(1,:) - a(2,:)) / (x(2) - x(1)) ^ 3;
+          2 * (a(1,:) - a(2,:)) / (x(2) - x(1)) ^ 3;
       c = (-2 * dfs - dfe) / (x(2) - x(1)) - ...
-	3 * (a(1,:) - a(2,:)) / (x(2) - x(1)) ^ 2;
+          3 * (a(1,:) - a(2,:)) / (x(2) - x(1)) ^ 2;
       b = dfs;
       a = a(1,:);
 
@@ -132,7 +132,7 @@
       a = a(1:n-1,:);
     else
       if (n == 3)
-	dg = 1.5 * h(1) - 0.5 * h(2);
+        dg = 1.5 * h(1) - 0.5 * h(2);
         c(2:n-1,:) = 1/dg(1);
       else
         dg = 2 * (h(1:n-2) .+ h(2:n-1));
@@ -153,9 +153,9 @@
       endif
 
       c(1,:) = (3 / h(1) * (a(2,:) - a(1,:)) - 3 * dfs
-		- c(2,:) * h(1)) / (2 * h(1));
+             - c(2,:) * h(1)) / (2 * h(1));
       c(n,:) = - (3 / h(n-1) * (a(n,:) - a(n-1,:)) - 3 * dfe
-		  + c(n-1,:) * h(n-1)) / (2 * h(n-1));
+             + c(n-1,:) * h(n-1)) / (2 * h(n-1));
       b(1:n-1,:) = diff (a) ./ h(1:n-1, idx) ...
         - h(1:n-1,idx) / 3 .* (c(2:n,:) + 2 * c(1:n-1,:));
       d = diff (c) ./ (3 * h(1:n-1, idx));
@@ -229,15 +229,14 @@
           - h(1:n-1, idx) / 3 .* (c(2:n,:) + 2 * c(1:n-1,:));
       d = diff (c) ./ (3 * h(1:n-1, idx));
 
-      d = d(1:n-1,:);
-      c = c(1:n-1,:);
-      b = b(1:n-1,:);
-      a = a(1:n-1,:);
+      d = d(1:n-1,:);d = d.'(:);
+      c = c(1:n-1,:);c = c.'(:);
+      b = b(1:n-1,:);b = b.'(:);
+      a = a(1:n-1,:);a = a.'(:);
     endif
 
   endif
-  coeffs = cat (3, d.', c.', b.', a.');
-  ret = mkpp (x, coeffs, szy(1:end-1));
+  ret = mkpp (x, cat (2, d, c, b, a), szy(1:end-1));
 
   if (nargin == 3)
     ret = ppval (ret, xi);
@@ -263,6 +262,9 @@
 %!assert (isempty(spline(x',y',[])));
 %!assert (isempty(spline(x,y,[])));
 %!assert (spline(x,[y;y],x), [spline(x,y,x);spline(x,y,x)],abserr)
+%!assert (spline(x,[y;y],x'), [spline(x,y,x);spline(x,y,x)],abserr)
+%!assert (spline(x',[y;y],x), [spline(x,y,x);spline(x,y,x)],abserr)
+%!assert (spline(x',[y;y],x'), [spline(x,y,x);spline(x,y,x)],abserr)
 %! y = cos(x) + i*sin(x);
 %!assert (spline(x,y,x), y, abserr)
 %!assert (real(spline(x,y,x)), real(y), abserr);
--- a/scripts/polynomial/unmkpp.m
+++ b/scripts/polynomial/unmkpp.m
@@ -50,15 +50,13 @@
   if (nargin == 0)
     print_usage ();
   endif
-  if (! isstruct (pp))
+  if (! (isstruct (pp) && strcmp (pp.form, "pp")))
     error ("unmkpp: expecting piecewise polynomial structure");
   endif
-  x = pp.x;
-  P = pp.P;
-  n = size (P, 2);
-  k = size (P, 3);
-  d = pp.d;
-  if (d == 1)
-    P = reshape (P, n, k);
-  endif
+  x = pp.breaks;
+  P = pp.coefs;
+  n = pp.pieces;
+  k = pp.order;
+  d = pp.dim;
+
 endfunction
--- a/scripts/set/powerset.m
+++ b/scripts/set/powerset.m
@@ -75,3 +75,9 @@
   endif
 
 endfunction
+
+
+%!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);
--- a/scripts/set/setxor.m
+++ b/scripts/set/setxor.m
@@ -1,17 +1,17 @@
-## Copyright (C) 2008-2011 Jaroslav Hajek
+## Copyright (C) 2008-2011 Jaroslav Hajek 
 ## Copyright (C) 2000, 2006-2007 Paul Kienzle
 ##
 ## 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
+## 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.
+## 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
@@ -20,17 +20,16 @@
 ## -*- 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})
 ##
 ## 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).
 ##
-## @deftypefnx {Function File} {[@var{c}, @var{ia}, @var{ib}] =} setxor (@var{a}, @var{b})
-##
-## 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}.
+## 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}.
 ##
 ## @seealso{unique, union, intersect, setdiff, ismember}
 ## @end deftypefn
--- a/scripts/signal/autoreg_matrix.m
+++ b/scripts/signal/autoreg_matrix.m
@@ -47,3 +47,16 @@
   endfor
 
 endfunction
+
+
+%!test
+%! K=4;
+%! A = zeros(1,K+1);
+%! A(1) = 1;
+%! B = eye(K+1);
+%! B(:,1) = 1;
+%! assert (autoreg_matrix(A,K),B);
+
+%!error autoreg_matrix()
+%!error autoreg_matrix(1)
+%!error autoreg_matrix(ones(4,1),5)
--- a/scripts/signal/fftshift.m
+++ b/scripts/signal/fftshift.m
@@ -58,9 +58,7 @@
     sz = size (x);
     sz2 = ceil (sz(dim) / 2);
     idx = cell ();
-    for i = 1:nd
-      idx{i} = 1:sz(i);
-    endfor
+    idx = repmat ({':'}, nd, 1);
     idx{dim} = [sz2+1:sz(dim), 1:sz2];
     retval = x(idx{:});
   else
--- a/scripts/signal/ifftshift.m
+++ b/scripts/signal/ifftshift.m
@@ -45,10 +45,7 @@
     nd = ndims (x);
     sz = size (x);
     sz2 = floor (sz(dim) / 2);
-    idx = cell ();
-    for i = 1:nd
-      idx{i} = 1:sz(i);
-    endfor
+    idx = repmat ({':'}, nd, 1);
     idx{dim} = [sz2+1:sz(dim), 1:sz2];
     retval = x(idx{:});
   else
--- a/scripts/signal/sinc.m
+++ b/scripts/signal/sinc.m
@@ -45,3 +45,10 @@
   endif
 
 endfunction
+
+
+%!assert (sinc (0), 1);
+%!assert (sinc (1), 0,1e-6);
+%!assert (sinc (1/2), 2/pi, 1e-6)
+
+%!error sinc()
--- a/scripts/signal/sinewave.m
+++ b/scripts/signal/sinewave.m
@@ -43,3 +43,13 @@
   endif
 
 endfunction
+
+%!assert (sinewave (1), 0);
+%!assert (sinewave (1, 4, 1), 1);
+%!assert (sinewave (1, 12, 1), 1/2, 1e-6);
+%!assert (sinewave (1, 12, 2), sqrt (3)/2, 1e-6);
+%!assert (sinewave (1, 20, 1), (sqrt (5)-1)/4, 1e-6);
+%!assert (sinewave (1), sinewave (1, 1,0));
+%!assert (sinewave (3, 4), sinewave(3, 4, 0));
+
+%!error sinewave ();
--- a/scripts/signal/unwrap.m
+++ b/scripts/signal/unwrap.m
@@ -55,11 +55,8 @@
       error ("unwrap: DIM must be an integer and a valid dimension");
     endif
   else
-    ## Find the first non-singleton dimension
-    dim = find (sz > 1, 1);
-    if (isempty (dim))
-      dim = 1;
-    endif
+    ## Find the first non-singleton dimension.
+    (dim = find (sz > 1, 1)) || (dim = 1);
   endif
 
   rng = 2*pi;
@@ -74,17 +71,14 @@
 
   ## Take first order difference to see so that wraps will show up
   ## as large values, and the sign will show direction.
-  idx = cell ();
-  for i = 1:nd
-    idx{i} = 1:sz(i);
-  endfor
+  idx = repmat ({':'}, nd, 1);
   idx{dim} = [1,1:m-1];
   d = x(idx{:}) - x;
 
-  ## Find only the peaks, and multiply them by the range so that there
-  ## are kronecker deltas at each wrap point multiplied by the range
-  ## value.
-  p =  rng * (((d > tol) > 0) - ((d < -tol) > 0));
+  ## Find only the peaks, and multiply them by the appropriate amount
+  ## of ranges so that there are kronecker deltas at each wrap point
+  ## multiplied by the appropriate amount of range values.
+  p =  ceil(abs(d)./rng) .* rng .* (((d > tol) > 0) - ((d < -tol) > 0));
 
   ## Now need to "integrate" this so that the deltas become steps.
   r = cumsum (p, dim);
@@ -134,4 +128,28 @@
 %! t(++i) = xassert(any(abs(r - unwrap(w,0.8)) > 100));
 %!
 %! assert(all(t));
-
+%!
+%!test
+%! A = [pi*(-4), pi*(-2+1/6), pi/4, pi*(2+1/3), pi*(4+1/2), pi*(8+2/3), pi*(16+1), pi*(32+3/2), pi*64];
+%! assert (unwrap(A), unwrap(A, pi));
+%! assert (unwrap(A, pi), unwrap(A, pi, 2));
+%! assert (unwrap(A', pi), unwrap(A', pi, 1));
+%!
+%!test
+%! A = [pi*(-4); pi*(2+1/3); pi*(16+1)];
+%! B = [pi*(-2+1/6); pi*(4+1/2); pi*(32+3/2)];
+%! C = [pi/4; pi*(8+2/3); pi*64];
+%! D = [pi*(-2+1/6); pi*(2+1/3); pi*(8+2/3)];
+%! E(:, :, 1) = [A, B, C, D];
+%! E(:, :, 2) = [A+B, B+C, C+D, D+A];
+%! F(:, :, 1) = [unwrap(A), unwrap(B), unwrap(C), unwrap(D)];
+%! F(:, :, 2) = [unwrap(A+B), unwrap(B+C), unwrap(C+D), unwrap(D+A)];
+%! assert (unwrap(E), F);
+%!
+%!test
+%! A = [0, 2*pi, 4*pi, 8*pi, 16*pi, 65536*pi];
+%! B = [pi*(-2+1/6), pi/4, pi*(2+1/3), pi*(4+1/2), pi*(8+2/3), pi*(16+1), pi*(32+3/2), pi*64];
+%! assert (unwrap(A), zeros(1, length(A)));
+%! assert (diff(unwrap(B), 1)<2*pi, true(1, length(B)-1));
+%!
+%!error unwrap()
rename from scripts/linear-algebra/gmres.m
rename to scripts/sparse/gmres.m
--- a/scripts/sparse/module.mk
+++ b/scripts/sparse/module.mk
@@ -5,6 +5,7 @@
   sparse/cgs.m \
   sparse/colperm.m \
   sparse/etreeplot.m \
+  sparse/gmres.m \
   sparse/gplot.m \
   sparse/nonzeros.m \
   sparse/pcg.m \
--- a/scripts/sparse/nonzeros.m
+++ b/scripts/sparse/nonzeros.m
@@ -27,12 +27,13 @@
     print_usage ();
   endif
 
-  [i, j, t] = find (s);
+  [~, ~, t] = find (s);
 
   t = t(:);
 
 endfunction
 
+
 %!assert(nonzeros([1,2;3,0]),[1;3;2])
 %!assert(nonzeros([1,2,3,0]),[1;2;3])
 %!assert(nonzeros(sparse([1,2;3,0])),[1;3;2])
--- a/scripts/sparse/svds.m
+++ b/scripts/sparse/svds.m
@@ -150,6 +150,8 @@
     ## Scale everything by the 1-norm to make things more stable.
     b = A / max_a;
     b_opts = opts;
+    ## Call to eigs is always a symmetric matrix by construction
+    b_opts.issym = true;
     b_opts.tol = opts.tol / max_a;
     b_sigma = sigma;
     if (!ischar (b_sigma))
--- a/scripts/specfun/bessel.m
+++ b/scripts/specfun/bessel.m
@@ -91,3 +91,4 @@
   error ("bessel: you must use besselj, bessely, besseli, or besselk");
 endfunction
 
+%!error bessel ()
rename from scripts/elfun/lcm.m
rename to scripts/specfun/lcm.m
--- a/scripts/elfun/lcm.m
+++ b/scripts/specfun/lcm.m
@@ -34,7 +34,7 @@
   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)))
+    elseif (! all (cellfun ("isnumeric", varargin)))
       error ("lcm: all arguments must be numeric");
     endif
 
--- a/scripts/specfun/module.mk
+++ b/scripts/specfun/module.mk
@@ -7,6 +7,7 @@
   specfun/factor.m \
   specfun/factorial.m \
   specfun/isprime.m \
+  specfun/lcm.m \
   specfun/legendre.m \
   specfun/nchoosek.m \
   specfun/nthroot.m \
--- a/scripts/specfun/nthroot.m
+++ b/scripts/specfun/nthroot.m
@@ -35,8 +35,9 @@
 ## @end group
 ## @end example
 ##
-## @var{n} must be a scalar.  If @var{n} is not an even integer and @var{X} has
-## negative entries, an error is produced.
+## @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
 
@@ -46,7 +47,11 @@
     print_usage ();
   endif
 
-  if (! isscalar (n))
+  if (any (iscomplex (x(:))))
+    error ("nthroot: X must not contain complex values");
+  endif
+
+  if (! isscalar (n) || n == 0)
     error ("nthroot: N must be a nonzero scalar");
   endif
 
@@ -58,7 +63,7 @@
     y = 1 ./ nthroot (x, -n);
   else
     ## Compute using power.
-    if (n == round (n) && mod (n, 2) == 1)
+    if (n == fix (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");
@@ -66,7 +71,7 @@
       y = x .^ (1/n);
     endif
 
-    if (finite (n) && n > 0 && n == round (n))
+    if (finite (n) && n > 0 && n == fix (n))
       ## Correction.
       y = ((n-1)*y + x ./ (y.^(n-1))) / n;
       y = merge (finite (y), y, x);
@@ -76,8 +81,18 @@
 
 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);
+
+%% 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))
+
--- a/scripts/specfun/perms.m
+++ b/scripts/specfun/perms.m
@@ -63,3 +63,11 @@
     endfor
   endif
 endfunction
+
+%!error perms ();
+%!error perms (1, 2);
+
+%!assert (perms ([1,2,3]), [1,2,3;2,1,3;1,3,2;2,3,1;3,1,2;3,2,1]);
+%!assert (perms (1:3), perms ([1,2,3]));
+
+%!assert (perms (int8([1,2,3])), int8([1,2,3;2,1,3;1,3,2;2,3,1;3,1,2;3,2,1]));
--- a/scripts/specfun/primes.m
+++ b/scripts/specfun/primes.m
@@ -92,3 +92,11 @@
   endif
 
 endfunction
+
+%!error primes ();
+%!error primes (1, 2);
+
+%!assert (size (primes (350)), [1, 70]);
+%!assert (size (primes (350)), [1, 70]);
+
+%!assert (primes (357)(end), 353);
--- a/scripts/special-matrix/module.mk
+++ b/scripts/special-matrix/module.mk
@@ -8,7 +8,6 @@
   special-matrix/magic.m \
   special-matrix/pascal.m \
   special-matrix/rosser.m \
-  special-matrix/sylvester_matrix.m \
   special-matrix/toeplitz.m \
   special-matrix/vander.m \
   special-matrix/wilkinson.m
--- a/scripts/startup/__finish__.m
+++ b/scripts/startup/__finish__.m
@@ -36,3 +36,5 @@
 
 endfunction
 
+## No test needed for internal helper function.
+%!assert (1)
--- a/scripts/statistics/base/center.m
+++ b/scripts/statistics/base/center.m
@@ -23,7 +23,7 @@
 ## If @var{x} is a vector, subtract its mean.
 ## If @var{x} is a matrix, do the above for each column.
 ## If the optional argument @var{dim} is given, operate along this dimension.
-## @seealso{studentize}
+## @seealso{zscore}
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
@@ -35,7 +35,7 @@
     print_usage ();
   endif
 
-  if (!isnumeric (x))
+  if (! (isnumeric (x) || islogical (x)))
     error ("center: X must be a numeric vector or matrix");
   endif
 
@@ -47,10 +47,7 @@
   sz = size (x);
   if (nargin != 2)
     ## Find the first non-singleton dimension.
-    dim = find (sz > 1, 1);
-    if (isempty (dim))
-      dim = 1;
-    endif
+    (dim = find (sz > 1, 1)) || (dim = 1);
   else
     if (!(isscalar (dim) && dim == fix (dim))
         || !(1 <= dim && dim <= nd))
@@ -58,25 +55,28 @@
     endif
   endif
 
-  n = size (x, dim);
+  n = sz(dim);
 
   if (n == 0)
     retval = x;
   else
-    retval = bsxfun (@minus, x, sum (x, dim) / n);
+    retval = bsxfun (@minus, x, mean (x, dim));
   endif
 
 endfunction
 
 %!assert(center ([1,2,3]), [-1,0,1])
+%!assert(center (single([1,2,3])), single([-1,0,1]))
 %!assert(center (int8 ([1,2,3])), [-1,0,1])
+%!assert(center (logical ([1, 0, 0, 1])), [0.5, -0.5, -0.5, 0.5])
 %!assert(center (ones (3,2,0,2)), zeros (3,2,0,2))
+%!assert(center (ones (3,2,0,2, 'single')), zeros (3,2,0,2, 'single'))
 %!assert(center (magic (3)), [3,-4,1;-2,0,2;-1,4,-3])
+%!assert(center ([1 2 3; 6 5 4], 2), [-1 0 1; 1 0 -1])
 
 %% Test input validation
 %!error center ()
 %!error center (1, 2, 3)
-%!error center ([true true])
 %!error center (1, ones(2,2))
 %!error center (1, 1.5)
 %!error center (1, 0)
new file mode 100644
--- /dev/null
+++ b/scripts/statistics/base/corr.m
@@ -0,0 +1,112 @@
+## Copyright (C) 1996-2011 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} {} corr (@var{x})
+## @deftypefnx {Function File} {} corr (@var{x}, @var{y})
+## Compute matrix of correlation coefficients.
+##
+## If each row of @var{x} and @var{y} is an observation and each column is
+## a variable, then the @w{(@var{i}, @var{j})-th} entry of
+## @code{corr (@var{x}, @var{y})} is the correlation between the
+## @var{i}-th variable in @var{x} and the @var{j}-th variable in @var{y}.
+## @tex
+## $$
+## {\rm corr}(x,y) = {{\rm cov}(x,y) \over {\rm std}(x) {\rm std}(y)}
+## $$
+## @end tex
+## @ifnottex
+##
+## @example
+## corr(x,y) = cov(x,y)/(std(x)*std(y))
+## @end example
+##
+## @end ifnottex
+## If called with one argument, compute @code{corr (@var{x}, @var{x})},
+## the correlation between the columns of @var{x}.
+## @seealso{cov}
+## @end deftypefn
+
+## Author: Kurt Hornik <hornik@wu-wien.ac.at>
+## Created: March 1993
+## Adapted-By: jwe
+
+function retval = corr (x, y = [])
+
+  if (nargin < 1 || nargin > 2)
+    print_usage ();
+  endif
+
+  ## Input validation is done by cov.m.  Don't repeat tests here
+
+  ## Special case, scalar is always 100% correlated with itself
+  if (isscalar (x))
+    if (isa (x, 'single'))
+      retval = single (1);
+    else
+      retval = 1;
+    endif
+    return;
+  endif
+
+  ## No check for division by zero error, which happens only when
+  ## there is a constant vector and should be rare.
+  if (nargin == 2)
+    c = cov (x, y);
+    s = std (x)' * std (y);
+    retval = c ./ s;
+  else
+    c = cov (x);
+    s = sqrt (diag (c));
+    retval = c ./ (s * s');
+  endif
+
+endfunction
+
+
+%!test
+%! x = rand (10);
+%! cc1 = corr (x);
+%! cc2 = corr (x, x);
+%! assert (size (cc1) == [10, 10] && size (cc2) == [10, 10]);
+%! assert (cc1, cc2, sqrt (eps));
+
+%!test
+%! x = [1:3]';
+%! y = [3:-1:1]';
+%! assert (corr (x,y), -1, 5*eps)
+%! assert (corr (x,flipud (y)), 1, 5*eps)
+%! assert (corr ([x, y]), [1 -1; -1 1], 5*eps)
+
+%!test
+%! x = single ([1:3]');
+%! y = single ([3:-1:1]');
+%! assert (corr (x,y), single (-1), 5*eps)
+%! assert (corr (x,flipud (y)), single (1), 5*eps)
+%! assert (corr ([x, y]), single ([1 -1; -1 1]), 5*eps)
+
+%!assert (corr (5), 1);
+%!assert (corr (single(5)), single(1));
+
+%% Test input validation
+%!error corr ();
+%!error corr (1, 2, 3);
+%!error corr ([1; 2], ["A", "B"]);
+%!error corr (ones (2,2,2));
+%!error corr (ones (2,2), ones (2,2,2));
+
--- a/scripts/statistics/base/cov.m
+++ b/scripts/statistics/base/cov.m
@@ -55,7 +55,7 @@
 ## @item 1:
 ##   normalize with @math{N}, this provides the second moment around the mean
 ## @end table
-## @seealso{corrcoef, cor}
+## @seealso{corr}
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
@@ -67,7 +67,8 @@
     print_usage ();
   endif
 
-  if (! (isnumeric (x) && isnumeric (y)))
+  if (   ! (isnumeric (x) || islogical (x))
+      || ! (isnumeric (y) || islogical (y)))
     error ("cov: X and Y must be numeric matrices or vectors");
   endif
 
@@ -75,7 +76,7 @@
     error ("cov: X and Y must be 2-D matrices or vectors");
   endif
 
-  if (nargin == 2 && isscalar(y))
+  if (nargin == 2 && isscalar (y))
     opt = y;
   endif
 
@@ -83,22 +84,27 @@
     error ("cov: normalization OPT must be 0 or 1");
   endif
 
+  ## Special case, scalar has zero covariance
   if (isscalar (x))
-    c = 0;
+    if (isa (x, 'single'))
+      c = single (0);
+    else
+      c = 0;
+    endif
     return;
   endif
 
-  if (rows (x) == 1)
-    x = x';
+  if (isrow (x))
+    x = x.';
   endif
   n = rows (x);
 
-  if (nargin == 1 || isscalar(y))
+  if (nargin == 1 || isscalar (y))
     x = center (x, 1);
     c = conj (x' * x / (n - 1 + opt));
   else
-    if (rows (y) == 1)
-      y = y';
+    if (isrow (y))
+      y = y.';
     endif
     if (rows (y) != n)
       error ("cov: X and Y must have the same number of observations");
@@ -110,17 +116,36 @@
 
 endfunction
 
+
 %!test
 %! x = rand (10);
 %! cx1 = cov (x);
 %! cx2 = cov (x, x);
-%! assert(size (cx1) == [10, 10] && size (cx2) == [10, 10] && norm(cx1-cx2) < 1e1*eps);
+%! assert(size (cx1) == [10, 10] && size (cx2) == [10, 10]);
+%! assert(cx1, cx2, 1e1*eps);
+
+%!test
+%! x = [1:3]';
+%! y = [3:-1:1]';
+%! assert (cov (x,y), -1, 5*eps)
+%! assert (cov (x,flipud (y)), 1, 5*eps)
+%! assert (cov ([x, y]), [1 -1; -1 1], 5*eps)
+
+%!test
+%! x = single ([1:3]');
+%! y = single ([3:-1:1]');
+%! assert (cov (x,y), single (-1), 5*eps)
+%! assert (cov (x,flipud (y)), single (1), 5*eps)
+%! assert (cov ([x, y]), single ([1 -1; -1 1]), 5*eps)
 
 %!test
 %! x = [1:5];
 %! c = cov (x);
-%! assert(isscalar (c));
-%! assert(c, 2.5);
+%! assert (isscalar (c));
+%! assert (c, 2.5);
+
+%!assert(cov (5), 0);
+%!assert(cov (single(5)), single(0));
 
 %!test
 %! x = [1:5];
@@ -129,13 +154,10 @@
 %! c = cov (x, 1);
 %! assert(c, 2);
 
-%!assert(cov (5), 0);
-
 %% Test input validation
 %!error cov ();
 %!error cov (1, 2, 3, 4);
-%!error cov ([true, true]);
-%!error cov ([1, 2], [true, true]);
+%!error cov ([1; 2], ["A", "B"]);
 %!error cov (ones (2,2,2));
 %!error cov (ones (2,2), ones (2,2,2));
 %!error cov (1, 3);
--- a/scripts/statistics/base/gls.m
+++ b/scripts/statistics/base/gls.m
@@ -82,10 +82,21 @@
   if (rx != ry)
     error ("gls: number of rows of X and Y must be equal");
   endif
-  if (!issquare(o) || ro != ry*cy)
+  if (!issquare (o) || ro != ry*cy)
     error ("gls: matrix O must be square matrix with rows = rows (Y) * cols (Y)");
   endif
 
+  if (isinteger (x))
+    x = double (x);
+  endif
+  if (isinteger (y))
+    y = double (y);
+  endif
+  if (isinteger (o))
+    o = double (o);
+  endif
+
+  ## Start of algorithm
   o = o^(-1/2);
   z = kron (eye (cy), x);
   z = o * z;
@@ -116,7 +127,7 @@
 %! y = 3*x + 2;
 %! x = [x, ones(5,1)];
 %! o = diag (ones (5,1));
-%! assert (gls (y,x,o), [3; 2], 50*eps)
+%! assert (gls (y,x,o), [3; 2], 50*eps);
 
 %% Test input validation
 %!error gls ()
--- a/scripts/statistics/base/histc.m
+++ b/scripts/statistics/base/histc.m
@@ -61,7 +61,7 @@
     error ("histc: EDGES must be real-valued, not complex");
   else
     ## Make sure 'edges' is sorted
-    edges = edges (:);
+    edges = edges(:);
     if (!issorted (edges) || edges(1) > edges(end))
       warning ("histc: edge values not sorted on input");
       edges = sort (edges);
@@ -72,10 +72,7 @@
   sz = size (x);
   if (nargin < 3)
     ## Find the first non-singleton dimension.
-    dim = find (sz > 1, 1);
-    if (isempty (dim))
-      dim = 1;
-    endif
+    (dim = find (sz > 1, 1)) || (dim = 1);
   else
     if (!(isscalar (dim) && dim == fix (dim))
         || !(1 <= dim && dim <= nd))
@@ -103,25 +100,25 @@
     ## Prepare indices
     idx1 = cell (1, dim-1);
     for k = 1:length (idx1)
-      idx1 {k} = 1:sz(k);
+      idx1{k} = 1:sz(k);
     endfor
     idx2 = cell (length (sz) - dim);
     for k = 1:length (idx2)
-      idx2 {k} = 1:sz(k+dim);
+      idx2{k} = 1:sz(k+dim);
     endfor
 
     ## Compute the histograms
     for k = 1:num_edges-1
       b = (edges (k) <= x & x < edges (k+1));
-      n (idx1 {:}, k, idx2 {:}) = sum (b, dim);
+      n(idx1{:}, k, idx2{:}) = sum (b, dim);
       if (nargout > 1)
-        idx (b) = k;
+        idx(b) = k;
       endif
     endfor
     b = (x == edges (end));
-    n (idx1 {:}, num_edges, idx2 {:}) = sum (b, dim);
+    n(idx1{:}, num_edges, idx2{:}) = sum (b, dim);
     if (nargout > 1)
-      idx (b) = num_edges;
+      idx(b) = num_edges;
     endif
 
   else
@@ -160,6 +157,7 @@
 
 endfunction
 
+
 %!test
 %! x = linspace (0, 10, 1001);
 %! n = histc (x, 0:10);
--- a/scripts/statistics/base/iqr.m
+++ b/scripts/statistics/base/iqr.m
@@ -39,7 +39,7 @@
     print_usage ();
   endif
 
-  if (!(ismatrix (x) && isnumeric (x)) || isscalar(x))
+  if (! (isnumeric (x) || islogical (x)))
     error ("iqr: X must be a numeric vector or matrix");
   endif
 
@@ -48,10 +48,7 @@
   nel = numel (x);
   if (nargin != 2)
     ## Find the first non-singleton dimension.
-    dim = find (sz > 1, 1);
-    if (isempty (dim))
-      dim = 1;
-    endif
+    (dim = find (sz > 1, 1)) || (dim = 1);
   else
     if (!(isscalar (dim) && dim == fix (dim))
         || !(1 <= dim && dim <= nd))
@@ -60,27 +57,33 @@
   endif
 
   ## This code is a bit heavy, but is needed until empirical_inv
-  ## takes other than vector arguments.
-  c = sz(dim);
+  ## can take a matrix, rather than just a vector argument.
+  n = sz(dim);
   sz(dim) = 1;
-  y = zeros (sz);
+  if (isa (x, 'single'))
+    y = zeros (sz, 'single');
+  else
+    y = zeros (sz);
+  endif
   stride = prod (sz(1:dim-1));
-  for i = 1 : nel / c;
+  for i = 1 : nel / n;
     offset = i;
     offset2 = 0;
     while (offset > stride)
       offset -= stride;
       offset2++;
     endwhile
-    offset += offset2 * stride * c;
-    rng = [0 : c-1] * stride + offset;
+    offset += offset2 * stride * n;
+    rng = [0 : n-1] * stride + offset;
 
-    y (i) = empirical_inv (3/4, x(rng)) - empirical_inv (1/4, x(rng));
+    y(i) = diff (empirical_inv ([1/4, 3/4], x(rng)));
   endfor
 
 endfunction
 
+
 %!assert (iqr (1:101), 50);
+%!assert (iqr (single(1:101)), single(50));
 
 %%!test
 %%! x = [1:100];
@@ -90,5 +93,6 @@
 %!error iqr ();
 %!error iqr (1, 2, 3);
 %!error iqr (1);
-%!error iqr ([true, true]);
+%!error iqr (['A'; 'B']);
 %!error iqr (1:10, 3);
+
--- a/scripts/statistics/base/kendall.m
+++ b/scripts/statistics/base/kendall.m
@@ -74,7 +74,8 @@
     print_usage ();
   endif
 
-  if (! (isnumeric (x) && isnumeric (y)))
+  if (   ! (isnumeric (x) || islogical (x))
+      || ! (isnumeric (y) || islogical (y)))
     error ("kendall: X and Y must be numeric matrices or vectors");
   endif
 
@@ -82,14 +83,14 @@
     error ("kendall: X and Y must be 2-D matrices or vectors");
   endif
 
-  if (rows (x) == 1)
-    x = x';
+  if (isrow (x))
+    x = x.';
   endif
   [n, c] = size (x);
 
   if (nargin == 2)
-    if (rows (y) == 1)
-      y = y';
+    if (isrow (y))
+      y = y.';
     endif
     if (rows (y) != n)
       error ("kendall: X and Y must have the same number of observations");
@@ -98,22 +99,36 @@
     endif
   endif
 
+  if (isa (x, 'single') || isa (y, 'single'))
+    cls = 'single';
+  else
+    cls = 'double';
+  endif
   r   = ranks (x);
-  m   = sign (kron (r, ones (n, 1)) - kron (ones (n, 1), r));
-  tau = corrcoef (m);
+  m   = sign (kron (r, ones (n, 1, cls)) - kron (ones (n, 1, cls), r));
+  tau = corr (m);
 
   if (nargin == 2)
-    tau = tau (1 : c, (c + 1) : columns (x));
+    tau = tau(1 : c, (c + 1) : columns (x));
   endif
 
 endfunction
 
 
+%!test
+%! x = [1:2:10];
+%! y = [100:10:149];
+%! assert (kendall (x,y), 1, 5*eps);
+%! assert (kendall (x,fliplr (y)), -1, 5*eps);
+
+%!assert (kendall (logical(1)), 1);
+%!assert (kendall (single(1)), single(1));
+
 %% Test input validation
 %!error kendall ();
 %!error kendall (1, 2, 3);
-%!error kendall ([true, true]);
-%!error kendall (ones(1,2), [true, true]);
+%!error kendall (['A'; 'B']);
+%!error kendall (ones(2,1), ['A'; 'B']);
 %!error kendall (ones (2,2,2));
 %!error kendall (ones (2,2), ones (2,2,2));
 %!error kendall (ones (2,2), ones (3,2));
--- a/scripts/statistics/base/kurtosis.m
+++ b/scripts/statistics/base/kurtosis.m
@@ -54,7 +54,7 @@
     print_usage ();
   endif
 
-  if (!isnumeric (x))
+  if (! (isnumeric (x) || islogical (x)))
     error ("kurtosis: X must be a numeric vector or matrix");
   endif
 
@@ -62,10 +62,7 @@
   sz = size (x);
   if (nargin != 2)
     ## Find the first non-singleton dimension.
-    dim = find (sz > 1, 1);
-    if (isempty (dim))
-      dim = 1;
-    endif
+    (dim = find (sz > 1, 1)) || (dim = 1);
   else
     if (!(isscalar (dim) && dim == fix (dim))
         || !(1 <= dim && dim <= nd))
@@ -73,16 +70,14 @@
     endif
   endif
 
-  c = sz(dim);
+  n = sz(dim);
   sz(dim) = 1;
-  idx = ones (1, nd);
-  idx(dim) = c;
-  x = x - repmat (mean (x, dim), idx);
+  x = center (x, dim);  # center also promotes integer to double for next line
   retval = zeros (sz, class (x));
   s = std (x, [], dim);
+  idx = find (s > 0);
   x = sum (x.^4, dim);
-  ind = find (s > 0);
-  retval(ind) = x(ind) ./ (c * s(ind) .^ 4) - 3;
+  retval(idx) = x(idx) ./ (n * s(idx) .^ 4) - 3;
 
 endfunction
 
@@ -90,12 +85,14 @@
 %!test
 %! x = [-1; 0; 0; 0; 1];
 %! y = [x, 2*x];
-%! assert(all (abs (kurtosis (y) - [-1.4, -1.4]) < sqrt (eps)));
+%! assert (kurtosis (y), [-1.4, -1.4], sqrt (eps));
+
+%!assert (kurtosis (single(1)), single(0));
 
 %% Test input validation
 %!error kurtosis ()
 %!error kurtosis (1, 2, 3)
-%!error kurtosis (true(1,2))
+%!error kurtosis (['A'; 'B'])
 %!error kurtosis (1, ones(2,2))
 %!error kurtosis (1, 1.5)
 %!error kurtosis (1, 0)
--- a/scripts/statistics/base/logit.m
+++ b/scripts/statistics/base/logit.m
@@ -47,6 +47,7 @@
 
 endfunction
 
+
 %!test
 %! p = [0.01:0.01:0.99];
 %! assert(logit (p), log (p ./ (1-p)), 25*eps)
--- a/scripts/statistics/base/mahalanobis.m
+++ b/scripts/statistics/base/mahalanobis.m
@@ -34,7 +34,8 @@
     print_usage ();
   endif
 
-  if (! (isnumeric (x) && isnumeric (y)))
+  if (   ! (isnumeric (x) || islogical (x))
+      || ! (isnumeric (y) || islogical (y)))
     error ("mahalanobis: X and Y must be numeric matrices or vectors");
   endif
 
@@ -49,11 +50,16 @@
     error ("mahalanobis: X and Y must have the same number of columns");
   endif
 
+  if (isinteger (x))
+    x = double (x);
+  endif
+
   xm = mean (x);
   ym = mean (y);
 
-  x = x - ones (xr, 1) * xm;
-  y = y - ones (yr, 1) * ym;
+  ## Center data by subtracting means
+  x = bsxfun (@minus, x, xm);
+  y = bsxfun (@minus, y, ym);
 
   w = (x' * x + y' * y) / (xr + yr - 2);
 
@@ -63,11 +69,12 @@
 
 endfunction
 
+
 %% Test input validation
 %!error mahalanobis ();
 %!error mahalanobis (1, 2, 3);
-%!error mahalanobis ([true], [true]);
-%!error mahalanobis ([1, 2], [true, true]);
+%!error mahalanobis ('A', 'B');
+%!error mahalanobis ([1, 2], ['A', 'B']);
 %!error mahalanobis (ones (2,2,2));
 %!error mahalanobis (ones (2,2), ones (2,2,2));
 %!error mahalanobis (ones (2,2), ones (2,3));
--- a/scripts/statistics/base/mean.m
+++ b/scripts/statistics/base/mean.m
@@ -69,15 +69,15 @@
     error ("mean: X must be a numeric vector or matrix");
   endif
 
-  need_dim = 0;
+  need_dim = false;
 
   if (nargin == 1)
     opt = "a";
-    need_dim = 1;
+    need_dim = true;
   elseif (nargin == 2)
     if (ischar (opt1))
       opt = opt1;
-      need_dim = 1;
+      need_dim = true;
     else
       dim = opt1;
       opt = "a";
@@ -100,22 +100,15 @@
   sz = size (x);
   if (need_dim)
     ## Find the first non-singleton dimension.
-    dim = find (sz > 1, 1);
-    if (isempty (dim))
-      dim = 1;
+    (dim = find (sz > 1, 1)) || (dim = 1);
+  else
+    if (!(isscalar (dim) && dim == fix (dim))
+      || !(1 <= dim && dim <= nd))
+      error ("mean: DIM must be an integer and a valid dimension");
     endif
   endif
 
-  if (!(isscalar (dim) && dim == fix (dim))
-      || !(1 <= dim && dim <= nd))
-    error ("mean: DIM must be an integer and a valid dimension");
-  endif
-
-  if (dim > nd)
-    n = 1;
-  else
-    n = sz(dim);
-  endif
+  n = sz(dim);
 
   if (strcmp (opt, "a"))
     y = sum (x, dim) / n;
@@ -129,6 +122,7 @@
 
 endfunction
 
+
 %!test
 %! x = -10:10;
 %! y = x';
@@ -137,9 +131,12 @@
 %! assert(mean (y) == 0);
 %! assert(mean (z) == [0, 10]);
 
+%!assert(mean (magic(3), 1), [5, 5, 5]);
+%!assert(mean (magic(3), 2), [5; 5; 5]);
 %!assert(mean ([2 8], 'g'), 4);
 %!assert(mean ([4 4 2], 'h'), 3);
 %!assert(mean (logical ([1 0 1 1])), 0.75);
+%!assert(mean (single ([1 0 1 1])), single (0.75));
 
 %% Test input validation
 %!error mean ();
--- a/scripts/statistics/base/meansq.m
+++ b/scripts/statistics/base/meansq.m
@@ -52,7 +52,7 @@
     print_usage ();
   endif
 
-  if (!isnumeric (x))
+  if (! (isnumeric (x) || islogical (x)))
     error ("mean: X must be a numeric vector or matrix");
   endif
 
@@ -60,29 +60,28 @@
   sz = size (x);
   if (nargin < 2)
     ## Find the first non-singleton dimension.
-    dim = find (sz > 1, 1);
-    if (isempty (dim))
-      dim = 1;
+    (dim = find (sz > 1, 1)) || (dim = 1);
+  else
+    if (!(isscalar (dim) && dim == fix (dim))
+        || !(1 <= dim && dim <= nd))
+      error ("mean: DIM must be an integer and a valid dimension");
     endif
   endif
 
-  if (!(isscalar (dim) && dim == fix (dim))
-      || !(1 <= dim && dim <= nd))
-    error ("mean: DIM must be an integer and a valid dimension");
-  endif
-
-  y = sumsq (x, dim) / size (x, dim);
+  y = sumsq (x, dim) / sz(dim);
 
 endfunction
 
 
-%!assert(meansq (1:5), 11)
-%!assert(meansq (magic (4)), [94.5, 92.5, 92.5, 94.5])
+%!assert(meansq (1:5), 11);
+%!assert(meansq (single(1:5)), single(11));
+%!assert(meansq (magic (4)), [94.5, 92.5, 92.5, 94.5]);
+%!assert(meansq (magic (4), 2), [109.5; 77.5; 77.5; 109.5]);
 
 %% Test input validation
 %!error meansq ()
 %!error meansq (1, 2, 3)
-%!error kurtosis ([true true])
+%!error meansq (['A'; 'B']);
 %!error meansq (1, ones(2,2))
 %!error meansq (1, 1.5)
 %!error meansq (1, 0)
--- a/scripts/statistics/base/median.m
+++ b/scripts/statistics/base/median.m
@@ -55,18 +55,19 @@
     print_usage ();
   endif
 
-  if (!isnumeric (x))
+  if (! (isnumeric (x) || islogical (x)))
     error ("median: X must be a numeric vector or matrix");
   endif
 
+  if (isempty (x))
+    error ("median: X cannot be an empty matrix");
+  endif
+
   nd = ndims (x);
   sz = size (x);
-  if (nargin != 2)
+  if (nargin < 2)
     ## Find the first non-singleton dimension.
-    dim = find (sz > 1, 1);
-    if (isempty (dim))
-      dim = 1;
-    endif
+    (dim = find (sz > 1, 1)) || (dim = 1);
   else
     if (!(isscalar (dim) && dim == fix (dim))
         || !(1 <= dim && dim <= nd))
@@ -74,22 +75,19 @@
     endif
   endif
 
-  if (numel (x) > 0)
-    n = size (x, dim);
-    k = floor ((n+1) / 2);
-    if (mod (n, 2) == 1)
-      retval = nth_element (x, k, dim);
-    else
-      retval = mean (nth_element (x, k:k+1, dim), dim);
-    endif
-    ## Inject NaNs where needed, to be consistent with Matlab.
-    retval(any (isnan (x), dim)) = NaN;
+  n = sz(dim);
+  k = floor ((n+1) / 2);
+  if (mod (n, 2) == 1)
+    retval = nth_element (x, k, dim);
   else
-    error ("median: invalid matrix argument");
+    retval = mean (nth_element (x, k:k+1, dim), dim);
   endif
+  ## Inject NaNs where needed, to be consistent with Matlab.
+  retval(any (isnan (x), dim)) = NaN;
 
 endfunction
 
+
 %!test
 %! x = [1, 2, 3, 4, 5, 6];
 %! x2 = x';
@@ -101,13 +99,14 @@
 %! assert(median ([x2, 2*x2]) == [3.5, 7]);
 %! assert(median ([y2, 3*y2]) == [4, 12]);
 
+%!assert(median (single([1,2,3])), single(2));
 %!assert(median ([1,2,NaN;4,5,6;NaN,8,9]), [NaN, 5, NaN]);
 
 %% Test input validation
 %!error median ();
 %!error median (1, 2, 3);
 %!error median ({1:5});
-%!error median (true(1,5));
+%!error median (['A'; 'B']);
 %!error median (1, ones(2,2));
 %!error median (1, 1.5);
 %!error median (1, 0);
--- a/scripts/statistics/base/mode.m
+++ b/scripts/statistics/base/mode.m
@@ -39,18 +39,15 @@
     print_usage ();
   endif
 
-  if (!isnumeric(x))
+  if (! (isnumeric (x) || islogical (x)))
     error ("mode: X must be a numeric vector or matrix");
   endif
 
   nd = ndims (x);
   sz = size (x);
-  if (nargin != 2)
+  if (nargin < 2)
     ## Find the first non-singleton dimension.
-    dim = find (sz > 1, 1);
-    if (isempty (dim))
-      dim = 1;
-    endif
+    (dim = find (sz > 1, 1)) || (dim = 1);
   else
     if (!(isscalar (dim) && dim == round (dim))
         || !(1 <= dim && dim <= nd))
@@ -78,11 +75,11 @@
   t = cat (dim, true (sz2), diff (xs, 1, dim) != 0);
 
   if (dim != 1)
-    t2 (permute (t != 0, perm)) = diff ([find(permute (t, perm))(:); prod(sz)+1]);
+    t2(permute (t != 0, perm)) = diff ([find(permute (t, perm))(:); prod(sz)+1]);
     f = max (ipermute (t2, perm), [], dim);
     xs = permute (xs, perm);
   else
-    t2 (t) = diff ([find(t)(:); prod(sz)+1]);
+    t2(t) = diff ([find(t)(:); prod(sz)+1]);
     f = max (t2, [], dim);
   endif
 
@@ -90,14 +87,15 @@
   if (issparse (x))
     m = sparse (sz2(1), sz2(2));
   else
-    m = zeros (sz2);
+    m = zeros (sz2, class (x));
   endif
   for i = 1 : prod (sz2)
-    c{i} = xs (t2 (:, i) == f(i), i);
-    m (i) = c{i}(1);
+    c{i} = xs(t2(:, i) == f(i), i);
+    m(i) = c{i}(1);
   endfor
 endfunction
 
+
 %!test
 %! [m, f, c] = mode (toeplitz (1:5));
 %! assert (m, [1,2,2,2,1]);
@@ -114,15 +112,19 @@
 %! [m2, f2, c2] = mode (full (a));
 %! assert (m, sparse (m2));
 %! assert (f, sparse (f2));
-%! assert (c, cellfun (@(x) sparse (0), c2, 'uniformoutput', false));
+%! c_exp(1:length(a)) = { sparse (0) };
+%! assert (c ,c_exp);
+%! assert (c2,c_exp );
 
-%!assert(mode([2,3,1,2,3,4],1),[2,3,1,2,3,4])
-%!assert(mode([2,3,1,2,3,4],2),2)
-%!assert(mode([2,3,1,2,3,4]),2)
+%!assert(mode ([2,3,1,2,3,4],1),[2,3,1,2,3,4]);
+%!assert(mode ([2,3,1,2,3,4],2),2);
+%!assert(mode ([2,3,1,2,3,4]),2);
+%!assert(mode (single([2,3,1,2,3,4])), single(2));
+%!assert(mode (int8([2,3,1,2,3,4])), int8(2));
 
-%!assert(mode([2;3;1;2;3;4],1),2)
-%!assert(mode([2;3;1;2;3;4],2),[2;3;1;2;3;4])
-%!assert(mode([2;3;1;2;3;4]),2)
+%!assert(mode ([2;3;1;2;3;4],1),2);
+%!assert(mode ([2;3;1;2;3;4],2),[2;3;1;2;3;4]);
+%!assert(mode ([2;3;1;2;3;4]),2);
 
 %!shared x
 %! x(:,:,1) = toeplitz (1:3);
@@ -157,7 +159,7 @@
 %!error mode ()
 %!error mode (1, 2, 3)
 %!error mode ({1 2 3})
-%!error mode (true(1,3))
+%!error mode (['A'; 'B'])
 %!error mode (1, ones(2,2))
 %!error mode (1, 1.5)
 %!error mode (1, 0)
--- a/scripts/statistics/base/module.mk
+++ b/scripts/statistics/base/module.mk
@@ -3,10 +3,8 @@
 statistics_base_FCN_FILES = \
   statistics/base/center.m \
   statistics/base/cloglog.m \
-  statistics/base/cor.m \
-  statistics/base/corrcoef.m \
+  statistics/base/corr.m \
   statistics/base/cov.m \
-  statistics/base/cut.m \
   statistics/base/gls.m \
   statistics/base/histc.m \
   statistics/base/iqr.m \
@@ -33,9 +31,9 @@
   statistics/base/spearman.m \
   statistics/base/statistics.m \
   statistics/base/std.m \
-  statistics/base/studentize.m \
   statistics/base/table.m \
-  statistics/base/var.m
+  statistics/base/var.m \
+  statistics/base/zscore.m
 
 FCN_FILES += $(statistics_base_FCN_FILES)
 
--- a/scripts/statistics/base/moment.m
+++ b/scripts/statistics/base/moment.m
@@ -110,27 +110,27 @@
 
 function m = moment (x, p, opt1, opt2)
 
-  if ((nargin < 2) || (nargin > 4))
+  if (nargin < 2 || nargin > 4)
     print_usage ();
   endif
 
-  if (!isnumeric(x) || isempty(x) )
+  if (!(isnumeric (x) || islogical (x)) || isempty (x))
     error ("moment: X must be a non-empty numeric matrix or vector");
   endif
 
-  if (!(isnumeric(p) && isscalar(p)))
+  if (! (isnumeric (p) && isscalar (p)))
     error ("moment: P must be a numeric scalar");
   endif
 
-  need_dim = 0;
+  need_dim = false;
 
   if (nargin == 2)
     type = "";
-    need_dim = 1;
+    need_dim = true;
   elseif (nargin == 3)
     if (ischar (opt1))
       type = opt1;
-      need_dim = 1;
+      need_dim = true;
     else
       dim = opt1;
       type = "";
@@ -151,10 +151,7 @@
   sz = size (x);
   if (need_dim)
     ## Find the first non-singleton dimension.
-    dim = find (sz > 1, 1);
-    if (isempty (dim))
-      dim = 1;
-    endif
+    (dim = find (sz > 1, 1)) || (dim = 1);
   else
     if (!(isscalar (dim) && dim == fix (dim)) ||
         !(1 <= dim && dim <= nd))
@@ -164,10 +161,8 @@
 
   n = sz(dim);
 
-  if any (type == "c")
-    rng = ones (1, length (sz));
-    rng(dim) = sz(dim);
-    x = x - repmat (sum (x, dim), rng) / n;
+  if (any (type == "c"))
+    x = center (x, dim);
   endif
   if any (type == "a")
     x = abs (x);
@@ -178,11 +173,21 @@
 endfunction
 
 
+%!test
+%! x = rand (10);
+%! assert (moment (x,1), mean (x), 1e1*eps);
+%! assert (moment (x,2), meansq (x), 1e1*eps);
+%! assert (moment (x,1,2), mean (x,2), 1e1*eps);
+%! assert (moment (x,1,'c'), mean (center (x)), 1e1*eps);
+%! assert (moment (x,1,'a'), mean (abs (x)), 1e1*eps);
+
+%!assert (moment (single([1 2 3]),1), single(2));
+
 %% Test input validation
 %!error moment ()
 %!error moment (1)
 %!error moment (1, 2, 3, 4, 5)
-%!error moment ([true true], 2)
+%!error moment (['A'; 'B'], 2)
 %!error moment (ones(2,0,3), 2)
 %!error moment (1, true)
 %!error moment (1, ones(2,2))
--- a/scripts/statistics/base/ols.m
+++ b/scripts/statistics/base/ols.m
@@ -100,6 +100,14 @@
     error ("ols: number of rows of X and Y must be equal");
   endif
 
+  if (isinteger (x))
+    x = double (x);
+  endif
+  if (isinteger (y))
+    y = double (y);
+  endif
+
+  ## Start of algorithm
   z = x' * x;
   rnk = rank (z);
 
@@ -118,6 +126,7 @@
 
 endfunction
 
+
 %!test
 %! x = [1:5]';
 %! y = 3*x + 2;
--- a/scripts/statistics/base/ppplot.m
+++ b/scripts/statistics/base/ppplot.m
@@ -77,6 +77,7 @@
 
 endfunction
 
+
 %% Test input validation
 %!error ppplot ();
 %!error ppplot (ones(2,2));
--- a/scripts/statistics/base/prctile.m
+++ b/scripts/statistics/base/prctile.m
@@ -40,52 +40,48 @@
 ## Author: Ben Abbott <bpabbott@mac.com>
 ## Description: Matlab style prctile function.
 
-function q = prctile (x, p, dim)
+function q = prctile (x, p = [], dim)
 
   if (nargin < 1 || nargin > 3)
     print_usage ();
   endif
 
-  if (!isnumeric(x))
+  if (! (isnumeric (x) || islogical (x)))
     error ("prctile: X must be a numeric vector or matrix");
   endif
-  if (!isnumeric(p))
-    error ("prctile: P must be a numeric vector");
+
+  if (isempty (p))
+    p = [0, 25, 50, 75, 100];
   endif
 
-  if (nargin == 1)
-    p = [0, 25, 50, 75, 100];
+  if (! (isnumeric (p) && isvector (p)))
+    error ("prctile: P must be a numeric vector");
   endif
 
   nd = ndims (x);
   if (nargin == 2)
     if (nd == 2)
-      ## If a matrix or vector, use the 1st dimension.
+      ## 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 (size(v) > 1, 1);
-      if (isempty (dim))
-        dim = 1;
-      endif
+      (dim = find (sz > 1, 1)) || (dim = 1);
     endif
   else
-    if (!(isscalar (dim) && dim == fix (dim)) ||
-        !(1 <= dim && dim <= nd))
+    if (!(isscalar (dim) && dim == fix (dim))
+        || !(1 <= dim && dim <= nd))
       error ("prctile: DIM must be an integer and a valid dimension");
     endif
   endif
 
   ## Convert from percent to decimal.
-  p = p / 100;
+  p /= 100;
 
-  ## The 5th method is compatible with Matlab.
-  method = 5;
-
-  q = quantile (x, p, dim, method);
+  q = quantile (x, p, dim);
 
 endfunction
 
+
 %!test
 %! pct = 50;
 %! q = prctile (1:4, pct, 1);
@@ -171,8 +167,9 @@
 %% Test input validation
 %!error prctile ()
 %!error prctile (1, 2, 3, 4)
-%!error prctile ([true, false], 10)
+%!error prctile (['A'; 'B'], 10)
 %!error prctile (1:10, [true, false])
+%!error prctile (1:10, ones (2,2))
 %!error prctile (1, 1, 1.5)
 %!error prctile (1, 1, 0)
 %!error prctile (1, 1, 3)
--- a/scripts/statistics/base/probit.m
+++ b/scripts/statistics/base/probit.m
@@ -27,10 +27,18 @@
 
 function y = probit (p)
 
-  if (nargin == 1)
-    y = stdnormal_inv (p);
-  else
+
+  if (nargin != 1)
     print_usage ();
   endif
 
+  y = stdnormal_inv (p);
+
 endfunction
+
+%!assert(probit([-1, 0, 0.5, 1, 2]), [NaN, -Inf, 0, Inf, NaN]);
+
+%% Test input validation
+%!error probit ()
+%!error probit (1, 2)
+
--- a/scripts/statistics/base/quantile.m
+++ b/scripts/statistics/base/quantile.m
@@ -90,31 +90,40 @@
 ##
 ## Examples:
 ##
-## @example
+## @c Set example in small font to prevent overfull line
+## @smallexample
 ## @group
-## x = randi (1000, [10, 1]);  # Create random empirical data in range 1-1000
-## q = quantile (x, [0, 1]);   # Return minimum, maximum of empirical distribution
-## q = quantile (x, [0.25 0.5 0.75]); # Return quartiles of empirical distribution
+## x = randi (1000, [10, 1]);  # Create empirical data in range 1-1000
+## q = quantile (x, [0, 1]);   # Return minimum, maximum of distribution
+## q = quantile (x, [0.25 0.5 0.75]); # Return quartiles of distribution
 ## @end group
-## @end example
+## @end smallexample
 ## @seealso{prctile}
 ## @end deftypefn
 
 ## 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 = 1, method = 5)
 
   if (nargin < 1 || nargin > 4)
     print_usage ();
   endif
 
-  if (nargin < 2)
+  if (! (isnumeric (x) || islogical (x)))
+    error ("quantile: X must be a numeric vector or matrix");
+  endif
+
+  if (isempty (p))
     p = [0.00 0.25, 0.50, 0.75, 1.00];
   endif
 
-  if (!(isscalar (dim) && dim == fix (dim)) ||
-      !(1 <= dim && dim <= ndims (x)))
+  if (! (isnumeric (p) && isvector (p)))
+    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");
   endif
 
@@ -143,6 +152,7 @@
 
 endfunction
 
+
 %!test
 %! p = 0.5;
 %! x = sort (rand (11));
@@ -282,9 +292,14 @@
 %% Test input validation
 %!error quantile ()
 %!error quantile (1, 2, 3, 4, 5)
+%!error quantile (['A'; 'B'], 10)
+%!error quantile (1:10, [true, false])
+%!error quantile (1:10, ones (2,2))
 %!error quantile (1, 1, 1.5)
 %!error quantile (1, 1, 0)
 %!error quantile (1, 1, 3)
+%!error quantile ((1:5)', 0.5, 1, 0)
+%!error quantile ((1:5)', 0.5, 1, 10)
 
 ## For the cumulative probability values in @var{p}, compute the
 ## quantiles, @var{q} (the inverse of the cdf), for the sample, @var{x}.
@@ -304,37 +319,35 @@
     print_usage ();
   endif
 
-  if (!isnumeric (x))
-    error ("quantile: X must be a numeric vector or matrix");
+  if (isinteger (x) || islogical (x))
+    x = double (x);
   endif
 
-  ## Save length and set shape of quantiles.
-  n = numel (p);
+  ## set shape of quantiles to column vector.
   p = p(:);
 
   ## Save length and set shape of samples.
   ## FIXME: does sort guarantee that NaN's come at the end?
   x = sort (x);
   m = sum (! isnan (x));
-  mx = size (x, 1);
-  nx = size (x, 2);
+  [xr, xc] = size (x);
 
   ## Initialize output values.
-  inv = Inf*(-(p < 0) + (p > 1));
-  inv = repmat (inv, 1, nx);
+  inv = Inf (class (x)) * (-(p < 0) + (p > 1));
+  inv = repmat (inv, 1, xc);
 
   ## Do the work.
-  if (any(k = find((p >= 0) & (p <= 1))))
+  if (any (k = find ((p >= 0) & (p <= 1))))
     n = length (k);
-    p = p (k);
-    ## Special case.
-    if (mx == 1)
+    p = p(k);
+    ## Special case of 1 row.
+    if (xr == 1)
       inv(k,:) = repmat (x, n, 1);
-      return
+      return;
     endif
 
     ## The column-distribution indices.
-    pcd = kron (ones (n, 1), mx*(0:nx-1));
+    pcd = kron (ones (n, 1), xr*(0:xc-1));
     mm = kron (ones (n, 1), m);
     switch (method)
       case {1, 2, 3}
@@ -375,7 +388,7 @@
             p = kron (p, m-1) + 1;
 
           case 8
-            ## Median unbiased .
+            ## Median unbiased.
             p = kron (p, m+1/3) + 1/3;
 
           case 9
@@ -387,7 +400,7 @@
         endswitch
 
         ## Duplicate single values.
-        imm1 = mm == 1;
+        imm1 = (mm == 1);
         x(2,imm1) = x(1,imm1);
 
         ## Interval indices.
--- a/scripts/statistics/base/range.m
+++ b/scripts/statistics/base/range.m
@@ -37,20 +37,24 @@
 
 function y = range (x, dim)
 
+  if (nargin < 1 || nargin > 2)
+    print_usage ();
+  endif
+
   if (nargin == 1)
     y = max (x) - min (x);
-  elseif (nargin == 2)
+  else
     y = max (x, [], dim) - min (x, [], dim);
-  else
-    print_usage ();
   endif
 
 endfunction
 
-%!assert(range (1:10), 9)
-%!assert(range (magic (3)), [5, 8, 5])
-%!assert(range (magic (3), 2), [7; 4; 7])
-%!assert(range (2), 0)
+
+%!assert(range (1:10), 9);
+%!assert(range (single(1:10)), single(9));
+%!assert(range (magic (3)), [5, 8, 5]);
+%!assert(range (magic (3), 2), [7; 4; 7]);
+%!assert(range (2), 0);
 
 %% Test input validation
 %!error range ()
--- a/scripts/statistics/base/ranks.m
+++ b/scripts/statistics/base/ranks.m
@@ -37,7 +37,7 @@
     print_usage ();
   endif
 
-  if (!isnumeric(x))
+  if (! (isnumeric (x) || islogical (x)))
     error ("ranks: X must be a numeric vector or matrix");
   endif
 
@@ -45,10 +45,7 @@
   sz = size (x);
   if (nargin != 2)
     ## Find the first non-singleton dimension.
-    dim = find (sz > 1, 1);
-    if (isempty (dim))
-      dim = 1;
-    endif
+    (dim = find (sz > 1, 1)) || (dim = 1);
   else
     if (!(isscalar (dim) && dim == fix (dim))
         || !(1 <= dim && dim <= nd))
@@ -89,18 +86,18 @@
 endfunction
 
 
-%!assert(ranks (1:2:10), 1:5)
-%!assert(ranks (10:-2:1), 5:-1:1)
-%!assert(ranks ([2, 1, 2, 4]), [2.5, 1, 2.5, 4])
-%!assert(ranks (ones(1, 5)), 3*ones(1, 5))
-%!assert(ranks (1e6*ones(1, 5)), 3*ones(1, 5))
-%!assert(ranks (rand (1, 5), 1), ones(1, 5))
+%!assert(ranks (1:2:10), 1:5);
+%!assert(ranks (10:-2:1), 5:-1:1);
+%!assert(ranks ([2, 1, 2, 4]), [2.5, 1, 2.5, 4]);
+%!assert(ranks (ones(1, 5)), 3*ones(1, 5));
+%!assert(ranks (1e6*ones(1, 5)), 3*ones(1, 5));
+%!assert(ranks (rand (1, 5), 1), ones(1, 5));
 
 %% Test input validation
 %!error ranks ()
 %!error ranks (1, 2, 3)
 %!error ranks ({1, 2})
-%!error ranks (true(2,1))
+%!error ranks (['A'; 'B'])
 %!error ranks (1, 1.5)
 %!error ranks (1, 0)
 %!error ranks (1, 3)
--- a/scripts/statistics/base/run_count.m
+++ b/scripts/statistics/base/run_count.m
@@ -36,7 +36,7 @@
     print_usage ();
   endif
 
-  if (!isnumeric(x))
+  if (! (isnumeric (x) || islogical (x)))
     error ("run_count: X must be a numeric vector or matrix");
   endif
 
@@ -48,10 +48,7 @@
   sz = size (x);
   if (nargin != 3)
     ## Find the first non-singleton dimension.
-    dim = find (sz > 1, 1);
-    if (isempty (dim))
-      dim = 1;
-    endif
+    (dim = find (sz > 1, 1)) || (dim = 1);
   else
     if (!(isscalar (dim) && dim == fix (dim))
         || !(1 <= dim && dim <= nd))
@@ -59,6 +56,7 @@
     endif
   endif
 
+  ## Algorithm works on rows.  Permute array if necessary, ipermute back at end
   if (dim != 1)
     perm = [1 : nd];
     perm(1) = dim;
@@ -76,7 +74,7 @@
   infvec = Inf ([1, sz(2 : end)]);
 
   ind = find (diff ([infvec; x; -infvec]) < 0);
-  tmp(ind(2:end) - 1) = diff(ind);
+  tmp(ind(2:end) - 1) = diff (ind);
   tmp = tmp(idx{:});
 
   sz(1) = n;
@@ -86,7 +84,7 @@
     retval(idx{:}) = sum (tmp == k);
   endfor
   idx{1} = n;
-  retval (idx{:}) = sum (tmp >= n);
+  retval(idx{:}) = sum (tmp >= n);
 
   if (dim != 1)
     retval = ipermute (retval, perm);
@@ -105,7 +103,7 @@
 %!error run_count (1)
 %!error run_count (1, 2, 3, 4)
 %!error run_count ({1, 2}, 3)
-%!error run_count (true(3), 3)
+%!error run_count (['A'; 'A'; 'B'], 3)
 %!error run_count (1:5, ones(2,2))
 %!error run_count (1:5, 1.5)
 %!error run_count (1:5, -2)
--- a/scripts/statistics/base/runlength.m
+++ b/scripts/statistics/base/runlength.m
@@ -30,11 +30,12 @@
 ## @end deftypefn
 
 function [count, value] = runlength (x)
+
   if (nargin != 1)
     print_usage ();
   endif
 
-  if (!isnumeric (x) || !isvector (x))
+  if (!(isnumeric (x) || islogical (x)) || !isvector (x))
     error ("runlength: X must be a numeric vector");
   endif
 
@@ -47,8 +48,10 @@
   if (nargout == 2)
     value = x(idx);
   endif
+
 endfunction
 
+
 %!assert (runlength([2 2 0 4 4 4 0 1 1 1 1]), [2 1 3 1 4]);
 %!assert (runlength([2 2 0 4 4 4 0 1 1 1 1]'), [2 1 3 1 4]);
 %!test
@@ -59,5 +62,5 @@
 %% Test input validation
 %!error runlength ()
 %!error runlength (1, 2)
-%!error runlength (true(1,2))
+%!error runlength (['A'; 'B'])
 %!error runlength (ones(2,2))
--- a/scripts/statistics/base/skewness.m
+++ b/scripts/statistics/base/skewness.m
@@ -51,7 +51,7 @@
     print_usage ();
   endif
 
-  if (!isnumeric(x))
+  if (! (isnumeric (x) || islogical (x)))
     error ("skewness: X must be a numeric vector or matrix");
   endif
 
@@ -59,10 +59,7 @@
   sz = size (x);
   if (nargin != 2)
     ## Find the first non-singleton dimension.
-    dim = find (sz > 1, 1);
-    if (isempty (dim))
-      dim = 1;
-    endif
+    (dim = find (sz > 1, 1)) || (dim = 1);
   else
     if (!(isscalar (dim) && dim == round (dim))
         || !(1 <= dim && dim <= nd))
@@ -70,19 +67,18 @@
     endif
   endif
 
-  c = sz(dim);
-  idx = ones (1, nd);
-  idx(dim) = c;
-  x = x - repmat (mean (x, dim), idx);
+  n = sz(dim);
   sz(dim) = 1;
+  x = center (x, dim);  # center also promotes integer to double for next line
   retval = zeros (sz, class (x));
   s = std (x, [], dim);
-  ind = find (s > 0);
+  idx = find (s > 0);
   x = sum (x .^ 3, dim);
-  retval(ind) = x(ind) ./ (c * s(ind) .^ 3);
+  retval(idx) = x(idx) ./ (n * s(idx) .^ 3);
 
 endfunction
 
+
 %!assert(skewness ([-1,0,1]), 0);
 %!assert(skewness ([-2,0,1]) < 0);
 %!assert(skewness ([-1,0,2]) > 0);
@@ -92,10 +88,12 @@
 %! y = [x, 2*x];
 %! assert(all (abs (skewness (y) - [0.75, 0.75]) < sqrt (eps)));
 
+%!assert (skewness (single(1)), single(0));
+
 %% Test input validation
 %!error skewness ()
 %!error skewness (1, 2, 3)
-%!error skewness ([true true])
+%!error skewness (['A'; 'B'])
 %!error skewness (1, ones(2,2))
 %!error skewness (1, 1.5)
 %!error skewness (1, 0)
--- a/scripts/statistics/base/spearman.m
+++ b/scripts/statistics/base/spearman.m
@@ -39,11 +39,12 @@
 
 function rho = spearman (x, y = [])
 
-  if ((nargin < 1) || (nargin > 2))
+  if (nargin < 1 || nargin > 2)
     print_usage ();
   endif
 
-  if (! (isnumeric (x) && isnumeric (y)))
+  if (   ! (isnumeric (x) || islogical (x))
+      || ! (isnumeric (y) || islogical (y)))
     error ("spearman: X and Y must be numeric matrices or vectors");
   endif
 
@@ -51,30 +52,43 @@
     error ("spearman: X and Y must be 2-D matrices or vectors");
   endif
 
-  if (rows (x) == 1)
-    x = x';
+  if (isrow (x))
+    x = x.';
   endif
-  n = rows (x);
 
   if (nargin == 1)
-    rho = corrcoef (ranks (x));
+    rho = corr (ranks (x));
   else
-    if (rows (y) == 1)
-      y = y';
+    if (isrow (y))
+      y = y.';
     endif
-    if (rows (y) != n)
+    if (rows (x) != rows (y))
       error ("spearman: X and Y must have the same number of observations");
     endif
-    rho = corrcoef (ranks (x), ranks (y));
+    rho = corr (ranks (x), ranks (y));
+  endif
+
+  ## Restore class cleared by ranks
+  if (isa (x, 'single') || isa (y, 'single'))
+    rho = single (rho);
   endif
 
 endfunction
 
+
+%!test
+%! x = 1:10;
+%! y = exp (x);
+%! assert (spearman (x,y), 1, 5*eps);
+%! assert (spearman (x,-y), -1, 5*eps);
+
+%!assert(spearman ([1 2 3], [-1 1 -2]), -0.5, 5*eps)
+
 %% Test input validation
 %!error spearman ();
 %!error spearman (1, 2, 3);
-%!error spearman ([true, true]);
-%!error spearman (ones(1,2), [true, true]);
+%!error spearman (['A'; 'B']);
+%!error spearman (ones(1,2), {1, 2});
 %!error spearman (ones (2,2,2));
 %!error spearman (ones (2,2), ones (2,2,2));
 %!error spearman (ones (2,2), ones (3,2));
--- a/scripts/statistics/base/statistics.m
+++ b/scripts/statistics/base/statistics.m
@@ -38,7 +38,7 @@
     print_usage ();
   endif
 
-  if (!isnumeric(x))
+  if (! (isnumeric (x) || islogical (x)))
     error ("statistics: X must be a numeric vector or matrix");
   endif
 
@@ -46,10 +46,7 @@
   sz = size (x);
   if (nargin != 2)
     ## Find the first non-singleton dimension.
-    dim = find (sz > 1, 1);
-    if (isempty (dim))
-      dim = 1;
-    endif
+    (dim = find (sz > 1, 1)) || (dim = 1);
   else
     if (!(isscalar (dim) && dim == round (dim))
         || !(1 <= dim && dim <= nd))
@@ -68,16 +65,22 @@
 
 endfunction
 
+
 %!test
-%! x = rand(7,5);
+%! x = rand (7,5);
 %! s = statistics (x);
-%! m = median (x);
-%! assert (m, s(3,:), eps);
+%! assert (min (x), s(1,:), eps);
+%! assert (median (x), s(3,:), eps);
+%! assert (max (x), s(5,:), eps);
+%! assert (mean (x), s(6,:), eps);
+%! assert (std (x), s(7,:), eps);
+%! assert (skewness (x), s(8,:), eps);
+%! assert (kurtosis (x), s(9,:), eps);
 
 %% Test input validation
 %!error statistics ()
 %!error statistics (1, 2, 3)
-%!error statistics ([true true])
+%!error statistics (['A'; 'B'])
 %!error statistics (1, ones(2,2))
 %!error statistics (1, 1.5)
 %!error statistics (1, 0)
--- a/scripts/statistics/base/std.m
+++ b/scripts/statistics/base/std.m
@@ -67,7 +67,7 @@
     print_usage ();
   endif
 
-  if (! (isnumeric (x)))
+  if (! (isnumeric (x) || islogical (x)))
     error ("std: X must be a numeric vector or matrix");
   endif
 
@@ -78,22 +78,27 @@
     error ("std: normalization OPT must be 0 or 1");
   endif
 
+  nd = ndims (x);
   sz = size (x);
   if (nargin < 3)
     ## Find the first non-singleton dimension.
-    dim = find (sz > 1, 1);
-    if (isempty (dim))
-      dim = 1;
+    (dim = find (sz > 1, 1)) || (dim = 1);
+  else
+    if (!(isscalar (dim) && dim == fix (dim))
+        || !(1 <= dim && dim <= nd))
+      error ("std: DIM must be an integer and a valid dimension");
     endif
   endif
 
-  n = size (x, dim);
-  if (n == 1)
-    retval = zeros (sz);
-  elseif (numel (x) > 0)
+  n = sz(dim);
+  if (n == 1 || isempty (x))
+    if (isa (x, 'single'))
+      retval = zeros (sz, 'single');
+    else
+      retval = zeros (sz);
+    endif
+  else
     retval = sqrt (sumsq (center (x, dim), dim) / (n - 1 + opt));
-  else
-    error ("std: X must not be empty");
   endif
 
 endfunction
@@ -102,14 +107,21 @@
 %!test
 %! x = ones (10, 2);
 %! y = [1, 3];
-%! assert(std (x) == [0, 0] && abs (std (y) - sqrt (2)) < sqrt (eps));
-%! assert (std (x, 0, 3), zeros (10, 2))
-%! assert (std (ones (3, 1, 2), 0, 2), zeros (3, 1, 2))
+%! assert(std (x) == [0, 0]);
+%! assert(std (y), sqrt (2), sqrt (eps));
+%! assert(std (x, 0, 2), zeros (10, 1));
+
+%!assert(std (ones (3, 1, 2), 0, 2), zeros (3, 1, 2));
+%!assert(std ([1 2], 0), sqrt(2)/2, 5*eps);
+%!assert(std ([1 2], 1), 0.5, 5*eps);
+%!assert(std(1), 0);
+%!assert(std(single(1)), single(0));
+%!assert(std([]), []);
+%!assert(std(ones (1,3,0,2)), ones (1,3,0,2));
 
 %% Test input validation
 %!error std ();
 %!error std (1, 2, 3, 4);
-%!error std (true(1,2))
+%!error std (['A'; 'B'])
 %!error std (1, -1);
-%!error std ([], 1);
 
--- a/scripts/statistics/base/table.m
+++ b/scripts/statistics/base/table.m
@@ -60,6 +60,7 @@
 
 endfunction
 
+
 %% Test input validation
 %!error table ()
 %!error table (1, 2, 3)
--- a/scripts/statistics/base/var.m
+++ b/scripts/statistics/base/var.m
@@ -64,7 +64,7 @@
     print_usage ();
   endif
 
-  if (!isnumeric (x))
+  if (! (isnumeric (x) || islogical (x)))
     error ("var: X must be a numeric vector or matrix");
   endif
 
@@ -75,16 +75,25 @@
     error ("var: normalization OPT must be 0 or 1");
   endif
 
+  nd = ndims (x);
+  sz = size (x);
   if (nargin < 3)
-    dim = find (size (x) > 1, 1);
-    if (isempty (dim))
-      dim = 1;
+    ## Find the first non-singleton dimension.
+    (dim = find (sz > 1, 1)) || (dim = 1);
+  else
+    if (!(isscalar (dim) && dim == fix (dim))
+        || !(1 <= dim && dim <= nd))
+      error ("var: DIM must be an integer and a valid dimension");
     endif
   endif
 
-  n = size (x, dim);
+  n = sz(dim);
   if (n == 1)
-    retval = zeros (size (x), class (x));
+    if (isa (x, 'single'))
+      retval = zeros (sz, 'single');
+    else
+      retval = zeros (sz);
+    endif
   elseif (numel (x) > 0)
     retval = sumsq (center (x, dim), dim) / (n - 1 + opt);
   else
@@ -93,15 +102,17 @@
 
 endfunction
 
-%!assert (var (13), 0)
-%!assert (var ([1,2,3]), 1)
-%!assert (var ([1,2,3], 1), 2/3, eps)
-%!assert (var ([1,2,3], [], 1), [0,0,0])
+
+%!assert(var (13), 0);
+%!assert(var (single(13)), single(0));
+%!assert(var ([1,2,3]), 1);
+%!assert(var ([1,2,3], 1), 2/3, eps);
+%!assert(var ([1,2,3], [], 1), [0,0,0]);
 
 %% Test input validation
 %!error var ()
 %!error var (1,2,3,4)
-%!error var (true(1,2))
+%!error var (['A'; 'B'])
 %!error var (1, -1);
 %!error var ([],1)
 
copy from scripts/statistics/base/studentize.m
copy to scripts/statistics/base/zscore.m
--- a/scripts/statistics/base/studentize.m
+++ b/scripts/statistics/base/zscore.m
@@ -17,8 +17,8 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} studentize (@var{x})
-## @deftypefnx {Function File} {} studentize (@var{x}, @var{dim})
+## @deftypefn  {Function File} {} zscore (@var{x})
+## @deftypefnx {Function File} {} zscore (@var{x}, @var{dim})
 ## If @var{x} is a vector, subtract its mean and divide by its standard
 ## deviation.
 ##
@@ -31,58 +31,54 @@
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Subtract mean and divide by standard deviation
 
-function t = studentize (x, dim)
+function z = zscore (x, dim)
 
   if (nargin != 1 && nargin != 2)
     print_usage ();
   endif
 
-  if (! isnumeric(x))
-    error ("studentize: X must be a numeric vector or matrix");
-  endif
-
-  if (isinteger (x))
-    x = double (x);
+  if (! (isnumeric (x) || islogical (x)))
+    error ("zscore: X must be a numeric vector or matrix");
   endif
 
   nd = ndims (x);
   sz = size (x);
   if (nargin != 2)
     ## Find the first non-singleton dimension.
-    dim = find (sz > 1, 1);
-    if (isempty (dim))
-      dim = 1;
-    endif
+    (dim = find (sz > 1, 1)) || (dim = 1);
   else
     if (!(isscalar (dim) && dim == fix (dim))
         || !(1 <= dim && dim <= nd))
-      error ("studentize: DIM must be an integer and a valid dimension");
+      error ("zscore: DIM must be an integer and a valid dimension");
     endif
   endif
 
-  c = sz(dim);
-  if (c == 0)
-    t = x;
+  n = sz(dim);
+  if (n == 0)
+    z = x;
   else
-    idx = ones (1, nd);
-    idx(dim) = c;
-    t = x - repmat (mean (x, dim), idx);
-    t = t ./ repmat (max (cat (dim, std(t, [], dim), ! any (t, dim)), [], dim), idx);
+    x = center (x, dim); # center also promotes integer to double for next line
+    z = zeros (sz, class (x));
+    s = std (x, [], dim);
+    s(s==0) = 1;
+    z = bsxfun (@rdivide, x, s);
   endif
 
 endfunction
 
-%!assert(studentize ([1,2,3]), [-1,0,1])
-%!assert(studentize (int8 ([1,2,3])), [-1,0,1])
-#%!assert(studentize (ones (3,2,0,2)), zeros (3,2,0,2))
-%!assert(studentize ([2,0,-2;0,2,0;-2,-2,2]), [1,0,-1;0,1,0;-1,-1,1])
+
+%!assert(zscore ([1,2,3]), [-1,0,1])
+%!assert(zscore (single([1,2,3])), single([-1,0,1]))
+%!assert(zscore (int8([1,2,3])), [-1,0,1])
+%!assert(zscore (ones (3,2,2,2)), zeros (3,2,2,2))
+%!assert(zscore ([2,0,-2;0,2,0;-2,-2,2]), [1,0,-1;0,1,0;-1,-1,1])
 
 %% Test input validation
-%!error studentize ()
-%!error studentize (1, 2, 3)
-%!error studentize ([true true])
-%!error studentize (1, ones(2,2))
-%!error studentize (1, 1.5)
-%!error studentize (1, 0)
-%!error studentize (1, 3)
+%!error zscore ()
+%!error zscore (1, 2, 3)
+%!error zscore (['A'; 'B'])
+%!error zscore (1, ones(2,2))
+%!error zscore (1, 1.5)
+%!error zscore (1, 0)
+%!error zscore (1, 3)
 
--- a/scripts/statistics/distributions/logistic_inv.m
+++ b/scripts/statistics/distributions/logistic_inv.m
@@ -31,7 +31,11 @@
     print_usage ();
   endif
 
-  inv = zeros (size (x));
+  if (isa (x, 'single'))
+    inv = zeros (size (x), 'single');
+  else
+    inv = zeros (size (x));
+  endif
 
   k = find ((x < 0) | (x > 1) | isnan (x));
   if (any (k))
--- a/scripts/statistics/tests/cor_test.m
+++ b/scripts/statistics/tests/cor_test.m
@@ -91,7 +91,7 @@
   m = method (1);
 
   if (m == "p")
-    r = cor (x, y);
+    r = corr (x, y);
     df = n - 2;
     t.method = "Pearson's product moment correlation";
     t.params = df;
--- a/scripts/statistics/tests/wilcoxon_test.m
+++ b/scripts/statistics/tests/wilcoxon_test.m
@@ -23,7 +23,7 @@
 ## @var{y}) == 1/2.  Under the null, the test statistic @var{z}
 ## approximately follows a standard normal distribution when @var{n} > 25.
 ##
-## @strong{Warning}: This function assumes a normal distribution for @var{z}
+## @strong{Caution:} This function assumes a normal distribution for @var{z}
 ## and thus is invalid for @var{n} @leq{} 25.
 ##
 ## With the optional argument string @var{alt}, the alternative of
--- a/scripts/strings/deblank.m
+++ b/scripts/strings/deblank.m
@@ -18,10 +18,22 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} deblank (@var{s})
-## Remove trailing blanks and nulls from @var{s}.  If @var{s}
+## Remove trailing whitespace and nulls from @var{s}.  If @var{s}
 ## is a matrix, @var{deblank} trims each row to the length of longest
-## string.  If @var{s} is a cell array, operate recursively on each
-## element of the cell array.
+## string.  If @var{s} is a cell array of strings, operate recursively on each
+## string element.
+##
+## Examples:
+## @example
+## @group
+## deblank ("    abc  ")
+##      @result{}  "    abc"
+##
+## deblank ([" abc   "; "   def   "])
+##      @result{}  [" abc  " ; "   def"]
+## @end group
+## @end example
+## @seealso{strtrim}
 ## @end deftypefn
 
 ## Author: Kurt Hornik <Kurt.Hornik@wu-wien.ac.at>
@@ -33,53 +45,34 @@
     print_usage ();
   endif
 
-  char_arg = ischar (s);
-
-  if (char_arg || isnumeric (s))
+  if (ischar (s))
 
-    if (! isempty (s))
-      if (char_arg)
-        k = find (! isspace (s) & s != "\0");
-      else
-        warning ("deblank: expecting character string argument");
-        k = find (s != 0);
-      endif
-
-      if (isempty (k))
-        s = resize (s, 0, 0);
-      else
-        s = s(:,1:ceil (max (k) / rows (s)));
-      endif
+    k = find (! isspace (s) & s != "\0");
+    if (isempty (s) || isempty (k))
+      s = "";
+    else
+      s = s(:,1:ceil (max (k) / rows (s)));
     endif
 
-  elseif (iscell(s))
+  elseif (iscellstr (s))
 
-    s = cellfun (@deblank, s, "uniformoutput", false);
+    s = regexprep (s, "[\\s\v\\0]+$", '');
 
   else
-    error ("deblank: expecting character string argument");
+    error ("deblank: S argument must be a string or cellstring");
   endif
 
 endfunction
 
-%!assert (strcmp (deblank (" f o o  "), " f o o"));
 
-%!assert (deblank ([]), [])
-%!assert (deblank ({}), {})
-%!assert (deblank (""), "")
-
-%!assert (deblank ([0,0,0]), [])
+%!assert (strcmp (deblank (" f o o \0"), " f o o"));
 %!assert (deblank ('   '), '')
 %!assert (deblank ("   "), "")
-
-%!assert (typeinfo (deblank ("   ")), "string")
-%!assert (typeinfo (deblank ('   ')), "sq_string")
+%!assert (deblank (""), "")
+%!assert (deblank ({}), {})
 
-%!assert (deblank ([1,2,0]), [1,2])
-%!assert (deblank ([1,2,0,32]), [1,2,0,32])
+%!error <Invalid call to deblank> deblank ();
+%!error <Invalid call to deblank> deblank ("foo", "bar");
+%!error <argument must be a string> deblank (1);
+%!error <argument must be a string> deblank ({[]});
 
-%!assert (deblank (int8 ([1,2,0])), int8 ([1,2]))
-
-%!error deblank ();
-
-%!error deblank ("foo", "bar");
--- a/scripts/strings/index.m
+++ b/scripts/strings/index.m
@@ -62,13 +62,13 @@
 
   if (strcmp (direction, "last"))
     if (iscell (f))
-      n = cellfun (@min, f);
+      n = cellfun ("min", f);
     else
       n = f(end);
     endif
   elseif (strcmp (direction, "first"))
     if (iscell (f))
-      n = cellfun (@max, f);
+      n = cellfun ("max", f);
     else
       n = f(1);
     endif
--- a/scripts/strings/mat2str.m
+++ b/scripts/strings/mat2str.m
@@ -28,7 +28,7 @@
 ## scalar then both real and imaginary parts of the matrix are printed
 ## to the same precision.  Otherwise @code{@var{n} (1)} defines the
 ## precision of the real part and @code{@var{n} (2)} defines the
-## precision of the imaginary part.  The default for @var{n} is 17.
+## precision of the imaginary part.  The default for @var{n} is 15.
 ##
 ## If the argument 'class' is given, then the class of @var{x} is
 ## included in the string in such a way that the eval will result in the
@@ -56,13 +56,13 @@
 
   if (nargin < 2 || isempty (n))
     ## Default precision
-    n = 17;
+    n = 15;
   endif
 
   if (nargin < 3)
     if (ischar (n))
       cls = n;
-      n = 17;
+      n = 15;
     else
       cls = "";
     endif
@@ -137,3 +137,4 @@
 %!assert (mat2str (true), "true");
 %!assert (mat2str (false), "false");
 %!assert (mat2str (logical (eye (2))), "[true,false;false,true]");
+%!assert (mat2str (0.7), "0.7")
--- a/scripts/strings/strcat.m
+++ b/scripts/strings/strcat.m
@@ -61,14 +61,14 @@
     elseif (nargin > 1)
       ## Convert to cells of strings
       uo = "uniformoutput";
-      reals = cellfun (@isreal, varargin);
+      reals = cellfun ("isreal", varargin);
       if (any (reals))
-        varargin(reals) = cellfun (@char, varargin(reals), uo, false);
+        varargin(reals) = cellfun ("char", varargin(reals), uo, false);
       endif
-      chars = cellfun (@ischar, varargin);
+      chars = cellfun ("isclass", varargin, "char");
       allchar = all (chars);
-      varargin(chars) = cellfun (@cellstr, varargin(chars), uo, false);
-      if (! all (cellfun (@iscell, varargin)))
+      varargin(chars) = cellfun ("cellstr", varargin(chars), uo, false);
+      if (! all (cellfun ("isclass", varargin, "cell")))
         error ("strcat: inputs must be strings or cells of strings");
       endif
 
@@ -81,7 +81,7 @@
       endif
 
       ## Cellfun handles everything for us.
-      st = cellfun (@horzcat, varargin{:}, uo, false);
+      st = cellfun ("horzcat", varargin{:}, uo, false);
 
       if (allchar)
         ## If all inputs were strings, return strings.
--- a/scripts/strings/strmatch.m
+++ b/scripts/strings/strmatch.m
@@ -19,13 +19,15 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} strmatch (@var{s}, @var{A}, "exact")
-## Return indices of entries of @var{A} that match the string @var{s}.
-## The second argument @var{A} may be a string matrix or a cell array of
-## strings.  If the third argument @code{"exact"} is not given, then
+## @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 @code{"exact"} is not given, then
 ## @var{s} only needs to match @var{A} up to the length of @var{s}.
-## Trailing whitespace is ignored.
-## Results are returned as a column vector.
+## Trailing spaces and nulls in @var{s} and @var{A} are ignored when matching.
+## option.
+## 
 ## For example:
 ##
 ## @example
@@ -33,13 +35,16 @@
 ## strmatch ("apple", "apple juice")
 ##      @result{} 1
 ##
-## strmatch ("apple", ["apple pie"; "apple juice"; "an apple"])
+## strmatch ("apple", ["apple  "; "apple juice"; "an apple"])
 ##      @result{} [1; 2]
 ##
-## strmatch ("apple", @{"apple pie"; "apple juice"; "tomato"@})
-##      @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{strcmpi} or @code{strncmpi} in all new code.
 ## @seealso{strfind, findstr, strcmp, strncmp, strcmpi, strncmpi, find}
 ## @end deftypefn
 
@@ -52,29 +57,19 @@
     print_usage ();
   endif
 
-  if (! ischar (s))
+  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
 
-  ## Truncate trailing whitespace.
-  s = strtrimr (s);
-
+  ## Trim blanks and nulls from search string
+  s = regexprep (s, "[ \\0]+$", '');
   len = length (s);
 
   exact = nargin == 3 && ischar (exact) && strcmp (exact, "exact");
 
-  if (iscell (A))
-    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 whitespace.
-      B = cellfun (@strtrimr, A(idx), "uniformoutput", false);
-      idx = idx (strcmp (s, B));
-    endif
-  elseif (ischar (A))
+  if (ischar (A))
     [nr, nc] = size (A);
     if (len > nc)
       idx = [];
@@ -82,34 +77,43 @@
       match = all (bsxfun (@eq, A(:,1:len), s), 2);
       if (exact)
         AA = A(:,len+1:nc);
-        match &= all (AA == "\0" | AA == " ", 2);
+        match &= all (AA == " " | AA == "\0", 2);
       endif
       idx = find (match);
     endif
   else
-    error ("strmatch: A must be a string or cell array of strings");
+    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
 
-## Removes nuls and blanks from the end of the array
-function s = strtrimr (s)
-  blnks = s == "\0" | s == " ";
-  i = find (blnks, 1, "last");
-  if (i && all (blnks(i:end)))
-    s = s(1:i-1);
-  endif
-endfunction
 
-%!error <Invalid call to strmatch> strmatch();
-%!error <Invalid call to strmatch> strmatch("a", "aaa", "exact", 1);
 %!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", ["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 b", {"a b", "a c", "c d"}));
-%!assert (strmatch ("", {"", "foo", "bar", ""}), [1, 4])
-%!assert (strmatch ('', { '', '% comment line', 'var a = 5', ''}, 'exact'), [1,4])
+%!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/strsplit.m
+++ b/scripts/strings/strsplit.m
@@ -28,7 +28,7 @@
 function s = strsplit (p, sep, strip_empty = false)
 
   if (nargin < 2 || nargin > 3 || ! ischar (p) || rows (p) > 1
-      || ! ischar (sep) || ! islogical (strip_empty))
+      || ! ischar (sep) || ! isscalar (strip_empty))
     print_usage ();
   endif
 
--- a/scripts/strings/strtrim.m
+++ b/scripts/strings/strtrim.m
@@ -18,20 +18,21 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} strtrim (@var{s})
-## Remove leading and trailing whitespace and nulls from @var{s}.  If
+## Remove leading and trailing whitespace from @var{s}.  If
 ## @var{s} is a matrix, @var{strtrim} trims each row to the length of
-## longest string.  If @var{s} is a cell array, operate recursively on
-## each element of the cell array.  For example:
+## longest string.  If @var{s} is a cell array of strings, operate recursively
+## on each string element.  For example:
 ##
 ## @example
 ## @group
 ## strtrim ("    abc  ")
-##      @result{} "abc"
+##      @result{}  "abc"
 ##
 ## strtrim ([" abc   "; "   def   "])
-##      @result{} ["abc  "; "  def"]
+##      @result{}  ["abc  "  ; "  def"]
 ## @end group
 ## @end example
+## @seealso{deblank}
 ## @end deftypefn
 
 ## Author: John Swensen <jpswensen@jhu.edu>
@@ -46,19 +47,19 @@
 
   if (ischar (s))
 
-    k = find (! isspace (s) & s != "\0");
+    k = find (! isspace (s));
     if (isempty (s) || isempty (k))
       s = "";
     else
       s = s(:, ceil (min (k) / rows (s)):ceil (max (k) / rows (s)));
     endif
 
-  elseif (iscell(s))
+  elseif (iscellstr (s))
 
-    s = regexprep (s, "^[\\s\v\\0]+|[\\s\v\\0]+$", '');
+    s = regexprep (s, "^[\\s\v]+|[\\s\v]+$", '');
 
   else
-    error ("strtrim: S argument must be a string");
+    error ("strtrim: S argument must be a string or cellstring");
   endif
 
 endfunction
@@ -73,4 +74,5 @@
 %!error <Invalid call to strtrim> strtrim ();
 %!error <Invalid call to strtrim> strtrim ("abc", "def");
 %!error <argument must be a string> strtrim (1);
+%!error <argument must be a string> strtrim ({[]});
 
--- a/scripts/strings/untabify.m
+++ b/scripts/strings/untabify.m
@@ -52,64 +52,72 @@
 
 function s = untabify (t, tw = 8, dblank = false)
 
- if (nargin > 0 && nargin < 4 && (ischar (t) || iscellstr (t)))
-   if (ischar (t))
-     s = replace_tabs (t, tw);
-   else
-     s = cellfun (@(str) replace_tabs (str, tw), t, "uniformoutput", false);
-   endif
-   if (dblank)
-     s = deblank (s);
-   endif
- else
-   print_usage ();
- endif
+  if (nargin < 1 || nargin > 3)
+    print_usage ();
+  elseif (! (ischar (t) || iscellstr (t)))
+    error ("untabify: T must be a string or cellstring");
+  endif
+ 
+  if (ischar (t))
+    s = replace_tabs (t, tw);
+  else
+    s = cellfun (@(str) replace_tabs (str, tw), t, "uniformoutput", false);
+  endif
+ 
+  if (dblank)
+    s = deblank (s);
+  endif
 
 endfunction
 
 function s = replace_tabs (t, tw)
- if (ndims (t) == 2)
-   if (isempty (t))
-     s = t;
-   else
-     nr = rows (t);
-     sc = cell (nr, 1);
-     for j = 1:nr
-       n = 1:numel(t(j,:));
-       m = find (t(j,:) == "\t");
-       t(j,m) = " ";
-       for i = 1:numel(m)
-         k = tw * ceil (n(m(i)) / tw);
-         dn = k - n(m(i));
-         n(m(i):end) += dn;
-       endfor
-       sc{j} = blanks (n(end));
-       sc{j}(n) = t(j,:);
-     endfor
-     s = char (sc);
-   endif
- else
-   error ("untabify: character strings to untabify must have 2 dimensions");
- endif
+
+  if (ndims (t) != 2)
+    error ("untabify: character strings to untabify must have 2 dimensions");
+  endif
+
+  if (isempty (t))
+    s = t;
+  else
+    nr = rows (t);
+    sc = cell (nr, 1);
+    for j = 1:nr
+      n = 1:numel(t(j,:));
+      m = find (t(j,:) == "\t");
+      t(j,m) = " ";
+      for i = 1:numel(m)
+        k = tw * ceil (n(m(i)) / tw);
+        dn = k - n(m(i));
+        n(m(i):end) += dn;
+      endfor
+      sc{j} = blanks (n(end));
+      sc{j}(n) = t(j,:);
+    endfor
+    s = char (sc);
+  endif
+
 endfunction
 
+
 %!test
 %! s = untabify ("\thello\t");
-%! assert (isequal (s, horzcat (blanks(8), "hello   ")))
+%! assert (s, [blanks(8) "hello" blanks(3)]);
+
+%!test
+%! s = untabify ("\thello\t", 2);
+%! assert (s, [blanks(2) "hello" blanks(1)]);
 
 %!test
 %! s = untabify ("\thello\t", 4, true);
-%! assert (isequal (s, horzcat (blanks(4), "hello")))
+%! assert (s, [blanks(4) "hello"]);
 
-%!test
-%! s = untabify ("\thello\t", 2, true);
-%! assert (isequal (s, horzcat (blanks(2), "hello")))
+%!assert (isempty (untabify ("")))
 
 %!test
-%! s = untabify ("");
-%! assert (isempty (s))
+%! s = char (randi ([97 97+25], 3, 3));
+%! assert (untabify (s), char (untabify (cellstr (s))));
 
-%!test
-%! s = char (fix (100 + 10*rand (3,3)));
-%! assert (isequal (untabify (s), untabify ({s}){1}))
+%!error untabify ()
+%!error untabify (1,2,3,4)
+%!error <must be a string> untabify (1)
 
--- a/scripts/strings/validatestring.m
+++ b/scripts/strings/validatestring.m
@@ -118,7 +118,7 @@
     ## are the matches a substring of each other, if so, choose the
     ## shortest.  If not, raise an error.
     match_idx = find (matches);
-    match_l = cellfun (@length, strarray(match_idx));
+    match_l = cellfun ("length", strarray(match_idx));
     longest_idx = find (match_l == max (match_l), 1);
     shortest_idx = find (match_l == min (match_l), 1);
     longest = strarray(match_idx)(longest_idx);
--- a/scripts/testfun/demo.m
+++ b/scripts/testfun/demo.m
@@ -17,35 +17,39 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Command} {} demo @var{name} @var{n}
+## @deftypefn  {Command} {} demo @var{name}
+## @deftypefnx {Command} {} demo @var{name} @var{n}
+## @deftypefnx {Function File} {} demo ('@var{name}')
 ## @deftypefnx {Function File} {} demo ('@var{name}', @var{n})
 ##
-## Runs any examples associated with the function '@var{name}'.
+## 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 somewhere on your path.  To keep them separate
-## from the usual script code, all lines are prefixed by @code{%!}.  Each
-## example is introduced by the keyword 'demo' flush left to the prefix,
-## with no intervening spaces.  The remainder of the example can contain
-## arbitrary Octave code.  For example:
+## 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 'demo' flush left to the
+## prefix with no intervening spaces.  The remainder of the example can
+## contain arbitrary Octave code.  For example:
 ##
 ## @example
 ## @group
-##    %!demo
-##    %! t=0:0.01:2*pi; x = sin(t);
-##    %! plot(t,x)
-##    %! %-------------------------------------------------
-##    %! % the figure window shows one cycle of a sine wave
+##   %!demo
+##   %! t=0:0.01:2*pi; x = sin(t);
+##   %! plot (t,x)
+##   %! %-------------------------------------------------
+##   %! % 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.  It is generally not necessary to use
-## disp or printf within the demo.
+## 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.
 ##
 ## Demos are run in a function environment with no access to external
-## variables.  This means that all demos in your function must use
-## separate initialization code.  Alternatively, you can combine your
-## demos into one huge demo, with the code:
+## 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");
@@ -53,11 +57,13 @@
 ##
 ## @noindent
 ## between the sections, but this is discouraged.  Other techniques
-## include using multiple plots by saying figure between each, or
-## using subplot to put multiple plots in the same window.
+## 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, since demo evaluates inside a function context, you cannot
-## define new functions inside a demo.  Instead you will have to
+## 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 "if 1 <demo stuff> endif"
@@ -73,6 +79,7 @@
 ##   %! endif
 ## @end group
 ## @end example
+##
 ## @seealso{test, example}
 ## @end deftypefn
 
@@ -88,20 +95,19 @@
 
   if (nargin < 2)
     n = 0;
-  elseif (strcmp ("char", class (n)))
+  elseif (ischar (n))
     n = str2double (n);
   endif 
 
   [code, idx] = test (name, "grabdemo");
-  if (length (idx) == 0)
-    warning ("demo not available for %s", name);
+  if (isempty (idx))
+    warning ("no demo available for %s", name);
     return;
   elseif (n >= length (idx))
     warning ("only %d demos available for %s", length (idx) - 1, name);
     return;
   endif
 
-
   if (n > 0)
     doidx = n;
   else
@@ -123,7 +129,7 @@
       __demo__;
     catch
       ## Let the programmer know which demo failed.
-      printf ("%s example %d: failed\n%s\n", name, doidx(i), __error_text__);
+      printf ("%s example %d: failed\n%s\n", name, doidx(i), lasterr ());
     end_try_catch
     clear __demo__;
   endfor
@@ -132,6 +138,6 @@
 
 %!demo
 %! t=0:0.01:2*pi; x = sin(t);
-%! plot(t,x)
+%! plot (t,x)
 %! %-------------------------------------------------
 %! % the figure window shows one cycle of a sine wave
--- a/scripts/testfun/example.m
+++ b/scripts/testfun/example.m
@@ -17,16 +17,18 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Command} {} example @var{name} @var{n}
+## @deftypefn  {Command} {} example @var{name}
+## @deftypefnx {Command} {} example @var{name} @var{n}
+## @deftypefnx {Function File} {} example ('@var{name}')
 ## @deftypefnx {Function File} {} example ('@var{name}', @var{n})
-## @deftypefnx {Function File} {[@var{x}, @var{idx}] =} example ('@var{name}', @var{n})
+## @deftypefnx {Function File} {[@var{s}, @var{idx}] =} example (@dots{})
 ##
-##  Display the code for example @var{n} associated with the function
-## '@var{name}', but do not run it.  If @var{n} is not given, all examples
+## Display the code for example @var{n} associated with the function
+## '@var{name}', but do not run it.  If @var{n} is not specified, all examples
 ## are displayed.
 ##
-## Called with output arguments, the examples are returned in the form of
-## a string @var{x}, with @var{idx} indicating the ending position of the
+## When called with output arguments, the examples are returned in the form of
+## a string @var{s}, with @var{idx} indicating the ending position of the
 ## various examples.
 ##
 ## See @code{demo} for a complete explanation.
@@ -41,7 +43,7 @@
 
   if (nargin < 2)
     n = 0;
-  elseif (strcmp ("char", class (n)))
+  elseif (ischar (n))
     n = str2double (n);
   endif 
 
@@ -65,15 +67,16 @@
     else
       doidx = 1:length(idx)-1;
     endif
-    if (length (idx) == 0)
-      warning ("example not available for %s", name);
+    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);
-      doidx = [];
+      return;
     endif
 
     for i = 1:length (doidx)
-      block = code (idx(doidx(i)):idx(doidx(i)+1)-1);
+      block = code(idx(doidx(i)):idx(doidx(i)+1)-1);
       printf ("%s example %d:%s\n\n", name, doidx(i), block);
     endfor
   endif
@@ -82,17 +85,18 @@
 
 %!## warning: don't modify the demos without modifying the tests!
 %!demo
-%! example('example');
+%! example ('example');
 %!demo
-%! t=0:0.01:2*pi; x=sin(t);
-%! plot(t,x)
+%! 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');
+%! [code, idx] = example ('example');
 %! assert (code, ...
-%!         "\n example('example');\n t=0:0.01:2*pi; x=sin(t);\n plot(t,x)")
-%! assert (idx, [1, 22, 59]);
+%!         "\n example ('example');\n t=0:0.01:2*pi; x = sin(t);\n plot (t,x)")
+%! assert (idx, [1, 23, 63]);
 
+%% Test input validation
 %!error example;
-%!error example('example',3,5)
+%!error example('example', 3, 5)
--- a/scripts/testfun/rundemos.m
+++ b/scripts/testfun/rundemos.m
@@ -35,6 +35,7 @@
     if (is_absolute_filename (directory))
       dirs = {directory};
     else
+      directory = regexprep (directory, ['\',filesep(),'$'], "");
       fullname = find_dir_in_path (directory);
       if (! isempty (fullname))
         dirs = {fullname};
--- a/scripts/testfun/runtests.m
+++ b/scripts/testfun/runtests.m
@@ -35,6 +35,7 @@
     if (is_absolute_filename (directory))
       dirs = {directory};
     else
+      directory = regexprep (directory, ['\',filesep(),'$'], "");
       fullname = find_dir_in_path (directory);
       if (! isempty (fullname))
         dirs = {fullname};
--- a/scripts/testfun/test.m
+++ b/scripts/testfun/test.m
@@ -132,7 +132,7 @@
     __rundemo = 0;
     __verbose = 0;
     __demo_code = "";
-    __demo_idx = 1;
+    __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);
@@ -286,7 +286,7 @@
           input ("Press <enter> to continue: ", "s");
         catch
           __success = 0;
-          __msg = sprintf ("%sdemo failed\n%s",  __signal_fail, __error_text__);
+          __msg = sprintf ("%sdemo failed\n%s",  __signal_fail, lasterr ());
         end_try_catch
         clear __test__;
 
@@ -359,7 +359,7 @@
         catch
           __success = 0;
           __msg = sprintf ("%stest failed: syntax error\n%s",
-                           __signal_fail, __error_text__);
+                           __signal_fail, lasterr ());
         end_try_catch
       endif
       __code = "";
@@ -389,7 +389,7 @@
       catch
         __success = 0;
         __msg = sprintf ("%stest failed: syntax error\n%s",
-                         __signal_fail, __error_text__);
+                         __signal_fail, lasterr ());
       end_try_catch
 
       if (__success)
@@ -488,13 +488,13 @@
         eval (sprintf ("%s__test__(%s);", __shared_r, __shared));
       catch
         if (strcmp (__type, "xtest"))
-           __msg = sprintf ("%sknown failure\n%s", __signal_fail, __error_text__);
+           __msg = sprintf ("%sknown failure\n%s", __signal_fail, lasterr ());
            __xfail++;
         else
-           __msg = sprintf ("%stest failed\n%s", __signal_fail, __error_text__);
+           __msg = sprintf ("%stest failed\n%s", __signal_fail, lasterr ());
            __success = 0;
         endif
-        if (isempty (__error_text__))
+        if (isempty (lasterr ()))
           error ("empty error text, probably Ctrl-C --- aborting");
         endif
       end_try_catch
--- a/scripts/time/datenum.m
+++ b/scripts/time/datenum.m
@@ -50,7 +50,7 @@
 ## Days can be fractional.
 ## @end itemize
 ##
-## @strong{Warning:} this function does not attempt to handle Julian
+## @strong{Caution:} this function does not attempt to handle Julian
 ## calendars so dates before Octave 15, 1582 are wrong by as much
 ## as eleven days.  Also be aware that only Roman Catholic countries
 ## adopted the calendar in 1582.  It took until 1924 for it to be
--- a/scripts/time/now.m
+++ b/scripts/time/now.m
@@ -37,7 +37,11 @@
 
 function t = now ()
 
-  t = datenum (clock ());
+  if (nargin == 0)
+    t = datenum (clock ());
+  else
+    print_usage ();
+  endif
 
   ## The following doesn't work (e.g., one hour off on 2005-10-04):
   ##
@@ -50,3 +54,8 @@
   ## changing by an hour the offset from CUT for part of the year.
 
 endfunction
+
+%!error now (1);
+%!assert (isnumeric (now ()));
+%!assert (now () > 0);
+%!assert (now () <= now ());
--- a/src/DLD-FUNCTIONS/__contourc__.cc
+++ b/src/DLD-FUNCTIONS/__contourc__.cc
@@ -333,3 +333,10 @@
 
   return retval;
 }
+
+/*
+
+## No test needed for internal helper function.
+%!assert (1)
+
+*/
--- a/src/DLD-FUNCTIONS/__delaunayn__.cc
+++ b/src/DLD-FUNCTIONS/__delaunayn__.cc
@@ -226,3 +226,10 @@
 
   return retval;
 }
+
+/*
+
+## No test needed for internal helper function.
+%!assert (1)
+
+*/
--- a/src/DLD-FUNCTIONS/__dispatch__.cc
+++ b/src/DLD-FUNCTIONS/__dispatch__.cc
@@ -129,3 +129,10 @@
 
   return retval;
 }
+
+/*
+
+## No test needed for internal helper function.
+%!assert (1)
+
+*/
--- a/src/DLD-FUNCTIONS/__dsearchn__.cc
+++ b/src/DLD-FUNCTIONS/__dsearchn__.cc
@@ -108,3 +108,10 @@
 
   return retval;
 }
+
+/*
+
+## No test needed for internal helper function.
+%!assert (1)
+
+*/
--- a/src/DLD-FUNCTIONS/__fltk_uigetfile__.cc
+++ b/src/DLD-FUNCTIONS/__fltk_uigetfile__.cc
@@ -130,4 +130,11 @@
   return retval;
 }
 
+/*
+
+## No test needed for internal helper function.
+%!assert (1)
+
+*/
+
 #endif
--- a/src/DLD-FUNCTIONS/__glpk__.cc
+++ b/src/DLD-FUNCTIONS/__glpk__.cc
@@ -854,3 +854,10 @@
 
   return retval;
 }
+
+/*
+
+## No test needed for internal helper function.
+%!assert (1)
+
+*/
--- a/src/DLD-FUNCTIONS/__init_fltk__.cc
+++ b/src/DLD-FUNCTIONS/__init_fltk__.cc
@@ -648,13 +648,13 @@
     begin ();
     {
 
+      canvas = new
+        OpenGL_fltk (0, 0, ww , hh - status_h, number ());
+
       uimenu = new
         fltk_uimenu(0, 0, ww, menu_h);
       uimenu->hide ();
 
-      canvas = new
-        OpenGL_fltk (0, 0, ww , hh - status_h, number ());
-
       bottom = new
         Fl_Box (0,
                 hh - status_h,
@@ -861,8 +861,11 @@
 
   void show_canvas (void)
   {
-    canvas->show ();
-    canvas->make_current ();
+    if (fp.is_visible ())
+      {
+        canvas->show ();
+        canvas->make_current ();
+      }
   }
 
   void hide_canvas (void)
@@ -1837,10 +1840,10 @@
                 case figure::properties::ID_MENUBAR:
                   figure_manager::toggle_menubar_visibility (ov.string_value (), fp.menubar_is("figure"));
                   break;
-                case figure::properties::ID_NAME:
                 case figure::properties::ID_CURRENTAXES:
                   figure_manager::update_canvas (go.get_handle (), fp.get_currentaxes ());
                   break;
+                case figure::properties::ID_NAME:
                 case figure::properties::ID_NUMBERTITLE:
                   figure_manager::set_name (ov.string_value ());
                   break;
--- a/src/DLD-FUNCTIONS/__lin_interpn__.cc
+++ b/src/DLD-FUNCTIONS/__lin_interpn__.cc
@@ -355,3 +355,10 @@
 
   return retval;
 }
+
+/*
+
+## No test needed for internal helper function.
+%!assert (1)
+
+*/
--- a/src/DLD-FUNCTIONS/__magick_read__.cc
+++ b/src/DLD-FUNCTIONS/__magick_read__.cc
@@ -531,6 +531,13 @@
   return output;
 }
 
+/*
+
+## No test needed for internal helper function.
+%!assert (1)
+
+*/
+
 #ifdef HAVE_MAGICK
 
 static void
@@ -916,6 +923,13 @@
 return retval;
 }
 
+/*
+
+## No test needed for internal helper function.
+%!assert (1)
+
+*/
+
 #ifdef HAVE_MAGICK
 
 template<class T>
@@ -1134,6 +1148,13 @@
   return retval;
 }
 
+/*
+
+## No test needed for internal helper function.
+%!assert (1)
+
+*/
+
 #undef GET_PARAM
 
 // Determine the file formats supported by GraphicsMagick.  This is
@@ -1193,3 +1214,10 @@
 
   return retval;
 }
+
+/*
+
+## No test needed for internal helper function.
+%!assert (1)
+
+*/
--- a/src/DLD-FUNCTIONS/__pchip_deriv__.cc
+++ b/src/DLD-FUNCTIONS/__pchip_deriv__.cc
@@ -147,3 +147,10 @@
 
   return retval;
 }
+
+/*
+
+## No test needed for internal helper function.
+%!assert (1)
+
+*/
--- a/src/DLD-FUNCTIONS/__qp__.cc
+++ b/src/DLD-FUNCTIONS/__qp__.cc
@@ -528,3 +528,10 @@
 
   return retval;
 }
+
+/*
+
+## No test needed for internal helper function.
+%!assert (1)
+
+*/
--- a/src/DLD-FUNCTIONS/__voronoi__.cc
+++ b/src/DLD-FUNCTIONS/__voronoi__.cc
@@ -248,3 +248,10 @@
 
   return retval;
 }
+
+/*
+
+## No test needed for internal helper function.
+%!assert (1)
+
+*/
--- a/src/DLD-FUNCTIONS/bsxfun.cc
+++ b/src/DLD-FUNCTIONS/bsxfun.cc
@@ -312,15 +312,18 @@
 DEFUN_DLD (bsxfun, args, ,
   "-*- texinfo -*-\n\
 @deftypefn {Loadable Function} {} bsxfun (@var{f}, @var{A}, @var{B})\n\
-Apply a binary function @var{f} element-by-element to two matrix arguments\n\
-@var{A} and @var{B}.  @var{f} is a function handle, inline function, or\n\
-string containing the name of the function to evaluate.\n\
-The function @var{f} must be capable of accepting two column-vector\n\
-arguments of equal length, or one column vector argument and a scalar.\n\
+The binary singleton expansion function applier does what its name\n\
+suggests: applies a binary function @var{f} element-by-element to two\n\
+array arguments @var{A} and @var{B}, and expands as necessary\n\
+singleton dimensions in either input argument. @var{f} is a function\n\
+handle, inline function, or string containing the name of the function\n\
+to evaluate. The function @var{f} must be capable of accepting two\n\
+column-vector arguments of equal length, or one column vector argument\n\
+and a scalar.\n\
 \n\
-The dimensions of @var{A} and @var{B} must be equal or singleton.  The\n\
-singleton dimensions of the matrices will be expanded to the same\n\
-dimensionality as the other matrix.\n\
+The dimensions of @var{A} and @var{B} must be equal or singleton. The\n\
+singleton dimensions of the arrays will be expanded to the same\n\
+dimensionality as the other array.\n\
 @seealso{arrayfun, cellfun}\n\
 @end deftypefn")
 {
@@ -766,4 +769,45 @@
 %!assert (bsxfun (@max, a, b), max (aa, bb));
 %!assert (bsxfun (@and, a > 0, b > 0), (aa > 0) & (bb > 0));
 %!assert (bsxfun (@or, a > 0, b > 0), (aa > 0) | (bb > 0));
+
+%% Test automatic bsxfun
+%
+%!test
+%! funs = {@plus, @minus, @times, @rdivide, @ldivide, @power, @max, @min, \
+%!         @rem, @mod, @atan2, @hypot, @eq, @ne, @lt, @le, @gt, @ge, \
+%!         @and, @or, @xor };
+%!
+%! float_types = {@single, @double};
+%! int_types = {@int8, @int16, @int32, @int64, \
+%!             @uint8, @uint16, @uint32, @uint64};
+%!
+%! x = rand (3)*10-5;
+%! y = rand (3,1)*10-5;
+%!
+%! for i=1:length (funs)
+%!   for j = 1:length(float_types)
+%!     for k = 1:length(int_types)
+%!
+%!       fun = funs{i};
+%!       f_type = float_types{j};
+%!       i_type = int_types{k};
+%!
+%!         assert (bsxfun (fun, f_type (x), i_type (y)), \
+%!                 fun (f_type(x), i_type (y)));
+%!         assert (bsxfun (fun, f_type (y), i_type (x)), \
+%!                 fun (f_type(y), i_type (x)));
+%!
+%!         assert (bsxfun (fun, i_type (x), i_type (y)), \
+%!                 fun (i_type (x), i_type (y)));
+%!         assert (bsxfun (fun, i_type (y), i_type (x)), \
+%!                 fun (i_type (y), i_type (x)));
+%!
+%!         assert (bsxfun (fun, f_type (x), f_type (y)), \
+%!                 fun (f_type (x), f_type (y)));
+%!         assert (bsxfun (fun, f_type(y), f_type(x)), \
+%!                 fun (f_type (y), f_type (x)));
+%!     endfor
+%!   endfor
+%! endfor
+%!
 */
--- a/src/DLD-FUNCTIONS/cellfun.cc
+++ b/src/DLD-FUNCTIONS/cellfun.cc
@@ -58,6 +58,8 @@
 #include "ov-uint32.h"
 #include "ov-uint64.h"
 
+#include "ov-fcn-handle.h"
+
 static octave_value_list
 get_output_list (octave_idx_type count, octave_idx_type nargout,
                  const octave_value_list& inputlist,
@@ -122,8 +124,10 @@
 @item ndims\n\
 Return the number of dimensions of each element.\n\
 \n\
-@item prodofsize\n\
-Return the product of dimensions of each element.\n\
+@item numel\n\
+@itemx prodofsize\n\
+Return the number of elements contained within each cell element.  The\n\
+number is the product of the dimensions of the object at each cell element.\n\
 \n\
 @item size\n\
 Return the size along the @var{k}-th dimension.\n\
@@ -142,7 +146,7 @@
 \n\
 @example\n\
 @group\n\
-cellfun (@@atan2, @{1, 0@}, @{0, 1@})\n\
+cellfun (\"atan2\", @{1, 0@}, @{0, 1@})\n\
      @result{}ans = [1.57080   0.00000]\n\
 @end group\n\
 @end example\n\
@@ -177,7 +181,7 @@
 \n\
 @example\n\
 @group\n\
-cellfun (\"tolower(x)\", @{\"Foo\", \"Bar\", \"FooBar\"@},\n\
+cellfun (\"tolower\", @{\"Foo\", \"Bar\", \"FooBar\"@},\n\
          \"UniformOutput\",false)\n\
 @result{} ans = @{\"foo\", \"bar\", \"foobar\"@}\n\
 @end group\n\
@@ -200,7 +204,7 @@
 @example\n\
 @group\n\
 function y = foo (s, x), y = NaN; endfunction\n\
-cellfun (@@factorial, @{-1,2@},'ErrorHandler',@@foo)\n\
+cellfun (\"factorial\", @{-1,2@}, 'ErrorHandler', @@foo)\n\
 @result{} ans = [NaN 2]\n\
 @end group\n\
 @end example\n\
@@ -220,6 +224,7 @@
     }
 
   octave_value func = args(0);
+  bool symbol_table_lookup = false;
 
   if (! args(1).is_cell ())
     {
@@ -337,6 +342,8 @@
               func = symbol_table::find_function (name);
               if (func.is_undefined ())
                 error ("cellfun: invalid function NAME: %s", name.c_str ());
+
+              symbol_table_lookup = true;
             }
         }
     }
@@ -347,6 +354,30 @@
   if (func.is_function_handle () || func.is_inline_function ()
       || func.is_function ())
     {
+
+      // The following is an optimisation because the symbol table can
+      // give a more specific function class, so this can result in
+      // fewer polymorphic function calls as the function gets called
+      // for each value of the array.
+      if (! symbol_table_lookup )
+        {
+          if (func.is_function_handle ())
+            {
+              octave_fcn_handle* f = func.fcn_handle_value ();
+
+              // Overloaded function handles need to check the type of
+              // the arguments for each element of the array, so they
+              // cannot be optimised this way.
+              if (f -> is_overloaded ())
+                goto nevermind;
+            }
+          octave_value f = symbol_table::find_function (func.function_value ()
+                                                         -> name ());
+          if (f.is_defined ())
+            func = f;
+        }
+      nevermind:
+
       unwind_protect frame;
       frame.protect_var (buffer_error_messages);
 
--- a/src/DLD-FUNCTIONS/chol.cc
+++ b/src/DLD-FUNCTIONS/chol.cc
@@ -493,9 +493,6 @@
 %!testif HAVE_CHOLMOD
 %! Ainv3 = cholinv(sparse(A));
 %! assert (norm(Ainv-Ainv3),0,1e-10)
-%!testif HAVE_CHOLMOD
-%! Ainv4 = spcholinv(sparse(A));
-%! assert (norm(Ainv-Ainv4),0,1e-10)
 
 */
 
--- a/src/DLD-FUNCTIONS/config-module.awk
+++ b/src/DLD-FUNCTIONS/config-module.awk
@@ -1,4 +1,7 @@
 BEGIN {
+  FS = "|";
+  nfiles = 0;
+
   print "## DO NOT EDIT -- generated from module-files by config-module.awk";
   print ""
   print "EXTRA_DIST += \\"
@@ -6,9 +9,14 @@
   print "  DLD-FUNCTIONS/config-module.awk \\"
   print "  DLD-FUNCTIONS/module-files"
   print ""
-  nfiles = 0;
-} {
-  files[++nfiles] = $1;
+}
+/^#.*/ { next; }
+{
+  nfiles++;
+  files[nfiles] = $1;
+  cppflags[nfiles] = $2;
+  ldflags[nfiles] = $3;
+  libraries[nfiles] = $4;
 } END {
   sep = " \\\n";
   print "DLD_FUNCTIONS_SRC = \\";
@@ -22,9 +30,9 @@
   sep = " \\\n";
   print "DLD_FUNCTIONS_LIBS = $(DLD_FUNCTIONS_SRC:.cc=.la)";
   print "";
-  print "octlib_LTLIBRARIES += $(DLD_FUNCTIONS_LIBS)";
+  print "if AMCOND_ENABLE_DYNAMIC_LINKING";
   print "";
-  print "if AMCOND_ENABLE_DYNAMIC_LINKING";
+  print "octlib_LTLIBRARIES += $(DLD_FUNCTIONS_LIBS)";
   print "";
   print "## Use stamp files to avoid problems with checking timestamps";
   print "## of symbolic links";
@@ -41,18 +49,28 @@
     print "\t  touch $(@F)";
     print "";
   }
+  print "else";
+  print "";
+  print "noinst_LTLIBRARIES = $(DLD_FUNCTIONS_LIBS)";
+  print "";
   print "endif";
-  print "";
 
   for (i = 1; i <= nfiles; i++) {
     basename = files[i];
     sub (/\.cc$/, "", basename);
+    print "";
     printf ("DLD_FUNCTIONS_%s_la_SOURCES = DLD-FUNCTIONS/%s\n",
 	    basename, files[i]);
-    printf ("DLD_FUNCTIONS_%s_la_LDFLAGS = @NO_UNDEFINED_LDFLAG@ -module\n",
-	    basename);
-    printf ("DLD_FUNCTIONS_%s_la_LIBADD = $(OCT_LINK_DEPS)\n", basename);
+    if (cppflags[i])
+      {
+        printf ("DLD-FUNCTIONS/%s.df: CPPFLAGS += %s\n",
+                basename, cppflags[i]);
+        printf ("DLD_FUNCTIONS_%s_la_CPPFLAGS = $(AM_CPPFLAGS) %s\n",
+                basename, cppflags[i]);
+      }
+    printf ("DLD_FUNCTIONS_%s_la_LDFLAGS = -avoid-version -module $(NO_UNDEFINED_LDFLAG) %s $(OCT_LINK_OPTS)\n",
+            basename, ldflags[i]);
+    printf ("DLD_FUNCTIONS_%s_la_LIBADD = liboctinterp.la ../liboctave/liboctave.la ../libcruft/libcruft.la %s $(OCT_LINK_DEPS)\n",
+            basename, libraries[i]);
   }
-  print "";
-
 }
--- a/src/DLD-FUNCTIONS/dot.cc
+++ b/src/DLD-FUNCTIONS/dot.cc
@@ -238,6 +238,17 @@
 
 /*
 
+%! assert(dot ([1, 2], [2, 3]), 11);
+
+%!test
+%! x = [2, 1; 2, 1];
+%! y = [-0.5, 2; 0.5, -2];
+%! assert(dot (x, y), [0 0]);
+
+%!test
+%! x = [ 1+i, 3-i; 1-i, 3-i];
+%! assert(dot (x, x), [4, 20]);
+
 */
 
 DEFUN_DLD (blkmm, args, ,
@@ -344,3 +355,14 @@
 
   return retval;
 }
+
+/*
+
+%!test
+%! x(:,:,1) = [1 2; 3 4];
+%! x(:,:,2) = [1 1; 1 1];
+%! z(:,:,1) = [7 10; 15 22];
+%! z(:,:,2) = [2 2; 2 2];
+%! assert(blkmm (x,x),z);
+
+*/
--- a/src/DLD-FUNCTIONS/eigs.cc
+++ b/src/DLD-FUNCTIONS/eigs.cc
@@ -323,6 +323,7 @@
   bool a_is_complex = false;
   bool b_is_complex = false;
   bool symmetric = false;
+  bool sym_tested = false;
   bool cholB = false;
   bool a_is_sparse = false;
   ColumnVector permB;
@@ -399,7 +400,8 @@
           else
             acm = (args(0).complex_matrix_value());
           a_is_complex = true;
-          symmetric = false; // ARAPACK doesn't special case complex symmetric
+          symmetric = false; // ARPACK doesn't special case complex symmetric
+          sym_tested = true;
         }
       else
         {
@@ -407,19 +409,17 @@
             {
               asmm = (args(0).sparse_matrix_value());
               a_is_sparse = true;
-              symmetric = asmm.is_symmetric();
             }
           else
             {
               amm = (args(0).matrix_value());
-              symmetric = amm.is_symmetric();
             }
         }
 
     }
 
   // Note hold off reading B till later to avoid issues of double
-  // copies of the matrix if B is full/real while A is complex..
+  // copies of the matrix if B is full/real while A is complex.
   if (!error_state && nargin > 1 + arg_offset &&
       !(args(1 + arg_offset).is_real_scalar ()))
     {
@@ -481,10 +481,13 @@
             {
               octave_value tmp;
 
-              // issym is ignored if A is not a function
+              // issym is ignored for complex matrix inputs
               tmp = map.getfield ("issym");
-              if (tmp.is_defined () && have_a_fun)
-                symmetric = tmp.double_value () != 0.;
+              if (tmp.is_defined () && !sym_tested)
+                {
+                  symmetric = tmp.double_value () != 0.;
+                  sym_tested = true;
+                }
 
               // isreal is ignored if A is not a function
               tmp = map.getfield ("isreal");
@@ -543,6 +546,15 @@
       return retval;
     }
 
+  // Test undeclared (no issym) matrix inputs for symmetry
+  if (!sym_tested && !have_a_fun)
+    {
+      if (a_is_sparse)
+        symmetric = asmm.is_symmetric();
+      else
+        symmetric = amm.is_symmetric();
+    }
+
   if (have_b)
     {
       if (a_is_complex || b_is_complex)
--- a/src/DLD-FUNCTIONS/filter.cc
+++ b/src/DLD-FUNCTIONS/filter.cc
@@ -104,16 +104,17 @@
       return y;
     }
 
-  octave_idx_type si_dim = 0;
-  for (octave_idx_type i = 0; i < x_dims.length (); i++)
+  for (octave_idx_type i = 1; i < dim; i++)
     {
-      if (i == dim)
-        continue;
-
-      if (x_dims(i) == 1)
-        continue;
-
-      if (si_dims(++si_dim) != x_dims(i))
+      if (si_dims(i) != x_dims(i-1))
+        {
+          error ("filter: dimensionality of SI and X must agree");
+          return y;
+        }
+    }
+  for (octave_idx_type i = dim+1; i < x_dims.length (); i++)
+    {
+      if (si_dims(i) != x_dims(i))
         {
           error ("filter: dimensionality of SI and X must agree");
           return y;
@@ -456,19 +457,10 @@
                 }
               else
                 {
-                  dim_vector si_dims = args (3).dims ();
-                  bool si_is_vector = true;
-                  for (int i = 0; i < si_dims.length (); i++)
-                    if (si_dims(i) != 1 && si_dims(i) < si_dims.numel ())
-                      {
-                        si_is_vector = false;
-                        break;
-                      }
-
                   si = args(3).float_complex_array_value ();
 
-                  if (si_is_vector)
-                    si = si.reshape (dim_vector (1, si.numel ()));
+                  if (si.is_vector () && x.is_vector ())
+                    si = si.reshape (dim_vector (si.numel (), 1));
                 }
 
               if (! error_state)
@@ -513,19 +505,10 @@
                 }
               else
                 {
-                  dim_vector si_dims = args (3).dims ();
-                  bool si_is_vector = true;
-                  for (int i = 0; i < si_dims.length (); i++)
-                    if (si_dims(i) != 1 && si_dims(i) < si_dims.numel ())
-                      {
-                        si_is_vector = false;
-                        break;
-                      }
-
                   si = args(3).complex_array_value ();
 
-                  if (si_is_vector)
-                    si = si.reshape (dim_vector (1, si.numel ()));
+                  if (si.is_vector () && x.is_vector ())
+                    si = si.reshape (dim_vector (si.numel (), 1));
                 }
 
               if (! error_state)
@@ -573,19 +556,10 @@
                 }
               else
                 {
-                  dim_vector si_dims = args (3).dims ();
-                  bool si_is_vector = true;
-                  for (int i = 0; i < si_dims.length (); i++)
-                    if (si_dims(i) != 1 && si_dims(i) < si_dims.numel ())
-                      {
-                        si_is_vector = false;
-                        break;
-                      }
-
                   si = args(3).float_array_value ();
 
-                  if (si_is_vector)
-                    si = si.reshape (dim_vector (1, si.numel ()));
+                  if (si.is_vector () && x.is_vector ())
+                    si = si.reshape (dim_vector (si.numel (), 1));
                 }
 
               if (! error_state)
@@ -630,19 +604,10 @@
                 }
               else
                 {
-                  dim_vector si_dims = args (3).dims ();
-                  bool si_is_vector = true;
-                  for (int i = 0; i < si_dims.length (); i++)
-                    if (si_dims(i) != 1 && si_dims(i) < si_dims.numel ())
-                      {
-                        si_is_vector = false;
-                        break;
-                      }
-
                   si = args(3).array_value ();
 
-                  if (si_is_vector)
-                    si = si.reshape (dim_vector (1, si.numel ()));
+                  if (si.is_vector () && x.is_vector ())
+                    si = si.reshape (dim_vector (si.numel (), 1));
                 }
 
               if (! error_state)
@@ -749,8 +714,20 @@
 %!
 %!assert(filter (1, ones(10,1)/10, []), []);
 %!assert(filter (1, ones(10,1)/10, zeros(0,10)), zeros(0,10));
+%!assert(filter (1, ones(10,1)/10, single (1:5)), repmat (single (10), 1, 5));
+%% Test using initial conditions
+%!assert(filter([1, 1, 1], [1, 1], [1 2], [1, 1]), [2 2]);
+%!assert(filter([1, 1, 1], [1, 1], [1 2], [1, 1]'), [2 2]);
 %!assert(filter([1, 3], [1], [1 2; 3 4; 5 6], [4, 5]), [5 7; 6 10; 14 18]);
-%!assert(filter (1, ones(10,1)/10, single (1:5)), repmat (single (10), 1, 5));
-%%  Should put some tests of the "DIM" parameter in here.
+%!error (filter([1, 3], [1], [1 2; 3 4; 5 6], [4, 5]'));
+%!assert(filter([1, 3, 2], [1], [1 2; 3 4; 5 6], [1 0 0; 1 0 0], 2), [2 6; 3 13; 5 21]);
+%% Test of DIM parameter
+%!test
+%! x = ones (2, 1, 3, 4);
+%! x(1,1,:,:) = [1 2 3 4; 5 6 7 8; 9 10 11 12];
+%! y0 = [1 1 6 2 15 3 2 1 8 2 18 3 3 1 10 2 21 3 4 1 12 2 24 3];
+%! y0 = reshape (y0, size (x));
+%! y = filter([1 1 1], 1, x, [], 3); 
+%! assert (y, y0);
 
 */
--- a/src/DLD-FUNCTIONS/givens.cc
+++ b/src/DLD-FUNCTIONS/givens.cc
@@ -203,3 +203,13 @@
 
   return retval;
 }
+
+/*
+
+%!assert (givens (1,1), [1, 1; -1, 1]/sqrt(2), 2*eps);
+%!assert (givens (1,0), eye(2));
+%!assert (givens (0,1), [0, 1; -1 0]);
+%!error givens(1);
+%!error givens()
+
+*/
--- a/src/DLD-FUNCTIONS/kron.cc
+++ b/src/DLD-FUNCTIONS/kron.cc
@@ -264,3 +264,15 @@
 
   return retval;
 }
+
+/*
+
+%!test
+%! x = ones(2);
+%! assert( kron (x, x), ones (4));
+
+%!test
+%! z =  [1,  2,  3,  4; 1,  2,  3,  4; 1,  2,  3,  4];
+%! assert( kron (1:4, ones (3, 1)), z)
+
+*/
--- a/src/DLD-FUNCTIONS/module-files
+++ b/src/DLD-FUNCTIONS/module-files
@@ -1,40 +1,41 @@
+# FILE|CPPFLAGS|LDFLAGS|LIBRARIES
 __contourc__.cc
-__delaunayn__.cc
+__delaunayn__.cc|$(QHULL_CPPFLAGS)|$(QHULL_LDFLAGS)|$(QHULL_LIBS)
 __dispatch__.cc
 __dsearchn__.cc
-__fltk_uigetfile__.cc
-__glpk__.cc
-__init_fltk__.cc
+__fltk_uigetfile__.cc|$(GRAPHICS_CFLAGS) $(FT2_CPPFLAGS)|$(GRAPHICS_LDFLAGS) $(FT2_LDFLAGS)|$(GRAPHICS_LIBS) $(FT2_LIBS)
+__glpk__.cc|$(GLPK_CPPFLAGS)|$(GLPK_LDFLAGS)|$(GLPK_LIBS)
+__init_fltk__.cc|$(GRAPHICS_CFLAGS) $(FT2_CPPFLAGS)|$(GRAPHICS_LDFLAGS) $(FT2_LDFLAGS)|$(GRAPHICS_LIBS) $(FT2_LIBS)
 __lin_interpn__.cc
-__magick_read__.cc
+__magick_read__.cc|$(MAGICK_CPPFLAGS)|$(MAGICK_LDFLAGS)|$(MAGICK_LIBS)
 __pchip_deriv__.cc
 __qp__.cc
-__voronoi__.cc
-amd.cc
+__voronoi__.cc|$(QHULL_CPPFLAGS)|$(QHULL_LDFLAGS)|$(QHULL_LIBS)
+amd.cc|$(SPARSE_XCPPFLAGS)|$(SPARSE_XLDFLAGS)|$(SPARSE_XLIBS)
 balance.cc
 besselj.cc
 betainc.cc
 bsxfun.cc
-ccolamd.cc
+ccolamd.cc|$(SPARSE_XCPPFLAGS)|$(SPARSE_XLDFLAGS)|$(SPARSE_XLIBS)
 cellfun.cc
-chol.cc
-colamd.cc
+chol.cc|$(QRUPDATE_CPPFLAGS) $(SPARSE_XCPPFLAGS)|$(QRUPDATE_LDFLAGS) $(SPARSE_XLDFLAGS)|$(QRUPDATE_LIBS) $(SPARSE_XLIBS)
+colamd.cc|$(SPARSE_XCPPFLAGS)|$(SPARSE_XLDFLAGS)|$(SPARSE_XLIBS)
 colloc.cc
 conv2.cc
-convhulln.cc
+convhulln.cc|$(QHULL_CPPFLAGS)|$(QHULL_LDFLAGS)|$(QHULL_LIBS)
 daspk.cc
 dasrt.cc
 dassl.cc
 det.cc
 dlmread.cc
-dmperm.cc
+dmperm.cc|$(SPARSE_XCPPFLAGS)|$(SPARSE_XLDFLAGS)|$(SPARSE_XLIBS)
 dot.cc
 eig.cc
-eigs.cc
-fft.cc
-fft2.cc
-fftn.cc
-fftw.cc
+eigs.cc|$(SPARSE_XCPPFLAGS)|$(SPARSE_XLDFLAGS)|$(SPARSE_XLIBS) $(LAPACK_LIBS) $(BLAS_LIBS)
+fft.cc|$(FFTW_XCPPFLAGS)|$(FFTW_XLDFLAGS)|$(FFTW_XLIBS)
+fft2.cc|$(FFTW_XCPPFLAGS)|$(FFTW_XLDFLAGS)|$(FFTW_XLIBS)
+fftn.cc|$(FFTW_XCPPFLAGS)|$(FFTW_XLDFLAGS)|$(FFTW_XLIBS)
+fftw.cc|$(FFTW_XCPPFLAGS)|$(FFTW_XLDFLAGS)|$(FFTW_XLIBS)
 filter.cc
 find.cc
 gammainc.cc
@@ -58,13 +59,13 @@
 nproc.cc
 onCleanup.cc
 pinv.cc
-qr.cc
+qr.cc|$(QRUPDATE_CPPFLAGS) $(SPARSE_XCPPFLAGS)|$(QRUPDATE_LDFLAGS) $(SPARSE_XLDFLAGS)|$(QRUPDATE_LIBS) $(SPARSE_XLIBS)
 quad.cc
 quadcc.cc
-qz.cc
+qz.cc|||$(LAPACK_LIBS) $(BLAS_LIBS)
 rand.cc
 rcond.cc
-regexp.cc
+regexp.cc|$(REGEX_CPPFLAGS)|$(REGEX_LDFLAGS)|$(REGEX_LIBS)
 schur.cc
 spparms.cc
 sqrtm.cc
@@ -73,10 +74,10 @@
 sub2ind.cc
 svd.cc
 syl.cc
-symbfact.cc
-symrcm.cc
+symbfact.cc|$(SPARSE_XCPPFLAGS)|$(SPARSE_XLDFLAGS)|$(SPARSE_XLIBS)
+symrcm.cc|$(SPARSE_XCPPFLAGS)|$(SPARSE_XLDFLAGS)|$(SPARSE_XLIBS)
 time.cc
 tril.cc
 tsearch.cc
 typecast.cc
-urlwrite.cc
+urlwrite.cc|$(CURL_CPPFLAGS)|$(CURL_LDFLAGS)|$(CURL_LIBS)
--- a/src/DLD-FUNCTIONS/qr.cc
+++ b/src/DLD-FUNCTIONS/qr.cc
@@ -76,6 +76,8 @@
   "-*- texinfo -*-\n\
 @deftypefn  {Loadable Function} {[@var{Q}, @var{R}, @var{P}] =} qr (@var{A})\n\
 @deftypefnx {Loadable Function} {[@var{Q}, @var{R}, @var{P}] =} qr (@var{A}, '0')\n\
+@deftypefnx {Loadable Function} {[@var{C}, @var{R}] =} qr (@var{A}, @var{B})\n\
+@deftypefnx {Loadable Function} {[@var{C}, @var{R}] =} qr (@var{A}, @var{B}, '0')\n\
 @cindex QR factorization\n\
 Compute the QR@tie{}factorization of @var{A}, using standard @sc{lapack}\n\
 subroutines.  For example, given the matrix @code{@var{A} = [1, 2; 3, 4]},\n\
@@ -188,7 +190,7 @@
 \n\
 @example\n\
 @group\n\
-[@var{C},@var{R}] = spqr (@var{A},@var{B})\n\
+[@var{C}, @var{R}] = qr (@var{A}, @var{B})\n\
 x = @var{R} \\ @var{C}\n\
 @end group\n\
 @end example\n\
--- a/src/DLD-FUNCTIONS/quadcc.cc
+++ b/src/DLD-FUNCTIONS/quadcc.cc
@@ -50,8 +50,7 @@
   int depth, rdepth, ndiv;
 } cquad_ival;
 
-/* Some constants and matrices that we'll need.
-    */
+/* Some constants and matrices that we'll need.  */
 
 static const double xi[33] = {
   -1., -0.99518472667219688624, -0.98078528040323044912,
@@ -1473,9 +1472,7 @@
 }
 
 
-
-/* The actual integration routine.
-    */
+/* The actual integration routine.  */
 
 DEFUN_DLD (quadcc, args, nargout,
 "-*- texinfo -*-\n\
@@ -1545,6 +1542,7 @@
 @seealso{quad, quadv, quadl, quadgk, trapz, dblquad, triplequad}\n\
 @end deftypefn")
 {
+  octave_value_list retval;
 
   /* Some constants that we will need. */
   static const int n[4] = { 4, 8, 16, 32 };
@@ -1563,11 +1561,11 @@
   double a, b, tol, iivals[cquad_heapsize], *sing;
 
   /* Variables needed for transforming the integrand. */
-  int wrap = 0;
+  bool wrap = false;
   double xw;
 
   /* Stuff we will need to call the integrand. */
-  octave_value_list fargs, retval;
+  octave_value_list fargs, fvals;
 
   /* Actual variables (as opposed to constants above). */
   double m, h, ml, hl, mr, hr, temp;
@@ -1580,48 +1578,49 @@
 
 
   /* Parse the input arguments. */
-  if (nargin < 1)
+  if (nargin < 3)
     {
-      error
-        ("quadcc: first argument (integrand) of type function handle required");
-      return octave_value_list ();
+      print_usage ();
+      return retval;
     }
+
+  if (args(0).is_function_handle () || args(0).is_inline_function ())
+    fcn = args(0).function_value ();
   else
     {
-      if (args (0).is_function_handle () || args (0).is_inline_function ())
-        fcn = args (0).function_value ();
-      else
-        {
-          error ("quadcc: first argument (integrand) must be a function handle or an inline function");
-          return octave_value_list();
-        }
+       std::string fcn_name = unique_symbol_name ("__quadcc_fcn_");
+       std::string fname = "function y = ";
+       fname.append (fcn_name);
+       fname.append ("(x) y = ");
+       fcn = extract_function (args(0), "quadcc", fcn_name, fname,
+                               "; endfunction");
     }
 
-  if (nargin < 2 || !args (1).is_real_scalar ())
+  if (!args(1).is_real_scalar ())
     {
-      error ("quadcc: second argument (left interval edge) must be a single real scalar");
-      return octave_value_list ();
+      error ("quadcc: lower limit of integration (A) must be a single real scalar");
+      return retval;
     }
   else
-    a = args (1).double_value ();
+    a = args(1).double_value ();
 
-  if (nargin < 3 || !args (2).is_real_scalar ())
+  if (!args(2).is_real_scalar ())
     {
-      error ("quadcc: third argument (right interval edge) must be a single real scalar");
-      return octave_value_list ();
+      error ("quadcc: upper limit of integration (B) must be a single real scalar");
+      return retval;
     }
   else
-    b = args (2).double_value ();
+    b = args(2).double_value ();
 
-  if (nargin < 4)
+  if (nargin < 4 || args(3).is_empty ())
     tol = 1.0e-6;
-  else if (!args (3).is_real_scalar ())
+  else if (!args(3).is_real_scalar () || args(3).double_value () <= 0)
     {
-      error ("quadcc: fourth argument (tolerance) must be a single real scalar");
-      return octave_value_list ();
+      error ("quadcc: tolerance (TOL) must be a single real scalar > 0");
+      return retval;
     }
   else
-    tol = args (3).double_value ();
+    tol = args(3).double_value ();
 
   if (nargin < 5)
     {
@@ -1629,20 +1628,21 @@
       iivals[0] = a;
       iivals[1] = b;
     }
-  else if (!(args (4).is_real_scalar () || args (4).is_real_matrix ()))
+  else if (!(args(4).is_real_scalar () || args(4).is_real_matrix ()))
     {
-      error ("quadcc: fifth argument (singularities) must be a vector of real values");
-      return octave_value_list ();
+      error ("quadcc: list of singularities (SING) must be a vector of real values");
+      return retval;
     }
   else
     {
-      nivals = 1 + args (4).length ();
-      if ( nivals > cquad_heapsize ) {
-        error ("quadcc: maximum number of singular points is limited to %i",
-               cquad_heapsize-1);
-        return octave_value_list();
+      nivals = 1 + args(4).length ();
+      if (nivals > cquad_heapsize) 
+        {
+          error ("quadcc: maximum number of singular points is limited to %i",
+                 cquad_heapsize-1);
+          return retval;
         }
-      sing = args (4).array_value ().fortran_vec ();
+      sing = args(4).array_value ().fortran_vec ();
       iivals[0] = a;
       for (i = 0; i < nivals - 2; i++)
         iivals[i + 1] = sing[i];
@@ -1652,7 +1652,7 @@
   /* If a or b are +/-Inf, transform the integral. */
   if (xisinf (a) || xisinf (b))
     {
-      wrap = 1;
+      wrap = true;
       for (i = 0; i <= nivals; i++)
         if (xisinf (iivals[i]))
           iivals[i] = copysign (1.0, iivals[i]);
@@ -1688,19 +1688,18 @@
           for (i = 0; i <= n[3]; i++)
             ex (i) = m + xi[i] * h;
         }
-      fargs (0) = ex;
-      retval = feval (fcn, fargs, 1);
-      if (retval.length () != 1 || !retval (0).is_real_matrix ())
+      fargs(0) = ex;
+      fvals = feval (fcn, fargs, 1);
+      if (fvals.length () != 1 || !fvals(0).is_real_matrix ())
         {
-          error
-            ("quadcc: integrand must return a single, real-valued vector");
-          return octave_value_list ();
+          error ("quadcc: integrand F must return a single, real-valued vector");
+          return retval;
         }
-      Matrix effex = retval (0).matrix_value ();
+      Matrix effex = fvals(0).matrix_value ();
       if (effex.length () != ex.length ())
         {
-          error ("quadcc: integrand must return a single, real-valued vector of the same size as the input");
-          return octave_value_list ();
+          error ("quadcc: integrand F must return a single, real-valued vector of the same size as the input");
+          return retval;
         }
       for (i = 0; i <= n[3]; i++)
         {
@@ -1809,18 +1808,18 @@
                 for (i = 0; i < n[d] / 2; i++)
                   ex (i) = m + xi[(2 * i + 1) * skip[d]] * h;
               }
-            fargs (0) = ex;
-            retval = feval (fcn, fargs, 1);
-            if (retval.length () != 1 || !retval (0).is_real_matrix ())
+            fargs(0) = ex;
+            fvals = feval (fcn, fargs, 1);
+            if (fvals.length () != 1 || !fvals(0).is_real_matrix ())
               {
-                error ("quadcc: integrand must return a single, real-valued vector");
-                return octave_value_list ();
+                error ("quadcc: integrand F must return a single, real-valued vector");
+                return retval;
               }
-            Matrix effex = retval (0).matrix_value ();
+            Matrix effex = fvals(0).matrix_value ();
             if (effex.length () != ex.length ())
               {
-                error ("quadcc: integrand must return a single, real-valued vector of the same size as the input");
-                return octave_value_list ();
+                error ("quadcc: integrand F must return a single, real-valued vector of the same size as the input");
+                return retval;
               }
             neval += effex.length ();
             for (i = 0; i < n[d] / 2; i++)
@@ -1957,18 +1956,18 @@
                 for (i = 0; i < n[0] - 1; i++)
                   ex (i) = ml + xi[(i + 1) * skip[0]] * hl;
               }
-            fargs (0) = ex;
-            retval = feval (fcn, fargs, 1);
-            if (retval.length () != 1 || !retval (0).is_real_matrix ())
+            fargs(0) = ex;
+            fvals = feval (fcn, fargs, 1);
+            if (fvals.length () != 1 || !fvals(0).is_real_matrix ())
               {
-                error ("quadcc: integrand must return a single, real-valued vector");
-                return octave_value_list ();
+                error ("quadcc: integrand F must return a single, real-valued vector");
+                return retval;
               }
-            Matrix effex = retval (0).matrix_value ();
+            Matrix effex = fvals(0).matrix_value ();
             if (effex.length () != ex.length ())
               {
-                error ("quadcc: integrand must return a single, real-valued vector of the same size as the input");
-                return octave_value_list ();
+                error ("quadcc: integrand F must return a single, real-valued vector of the same size as the input");
+                return retval;
               }
             neval += effex.length ();
             for (i = 0; i < n[0] - 1; i++)
@@ -2053,18 +2052,18 @@
                 for (i = 0; i < n[0] - 1; i++)
                   ex (i) = mr + xi[(i + 1) * skip[0]] * hr;
               }
-            fargs (0) = ex;
-            retval = feval (fcn, fargs, 1);
-            if (retval.length () != 1 || !retval (0).is_real_matrix ())
+            fargs(0) = ex;
+            fvals = feval (fcn, fargs, 1);
+            if (fvals.length () != 1 || !fvals(0).is_real_matrix ())
               {
-                error ("quadcc: integrand must return a single, real-valued vector");
-                return octave_value_list ();
+                error ("quadcc: integrand F must return a single, real-valued vector");
+                return retval;
               }
-            Matrix effex = retval (0).matrix_value ();
+            Matrix effex = fvals(0).matrix_value ();
             if (effex.length () != ex.length ())
               {
-                error ("quadcc: integrand must return a single, real-valued vector of the same size as the input");
-                return octave_value_list ();
+                error ("quadcc: integrand F must return a single, real-valued vector of the same size as the input");
+                return retval;
               }
             neval += effex.length ();
             for (i = 0; i < n[0] - 1; i++)
@@ -2234,11 +2233,39 @@
     }
 */
   /* Clean up and present the results. */
-  retval (0) = igral;
+  if (nargout > 2)
+    retval(2) = neval;
   if (nargout > 1)
-    retval (1) = err;
-  if (nargout > 2)
-    retval (2) = neval;
+    retval(1) = err;
+  retval(0) = igral;
   /* All is well that ends well. */
   return retval;
 }
+
+
+/* 
+
+%!assert (quadcc(@sin,-pi,pi), 0, 1e-6)
+%!assert (quadcc(inline('sin'),-pi,pi), 0, 1e-6)
+%!assert (quadcc('sin',-pi,pi), 0, 1e-6)
+
+%!assert (quadcc(@sin,-pi,0), -2, 1e-6)
+%!assert (quadcc(@sin,0,pi), 2, 1e-6)
+%!assert (quadcc(@(x) 1./sqrt(x), 0, 1), 2, 1e-6)
+%!assert (quadcc(@(x) 1./(sqrt(x).*(x+1)), 0, Inf), pi, 1e-6)
+
+%!assert (quadcc (@(x) exp(-x .^ 2), -Inf, Inf), sqrt(pi), 1e-6)
+%!assert (quadcc (@(x) exp(-x .^ 2), -Inf, 0), sqrt(pi)/2, 1e-6)
+
+%% Test input validation
+%!error (quadcc ())
+%!error (quadcc (@sin))
+%!error (quadcc (@sin, 0))
+%!error (quadcc (@sin, ones(2), pi))
+%!error (quadcc (@sin, -i, pi))
+%!error (quadcc (@sin, 0, ones(2)))
+%!error (quadcc (@sin, 0, i))
+%!error (quadcc (@sin, 0, pi, 0))
+%!error (quadcc (@sin, 0, pi, 1e-6, [ i ]))
+
+*/
--- a/src/DLD-FUNCTIONS/rand.cc
+++ b/src/DLD-FUNCTIONS/rand.cc
@@ -177,20 +177,17 @@
 
                 octave_idx_type base = NINTbig (r.base ());
                 octave_idx_type incr = NINTbig (r.inc ());
-                octave_idx_type lim = NINTbig (r.limit ());
 
-                if (base < 0 || lim < 0)
-                  error ("%s: all dimensions must be positive", fcn);
-                else
+                for (octave_idx_type i = 0; i < n; i++)
                   {
-                    for (octave_idx_type i = 0; i < n; i++)
-                      {
-                        dims(i) = base;
-                        base += incr;
-                      }
+                    //Negative dimensions are treated as zero for Matlab
+                    //compatibility
+                    dims(i) = base >= 0 ? base : 0;
+                    base += incr;
+                  }
 
-                    goto gen_matrix;
-                  }
+                goto gen_matrix;
+
               }
             else
               error ("%s: all elements of range must be integers",
@@ -208,15 +205,10 @@
 
                 for (octave_idx_type i = 0; i < len; i++)
                   {
+                    //Negative dimensions are treated as zero for Matlab
+                    //compatibility
                     octave_idx_type elt = iv(i);
-
-                    if (elt < 0)
-                      {
-                        error ("%s: all dimensions must be positive", fcn);
-                        goto done;
-                      }
-
-                    dims(i) = iv(i);
+                    dims(i) = elt >=0 ? elt : 0;
                   }
 
                 goto gen_matrix;
@@ -278,13 +270,14 @@
 
             for (int i = 0; i < nargin; i++)
               {
-                dims(i) = args(idx+i).int_value ();
-
+                octave_idx_type elt = args(idx+i).int_value ();
                 if (error_state)
                   {
                     error ("%s: expecting integer arguments", fcn);
                     goto done;
                   }
+                //Negative is zero for Matlab compatibility
+                dims(i) = elt >= 0 ? elt : 0;
               }
 
             goto gen_matrix;
--- a/src/DLD-FUNCTIONS/rcond.cc
+++ b/src/DLD-FUNCTIONS/rcond.cc
@@ -85,3 +85,12 @@
 
   return retval;
 }
+
+/*
+
+%!assert( rcond (eye (2)), 1)
+%!assert( rcond (ones (2)), 0)
+%!assert( rcond ([1 1; 2 1]), 1/9)
+%!assert( rcond (magic (4)), 0, eps)
+
+*/
--- a/src/DLD-FUNCTIONS/sqrtm.cc
+++ b/src/DLD-FUNCTIONS/sqrtm.cc
@@ -49,22 +49,20 @@
 
   bool singular = false;
 
-  /*
-   * the following code is equivalent to this triple loop:
-   *
-   *  n = rows (T);
-   *  for j = 1:n
-   *    T(j,j) = sqrt (T(j,j));
-   *    for i = j-1:-1:1
-   *      T(i,j) /= (T(i,i) + T(j,j));
-   *      k = 1:i-1;
-   *      T(k,j) -= T(k,i) * T(i,j);
-   *    endfor
-   *  endfor
-   *
-   *  this is an in-place, cache-aligned variant of the code
-   *  given in Higham's paper.
-  */
+  // The following code is equivalent to this triple loop:
+  //
+  //   n = rows (T);
+  //   for j = 1:n
+  //     T(j,j) = sqrt (T(j,j));
+  //     for i = j-1:-1:1
+  //       T(i,j) /= (T(i,i) + T(j,j));
+  //       k = 1:i-1;
+  //       T(k,j) -= T(k,i) * T(i,j);
+  //     endfor
+  //   endfor
+  //
+  // this is an in-place, cache-aligned variant of the code
+  // given in Higham's paper.
 
   const octave_idx_type n = T.rows ();
   element_type *Tp = T.fortran_vec ();
@@ -117,38 +115,32 @@
         {
         case MatrixType::Upper:
         case MatrixType::Diagonal:
-            {
-              if (! x.diag ().any_element_is_negative ())
-                {
-                  // Do it in real arithmetic.
-                  sqrtm_utri_inplace (x);
-                  retval = x;
-                  retval.matrix_type (mt);
-                }
-              else
-                iscomplex = true;
-
-              break;
-            }
-        case MatrixType::Lower:
+          if (! x.diag ().any_element_is_negative ())
             {
-              if (! x.diag ().any_element_is_negative ())
-                {
-                  x = x.transpose ();
-                  sqrtm_utri_inplace (x);
-                  retval = x.transpose ();
-                  retval.matrix_type (mt);
-                }
-              else
-                iscomplex = true;
+              // Do it in real arithmetic.
+              sqrtm_utri_inplace (x);
+              retval = x;
+              retval.matrix_type (mt);
+            }
+          else
+            iscomplex = true;
+          break;
 
-              break;
+        case MatrixType::Lower:
+          if (! x.diag ().any_element_is_negative ())
+            {
+              x = x.transpose ();
+              sqrtm_utri_inplace (x);
+              retval = x.transpose ();
+              retval.matrix_type (mt);
             }
+          else
+            iscomplex = true;
+          break;
+
         default:
-          {
-            iscomplex = true;
-            break;
-          }
+          iscomplex = true;
+          break;
         }
 
       if (iscomplex)
@@ -166,46 +158,41 @@
         {
         case MatrixType::Upper:
         case MatrixType::Diagonal:
-            {
-              sqrtm_utri_inplace (x);
-              retval = x;
-              retval.matrix_type (mt);
+          sqrtm_utri_inplace (x);
+          retval = x;
+          retval.matrix_type (mt);
+          break;
 
-              break;
-            }
         case MatrixType::Lower:
-            {
-              x = x.transpose ();
-              sqrtm_utri_inplace (x);
-              retval = x.transpose ();
-              retval.matrix_type (mt);
+          x = x.transpose ();
+          sqrtm_utri_inplace (x);
+          retval = x.transpose ();
+          retval.matrix_type (mt);
+          break;
 
-              break;
-            }
         default:
-            {
-              ComplexMatrix u;
+          {
+            ComplexMatrix u;
 
-              do
-                {
-                  ComplexSCHUR schur (x, std::string (), true);
-                  x = schur.schur_matrix ();
-                  u = schur.unitary_matrix ();
-                }
-              while (0); // schur no longer needed.
+            do
+              {
+                ComplexSCHUR schur (x, std::string (), true);
+                x = schur.schur_matrix ();
+                u = schur.unitary_matrix ();
+              }
+            while (0); // schur no longer needed.
 
-              sqrtm_utri_inplace (x);
+            sqrtm_utri_inplace (x);
 
-              x = u * x; // original x no longer needed.
-              ComplexMatrix res = xgemm (x, u, blas_no_trans, blas_conj_trans);
+            x = u * x; // original x no longer needed.
+            ComplexMatrix res = xgemm (x, u, blas_no_trans, blas_conj_trans);
 
-              if (cutoff > 0 && xnorm (imag (res), one) <= cutoff)
-                retval = real (res);
-              else
-                retval = res;
-
-              break;
-            }
+            if (cutoff > 0 && xnorm (imag (res), one) <= cutoff)
+              retval = real (res);
+            else
+              retval = res;
+          }
+          break;
         }
     }
 
@@ -246,22 +233,17 @@
     }
 
   if (arg.is_diag_matrix ())
-    {
-      // sqrtm of a diagonal matrix is just sqrt.
-      retval(0) = arg.sqrt ();
-    }
+    // sqrtm of a diagonal matrix is just sqrt.
+    retval(0) = arg.sqrt ();
   else if (arg.is_single_type ())
-    {
-      retval(0) = do_sqrtm<FloatMatrix, FloatComplexMatrix, FloatComplexSCHUR> (arg);
-    }
+    retval(0) = do_sqrtm<FloatMatrix, FloatComplexMatrix, FloatComplexSCHUR> (arg);
   else if (arg.is_numeric_type ())
-    {
-      retval(0) = do_sqrtm<Matrix, ComplexMatrix, ComplexSCHUR> (arg);
-    }
+    retval(0) = do_sqrtm<Matrix, ComplexMatrix, ComplexSCHUR> (arg);
 
   if (nargout > 1 && ! error_state)
     {
       // This corresponds to generic code
+      //
       //   norm (s*s - x, "fro") / norm (x, "fro");
 
       octave_value s = retval(0);
@@ -270,3 +252,22 @@
 
   return retval;
 }
+
+/*
+
+%!assert (sqrtm (2*ones (2)), ones (2), 3*eps)
+
+## The following two tests are from the reference in the docstring above.
+
+%!test
+%! x = [0 1; 0 0];
+%! assert (any (isnan (sqrtm (x))(:) ))
+
+%!test
+%! x = eye (4); x(2,2) = x(3,3) = 2^-26; x(1,4) = 1;
+%! z = eye (4); z(2,2) = z(3,3) = 2^-13; z(1,4) = 0.5;
+%! [y, err] = sqrtm(x);
+%! assert (y, z)
+%! assert (err, 0)   ## Yes, this one has to hold exactly
+
+*/
--- a/src/DLD-FUNCTIONS/urlwrite.cc
+++ b/src/DLD-FUNCTIONS/urlwrite.cc
@@ -112,11 +112,11 @@
           {
             BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
 
-            CURLcode res = curl_easy_perform (curl);
-            if (res != CURLE_OK)
+            errnum = curl_easy_perform (curl);
+            if (errnum != CURLE_OK)
               {
                 if (curlerror)
-                  error ("%s", curl_easy_strerror (res));
+                  error ("%s", curl_easy_strerror (errnum));
               }
             else
               retval = true;
@@ -145,6 +145,7 @@
     std::string host;
     bool valid;
     bool ascii;
+    mutable CURLcode errnum;
 
   private:
     CURL *curl;
@@ -250,11 +251,7 @@
 
   std::string lasterror (void) const
     {
-      CURLcode errnum;
-
-      curl_easy_getinfo (rep->handle(), CURLINFO_OS_ERRNO, &errnum);
-
-      return std::string (curl_easy_strerror (errnum));
+      return std::string (curl_easy_strerror (rep->errnum));
     }
 
   void set_ostream (std::ostream& os) const
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -310,6 +310,7 @@
   defaults.h \
   graphics.h \
   oct-conf.h \
+  profiler.h \
   mxarray.h \
   version.h
 
@@ -446,6 +447,7 @@
   pager.cc \
   pr-output.cc \
   procstream.cc \
+  profiler.cc \
   sighandlers.cc \
   siglist.c \
   sparse.cc \
@@ -478,20 +480,15 @@
 include TEMPLATE-INST/module.mk
 
 if AMCOND_ENABLE_DYNAMIC_LINKING
-  DLD_DYNAMIC_SRC = $(DLD_FUNCTIONS_SRC)
-  DLD_STATIC_SRC =
   OCT_FILES = $(DLD_FUNCTIONS_LIBS:.la=.oct)
   OCT_STAMP_FILES = $(subst DLD-FUNCTIONS/,DLD-FUNCTIONS/$(am__leading_dot),$(DLD_FUNCTIONS_LIBS:.la=.oct-stamp))
 else
-  DLD_DYNAMIC_SRC =
-  DLD_STATIC_SRC = $(DLD_FUNCTIONS_SRC)
   OCT_FILES =
   OCT_STAMP_FILES =
 endif
 
 liboctinterp_la_SOURCES = \
   $(DIST_SRC) \
-  $(DLD_STATIC_SRC) \
   $(OPERATORS_SRC) \
   $(TEMPLATE_INST_SRC)
 
@@ -506,87 +503,14 @@
   version.h \
   $(OPT_INC)
 
+liboctinterp_la_CPPFLAGS = @OCTINTERP_DLL_DEFS@ $(AM_CPPFLAGS)
 
-if AMCOND_ENABLE_DYNAMIC_LINKING
-  OCTAVE_LIBS = \
-    ./liboctinterp.la \
-    ../liboctave/liboctave.la \
-    ../libcruft/libcruft.la \
-    ../libcruft/libranlib.la \
-    ../libgnu/libgnu.la \
-    $(SPARSE_XLDFLAGS) $(SPARSE_XLIBS) \
-    $(QRUPDATE_LDFLAGS) $(QRUPDATE_LIBS) \
-    $(FFTW_XLDFLAGS) $(FFTW_XLIBS) \
-    $(LAPACK_LIBS) $(BLAS_LIBS) \
-    $(GRAPHICS_LDFLAGS) $(GRAPHICS_LIBS) \
-    $(FT2_LDFLAGS) $(FT2_LIBS) \
-    $(HDF5_LDFLAGS) $(HDF5_LIBS) $(Z_LDFLAGS) $(Z_LIBS) \
-    $(OPENGL_LIBS) $(X11_LIBS) $(CARBON_LIBS) \
-    $(READLINE_LIBS) $(TERM_LIBS) \
-    $(LIBGLOB) \
-    $(REGEX_LDFLAGS) $(REGEX_LIBS) \
-    $(LAPACK_LIBS) $(BLAS_LIBS) \
-    $(DL_LIBS) $(PTHREAD_LIBS) \
-    $(LIBS) \
-    $(FLIBS)
-else
-  ## FIXME -- this list is probably not complete now.  It may not even
-  ## be possible to build a statically linked copy of Octave that is
-  ## fully functional.
-  OCTAVE_LIBS = \
-    ./liboctinterp.la \
-    ../liboctave/liboctave.la \
-    ../libcruft/libcruft.la \
-    ../libcruft/libranlib.la \
-    ../libgnu/libgnu.la \
-    $(FFTW_XLDFLAGS) $(FFTW_XLIBS) \
-    $(QHULL_LDFLAGS) $(QHULL_LIBS) \
-    $(QRUPDATE_LDFLAGS) $(QRUPDATE_LIBS) \
-    $(SPARSE_XLDFLAGS) $(SPARSE_XLIBS) \
-    $(REGEX_LDFLAGS) $(REGEX_LIBS) \
-    $(CURL_LDFLAGS) $(CURL_LIBS) \
-    $(GLPK_LDFLAGS) $(GLPK_LIBS) \
-    $(MAGICK_LDFLAGS) $(MAGICK_LIBS) \
-    $(GRAPHICS_LDFLAGS) $(GRAPHICS_LIBS) \
-    $(FT2_LDFLAGS) $(FT2_LIBS) \
-    $(HDF5_LDFLAGS) $(HDF5_LIBS) $(Z_LDFLAGS) $(Z_LIBS) \
-    $(OPENGL_LIBS) $(X11_LIBS) $(CARBON_LIBS) \
-    $(READLINE_LIBS) $(TERM_LIBS) \
-    $(LIBGLOB) \
-    $(LAPACK_LIBS) $(BLAS_LIBS) \
-    $(DL_LIBS) $(PTHREAD_LIBS) \
-    $(LIBS) \
-    $(FLIBS)
-endif
+include link-deps.mk
 
-OCTINTERP_LINK_DEPS = \
-  $(RLD_FLAG) \
+liboctinterp_la_LIBADD = \
   ../liboctave/liboctave.la \
   ../libcruft/libcruft.la \
-  ../libcruft/libranlib.la \
-  ../libgnu/libgnu.la \
-  $(FFTW_XLDFLAGS) $(FFTW_XLIBS) \
-  $(FT2_LDFLAGS) $(FT2_LIBS) \
-  $(HDF5_LDFLAGS) $(HDF5_LIBS) $(Z_LDFLAGS) $(Z_LIBS) \
-  $(OPENGL_LIBS) $(X11_LIBS) $(CARBON_LIBS) \
-  $(READLINE_LIBS) $(TERM_LIBS) \
-  $(LIBGLOB) \
-  $(LAPACK_LIBS) $(BLAS_LIBS) \
-  $(LIBS) \
-  $(FLIBS)
-
-liboctinterp_la_LIBADD = $(OCTINTERP_LINK_DEPS)
-
-## Additional library dependencies used by module.mk files
-OCT_LINK_DEPS = \
-  $(RLD_FLAG) $(LDFLAGS) \
-  ./liboctinterp.la \
-  ../liboctave/liboctave.la \
-  ../libcruft/libcruft.la \
-  ../libcruft/libranlib.la \
-  ../libgnu/libgnu.la
-
-liboctinterp_la_CPPFLAGS = @OCTINTERP_DLL_DEFS@ $(AM_CPPFLAGS)
+  $(LIBOCTINTERP_LINK_DEPS)
 
 # Increment these as needed and according to the rules in the libtool manual:
 liboctinterp_current = 0
@@ -598,120 +522,39 @@
 liboctinterp_la_LDFLAGS = \
   -version-info $(liboctinterp_version_info) \
   $(NO_UNDEFINED_LDFLAG) \
-  -bindir $(bindir)
+  -bindir $(bindir) \
+  $(LIBOCTINTERP_LINK_OPTS)
 
 display.df display.lo: CPPFLAGS += $(X11_FLAGS)
 
-DLD-FUNCTIONS/__magick_read__.df: CPPFLAGS += $(MAGICK_CPPFLAGS)
-DLD_FUNCTIONS___magick_read___la_CPPFLAGS = $(AM_CPPFLAGS) $(MAGICK_CPPFLAGS)
-DLD_FUNCTIONS___magick_read___la_LIBADD += $(MAGICK_LDFLAGS) $(MAGICK_LIBS)
-
-DLD-FUNCTIONS/convhulln.df: CPPFLAGS += $(QHULL_CPPFLAGS)
-DLD_FUNCTIONS_convhulln_la_CPPFLAGS = $(AM_CPPFLAGS) $(QHULL_CPPFLAGS)
-DLD_FUNCTIONS_convhulln_la_LIBADD += $(QHULL_LDFLAGS) $(QHULL_LIBS)
-
-DLD-FUNCTIONS/__delaunayn__.df: CPPFLAGS += $(QHULL_CPPFLAGS)
-DLD_FUNCTIONS___delaunayn___la_CPPFLAGS = $(AM_CPPFLAGS) $(QHULL_CPPFLAGS)
-DLD_FUNCTIONS___delaunayn___la_LIBADD += $(QHULL_LDFLAGS) $(QHULL_LIBS)
-
-DLD-FUNCTIONS/__voronoi__.df: CPPFLAGS += $(QHULL_CPPFLAGS)
-DLD_FUNCTIONS___voronoi___la_CPPFLAGS = $(AM_CPPFLAGS) $(QHULL_CPPFLAGS)
-DLD_FUNCTIONS___voronoi___la_LIBADD += $(QHULL_LDFLAGS) $(QHULL_LIBS)
-
-DLD-FUNCTIONS/eigs.df: CPPFLAGS += $(SPARSE_XCPPFLAGS)
-DLD_FUNCTIONS_eigs_la_CPPFLAGS = $(AM_CPPFLAGS) $(SPARSE_XCPPFLAGS)
-DLD_FUNCTIONS_eigs_la_LIBADD += $(SPARSE_XLDFLAGS) $(SPARSE_XLIBS) $(LAPACK_LIBS) $(BLAS_LIBS)
-
-#DLD-FUNCTIONS/qz.df DLD-FUNCTIONS/qz.lo:
-DLD_FUNCTIONS_qz_la_LIBADD += $(LAPACK_LIBS) $(BLAS_LIBS)
-
-DLD-FUNCTIONS/qr.df: CPPFLAGS += $(QRUPDATE_CPPFLAGS) $(SPARSE_XCPPFLAGS)
-DLD_FUNCTIONS_qr_la_CPPFLAGS = $(AM_CPPFLAGS) $(QRUPDATE_CPPFLAGS) $(SPARSE_XCPPFLAGS)
-DLD_FUNCTIONS_qr_la_LIBADD += $(QRUPDATE_LDFLAGS) $(QRUPDATE_LIBS) $(SPARSE_XLDFLAGS) $(SPARSE_XLIBS)
-
-DLD-FUNCTIONS/chol.df: CPPFLAGS += $(QRUPDATE_CPPFLAGS) $(SPARSE_XCPPFLAGS)
-DLD_FUNCTIONS_chol_la_CPPFLAGS = $(AM_CPPFLAGS) $(QRUPDATE_CPPFLAGS) $(SPARSE_XCPPFLAGS)
-DLD_FUNCTIONS_chol_la_LIBADD += $(QRUPDATE_LDFLAGS) $(QRUPDATE_LIBS) $(SPARSE_XLDFLAGS) $(SPARSE_XLIBS)
-
-DLD-FUNCTIONS/regexp.df: CPPFLAGS += $(REGEX_CPPFLAGS)
-DLD_FUNCTIONS_regexp_la_CPPFLAGS = $(AM_CPPFLAGS) $(REGEX_CPPFLAGS)
-DLD_FUNCTIONS_regexp_la_LIBADD += $(REGEX_LDFLAGS) $(REGEX_LIBS)
-
-DLD-FUNCTIONS/urlwrite.df: CPPFLAGS += $(CURL_CPPFLAGS)
-DLD_FUNCTIONS_urlwrite_la_CPPFLAGS = $(AM_CPPFLAGS) $(CURL_CPPFLAGS)
-DLD_FUNCTIONS_urlwrite_la_LIBADD += $(CURL_LDFLAGS) $(CURL_LIBS)
-
-DLD-FUNCTIONS/__fltk_uigetfile__.df: CPPFLAGS += $(GRAPHICS_CFLAGS) $(FT2_CPPFLAGS)
-DLD_FUNCTIONS___fltk_uigetfile___la_CPPFLAGS = $(AM_CPPFLAGS) $(GRAPHICS_CFLAGS) $(FT2_CPPFLAGS)
-DLD_FUNCTIONS___fltk_uigetfile___la_LIBADD += $(GRAPHICS_LDFLAGS) $(GRAPHICS_LIBS) $(FT2_LDFLAGS) $(FT2_LIBS)
-
-DLD-FUNCTIONS/__glpk__.df: CPPFLAGS += $(GLPK_CPPFLAGS)
-DLD_FUNCTIONS___glpk___la_CPPFLAGS = $(AM_CPPFLAGS) $(GLPK_CPPFLAGS)
-DLD_FUNCTIONS___glpk___la_LIBADD += $(GLPK_LDFLAGS) $(GLPK_LIBS)
-
-DLD-FUNCTIONS/__init_fltk__.df: CPPFLAGS += $(GRAPHICS_CFLAGS) $(FT2_CPPFLAGS)
-DLD_FUNCTIONS___init_fltk___la_CPPFLAGS = $(AM_CPPFLAGS) $(GRAPHICS_CFLAGS) $(FT2_CPPFLAGS)
-DLD_FUNCTIONS___init_fltk___la_LIBADD += $(GRAPHICS_LDFLAGS) $(GRAPHICS_LIBS) $(FT2_LDFLAGS) $(FT2_LIBS)
-
-DLD-FUNCTIONS/amd.df: CPPFLAGS += $(SPARSE_XCPPFLAGS)
-DLD_FUNCTIONS_amd_la_CPPFLAGS = $(AM_CPPFLAGS) $(SPARSE_XCPPFLAGS)
-DLD_FUNCTIONS_amd_la_LIBADD += $(SPARSE_XLDFLAGS) $(SPARSE_XLIBS)
-
-DLD-FUNCTIONS/colamd.df: CPPFLAGS += $(SPARSE_XCPPFLAGS)
-DLD_FUNCTIONS_colamd_la_CPPFLAGS = $(AM_CPPFLAGS) $(SPARSE_XCPPFLAGS)
-DLD_FUNCTIONS_colamd_la_LIBADD += $(SPARSE_XLDFLAGS) $(SPARSE_XLIBS)
-
-DLD-FUNCTIONS/ccolamd.df: CPPFLAGS += $(SPARSE_XCPPFLAGS)
-DLD_FUNCTIONS_ccolamd_la_CPPFLAGS = $(AM_CPPFLAGS) $(SPARSE_XCPPFLAGS)
-DLD_FUNCTIONS_ccolamd_la_LIBADD += $(SPARSE_XLDFLAGS) $(SPARSE_XLIBS)
-
-DLD-FUNCTIONS/symbfact.df: CPPFLAGS += $(SPARSE_XCPPFLAGS)
-DLD_FUNCTIONS_symbfact_la_CPPFLAGS = $(AM_CPPFLAGS) $(SPARSE_XCPPFLAGS)
-DLD_FUNCTIONS_symbfact_la_LIBADD += $(SPARSE_XLDFLAGS) $(SPARSE_XLIBS)
-
-DLD-FUNCTIONS/dmperm.df: CPPFLAGS += $(SPARSE_XCPPFLAGS)
-DLD_FUNCTIONS_dmperm_la_CPPFLAGS = $(AM_CPPFLAGS) $(SPARSE_XCPPFLAGS)
-DLD_FUNCTIONS_dmperm_la_LIBADD += $(SPARSE_XLDFLAGS) $(SPARSE_XLIBS)
-
-DLD-FUNCTIONS/symrcm.df: CPPFLAGS += $(SPARSE_XCPPFLAGS)
-DLD_FUNCTIONS_symrcm_la_CPPFLAGS = $(AM_CPPFLAGS) $(SPARSE_XCPPFLAGS)
-DLD_FUNCTIONS_symrcm_la_LIBADD += $(SPARSE_XLDFLAGS) $(SPARSE_XLIBS)
-
-DLD-FUNCTIONS/fft.df: CPPFLAGS += $(FFTW_XCPPFLAGS)
-DLD_FUNCTIONS_fft_la_CPPFLAGS = $(AM_CPPFLAGS) $(FFTW_XCPPFLAGS)
-DLD_FUNCTIONS_fft_la_LIBADD += $(FFTW_XLDFLAGS) $(FFTW_XLIBS)
-
-DLD-FUNCTIONS/fft2.df: CPPFLAGS += $(FFTW_XCPPFLAGS)
-DLD_FUNCTIONS_fft2_la_CPPFLAGS = $(AM_CPPFLAGS) $(FFTW_XCPPFLAGS)
-DLD_FUNCTIONS_fft2_la_LIBADD += $(FFTW_XLDFLAGS) $(FFTW_XLIBS)
-
-DLD-FUNCTIONS/fftn.df: CPPFLAGS += $(FFTW_XCPPFLAGS)
-DLD_FUNCTIONS_fftn_la_CPPFLAGS = $(AM_CPPFLAGS) $(FFTW_XCPPFLAGS)
-DLD_FUNCTIONS_fftn_la_LIBADD += $(FFTW_XLDFLAGS) $(FFTW_XLIBS)
-
-DLD-FUNCTIONS/fftw.df: CPPFLAGS += $(FFTW_XCPPFLAGS)
-DLD_FUNCTIONS_fftw_la_CPPFLAGS = $(AM_CPPFLAGS) $(FFTW_XCPPFLAGS)
-DLD_FUNCTIONS_fftw_la_LIBADD += $(FFTW_XLDFLAGS) $(FFTW_XLIBS)
-
-
 octave_SOURCES = main.c
 
-octave_LDADD = $(OCTAVE_LIBS)
+octave_LDADD = \
+  liboctinterp.la \
+  ../liboctave/liboctave.la \
+  ../libcruft/libcruft.la \
+  $(OCTAVE_LINK_DEPS)
 
+octave_LDFLAGS = \
+  $(NO_UNDEFINED_LDFLAG) \
+  $(OCTAVE_LINK_OPTS)
 
 ## Section for defining and creating DEF_FILES
 SRC_DEF_FILES := $(shell $(srcdir)/find-defun-files.sh "$(srcdir)" $(DIST_SRC))
 
-DLD_STATIC_DEF_FILES  = $(DLD_STATIC_SRC:.cc=.df)
-DLD_DYNAMIC_DEF_FILES = $(DLD_DYNAMIC_SRC:.cc=.df)
+DLD_FUNCTIONS_DEF_FILES = $(DLD_FUNCTIONS_SRC:.cc=.df)
 
 ## builtins.cc depends on $(DEF_FILES), so DEF_FILES should only include
 ## .df files that correspond to sources included in liboctave.
-DEF_FILES = $(SRC_DEF_FILES) $(DLD_STATIC_DEF_FILES)
+if AMCOND_ENABLE_DYNAMIC_LINKING
+  DEF_FILES = $(SRC_DEF_FILES)
+else
+  DEF_FILES = $(SRC_DEF_FILES) $(DLD_FUNCTIONS_DEF_FILES)
+endif
 
-ALL_DEF_FILES = $(DEF_FILES) $(DLD_DYNAMIC_DEF_FILES)
+ALL_DEF_FILES = $(SRC_DEF_FILES) $(DLD_FUNCTIONS_DEF_FILES)
 
-$(DEF_FILES) $(DYNAMIC_DLD_DEF_FILES): mkdefs Makefile
+$(SRC_DEF_FILES): mkdefs Makefile
 
 $(DEF_FILES): $(OPT_HANDLERS) $(OPT_INC)
 
@@ -794,9 +637,13 @@
 $(OPT_INC) : %.h : %.in
 	$(MAKE) -C $(@D) $(@F)
 
-DLD-FUNCTIONS/PKG_ADD: $(DLD_DYNAMIC_DEF_FILES) mk-pkg-add
-	$(srcdir)/mk-pkg-add $(DLD_DYNAMIC_DEF_FILES) > $@-t
+if AMCOND_ENABLE_DYNAMIC_LINKING
+DLD_FUNCTIONS_PKG_ADD_FILE = DLD-FUNCTIONS/PKG_ADD
+
+DLD-FUNCTIONS/PKG_ADD: $(DLD_FUNCTIONS_DEF_FILES) mk-pkg-add
+	$(srcdir)/mk-pkg-add $(DLD_FUNCTIONS_DEF_FILES) > $@-t
 	mv $@-t $@
+endif
 
 lex.lo lex.o oct-parse.lo oct-parse.o: \
   AM_CXXFLAGS := $(filter-out -Wold-style-cast, $(AM_CXXFLAGS))
@@ -828,8 +675,7 @@
 gendoc$(BUILD_EXEEXT): gendoc.cc
 	$(BUILD_CXX) $(BUILD_CXXFLAGS) -o $@ $^ $(BUILD_LDFLAGS)
 
-
-all-local: $(OCT_STAMP_FILES) DLD-FUNCTIONS/PKG_ADD .DOCSTRINGS
+all-local: $(OCT_STAMP_FILES) $(DLD_FUNCTIONS_PKG_ADD_FILE) .DOCSTRINGS
 
 if AMCOND_BUILD_COMPILED_AUX_PROGRAMS
 octave-config.cc: octave-config.cc.in Makefile
@@ -882,8 +728,8 @@
 if AMCOND_ENABLE_DYNAMIC_LINKING
 install-oct:
 	$(top_srcdir)/build-aux/mkinstalldirs $(DESTDIR)$(octfiledir)
-	if [ -n "`cat DLD-FUNCTIONS/PKG_ADD`" ]; then \
-	  $(INSTALL_DATA) DLD-FUNCTIONS/PKG_ADD $(DESTDIR)$(octfiledir)/PKG_ADD; \
+	if [ -n "`cat $(DLD_FUNCTIONS_PKG_ADD_FILE)`" ]; then \
+	  $(INSTALL_DATA) $(DLD_FUNCTIONS_PKG_ADD_FILE) $(DESTDIR)$(octfiledir)/PKG_ADD; \
 	fi
 	cd $(DESTDIR)$(octlibdir) && \
 	for ltlib in $(DLD_FUNCTIONS_LIBS); do \
@@ -911,7 +757,7 @@
 
 CLEANFILES = \
   $(bin_SCRIPTS) \
-  DLD-FUNCTIONS/PKG_ADD \
+  $(DLD_FUNCTIONS_PKG_ADD_FILE) \
   doc-files \
   gendoc.cc \
   gendoc$(BUILD_EXEEXT) \
--- a/src/OPERATORS/op-int.h
+++ b/src/OPERATORS/op-int.h
@@ -21,6 +21,7 @@
 */
 
 #include "quit.h"
+#include "bsxfun.h"
 
 #define DEFINTBINOP_OP(name, t1, t2, op, t3) \
   BINOPDECL (name, a1, a2) \
@@ -703,8 +704,15 @@
     dim_vector b_dims = b.dims (); \
     if (a_dims != b_dims) \
       { \
-        gripe_nonconformant ("operator .^", a_dims, b_dims); \
-        return octave_value (); \
+        if (is_valid_bsxfun (a_dims, b_dims)) \
+          { \
+            return bsxfun_pow (a, b); \
+          } \
+        else \
+          { \
+            gripe_nonconformant ("operator .^", a_dims, b_dims);  \
+            return octave_value (); \
+          } \
       } \
     T1 ## NDArray result (a_dims); \
     for (int i = 0; i < a.length (); i++) \
@@ -722,8 +730,15 @@
     dim_vector b_dims = b.dims (); \
     if (a_dims != b_dims) \
       { \
-        gripe_nonconformant ("operator .^", a_dims, b_dims); \
-        return octave_value (); \
+        if (is_valid_bsxfun (a_dims, b_dims)) \
+          { \
+            return bsxfun_pow (a, b); \
+          } \
+        else \
+          { \
+            gripe_nonconformant ("operator .^", a_dims, b_dims);  \
+            return octave_value (); \
+          } \
       } \
     T1 ## NDArray result (a_dims); \
     for (int i = 0; i < a.length (); i++) \
@@ -741,8 +756,15 @@
     dim_vector b_dims = b.dims (); \
     if (a_dims != b_dims) \
       { \
-        gripe_nonconformant ("operator .^", a_dims, b_dims); \
-        return octave_value (); \
+        if (is_valid_bsxfun (a_dims, b_dims)) \
+          { \
+            return bsxfun_pow (a, b); \
+          } \
+        else \
+          { \
+            gripe_nonconformant ("operator .^", a_dims, b_dims);  \
+            return octave_value (); \
+          } \
       } \
     T2 ## NDArray result (a_dims); \
     for (int i = 0; i < a.length (); i++) \
@@ -760,8 +782,15 @@
     dim_vector b_dims = b.dims (); \
     if (a_dims != b_dims) \
       { \
-        gripe_nonconformant ("operator .^", a_dims, b_dims); \
-        return octave_value (); \
+        if (is_valid_bsxfun (a_dims, b_dims)) \
+          { \
+            return bsxfun_pow (a, b); \
+          } \
+        else \
+          { \
+            gripe_nonconformant ("operator .^", a_dims, b_dims);  \
+            return octave_value (); \
+          } \
       } \
     T1 ## NDArray result (a_dims); \
     for (int i = 0; i < a.length (); i++) \
@@ -779,8 +808,15 @@
     dim_vector b_dims = b.dims (); \
     if (a_dims != b_dims) \
       { \
-        gripe_nonconformant ("operator .^", a_dims, b_dims); \
-        return octave_value (); \
+        if (is_valid_bsxfun (a_dims, b_dims)) \
+          { \
+            return bsxfun_pow (a, b); \
+          } \
+        else \
+          { \
+            gripe_nonconformant ("operator .^", a_dims, b_dims);  \
+            return octave_value (); \
+          } \
       } \
     T2 ## NDArray result (a_dims); \
     for (int i = 0; i < a.length (); i++) \
--- a/src/data.cc
+++ b/src/data.cc
@@ -1943,6 +1943,9 @@
 %!error <dimension mismatch> cat (3, cat (3, [], []), [1,2;3,4]);
 %!error <dimension mismatch> cat (3, zeros (0, 0, 2), [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)) );
+
 */
 
 static octave_value
@@ -4194,8 +4197,8 @@
 @end example\n\
 \n\
 Calling @code{eye} with no arguments is equivalent to calling it\n\
-with an argument of 1.  This odd definition is for compatibility\n\
-with @sc{matlab}.\n\
+with an argument of 1.  Any negative dimensions are treated as zero. \n\
+These odd definitions are for compatibility with @sc{matlab}.\n\
 @seealso{speye}\n\
 @end deftypefn")
 {
--- a/src/defaults.cc
+++ b/src/defaults.cc
@@ -419,6 +419,17 @@
   return SET_NONEMPTY_INTERNAL_STRING_VARIABLE (EDITOR);
 }
 
+/*
+%!error (EDITOR (1, 2));
+%!test
+%! orig_val = EDITOR ();
+%! old_val = EDITOR ("X");
+%! assert (orig_val, old_val);
+%! assert (EDITOR (), "X");
+%! EDITOR (orig_val);
+%! assert (EDITOR (), orig_val);
+*/
+
 DEFUN (EXEC_PATH, args, nargout,
   "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {@var{val} =} EXEC_PATH ()\n\
@@ -438,6 +449,17 @@
   return retval;
 }
 
+/*
+%!error (EXEC_PATH (1, 2));
+%!test
+%! orig_val = EXEC_PATH ();
+%! old_val = EXEC_PATH ("X");
+%! assert (orig_val, old_val);
+%! assert (EXEC_PATH (), "X");
+%! EXEC_PATH (orig_val);
+%! assert (EXEC_PATH (), orig_val);
+*/
+
 DEFUN (IMAGE_PATH, args, nargout,
   "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {@var{val} =} IMAGE_PATH ()\n\
@@ -449,6 +471,17 @@
   return SET_NONEMPTY_INTERNAL_STRING_VARIABLE (IMAGE_PATH);
 }
 
+/*
+%!error (IMAGE_PATH (1, 2));
+%!test
+%! orig_val = IMAGE_PATH ();
+%! old_val = IMAGE_PATH ("X");
+%! assert (orig_val, old_val);
+%! assert (IMAGE_PATH (), "X");
+%! IMAGE_PATH (orig_val);
+%! assert (IMAGE_PATH (), orig_val);
+*/
+
 DEFUN (OCTAVE_HOME, args, ,
   "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} OCTAVE_HOME ()\n\
@@ -465,6 +498,11 @@
   return retval;
 }
 
+/*
+%!error OCTAVE_HOME (1);
+%!assert (ischar (OCTAVE_HOME ()));
+*/
+
 DEFUNX ("OCTAVE_VERSION", FOCTAVE_VERSION, args, ,
   "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} OCTAVE_VERSION ()\n\
@@ -482,3 +520,8 @@
 
   return retval;
 }
+
+/*
+%!error OCTAVE_VERSION (1);
+%!assert (ischar (OCTAVE_VERSION ()));
+*/
--- a/src/error.cc
+++ b/src/error.cc
@@ -1066,6 +1066,10 @@
 
           octave_scalar_map m = args(0).scalar_map_value ();
 
+          // empty struct is not an error.  return and resume calling function.
+          if (m.nfields () == 0)
+            return retval;
+
           if (m.contains ("message"))
             {
               octave_value c = m.getfield ("message");
@@ -1684,10 +1688,6 @@
   return retval;
 }
 
-// For backward compatibility.
-DEFALIAS (error_text, lasterr);
-DEFALIAS (__error_text__, lasterr);
-
 DEFUN (lastwarn, args, nargout,
   "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {[@var{msg}, @var{msgid}] =} lastwarn (@var{msg}, @var{msgid})\n\
--- a/src/genprops.awk
+++ b/src/genprops.awk
@@ -300,8 +300,9 @@
         emit_get_accessor(i, "graphics_handle", "handle_value");
       else if (type[i] == "string_property")
         emit_get_accessor(i, "std::string", "string_value");
-      else if (type[i] == "string_array_property")
-          emit_get_accessor(i, "octave_value", "get");
+      else if (type[i] == "string_array_property" \
+               || type[i] == "text_label_property")
+        emit_get_accessor(i, "octave_value", "get");
       else if (type[i] == "double_property")
         emit_get_accessor(i, "double", "double_value");
       else if (type[i] == "double_radio_property")
--- a/src/gl-render.cc
+++ b/src/gl-render.cc
@@ -665,7 +665,7 @@
                                    double p1, double p1N,
                                    double p2, double p2N,
                                    double dx, double dy, double dz,
-                                   int xyz, bool doubleside)
+                                   int xyz, bool mirror)
 {
   glBegin (GL_LINES);
 
@@ -679,7 +679,7 @@
             {
               glVertex3d (val, p1, p2);
               glVertex3d (val, p1+dy, p2+dz);
-              if (doubleside)
+              if (mirror)
                 {
                   glVertex3d (val, p1N, p2N);
                   glVertex3d (val, p1N-dy, p2N-dz);
@@ -689,7 +689,7 @@
             {
               glVertex3d (p1, val, p2);
               glVertex3d (p1+dx, val, p2+dz);
-              if (doubleside)
+              if (mirror)
                 {
                   glVertex3d (p1N, val, p2N);
                   glVertex3d (p1N-dx, val, p2N-dz);
@@ -699,7 +699,7 @@
             {
               glVertex3d (p1, p2, val);
               glVertex3d (p1+dx, p2+dy, val);
-              if (doubleside)
+              if (mirror)
                 {
                   glVertex3d (p1N, p2N, val);
                   glVertex3d (p1N-dx, p2N-dy, val);
@@ -966,7 +966,7 @@
       string_vector xticklabels = props.get_xticklabel ().all_strings ();
       int wmax = 0, hmax = 0;
       bool tick_along_z = nearhoriz || xisinf (fy);
-      bool box = props.is_box ();
+      bool mirror = props.is_box () && xstate != AXE_ANY_DIR;
 
       set_color (props.get_xcolor_rgb ());
 
@@ -982,14 +982,14 @@
           render_tickmarks (xticks, x_min, x_max, ypTick, ypTick,
                             zpTick, zpTickN, 0., 0.,
                             signum(zpTick-zpTickN)*fz*xticklen,
-                            0, (box && xstate != AXE_ANY_DIR));
+                            0, mirror);
         }
       else
         {
           render_tickmarks (xticks, x_min, x_max, ypTick, ypTickN,
                             zpTick, zpTick, 0.,
                             signum(ypTick-ypTickN)*fy*xticklen,
-                            0., 0, (box && xstate != AXE_ANY_DIR));
+                            0., 0, mirror);
         }
 
       // tick texts
@@ -1021,12 +1021,12 @@
             render_tickmarks (xmticks, x_min, x_max, ypTick, ypTick,
                               zpTick, zpTickN, 0., 0.,
                               signum(zpTick-zpTickN)*fz*xticklen/2,
-                              0, (box && xstate != AXE_ANY_DIR));
+                              0, mirror);
           else
             render_tickmarks (xmticks, x_min, x_max, ypTick, ypTickN,
                               zpTick, zpTick, 0.,
                               signum(ypTick-ypTickN)*fy*xticklen/2,
-                              0., 0, (box && xstate != AXE_ANY_DIR));
+                              0., 0, mirror);
         }
 
       gh_manager::get_object (props.get_xlabel ()).set ("visible", "on");
@@ -1073,7 +1073,8 @@
       string_vector yticklabels = props.get_yticklabel ().all_strings ();
       int wmax = 0, hmax = 0;
       bool tick_along_z = nearhoriz || xisinf (fx);
-      bool box = props.is_box ();
+      bool mirror = props.is_box () && ystate != AXE_ANY_DIR
+                    && (props.get_tag () != "plotyy");
 
       set_color (props.get_ycolor_rgb ());
 
@@ -1088,12 +1089,12 @@
         render_tickmarks (yticks, y_min, y_max, xpTick, xpTick,
                           zpTick, zpTickN, 0., 0.,
                           signum(zpTick-zpTickN)*fz*yticklen,
-                          1, (box && ystate != AXE_ANY_DIR));
+                          1, mirror);
       else
         render_tickmarks (yticks, y_min, y_max, xpTick, xpTickN,
                           zpTick, zpTick,
                           signum(xPlaneN-xPlane)*fx*yticklen,
-                          0., 0., 1, (box && ystate != AXE_ANY_DIR));
+                          0., 0., 1, mirror);
 
       // tick texts
       if (yticklabels.numel () > 0)
@@ -1125,12 +1126,12 @@
             render_tickmarks (ymticks, y_min, y_max, xpTick, xpTick,
                               zpTick, zpTickN, 0., 0.,
                               signum(zpTick-zpTickN)*fz*yticklen/2,
-                              1, (box && ystate != AXE_ANY_DIR));
+                              1, mirror);
           else
             render_tickmarks (ymticks, y_min, y_max, xpTick, xpTickN,
                               zpTick, zpTick,
                               signum(xpTick-xpTickN)*fx*yticklen/2,
-                              0., 0., 1, (box && ystate != AXE_ANY_DIR));
+                              0., 0., 1, mirror);
         }
 
       gh_manager::get_object (props.get_ylabel ()).set ("visible", "on");
@@ -1169,7 +1170,7 @@
       Matrix zmticks = xform.zscale (props.get_zmtick ().matrix_value ());
       string_vector zticklabels = props.get_zticklabel ().all_strings ();
       int wmax = 0, hmax = 0;
-      bool box = props.is_box ();
+      bool mirror = props.is_box () && zstate != AXE_ANY_DIR;
 
       set_color (props.get_zcolor_rgb ());
 
@@ -1185,7 +1186,7 @@
             render_tickmarks (zticks, z_min, z_max, xPlaneN, xPlane,
                               yPlane, yPlane,
                               signum(xPlaneN-xPlane)*fx*zticklen,
-                              0., 0., 2, (box && zstate != AXE_ANY_DIR));
+                              0., 0., 2, mirror);
           else
             render_tickmarks (zticks, z_min, z_max, xPlaneN, xPlaneN,
                               yPlane, yPlane, 0.,
@@ -1198,7 +1199,7 @@
             render_tickmarks (zticks, z_min, z_max, xPlaneN, xPlane,
                               yPlaneN, yPlane, 0.,
                               signum(yPlaneN-yPlane)*fy*zticklen,
-                              0., 2, (box && zstate != AXE_ANY_DIR));
+                              0., 2, mirror);
           else
             render_tickmarks (zticks, z_min, z_max, xPlane, xPlane,
                               yPlaneN, yPlane,
@@ -1250,7 +1251,7 @@
                 render_tickmarks (zmticks, z_min, z_max, xPlaneN, xPlane,
                                   yPlane, yPlane,
                                   signum(xPlaneN-xPlane)*fx*zticklen/2,
-                                  0., 0., 2, (box && zstate != AXE_ANY_DIR));
+                                  0., 0., 2, mirror);
               else
                 render_tickmarks (zmticks, z_min, z_max, xPlaneN, xPlaneN,
                                   yPlane, yPlane, 0.,
@@ -1263,7 +1264,7 @@
                 render_tickmarks (zmticks, z_min, z_max, xPlane, xPlane,
                                   yPlaneN, yPlane, 0.,
                                   signum(yPlaneN-yPlane)*fy*zticklen/2,
-                                  0., 2, (box && zstate != AXE_ANY_DIR));
+                                  0., 2, mirror);
               else
                 render_tickmarks (zmticks, z_min, z_max, xPlane, xPlane,
                                   yPlaneN, yPlaneN,
@@ -2421,7 +2422,7 @@
 void
 opengl_renderer::draw_text (const text::properties& props)
 {
-  if (props.get_string ().empty ())
+  if (props.get_string ().is_empty ())
     return;
 
   const Matrix pos = xform.scale (props.get_data_position ());
--- a/src/gl2ps-renderer.cc
+++ b/src/gl2ps-renderer.cc
@@ -199,7 +199,7 @@
 void
 glps_renderer::draw_text (const text::properties& props)
 {
-  if (props.get_string ().empty ())
+  if (props.get_string ().is_empty ())
     return;
 
   set_font (props);
@@ -223,9 +223,15 @@
   // FIXME: handle margin and surrounding box
 
   glRasterPos3d (pos(0), pos(1), pos(2));
-  gl2psTextOpt (props.get_string ().c_str (), fontname.c_str (), fontsize,
+
+  octave_value string_prop = props.get_string ();
+
+  string_vector sv = string_prop.all_strings ();
+
+  std::string s = sv.join ("\n");
+
+  gl2psTextOpt (s.c_str (), fontname.c_str (), fontsize, 
                 alignment_to_mode (halign, valign), props.get_rotation ());
-
 }
 
 #endif
--- a/src/gl2ps.c
+++ b/src/gl2ps.c
@@ -50,7 +50,7 @@
 #include <png.h>
 #endif
 
-/*********************************************************************
+/********************************************************************* 
  *
  * Private definitions, data structures and prototypes
  *
@@ -167,7 +167,6 @@
      written to the file or not, and 'format' indicates if it is
      visible or not */
   GLenum format, type;
-  GLfloat zoom_x, zoom_y;
   GLfloat *pixels;
 } GL2PSimage;
 
@@ -228,7 +227,7 @@
   GLboolean zerosurfacearea;
   GL2PSbsptree2d *imagetree;
   GL2PSprimitive *primitivetoadd;
-
+  
   /* PDF-specific */
   int streamlength;
   GL2PSlist *pdfprimlist, *pdfgrouplist;
@@ -266,7 +265,7 @@
 
 static GLint gl2psPrintPrimitives(void);
 
-/*********************************************************************
+/********************************************************************* 
  *
  * Utility routines
  *
@@ -283,7 +282,7 @@
     case GL2PS_ERROR : fprintf(stderr, "GL2PS error: "); break;
     }
     va_start(args, fmt);
-    vfprintf(stderr, fmt, args);
+    vfprintf(stderr, fmt, args); 
     va_end(args);
     fprintf(stderr, "\n");
   }
@@ -360,16 +359,16 @@
 static int gl2psAllocCompress(unsigned int srcsize)
 {
   gl2psFreeCompress();
-
+  
   if(!gl2ps->compress || !srcsize)
     return GL2PS_ERROR;
-
+  
   gl2ps->compress->srcLen = srcsize;
   gl2ps->compress->destLen = (int)ceil(1.001 * gl2ps->compress->srcLen + 12);
   gl2ps->compress->src = (Bytef*)gl2psMalloc(gl2ps->compress->srcLen);
   gl2ps->compress->start = gl2ps->compress->src;
   gl2ps->compress->dest = (Bytef*)gl2psMalloc(gl2ps->compress->destLen);
-
+  
   return GL2PS_SUCCESS;
 }
 
@@ -377,18 +376,18 @@
 {
   if(!gl2ps->compress || !srcsize)
     return NULL;
-
+  
   if(srcsize < gl2ps->compress->srcLen)
     return gl2ps->compress->start;
-
+  
   gl2ps->compress->srcLen = srcsize;
   gl2ps->compress->destLen = (int)ceil(1.001 * gl2ps->compress->srcLen + 12);
-  gl2ps->compress->src = (Bytef*)gl2psRealloc(gl2ps->compress->src,
+  gl2ps->compress->src = (Bytef*)gl2psRealloc(gl2ps->compress->src, 
                                               gl2ps->compress->srcLen);
   gl2ps->compress->start = gl2ps->compress->src;
-  gl2ps->compress->dest = (Bytef*)gl2psRealloc(gl2ps->compress->dest,
+  gl2ps->compress->dest = (Bytef*)gl2psRealloc(gl2ps->compress->dest, 
                                                gl2ps->compress->destLen);
-
+  
   return gl2ps->compress->start;
 }
 
@@ -407,8 +406,8 @@
 {
   /* For compatibility with older zlib versions, we use compress(...)
      instead of compress2(..., Z_BEST_COMPRESSION) */
-  return compress(gl2ps->compress->dest, &gl2ps->compress->destLen,
-                  gl2ps->compress->start, gl2ps->compress->srcLen);
+  return compress(gl2ps->compress->dest, &gl2ps->compress->destLen, 
+                  gl2ps->compress->start, gl2ps->compress->srcLen);  
 }
 
 #endif
@@ -456,7 +455,7 @@
     /* add the gzip file header */
     fwrite(tmp, 10, 1, gl2ps->stream);
   }
-#endif
+#endif  
 }
 
 static void gl2psPrintGzipFooter()
@@ -477,7 +476,7 @@
         n += 4; /* DICTID */
       }
       /* write the data, without the zlib header and footer */
-      fwrite(gl2ps->compress->dest+n, gl2ps->compress->destLen-(n+4),
+      fwrite(gl2ps->compress->dest+n, gl2ps->compress->destLen-(n+4), 
              1, gl2ps->stream);
       /* add the gzip file footer */
       crc = crc32(0L, gl2ps->compress->start, gl2ps->compress->srcLen);
@@ -496,7 +495,7 @@
     gl2psFree(gl2ps->compress);
     gl2ps->compress = NULL;
   }
-#endif
+#endif 
 }
 
 /* The list handling routines */
@@ -545,7 +544,7 @@
 
 static void gl2psListDelete(GL2PSlist *list)
 {
-  if(!list) return;
+  if(!list) return;  
   gl2psFree(list->array);
   gl2psFree(list);
 }
@@ -618,7 +617,7 @@
 
 static void gl2psEncodeBase64Block(unsigned char in[3], unsigned char out[4], int len)
 {
-  static const char cb64[] =
+  static const char cb64[] = 
     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 
   out[0] = cb64[ in[0] >> 2 ];
@@ -671,7 +670,7 @@
     return GL_FALSE;
   return GL_TRUE;
 }
-
+  
 static GLboolean gl2psVertsSameColor(const GL2PSprimitive *prim)
 {
   int i;
@@ -690,20 +689,20 @@
   int i;
 
   if(n < 2) return GL_TRUE;
-
+  
   for(i = 1; i < n; i++){
     if(fabs(rgba[0][0] - rgba[i][0]) > threshold[0] ||
        fabs(rgba[0][1] - rgba[i][1]) > threshold[1] ||
        fabs(rgba[0][2] - rgba[i][2]) > threshold[2])
       return GL_FALSE;
   }
-
+  
   return GL_TRUE;
 }
 
 static void gl2psSetLastColor(GL2PSrgba rgba)
 {
-  int i;
+  int i;        
   for(i = 0; i < 3; ++i){
     gl2ps->lastrgba[i] = rgba[i];
   }
@@ -712,13 +711,13 @@
 static GLfloat gl2psGetRGB(GL2PSimage *im, GLuint x, GLuint y,
                            GLfloat *red, GLfloat *green, GLfloat *blue)
 {
-
+  
   GLsizei width = im->width;
   GLsizei height = im->height;
   GLfloat *pixels = im->pixels;
   GLfloat *pimag;
 
-  /* OpenGL image is from down to up, PS image is up to down */
+  /* OpenGL image is from down to up, PS image is up to down */  
   switch(im->format){
   case GL_RGBA:
     pimag = pixels + 4 * (width * (height - 1 - y) + x);
@@ -741,13 +740,11 @@
 {
   int size;
   GL2PSimage *image = (GL2PSimage*)gl2psMalloc(sizeof(GL2PSimage));
-
+  
   image->width = im->width;
   image->height = im->height;
   image->format = im->format;
   image->type = im->type;
-  image->zoom_x = im->zoom_x;
-  image->zoom_y = im->zoom_y;
 
   switch(image->format){
   case GL_RGBA:
@@ -761,7 +758,7 @@
 
   image->pixels = (GLfloat*)gl2psMalloc(size);
   memcpy(image->pixels, im->pixels, size);
-
+  
   return image;
 }
 
@@ -783,7 +780,7 @@
 {
   unsigned int i;
   GL2PSlist *png = (GL2PSlist*)png_get_io_ptr(png_ptr);
-  for(i = 0; i < length; i++)
+  for(i = 0; i < length; i++) 
     gl2psListAdd(png, &data[i]);
 }
 
@@ -801,21 +798,21 @@
 
   if(!(png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)))
     return;
-
+  
   if(!(info_ptr = png_create_info_struct(png_ptr))){
     png_destroy_write_struct(&png_ptr, NULL);
     return;
   }
-
+  
   if(setjmp(png_jmpbuf(png_ptr))) {
     png_destroy_write_struct(&png_ptr, &info_ptr);
     return;
   }
-
+  
   png_set_write_fn(png_ptr, (void *)png, gl2psUserWritePNG, gl2psUserFlushPNG);
   png_set_compression_level(png_ptr, Z_DEFAULT_COMPRESSION);
-  png_set_IHDR(png_ptr, info_ptr, pixmap->width, pixmap->height, 8,
-               PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
+  png_set_IHDR(png_ptr, info_ptr, pixmap->width, pixmap->height, 8, 
+               PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, 
                PNG_FILTER_TYPE_BASE);
   png_write_info(png_ptr, info_ptr);
 
@@ -839,7 +836,7 @@
 
 /* Helper routines for text strings */
 
-static GLint gl2psAddText(GLint type, const char *str, const char *fontname,
+static GLint gl2psAddText(GLint type, const char *str, const char *fontname, 
                           GLshort fontsize, GLint alignment, GLfloat angle)
 {
   GLfloat pos[4];
@@ -871,7 +868,7 @@
   glGetFloatv(GL_CURRENT_RASTER_COLOR, prim->verts[0].rgba);
   prim->data.text = (GL2PSstring*)gl2psMalloc(sizeof(GL2PSstring));
   prim->data.text->str = (char*)gl2psMalloc((strlen(str)+1)*sizeof(char));
-  strcpy(prim->data.text->str, str);
+  strcpy(prim->data.text->str, str); 
   prim->data.text->fontname = (char*)gl2psMalloc((strlen(fontname)+1)*sizeof(char));
   strcpy(prim->data.text->fontname, fontname);
   prim->data.text->fontsize = fontsize;
@@ -880,7 +877,7 @@
 
   gl2psListAdd(gl2ps->auxprimitives, &prim);
   glPassThrough(GL2PS_TEXT_TOKEN);
-
+    
   return GL2PS_SUCCESS;
 }
 
@@ -888,13 +885,13 @@
 {
   GL2PSstring *text = (GL2PSstring*)gl2psMalloc(sizeof(GL2PSstring));
   text->str = (char*)gl2psMalloc((strlen(t->str)+1)*sizeof(char));
-  strcpy(text->str, t->str);
+  strcpy(text->str, t->str); 
   text->fontname = (char*)gl2psMalloc((strlen(t->fontname)+1)*sizeof(char));
   strcpy(text->fontname, t->fontname);
   text->fontsize = t->fontsize;
   text->alignment = t->alignment;
   text->angle = t->angle;
-
+  
   return text;
 }
 
@@ -914,7 +911,7 @@
   /* returns TRUE if gl2ps supports the argument combination: only two
      blending modes have been implemented so far */
 
-  if( (sfactor == GL_SRC_ALPHA && dfactor == GL_ONE_MINUS_SRC_ALPHA) ||
+  if( (sfactor == GL_SRC_ALPHA && dfactor == GL_ONE_MINUS_SRC_ALPHA) || 
       (sfactor == GL_ONE && dfactor == GL_ZERO) )
     return GL_TRUE;
   return GL_FALSE;
@@ -934,7 +931,7 @@
     v->rgba[3] = 1.0F;
     return;
   }
-
+  
   switch(gl2ps->blendfunc[0]){
   case GL_ONE:
     v->rgba[3] = 1.0F;
@@ -955,9 +952,9 @@
      a remarkable amount of PDF handling code inside this file depends
      on it if activated */
   /*
-  t->prop = T_CONST_COLOR;
+  t->prop = T_CONST_COLOR;    
   for(i = 0; i < 3; ++i){
-    if(!GL2PS_ZERO(t->vertex[0].rgba[i] - t->vertex[1].rgba[i]) ||
+    if(!GL2PS_ZERO(t->vertex[0].rgba[i] - t->vertex[1].rgba[i]) || 
        !GL2PS_ZERO(t->vertex[1].rgba[i] - t->vertex[2].rgba[i])){
       t->prop = T_VAR_COLOR;
       break;
@@ -965,7 +962,7 @@
   }
   */
 
-  if(!GL2PS_ZERO(t->vertex[0].rgba[3] - t->vertex[1].rgba[3]) ||
+  if(!GL2PS_ZERO(t->vertex[0].rgba[3] - t->vertex[1].rgba[3]) || 
      !GL2PS_ZERO(t->vertex[1].rgba[3] - t->vertex[2].rgba[3])){
     t->prop |= T_VAR_ALPHA;
   }
@@ -1008,7 +1005,7 @@
   }
 
   prim = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
-
+  
   prim->type = p->type;
   prim->numverts = p->numverts;
   prim->boundary = p->boundary;
@@ -1044,17 +1041,17 @@
   return GL_TRUE;
 }
 
-/*********************************************************************
+/********************************************************************* 
  *
- * 3D sorting routines
+ * 3D sorting routines 
  *
  *********************************************************************/
 
 static GLfloat gl2psComparePointPlane(GL2PSxyz point, GL2PSplane plane)
 {
-  return (plane[0] * point[0] +
-          plane[1] * point[1] +
-          plane[2] * point[2] +
+  return (plane[0] * point[0] + 
+          plane[1] * point[1] + 
+          plane[2] * point[2] + 
           plane[3]);
 }
 
@@ -1101,13 +1098,13 @@
   switch(prim->type){
   case GL2PS_TRIANGLE :
   case GL2PS_QUADRANGLE :
-    v[0] = prim->verts[1].xyz[0] - prim->verts[0].xyz[0];
-    v[1] = prim->verts[1].xyz[1] - prim->verts[0].xyz[1];
-    v[2] = prim->verts[1].xyz[2] - prim->verts[0].xyz[2];
-    w[0] = prim->verts[2].xyz[0] - prim->verts[0].xyz[0];
-    w[1] = prim->verts[2].xyz[1] - prim->verts[0].xyz[1];
-    w[2] = prim->verts[2].xyz[2] - prim->verts[0].xyz[2];
-    if((GL2PS_ZERO(v[0]) && GL2PS_ZERO(v[1]) && GL2PS_ZERO(v[2])) ||
+    v[0] = prim->verts[1].xyz[0] - prim->verts[0].xyz[0]; 
+    v[1] = prim->verts[1].xyz[1] - prim->verts[0].xyz[1]; 
+    v[2] = prim->verts[1].xyz[2] - prim->verts[0].xyz[2]; 
+    w[0] = prim->verts[2].xyz[0] - prim->verts[0].xyz[0]; 
+    w[1] = prim->verts[2].xyz[1] - prim->verts[0].xyz[1]; 
+    w[2] = prim->verts[2].xyz[2] - prim->verts[0].xyz[2]; 
+    if((GL2PS_ZERO(v[0]) && GL2PS_ZERO(v[1]) && GL2PS_ZERO(v[2])) || 
        (GL2PS_ZERO(w[0]) && GL2PS_ZERO(w[1]) && GL2PS_ZERO(w[2]))){
       plane[0] = plane[1] = 0.0F;
       plane[2] = 1.0F;
@@ -1115,16 +1112,16 @@
     }
     else{
       gl2psGetNormal(v, w, plane);
-      plane[3] =
-        - plane[0] * prim->verts[0].xyz[0]
-        - plane[1] * prim->verts[0].xyz[1]
+      plane[3] = 
+        - plane[0] * prim->verts[0].xyz[0] 
+        - plane[1] * prim->verts[0].xyz[1] 
         - plane[2] * prim->verts[0].xyz[2];
     }
     break;
   case GL2PS_LINE :
-    v[0] = prim->verts[1].xyz[0] - prim->verts[0].xyz[0];
-    v[1] = prim->verts[1].xyz[1] - prim->verts[0].xyz[1];
-    v[2] = prim->verts[1].xyz[2] - prim->verts[0].xyz[2];
+    v[0] = prim->verts[1].xyz[0] - prim->verts[0].xyz[0]; 
+    v[1] = prim->verts[1].xyz[1] - prim->verts[0].xyz[1]; 
+    v[2] = prim->verts[1].xyz[2] - prim->verts[0].xyz[2]; 
     if(GL2PS_ZERO(v[0]) && GL2PS_ZERO(v[1]) && GL2PS_ZERO(v[2])){
       plane[0] = plane[1] = 0.0F;
       plane[2] = 1.0F;
@@ -1135,9 +1132,9 @@
       else if(GL2PS_ZERO(v[1])) w[1] = 1.0F;
       else                      w[2] = 1.0F;
       gl2psGetNormal(v, w, plane);
-      plane[3] =
-        - plane[0] * prim->verts[0].xyz[0]
-        - plane[1] * prim->verts[0].xyz[1]
+      plane[3] = 
+        - plane[0] * prim->verts[0].xyz[0] 
+        - plane[1] * prim->verts[0].xyz[1] 
         - plane[2] * prim->verts[0].xyz[2];
     }
     break;
@@ -1172,11 +1169,11 @@
     sect = -gl2psComparePointPlane(a->xyz, plane) / psca;
   else
     sect = 0.0F;
-
+  
   c->xyz[0] = a->xyz[0] + v[0] * sect;
   c->xyz[1] = a->xyz[1] + v[1] * sect;
   c->xyz[2] = a->xyz[2] + v[2] * sect;
-
+  
   c->rgba[0] = (1 - sect) * a->rgba[0] + sect * b->rgba[0];
   c->rgba[1] = (1 - sect) * a->rgba[1] + sect * b->rgba[1];
   c->rgba[2] = (1 - sect) * a->rgba[2] + sect * b->rgba[2];
@@ -1199,10 +1196,10 @@
       numverts = 4;
     }
     switch(numverts){
-    case 1 : child->type = GL2PS_POINT; break;
-    case 2 : child->type = GL2PS_LINE; break;
-    case 3 : child->type = GL2PS_TRIANGLE; break;
-    case 4 : child->type = GL2PS_QUADRANGLE; break;
+    case 1 : child->type = GL2PS_POINT; break; 
+    case 2 : child->type = GL2PS_LINE; break; 
+    case 3 : child->type = GL2PS_TRIANGLE; break; 
+    case 4 : child->type = GL2PS_QUADRANGLE; break;    
     default: child->type = GL2PS_NO_TYPE; break;
     }
   }
@@ -1221,13 +1218,13 @@
       child->verts[i] = parent->verts[index0[i]];
     }
     else{
-      gl2psCutEdge(&parent->verts[index0[i]], &parent->verts[index1[i]],
+      gl2psCutEdge(&parent->verts[index0[i]], &parent->verts[index1[i]], 
                    plane, &child->verts[i]);
     }
   }
 }
 
-static void gl2psAddIndex(GLshort *index0, GLshort *index1, GLshort *nb,
+static void gl2psAddIndex(GLshort *index0, GLshort *index1, GLshort *nb, 
                           GLshort i, GLshort j)
 {
   GLint k;
@@ -1250,9 +1247,9 @@
 {
   GLint type = GL2PS_COINCIDENT;
   GLshort i, j;
-  GLfloat d[5];
-
-  for(i = 0; i < prim->numverts; i++){
+  GLfloat d[5]; 
+
+  for(i = 0; i < prim->numverts; i++){  
     d[i] = gl2psComparePointPlane(prim->verts[i].xyz, plane);
   }
 
@@ -1264,11 +1261,11 @@
       j = gl2psGetIndex(i, prim->numverts);
       if(d[j] > GL2PS_EPSILON){
         if(type == GL2PS_COINCIDENT)      type = GL2PS_IN_BACK_OF;
-        else if(type != GL2PS_IN_BACK_OF) return 1;
+        else if(type != GL2PS_IN_BACK_OF) return 1; 
         if(d[i] < -GL2PS_EPSILON)         return 1;
       }
       else if(d[j] < -GL2PS_EPSILON){
-        if(type == GL2PS_COINCIDENT)       type = GL2PS_IN_FRONT_OF;
+        if(type == GL2PS_COINCIDENT)       type = GL2PS_IN_FRONT_OF;   
         else if(type != GL2PS_IN_FRONT_OF) return 1;
         if(d[i] > GL2PS_EPSILON)           return 1;
       }
@@ -1277,16 +1274,16 @@
   return 0;
 }
 
-static GLint gl2psSplitPrimitive(GL2PSprimitive *prim, GL2PSplane plane,
+static GLint gl2psSplitPrimitive(GL2PSprimitive *prim, GL2PSplane plane, 
                                  GL2PSprimitive **front, GL2PSprimitive **back)
 {
   GLshort i, j, in = 0, out = 0, in0[5], in1[5], out0[5], out1[5];
   GLint type;
-  GLfloat d[5];
+  GLfloat d[5]; 
 
   type = GL2PS_COINCIDENT;
 
-  for(i = 0; i < prim->numverts; i++){
+  for(i = 0; i < prim->numverts; i++){  
     d[i] = gl2psComparePointPlane(prim->verts[i].xyz, plane);
   }
 
@@ -1301,7 +1298,7 @@
       j = gl2psGetIndex(i, prim->numverts);
       if(d[j] > GL2PS_EPSILON){
         if(type == GL2PS_COINCIDENT)      type = GL2PS_IN_BACK_OF;
-        else if(type != GL2PS_IN_BACK_OF) type = GL2PS_SPANNING;
+        else if(type != GL2PS_IN_BACK_OF) type = GL2PS_SPANNING; 
         if(d[i] < -GL2PS_EPSILON){
           gl2psAddIndex(in0, in1, &in, i, j);
           gl2psAddIndex(out0, out1, &out, i, j);
@@ -1310,7 +1307,7 @@
         gl2psAddIndex(out0, out1, &out, j, -1);
       }
       else if(d[j] < -GL2PS_EPSILON){
-        if(type == GL2PS_COINCIDENT)       type = GL2PS_IN_FRONT_OF;
+        if(type == GL2PS_COINCIDENT)       type = GL2PS_IN_FRONT_OF;   
         else if(type != GL2PS_IN_FRONT_OF) type = GL2PS_SPANNING;
         if(d[i] > GL2PS_EPSILON){
           gl2psAddIndex(in0, in1, &in, i, j);
@@ -1337,7 +1334,7 @@
   return type;
 }
 
-static void gl2psDivideQuad(GL2PSprimitive *quad,
+static void gl2psDivideQuad(GL2PSprimitive *quad, 
                             GL2PSprimitive **t1, GL2PSprimitive **t2)
 {
   *t1 = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
@@ -1366,17 +1363,17 @@
   GL2PSprimitive *q, *w;
   GLfloat dq = 0.0F, dw = 0.0F, diff;
   int i;
-
+  
   q = *(GL2PSprimitive**)a;
   w = *(GL2PSprimitive**)b;
 
   for(i = 0; i < q->numverts; i++){
-    dq += q->verts[i].xyz[2];
+    dq += q->verts[i].xyz[2]; 
   }
   dq /= (GLfloat)q->numverts;
 
   for(i = 0; i < w->numverts; i++){
-    dw += w->verts[i].xyz[2];
+    dw += w->verts[i].xyz[2]; 
   }
   dw /= (GLfloat)w->numverts;
 
@@ -1427,7 +1424,7 @@
       for(j = 0; j < gl2psListNbr(primitives); j++){
         if(j != i){
           prim2 = *(GL2PSprimitive**)gl2psListPointer(primitives, j);
-          count += gl2psTestSplitPrimitive(prim2, plane);
+          count += gl2psTestSplitPrimitive(prim2, plane); 
         }
         if(count > best) break;
       }
@@ -1461,7 +1458,7 @@
 static void gl2psFreePrimitive(void *data)
 {
   GL2PSprimitive *q;
-
+  
   q = *(GL2PSprimitive**)data;
   gl2psFree(q->verts);
   if(q->type == GL2PS_TEXT || q->type == GL2PS_SPECIAL){
@@ -1486,7 +1483,7 @@
     gl2psListAdd(list, &t2);
     gl2psFreePrimitive(&prim);
   }
-
+  
 }
 
 static void gl2psFreeBspTree(GL2PSbsptree **tree)
@@ -1598,7 +1595,7 @@
     }
     gl2psTraverseBspTree(tree->front, eye, epsilon, compare, action, inverse);
   }
-  else if(GL_TRUE == compare(-epsilon, result)){
+  else if(GL_TRUE == compare(-epsilon, result)){ 
     gl2psTraverseBspTree(tree->front, eye, epsilon, compare, action, inverse);
     if(inverse){
       gl2psListActionInverse(tree->primitives, action);
@@ -1666,18 +1663,18 @@
     else if(prim->offset && (prim->type == GL2PS_TRIANGLE)){
       factor = gl2ps->offset[0];
       units = gl2ps->offset[1];
-      area =
-        (prim->verts[1].xyz[0] - prim->verts[0].xyz[0]) *
-        (prim->verts[2].xyz[1] - prim->verts[1].xyz[1]) -
-        (prim->verts[2].xyz[0] - prim->verts[1].xyz[0]) *
+      area = 
+        (prim->verts[1].xyz[0] - prim->verts[0].xyz[0]) * 
+        (prim->verts[2].xyz[1] - prim->verts[1].xyz[1]) - 
+        (prim->verts[2].xyz[0] - prim->verts[1].xyz[0]) * 
         (prim->verts[1].xyz[1] - prim->verts[0].xyz[1]);
       if(!GL2PS_ZERO(area)){
-        dZdX =
+        dZdX = 
           ((prim->verts[2].xyz[1] - prim->verts[1].xyz[1]) *
            (prim->verts[1].xyz[2] - prim->verts[0].xyz[2]) -
            (prim->verts[1].xyz[1] - prim->verts[0].xyz[1]) *
            (prim->verts[2].xyz[2] - prim->verts[1].xyz[2])) / area;
-        dZdY =
+        dZdY = 
           ((prim->verts[1].xyz[0] - prim->verts[0].xyz[0]) *
            (prim->verts[2].xyz[2] - prim->verts[1].xyz[2]) -
            (prim->verts[2].xyz[0] - prim->verts[1].xyz[0]) *
@@ -1695,15 +1692,15 @@
   }
 }
 
-/*********************************************************************
+/********************************************************************* 
  *
- * 2D sorting routines (for occlusion culling)
+ * 2D sorting routines (for occlusion culling) 
  *
  *********************************************************************/
 
 static GLint gl2psGetPlaneFromPoints(GL2PSxyz a, GL2PSxyz b, GL2PSplane plane)
 {
-  GLfloat n;
+  GLfloat n; 
 
   plane[0] = b[1] - a[1];
   plane[1] = a[0] - b[0];
@@ -1712,7 +1709,7 @@
   if(!GL2PS_ZERO(n)){
     plane[0] /= n;
     plane[1] /= n;
-    plane[3] = -plane[0]*a[0]-plane[1]*a[1];
+    plane[3] = -plane[0]*a[0]-plane[1]*a[1]; 
     return 1;
   }
   else{
@@ -1897,8 +1894,8 @@
 }
 
 static void gl2psSplitPrimitive2D(GL2PSprimitive *prim,
-                                  GL2PSplane plane,
-                                  GL2PSprimitive **front,
+                                  GL2PSplane plane, 
+                                  GL2PSprimitive **front, 
                                   GL2PSprimitive **back)
 {
   /* cur will hold the position of the current vertex
@@ -1907,10 +1904,10 @@
      v1 and v2 represent the current and previous vertices, respectively
      flag is set if the current vertex should be checked against the plane */
   GLint cur = -1, prev = -1, i, v1 = 0, v2 = 0, flag = 1, prev0 = -1;
-
+  
   /* list of vertices that will go in front and back primitive */
   GL2PSvertex *front_list = NULL, *back_list = NULL;
-
+  
   /* number of vertices in front and back list */
   GLshort front_count = 0, back_count = 0;
 
@@ -1927,7 +1924,7 @@
       if(i == 0){
         prev0 = cur;
       }
-    }
+    } 
     if(((prev == -1) || (prev == cur) || (prev == 0) || (cur == 0)) &&
        (i < prim->numverts)){
       if(cur == GL2PS_POINT_INFRONT){
@@ -1982,12 +1979,12 @@
 {
   GLint ret = 0;
   GL2PSprimitive *frontprim = NULL, *backprim = NULL;
-
+  
   /* FIXME: until we consider the actual extent of text strings and
      pixmaps, never cull them. Otherwise the whole string/pixmap gets
      culled as soon as the reference point is hidden */
-  if(prim->type == GL2PS_PIXMAP ||
-     prim->type == GL2PS_TEXT ||
+  if(prim->type == GL2PS_PIXMAP || 
+     prim->type == GL2PS_TEXT || 
      prim->type == GL2PS_SPECIAL){
     return 1;
   }
@@ -2001,7 +1998,7 @@
   else{
     switch(gl2psCheckPrimitive(prim, (*tree)->plane)){
     case GL2PS_IN_BACK_OF: return gl2psAddInBspImageTree(prim, &(*tree)->back);
-    case GL2PS_IN_FRONT_OF:
+    case GL2PS_IN_FRONT_OF: 
       if((*tree)->front != NULL) return gl2psAddInBspImageTree(prim, &(*tree)->front);
       else                       return 0;
     case GL2PS_SPANNING:
@@ -2136,14 +2133,14 @@
   gl2psBuildPolygonBoundary(tree->front);
 }
 
-/*********************************************************************
+/********************************************************************* 
  *
  * Feedback buffer parser
  *
  *********************************************************************/
 
-static void gl2psAddPolyPrimitive(GLshort type, GLshort numverts,
-                                  GL2PSvertex *verts, GLint offset,
+static void gl2psAddPolyPrimitive(GLshort type, GLshort numverts, 
+                                  GL2PSvertex *verts, GLint offset, 
                                   GLushort pattern, GLint factor,
                                   GLfloat width, char boundary)
 {
@@ -2210,7 +2207,7 @@
   while(used > 0){
 
     if(GL_TRUE == boundary) gl2ps->boundary = GL_TRUE;
-
+    
     switch((GLint)*current){
     case GL_POINT_TOKEN :
       current ++;
@@ -2218,7 +2215,7 @@
       i = gl2psGetVertex(&vertices[0], current);
       current += i;
       used    -= i;
-      gl2psAddPolyPrimitive(GL2PS_POINT, 1, vertices, 0,
+      gl2psAddPolyPrimitive(GL2PS_POINT, 1, vertices, 0, 
                             pattern, factor, psize, 0);
       break;
     case GL_LINE_TOKEN :
@@ -2231,7 +2228,7 @@
       i = gl2psGetVertex(&vertices[1], current);
       current += i;
       used    -= i;
-      gl2psAddPolyPrimitive(GL2PS_LINE, 2, vertices, 0,
+      gl2psAddPolyPrimitive(GL2PS_LINE, 2, vertices, 0, 
                             pattern, factor, lwidth, 0);
       break;
     case GL_POLYGON_TOKEN :
@@ -2262,7 +2259,7 @@
         else
           v ++;
       }
-      break;
+      break;      
     case GL_BITMAP_TOKEN :
     case GL_DRAW_PIXEL_TOKEN :
     case GL_COPY_PIXEL_TOKEN :
@@ -2271,7 +2268,7 @@
       i = gl2psGetVertex(&vertices[0], current);
       current += i;
       used    -= i;
-      break;
+      break;      
     case GL_PASS_THROUGH_TOKEN :
       switch((GLint)current[1]){
       case GL2PS_BEGIN_OFFSET_TOKEN : offset = 1; break;
@@ -2281,32 +2278,32 @@
       case GL2PS_END_STIPPLE_TOKEN : pattern = factor = 0; break;
       case GL2PS_BEGIN_BLEND_TOKEN : gl2ps->blending = GL_TRUE; break;
       case GL2PS_END_BLEND_TOKEN : gl2ps->blending = GL_FALSE; break;
-      case GL2PS_BEGIN_STIPPLE_TOKEN :
+      case GL2PS_BEGIN_STIPPLE_TOKEN : 
         current += 2;
-        used -= 2;
-        pattern = (GLushort)current[1];
+        used -= 2; 
+        pattern = (GLushort)current[1]; 
         current += 2;
-        used -= 2;
-        factor = (GLint)current[1];
+        used -= 2; 
+        factor = (GLint)current[1]; 
         break;
-      case GL2PS_SRC_BLEND_TOKEN :
-        current += 2;
-        used -= 2;
+      case GL2PS_SRC_BLEND_TOKEN : 
+        current += 2; 
+        used -= 2; 
         gl2ps->blendfunc[0] = (GLint)current[1];
         break;
-      case GL2PS_DST_BLEND_TOKEN :
-        current += 2;
-        used -= 2;
+      case GL2PS_DST_BLEND_TOKEN : 
+        current += 2; 
+        used -= 2; 
         gl2ps->blendfunc[1] = (GLint)current[1];
         break;
-      case GL2PS_POINT_SIZE_TOKEN :
-        current += 2;
-        used -= 2;
+      case GL2PS_POINT_SIZE_TOKEN : 
+        current += 2; 
+        used -= 2; 
         psize = current[1];
         break;
-      case GL2PS_LINE_WIDTH_TOKEN :
-        current += 2;
-        used -= 2;
+      case GL2PS_LINE_WIDTH_TOKEN : 
+        current += 2; 
+        used -= 2; 
         lwidth = current[1];
         break;
       case GL2PS_IMAGEMAP_TOKEN :
@@ -2320,26 +2317,24 @@
         prim->pattern = 0;
         prim->factor = 0;
         prim->width = 1;
-
+        
         node = (GL2PSimagemap*)gl2psMalloc(sizeof(GL2PSimagemap));
         node->image = (GL2PSimage*)gl2psMalloc(sizeof(GL2PSimage));
         node->image->type = 0;
         node->image->format = 0;
-        node->image->zoom_x = 1.0F;
-        node->image->zoom_y = 1.0F;
         node->next = NULL;
-
+        
         if(gl2ps->imagemap_head == NULL)
           gl2ps->imagemap_head = node;
         else
           gl2ps->imagemap_tail->next = node;
         gl2ps->imagemap_tail = node;
         prim->data.image = node->image;
-
+        
         current += 2; used -= 2;
         i = gl2psGetVertex(&prim->verts[0], &current[1]);
         current += i; used -= i;
-
+        
         node->image->width = (GLint)current[2];
         current += 2; used -= 2;
         node->image->height = (GLint)current[2];
@@ -2359,12 +2354,12 @@
 
         sizeoffloat = sizeof(GLfloat);
         v = 2 * sizeoffloat;
-        vtot = node->image->height + node->image->height *
+        vtot = node->image->height + node->image->height * 
           ((node->image->width - 1) / 8);
         node->image->pixels = (GLfloat*)gl2psMalloc(v + vtot);
         node->image->pixels[0] = prim->verts[0].xyz[0];
         node->image->pixels[1] = prim->verts[0].xyz[1];
-
+        
         for(i = 0; i < vtot; i += sizeoffloat){
           current += 2; used -= 2;
           if((vtot - i) >= 4)
@@ -2378,15 +2373,15 @@
       case GL2PS_DRAW_PIXELS_TOKEN :
       case GL2PS_TEXT_TOKEN :
         if(auxindex < gl2psListNbr(gl2ps->auxprimitives))
-          gl2psListAdd(gl2ps->primitives,
+          gl2psListAdd(gl2ps->primitives, 
                        gl2psListPointer(gl2ps->auxprimitives, auxindex++));
         else
           gl2psMsg(GL2PS_ERROR, "Wrong number of auxiliary tokens in buffer");
         break;
       }
-      current += 2;
-      used -= 2;
-      break;
+      current += 2; 
+      used -= 2; 
+      break;      
     default :
       gl2psMsg(GL2PS_WARNING, "Unknown token in buffer");
       current ++;
@@ -2398,7 +2393,7 @@
   gl2psListReset(gl2ps->auxprimitives);
 }
 
-/*********************************************************************
+/********************************************************************* 
  *
  * PostScript routines
  *
@@ -2428,17 +2423,17 @@
   if((width <= 0) || (height <= 0)) return;
 
   gl2psPrintf("gsave\n");
-  gl2psPrintf("%.2f %.2f translate\n", x, y);
-  gl2psPrintf("%.2f %.2f scale\n", width * im->zoom_x, height * im->zoom_y);
+  gl2psPrintf("%.2f %.2f translate\n", x, y); 
+  gl2psPrintf("%d %d scale\n", width, height); 
 
   if(greyscale){ /* greyscale */
-    gl2psPrintf("/picstr %d string def\n", width);
-    gl2psPrintf("%d %d %d\n", width, height, 8);
-    gl2psPrintf("[ %d 0 0 -%d 0 %d ]\n", width, height, height);
+    gl2psPrintf("/picstr %d string def\n", width); 
+    gl2psPrintf("%d %d %d\n", width, height, 8); 
+    gl2psPrintf("[ %d 0 0 -%d 0 %d ]\n", width, height, height); 
     gl2psPrintf("{ currentfile picstr readhexstring pop }\n");
     gl2psPrintf("image\n");
     for(row = 0; row < height; row++){
-      for(col = 0; col < width; col++){
+      for(col = 0; col < width; col++){ 
         gl2psGetRGB(im, col, row, &dr, &dg, &db);
         fgrey = (0.30F * dr + 0.59F * dg + 0.11F * db);
         grey = (unsigned char)(255. * fgrey);
@@ -2446,8 +2441,8 @@
       }
       gl2psPrintf("\n");
     }
-    nbhex = width * height * 2;
-    gl2psPrintf("%%%% nbhex digit          :%d\n", nbhex);
+    nbhex = width * height * 2; 
+    gl2psPrintf("%%%% nbhex digit          :%d\n", nbhex); 
   }
   else if(nbit == 2){ /* color, 2 bits for r and g and b; rgbs following each other */
     nrgb = width  * 3;
@@ -2468,7 +2463,7 @@
         if(icase == 1) {
           if(col < width) {
             gl2psGetRGB(im, col, row, &dr, &dg, &db);
-          }
+          } 
           else {
             dr = dg = db = 0;
           }
@@ -2481,7 +2476,7 @@
           b = (b<<2) + blue;
           if(col < width) {
             gl2psGetRGB(im, col, row, &dr, &dg, &db);
-          }
+          } 
           else {
             dr = dg = db = 0;
           }
@@ -2493,7 +2488,7 @@
           gl2psWriteByte(b);
           b = 0;
           icase++;
-        }
+        } 
         else if(icase == 2) {
           b = green;
           b = (b<<2) + blue;
@@ -2512,7 +2507,7 @@
           gl2psWriteByte(b);
           b = 0;
           icase++;
-        }
+        } 
         else if(icase == 3) {
           b = blue;
           if(col < width) {
@@ -2540,7 +2535,7 @@
     nrgb = width  * 3;
     nbits = nrgb * nbit;
     nbyte = nbits / 8;
-    if((nbyte * 8) != nbits) nbyte++;
+    if((nbyte * 8) != nbits) nbyte++; 
     gl2psPrintf("/rgbstr %d string def\n", nbyte);
     gl2psPrintf("%d %d %d\n", width, height, nbit);
     gl2psPrintf("[ %d 0 0 -%d 0 %d ]\n", width, height, height);
@@ -2554,7 +2549,7 @@
         if(icase == 1) {
           if(col < width) {
             gl2psGetRGB(im, col, row, &dr, &dg, &db);
-          }
+          } 
           else {
             dr = dg = db = 0;
           }
@@ -2563,12 +2558,12 @@
           green = (unsigned char)(15. * dg);
           gl2psPrintf("%x%x", red, green);
           icase++;
-        }
+        } 
         else if(icase == 2) {
           blue = (unsigned char)(15. * db);
           if(col < width) {
             gl2psGetRGB(im, col, row, &dr, &dg, &db);
-          }
+          } 
           else {
             dr = dg = db = 0;
           }
@@ -2591,7 +2586,7 @@
     nbyte = width * 3;
     gl2psPrintf("/rgbstr %d string def\n", nbyte);
     gl2psPrintf("%d %d %d\n", width, height, 8);
-    gl2psPrintf("[ %d 0 0 -%d 0 %d ]\n", width, height, height);
+    gl2psPrintf("[ %d 0 0 -%d 0 %d ]\n", width, height, height); 
     gl2psPrintf("{ currentfile rgbstr readhexstring pop }\n");
     gl2psPrintf("false 3\n");
     gl2psPrintf("colorimage\n");
@@ -2608,7 +2603,7 @@
       gl2psPrintf("\n");
     }
   }
-
+  
   gl2psPrintf("grestore\n");
 }
 
@@ -2616,14 +2611,14 @@
                                          GLsizei width, GLsizei height,
                                          const unsigned char *imagemap){
   int i, size;
-
+  
   if((width <= 0) || (height <= 0)) return;
-
+  
   size = height + height * (width - 1) / 8;
-
+  
   gl2psPrintf("gsave\n");
   gl2psPrintf("%.2f %.2f translate\n", x, y);
-  gl2psPrintf("%d %d scale\n%d %d\ntrue\n", width, height,width, height);
+  gl2psPrintf("%d %d scale\n%d %d\ntrue\n", width, height,width, height); 
   gl2psPrintf("[ %d 0 0 -%d 0 %d ] {<", width, height);
   for(i = 0; i < size; i++){
     gl2psWriteByte(*imagemap);
@@ -2657,7 +2652,7 @@
               "%%%%LanguageLevel: 3\n"
               "%%%%DocumentData: Clean7Bit\n"
               "%%%%Pages: 1\n",
-              gl2ps->title, GL2PS_MAJOR_VERSION, GL2PS_MINOR_VERSION,
+              gl2ps->title, GL2PS_MAJOR_VERSION, GL2PS_MINOR_VERSION, 
               GL2PS_PATCH_VERSION, GL2PS_EXTRA_VERSION, GL2PS_COPYRIGHT,
               gl2ps->producer, ctime(&now));
 
@@ -2666,18 +2661,18 @@
                 "%%%%DocumentMedia: Default %d %d 0 () ()\n",
                 (gl2ps->options & GL2PS_LANDSCAPE) ? "Landscape" : "Portrait",
                 (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[3] :
-                (int)gl2ps->viewport[2],
-                (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[2] :
+                (int)gl2ps->viewport[2], 
+                (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[2] : 
                 (int)gl2ps->viewport[3]);
   }
 
   gl2psPrintf("%%%%BoundingBox: %d %d %d %d\n"
               "%%%%EndComments\n",
-              (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[1] :
+              (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[1] : 
               (int)gl2ps->viewport[0],
               (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[0] :
               (int)gl2ps->viewport[1],
-              (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[3] :
+              (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[3] : 
               (int)gl2ps->viewport[2],
               (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[2] :
               (int)gl2ps->viewport[3]);
@@ -2725,7 +2720,7 @@
   /* rotated text routines: same nameanem with R appended */
 
   gl2psPrintf("/FCT { FC translate 0 0 } BD\n"
-              "/SR  { gsave FCT moveto rotate show grestore } BD\n"
+              "/SR  { gsave FCT moveto rotate show grestore } BD\n"  
               "/SBCR{ gsave FCT moveto rotate SW -2 div 0 rmoveto show grestore } BD\n"
               "/SBRR{ gsave FCT moveto rotate SW neg 0 rmoveto show grestore } BD\n"
               "/SCLR{ gsave FCT moveto rotate 0 SH -2 div rmoveto show grestore} BD\n");
@@ -2740,7 +2735,7 @@
               "/L  { lineto } BD\n"
               "/LE { lineto stroke } BD\n"
               "/T  { newpath moveto lineto lineto closepath fill } BD\n");
-
+  
   /* Smooth-shaded triangle with PostScript level 3 shfill operator:
         x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 STshfill */
 
@@ -2794,11 +2789,11 @@
               "      4 index 10 index add 0.5 mul\n" /* g12 = (g1+g2)/2 */
               "      4 index 10 index add 0.5 mul\n" /* b12 = (b1+b2)/2 */
               "      5 copy 5 copy 40 5 roll 25 5 roll 15 5 roll 25 5 roll\n");
-
+  
   /* stack = (V3) (V13) (V23) (V13) (V12) (V23) (V13) (V1) (V12) (V23) (V12) (V2) */
 
   gl2psPrintf("      STnoshfill STnoshfill STnoshfill STnoshfill } BD\n");
-
+  
   /* Gouraud shaded triangle using recursive subdivision until the difference
      between corner colors does not exceed the thresholds:
         x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 STnoshfill  */
@@ -2832,7 +2827,7 @@
               "          ifelse }\n"
               "        ifelse }\n"
               "      ifelse } BD\n");
-
+  
   gl2psPrintf("tryPS3shading\n"
               "{ /shfill where\n"
               "  { /ST { STshfill } BD }\n"
@@ -2849,7 +2844,7 @@
               "%%%%EndSetup\n"
               "%%%%Page: 1 1\n"
               "%%%%BeginPageSetup\n");
-
+  
   if(gl2ps->options & GL2PS_LANDSCAPE){
     gl2psPrintf("%d 0 translate 90 rotate\n",
                 (int)gl2ps->viewport[3]);
@@ -2859,14 +2854,14 @@
               "mark\n"
               "gsave\n"
               "1.0 1.0 scale\n");
-
+          
   if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
     gl2psPrintf("%g %g %g C\n"
                 "newpath %d %d moveto %d %d lineto %d %d lineto %d %d lineto\n"
                 "closepath fill\n",
-                gl2ps->bgcolor[0], gl2ps->bgcolor[1], gl2ps->bgcolor[2],
-                (int)gl2ps->viewport[0], (int)gl2ps->viewport[1], (int)gl2ps->viewport[2],
-                (int)gl2ps->viewport[1], (int)gl2ps->viewport[2], (int)gl2ps->viewport[3],
+                gl2ps->bgcolor[0], gl2ps->bgcolor[1], gl2ps->bgcolor[2], 
+                (int)gl2ps->viewport[0], (int)gl2ps->viewport[1], (int)gl2ps->viewport[2], 
+                (int)gl2ps->viewport[1], (int)gl2ps->viewport[2], (int)gl2ps->viewport[3], 
                 (int)gl2ps->viewport[0], (int)gl2ps->viewport[3]);
   }
 }
@@ -2896,7 +2891,7 @@
   }
 }
 
-static void gl2psParseStipplePattern(GLushort pattern, GLint factor,
+static void gl2psParseStipplePattern(GLushort pattern, GLint factor, 
                                      int *nb, int array[10])
 {
   int i, n;
@@ -2936,10 +2931,10 @@
 
   if(pattern == gl2ps->lastpattern && factor == gl2ps->lastfactor)
     return 0;
-
+  
   gl2ps->lastpattern = pattern;
   gl2ps->lastfactor = factor;
-
+  
   if(!pattern || !factor){
     /* solid line */
     len += gl2psPrintf("[] 0 %s\n", str);
@@ -2953,7 +2948,7 @@
     }
     len += gl2psPrintf("] 0 %s\n", str);
   }
-
+  
   return len;
 }
 
@@ -2976,7 +2971,7 @@
   switch(prim->type){
   case GL2PS_POINT :
     gl2psPrintPostScriptColor(prim->verts[0].rgba);
-    gl2psPrintf("%g %g %g P\n",
+    gl2psPrintf("%g %g %g P\n", 
                 prim->verts[0].xyz[0], prim->verts[0].xyz[1], 0.5 * prim->width);
     break;
   case GL2PS_LINE :
@@ -3139,14 +3134,14 @@
     gl2psPrintf("%g %g %g C\n"
                 "newpath %d %d moveto %d %d lineto %d %d lineto %d %d lineto\n"
                 "closepath fill\n",
-                rgba[0], rgba[1], rgba[2],
+                rgba[0], rgba[1], rgba[2], 
                 x, y, x+w, y, x+w, y+h, x, y+h);
   }
-
+    
   gl2psPrintf("newpath %d %d moveto %d %d lineto %d %d lineto %d %d lineto\n"
               "closepath clip\n",
               x, y, x+w, y, x+w, y+h, x, y+h);
-
+  
 }
 
 static GLint gl2psPrintPostScriptEndViewport(void)
@@ -3188,7 +3183,7 @@
   "Encapsulated Postscript"
 };
 
-/*********************************************************************
+/********************************************************************* 
  *
  * LaTeX routines
  *
@@ -3216,7 +3211,7 @@
 
   time(&now);
 
-  fprintf(gl2ps->stream,
+  fprintf(gl2ps->stream, 
           "%% Title: %s\n"
           "%% Creator: GL2PS %d.%d.%d%s, %s\n"
           "%% For: %s\n"
@@ -3225,7 +3220,7 @@
           GL2PS_PATCH_VERSION, GL2PS_EXTRA_VERSION, GL2PS_COPYRIGHT,
           gl2ps->producer, ctime(&now));
 
-  fprintf(gl2ps->stream,
+  fprintf(gl2ps->stream, 
           "\\setlength{\\unitlength}{1pt}\n"
           "\\begin{picture}(0,0)\n"
           "\\includegraphics{%s}\n"
@@ -3243,13 +3238,10 @@
 
   switch(prim->type){
   case GL2PS_TEXT :
-    fprintf(gl2ps->stream, "\\fontsize{%d}{0}\n\\selectfont",
+    fprintf(gl2ps->stream, "\\fontsize{%d}{0}\n\\selectfont", 
             prim->data.text->fontsize);
-    fprintf(gl2ps->stream, "\\put(%g,%g)",
+    fprintf(gl2ps->stream, "\\put(%g,%g){\\makebox(0,0)",
             prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
-    if(prim->data.text->angle)
-      fprintf(gl2ps->stream, "{\\rotatebox{%g}", prim->data.text->angle);
-    fprintf(gl2ps->stream, "{\\makebox(0,0)");
     switch(prim->data.text->alignment){
     case GL2PS_TEXT_C:
       fprintf(gl2ps->stream, "{");
@@ -3280,6 +3272,8 @@
       fprintf(gl2ps->stream, "[bl]{");
       break;
     }
+    if(prim->data.text->angle)
+      fprintf(gl2ps->stream, "\\rotatebox{%g}{", prim->data.text->angle);
     fprintf(gl2ps->stream, "\\textcolor[rgb]{%g,%g,%g}{{%s}}",
             prim->verts[0].rgba[0], prim->verts[0].rgba[1], prim->verts[0].rgba[2],
             prim->data.text->str);
@@ -3307,7 +3301,7 @@
 static void gl2psPrintTeXBeginViewport(GLint viewport[4])
 {
   glRenderMode(GL_FEEDBACK);
-
+  
   if(gl2ps->header){
     gl2psPrintTeXHeader();
     gl2ps->header = GL_FALSE;
@@ -3336,7 +3330,7 @@
   "LaTeX text"
 };
 
-/*********************************************************************
+/********************************************************************* 
  *
  * PDF routines
  *
@@ -3372,7 +3366,7 @@
 static int gl2psPrintPDFFillColor(GL2PSrgba rgba)
 {
   int i, offs = 0;
-
+  
   for(i = 0; i < 3; ++i){
     if(GL2PS_ZERO(rgba[i]))
       offs += gl2psPrintf("%.0f ", 0.);
@@ -3398,18 +3392,18 @@
 static void gl2psPutPDFText(GL2PSstring *text, int cnt, GLfloat x, GLfloat y)
 {
   GLfloat rad, crad, srad;
-
+  
   if(text->angle == 0.0F){
     gl2ps->streamlength += gl2psPrintf
       ("BT\n"
        "/F%d %d Tf\n"
        "%f %f Td\n"
        "(%s) Tj\n"
-       "ET\n",
+       "ET\n", 
        cnt, text->fontsize, x, y, text->str);
   }
   else{
-    rad = (GLfloat)M_PI * text->angle / 180.0F;
+    rad = M_PI * text->angle / 180.0F;
     srad = (GLfloat)sin(rad);
     crad = (GLfloat)cos(rad);
     gl2ps->streamlength += gl2psPrintf
@@ -3434,23 +3428,23 @@
 
 static void gl2psPDFstacksInit(void)
 {
-  gl2ps->objects_stack = 7 /* FIXED_XREF_ENTRIES */ + 1;
-  gl2ps->extgs_stack = 0;
-  gl2ps->font_stack = 0;
-  gl2ps->im_stack = 0;
-  gl2ps->trgroupobjects_stack = 0;
-  gl2ps->shader_stack = 0;
-  gl2ps->mshader_stack = 0;
+  gl2ps->objects_stack = 7 /* FIXED_XREF_ENTRIES */ + 1; 
+  gl2ps->extgs_stack = 0;   
+  gl2ps->font_stack = 0;    
+  gl2ps->im_stack = 0;      
+  gl2ps->trgroupobjects_stack = 0;    
+  gl2ps->shader_stack = 0;  
+  gl2ps->mshader_stack = 0; 
 }
 
 static void gl2psPDFgroupObjectInit(GL2PSpdfgroup *gro)
 {
   if(!gro)
     return;
-
+  
   gro->ptrlist = NULL;
-  gro->fontno = gro->gsno = gro->imno = gro->maskshno = gro->shno
-    = gro->trgroupno = gro->fontobjno = gro->imobjno = gro->shobjno
+  gro->fontno = gro->gsno = gro->imno = gro->maskshno = gro->shno 
+    = gro->trgroupno = gro->fontobjno = gro->imobjno = gro->shobjno 
     = gro->maskshobjno = gro->gsobjno = gro->trgroupobjno = -1;
 }
 
@@ -3475,7 +3469,7 @@
   gl2ps->pdfgrouplist = gl2psListCreate(500, 500, sizeof(GL2PSpdfgroup));
   gl2psInitTriangle(&lastt);
 
-  for(i = 0; i < gl2psListNbr(gl2ps->pdfprimlist); ++i){
+  for(i = 0; i < gl2psListNbr(gl2ps->pdfprimlist); ++i){  
     p = *(GL2PSprimitive**)gl2psListPointer(gl2ps->pdfprimlist, i);
     switch(p->type){
     case GL2PS_PIXMAP:
@@ -3493,7 +3487,7 @@
       gl2psListAdd(gl2ps->pdfgrouplist, &gro);
       break;
     case GL2PS_LINE:
-      if(lasttype != p->type || lastwidth != p->width ||
+      if(lasttype != p->type || lastwidth != p->width || 
          lastpattern != p->pattern || lastfactor != p->factor ||
          !gl2psSameColor(p->verts[0].rgba, lastrgba)){
         gl2psPDFgroupObjectInit(&gro);
@@ -3512,7 +3506,7 @@
       lastrgba[2] = p->verts[0].rgba[2];
       break;
     case GL2PS_POINT:
-      if(lasttype != p->type || lastwidth != p->width ||
+      if(lasttype != p->type || lastwidth != p->width || 
          !gl2psSameColor(p->verts[0].rgba, lastrgba)){
         gl2psPDFgroupObjectInit(&gro);
         gro.ptrlist = gl2psListCreate(1,2,sizeof(GL2PSprimitive*));
@@ -3529,10 +3523,10 @@
       break;
     case GL2PS_TRIANGLE:
       gl2psFillTriangleFromPrimitive(&tmpt, p, GL_TRUE);
-      lastTriangleWasNotSimpleWithSameColor =
+      lastTriangleWasNotSimpleWithSameColor = 
         !(tmpt.prop & T_CONST_COLOR && tmpt.prop & T_ALPHA_1) ||
         !gl2psSameColor(tmpt.vertex[0].rgba, lastt.vertex[0].rgba);
-      if(lasttype == p->type && tmpt.prop == lastt.prop &&
+      if(lasttype == p->type && tmpt.prop == lastt.prop && 
          lastTriangleWasNotSimpleWithSameColor){
         /* TODO Check here for last alpha */
         gl2psListAdd(gro.ptrlist, &p);
@@ -3547,7 +3541,7 @@
       break;
     default:
       break;
-    }
+    } 
     lasttype = p->type;
   }
 }
@@ -3556,7 +3550,7 @@
 {
   GL2PStriangle t;
   GL2PSprimitive *prim = NULL;
-
+  
   if(!gro)
     return;
 
@@ -3569,35 +3563,35 @@
     return;
 
   gl2psFillTriangleFromPrimitive(&t, prim, GL_TRUE);
-
-  if(t.prop & T_CONST_COLOR && t.prop & T_ALPHA_LESS_1){
-    gro->gsno = gl2ps->extgs_stack++;
+  
+  if(t.prop & T_CONST_COLOR && t.prop & T_ALPHA_LESS_1){        
+    gro->gsno = gl2ps->extgs_stack++; 
     gro->gsobjno = gl2ps->objects_stack ++;
   }
-  else if(t.prop & T_CONST_COLOR && t.prop & T_VAR_ALPHA){
+  else if(t.prop & T_CONST_COLOR && t.prop & T_VAR_ALPHA){              
     gro->gsno = gl2ps->extgs_stack++;
     gro->gsobjno = gl2ps->objects_stack++;
-    gro->trgroupno = gl2ps->trgroupobjects_stack++;
+    gro->trgroupno = gl2ps->trgroupobjects_stack++; 
     gro->trgroupobjno = gl2ps->objects_stack++;
     gro->maskshno = gl2ps->mshader_stack++;
     gro->maskshobjno = gl2ps->objects_stack++;
   }
-  else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_1){
+  else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_1){          
     gro->shno = gl2ps->shader_stack++;
     gro->shobjno = gl2ps->objects_stack++;
   }
-  else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_LESS_1){
+  else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_LESS_1){             
     gro->gsno = gl2ps->extgs_stack++;
     gro->gsobjno = gl2ps->objects_stack++;
-    gro->shno = gl2ps->shader_stack++;
+    gro->shno = gl2ps->shader_stack++; 
     gro->shobjno = gl2ps->objects_stack++;
   }
-  else if(t.prop & T_VAR_COLOR && t.prop & T_VAR_ALPHA){
+  else if(t.prop & T_VAR_COLOR && t.prop & T_VAR_ALPHA){                
     gro->gsno = gl2ps->extgs_stack++;
     gro->gsobjno = gl2ps->objects_stack++;
-    gro->shno = gl2ps->shader_stack++;
+    gro->shno = gl2ps->shader_stack++; 
     gro->shobjno = gl2ps->objects_stack++;
-    gro->trgroupno = gl2ps->trgroupobjects_stack++;
+    gro->trgroupno = gl2ps->trgroupobjects_stack++; 
     gro->trgroupobjno = gl2ps->objects_stack++;
     gro->maskshno = gl2ps->mshader_stack++;
     gro->maskshobjno = gl2ps->objects_stack++;
@@ -3630,14 +3624,14 @@
       gl2ps->streamlength += gl2psPrintf("1 J\n");
       gl2ps->streamlength += gl2psPrintPDFLineWidth(prim->width);
       gl2ps->streamlength += gl2psPrintPDFStrokeColor(prim->verts[0].rgba);
-      for(j = 0; j <= lastel; ++j){
+      for(j = 0; j <= lastel; ++j){  
         prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
         gl2ps->streamlength +=
           gl2psPrintf("%f %f m %f %f l\n",
                       prim->verts[0].xyz[0], prim->verts[0].xyz[1],
                       prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
       }
-      gl2ps->streamlength += gl2psPrintf("S\n");
+      gl2ps->streamlength += gl2psPrintf("S\n"); 
       gl2ps->streamlength += gl2psPrintf("0 J\n");
       break;
     case GL2PS_LINE:
@@ -3648,10 +3642,10 @@
       gl2ps->streamlength += gl2psPrintPDFStrokeColor(prim->verts[0].rgba);
       gl2ps->streamlength += gl2psPrintPostScriptDash(prim->pattern, prim->factor, "d");
       /* start new path */
-      gl2ps->streamlength +=
-        gl2psPrintf("%f %f m\n",
+      gl2ps->streamlength += 
+        gl2psPrintf("%f %f m\n", 
                     prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
-
+      
       for(j = 1; j <= lastel; ++j){
         prev = prim;
         prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
@@ -3659,38 +3653,38 @@
           /* the starting point of the new segment does not match the
              end point of the previous line, so we end the current
              path and start a new one */
-          gl2ps->streamlength +=
-            gl2psPrintf("%f %f l\n",
+          gl2ps->streamlength += 
+            gl2psPrintf("%f %f l\n", 
                         prev->verts[1].xyz[0], prev->verts[1].xyz[1]);
-          gl2ps->streamlength +=
-            gl2psPrintf("%f %f m\n",
+          gl2ps->streamlength += 
+            gl2psPrintf("%f %f m\n", 
                         prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
         }
         else{
           /* the two segements are connected, so we just append to the
              current path */
-          gl2ps->streamlength +=
+          gl2ps->streamlength += 
             gl2psPrintf("%f %f l\n",
                         prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
         }
       }
       /* end last path */
-      gl2ps->streamlength +=
-        gl2psPrintf("%f %f l\n",
+      gl2ps->streamlength += 
+        gl2psPrintf("%f %f l\n", 
                     prim->verts[1].xyz[0], prim->verts[1].xyz[1]);
       gl2ps->streamlength += gl2psPrintf("S\n");
       break;
     case GL2PS_TRIANGLE:
       gl2psFillTriangleFromPrimitive(&t, prim, GL_TRUE);
       gl2psSortOutTrianglePDFgroup(gro);
-
+      
       /* No alpha and const color: Simple PDF draw orders  */
-      if(t.prop & T_CONST_COLOR && t.prop & T_ALPHA_1){
-        gl2ps->streamlength += gl2psPrintPDFFillColor(t.vertex[0].rgba);
-        for(j = 0; j <= lastel; ++j){
+      if(t.prop & T_CONST_COLOR && t.prop & T_ALPHA_1){         
+        gl2ps->streamlength += gl2psPrintPDFFillColor(t.vertex[0].rgba);        
+        for(j = 0; j <= lastel; ++j){  
           prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
           gl2psFillTriangleFromPrimitive(&t, prim, GL_FALSE);
-          gl2ps->streamlength
+          gl2ps->streamlength 
             += gl2psPrintf("%f %f m\n"
                            "%f %f l\n"
                            "%f %f l\n"
@@ -3700,17 +3694,17 @@
                            t.vertex[2].xyz[0], t.vertex[2].xyz[1]);
         }
       }
-      /* Const alpha < 1 and const color: Simple PDF draw orders
+      /* Const alpha < 1 and const color: Simple PDF draw orders 
          and an extra extended Graphics State for the alpha const */
-      else if(t.prop & T_CONST_COLOR && t.prop & T_ALPHA_LESS_1){
+      else if(t.prop & T_CONST_COLOR && t.prop & T_ALPHA_LESS_1){               
         gl2ps->streamlength += gl2psPrintf("q\n"
                                            "/GS%d gs\n",
                                            gro->gsno);
         gl2ps->streamlength += gl2psPrintPDFFillColor(prim->verts[0].rgba);
-        for(j = 0; j <= lastel; ++j){
+        for(j = 0; j <= lastel; ++j){  
           prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
           gl2psFillTriangleFromPrimitive(&t, prim, GL_FALSE);
-          gl2ps->streamlength
+          gl2ps->streamlength 
             += gl2psPrintf("%f %f m\n"
                            "%f %f l\n"
                            "%f %f l\n"
@@ -3721,19 +3715,19 @@
         }
         gl2ps->streamlength += gl2psPrintf("Q\n");
       }
-      /* Variable alpha and const color: Simple PDF draw orders
-         and an extra extended Graphics State + Xobject + Shader
+      /* Variable alpha and const color: Simple PDF draw orders 
+         and an extra extended Graphics State + Xobject + Shader 
          object for the alpha mask */
-      else if(t.prop & T_CONST_COLOR && t.prop & T_VAR_ALPHA){
+      else if(t.prop & T_CONST_COLOR && t.prop & T_VAR_ALPHA){          
         gl2ps->streamlength += gl2psPrintf("q\n"
                                            "/GS%d gs\n"
                                            "/TrG%d Do\n",
                                            gro->gsno, gro->trgroupno);
         gl2ps->streamlength += gl2psPrintPDFFillColor(prim->verts[0].rgba);
-        for(j = 0; j <= lastel; ++j){
+        for(j = 0; j <= lastel; ++j){  
           prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
           gl2psFillTriangleFromPrimitive(&t, prim, GL_FALSE);
-          gl2ps->streamlength
+          gl2ps->streamlength 
             += gl2psPrintf("%f %f m\n"
                            "%f %f l\n"
                            "%f %f l\n"
@@ -3746,23 +3740,23 @@
       }
       /* Variable color and no alpha: Shader Object for the colored
          triangle(s) */
-      else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_1){
+      else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_1){              
         gl2ps->streamlength += gl2psPrintf("/Sh%d sh\n", gro->shno);
       }
-      /* Variable color and const alpha < 1: Shader Object for the
-         colored triangle(s) and an extra extended Graphics State
+      /* Variable color and const alpha < 1: Shader Object for the 
+         colored triangle(s) and an extra extended Graphics State 
          for the alpha const */
-      else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_LESS_1){
+      else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_LESS_1){         
         gl2ps->streamlength += gl2psPrintf("q\n"
                                            "/GS%d gs\n"
                                            "/Sh%d sh\n"
                                            "Q\n",
                                            gro->gsno, gro->shno);
       }
-      /* Variable alpha and color: Shader Object for the colored
-         triangle(s) and an extra extended Graphics State
+      /* Variable alpha and color: Shader Object for the colored 
+         triangle(s) and an extra extended Graphics State 
          + Xobject + Shader object for the alpha mask */
-      else if(t.prop & T_VAR_COLOR && t.prop & T_VAR_ALPHA){
+      else if(t.prop & T_VAR_COLOR && t.prop & T_VAR_ALPHA){            
         gl2ps->streamlength += gl2psPrintf("q\n"
                                            "/GS%d gs\n"
                                            "/TrG%d Do\n"
@@ -3774,12 +3768,12 @@
     case GL2PS_PIXMAP:
       for(j = 0; j <= lastel; ++j){
         prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
-        gl2psPutPDFImage(prim->data.image, gro->imno, prim->verts[0].xyz[0],
+        gl2psPutPDFImage(prim->data.image, gro->imno, prim->verts[0].xyz[0], 
                          prim->verts[0].xyz[1]);
       }
       break;
     case GL2PS_TEXT:
-      for(j = 0; j <= lastel; ++j){
+      for(j = 0; j <= lastel; ++j){  
         prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
         gl2ps->streamlength += gl2psPrintPDFFillColor(prim->verts[0].rgba);
         gl2psPutPDFText(prim->data.text, gro->fontno, prim->verts[0].xyz[0],
@@ -3788,7 +3782,7 @@
       break;
     default:
       break;
-    }
+    } 
   }
 }
 
@@ -3801,15 +3795,15 @@
   int i;
 
   offs += fprintf(gl2ps->stream,
-                  "/ExtGState\n"
+                  "/ExtGState\n" 
                   "<<\n"
                   "/GSa 7 0 R\n");
-  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){
-    gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i);
+  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){  
+    gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i); 
     if(gro->gsno >= 0)
       offs += fprintf(gl2ps->stream, "/GS%d %d 0 R\n", gro->gsno, gro->gsobjno);
   }
-  offs += fprintf(gl2ps->stream, ">>\n");
+  offs += fprintf(gl2ps->stream, ">>\n"); 
   return offs;
 }
 
@@ -3824,14 +3818,14 @@
   offs += fprintf(gl2ps->stream,
                   "/Shading\n"
                   "<<\n");
-  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){
-    gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i);
+  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){  
+    gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i); 
     if(gro->shno >= 0)
       offs += fprintf(gl2ps->stream, "/Sh%d %d 0 R\n", gro->shno, gro->shobjno);
     if(gro->maskshno >= 0)
       offs += fprintf(gl2ps->stream, "/TrSh%d %d 0 R\n", gro->maskshno, gro->maskshobjno);
   }
-  offs += fprintf(gl2ps->stream,">>\n");
+  offs += fprintf(gl2ps->stream,">>\n");  
   return offs;
 }
 
@@ -3848,8 +3842,8 @@
                   "/XObject\n"
                   "<<\n");
 
-  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){
-    gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i);
+  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){  
+    gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i); 
     if(!gl2psListNbr(gro->ptrlist))
       continue;
     p = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, 0);
@@ -3881,8 +3875,8 @@
 
   offs += fprintf(gl2ps->stream, "/Font\n<<\n");
 
-  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){
-    gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i);
+  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){  
+    gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i); 
     if(gro->fontno < 0)
       continue;
     gro->fontobjno = gl2ps->objects_stack++;
@@ -3897,11 +3891,11 @@
 {
   int i;
   GL2PSpdfgroup *gro = NULL;
-
+  
   if(!gl2ps->pdfgrouplist)
     return;
 
-  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){
+  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){ 
     gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist,i);
     gl2psListDelete(gro->ptrlist);
   }
@@ -3917,10 +3911,10 @@
   int offs;
   time_t now;
   struct tm *newtime;
-
+  
   time(&now);
   newtime = gmtime(&now);
-
+  
   offs = fprintf(gl2ps->stream,
                  "1 0 obj\n"
                  "<<\n"
@@ -3930,20 +3924,20 @@
                  gl2ps->title, GL2PS_MAJOR_VERSION, GL2PS_MINOR_VERSION,
                  GL2PS_PATCH_VERSION, GL2PS_EXTRA_VERSION, GL2PS_COPYRIGHT,
                  gl2ps->producer);
-
+  
   if(!newtime){
-    offs += fprintf(gl2ps->stream,
+    offs += fprintf(gl2ps->stream, 
                     ">>\n"
                     "endobj\n");
     return offs;
   }
-
-  offs += fprintf(gl2ps->stream,
+  
+  offs += fprintf(gl2ps->stream, 
                   "/CreationDate (D:%d%02d%02d%02d%02d%02d)\n"
                   ">>\n"
                   "endobj\n",
-                  newtime->tm_year+1900,
-                  newtime->tm_mon+1,
+                  newtime->tm_year+1900, 
+                  newtime->tm_mon+1, 
                   newtime->tm_mday,
                   newtime->tm_hour,
                   newtime->tm_min,
@@ -3955,7 +3949,7 @@
 
 static int gl2psPrintPDFCatalog(void)
 {
-  return fprintf(gl2ps->stream,
+  return fprintf(gl2ps->stream, 
                  "2 0 obj\n"
                  "<<\n"
                  "/Type /Catalog\n"
@@ -3966,9 +3960,9 @@
 
 static int gl2psPrintPDFPages(void)
 {
-  return fprintf(gl2ps->stream,
+  return fprintf(gl2ps->stream, 
                  "3 0 obj\n"
-                 "<<\n"
+                 "<<\n" 
                  "/Type /Pages\n"
                  "/Kids [6 0 R]\n"
                  "/Count 1\n"
@@ -3981,13 +3975,13 @@
 static int gl2psOpenPDFDataStream(void)
 {
   int offs = 0;
-
-  offs += fprintf(gl2ps->stream,
+  
+  offs += fprintf(gl2ps->stream, 
                   "4 0 obj\n"
-                  "<<\n"
+                  "<<\n" 
                   "/Length 5 0 R\n" );
   offs += gl2psPrintPDFCompressorType();
-  offs += fprintf(gl2ps->stream,
+  offs += fprintf(gl2ps->stream, 
                   ">>\n"
                   "stream\n");
   return offs;
@@ -4000,13 +3994,13 @@
   int offs;
 
   offs = gl2psPrintf("/GSa gs\n");
-
+  
   if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
     offs += gl2psPrintPDFFillColor(gl2ps->bgcolor);
     offs += gl2psPrintf("%d %d %d %d re\n",
                         (int)gl2ps->viewport[0], (int)gl2ps->viewport[1],
                         (int)gl2ps->viewport[2], (int)gl2ps->viewport[3]);
-    offs += gl2psPrintf("f\n");
+    offs += gl2psPrintf("f\n");  
   }
   return offs;
 }
@@ -4019,26 +4013,26 @@
   gl2ps->pdfprimlist = gl2psListCreate(500, 500, sizeof(GL2PSprimitive*));
   gl2psPDFstacksInit();
 
-  gl2ps->xreflist = (int*)gl2psMalloc(sizeof(int) * gl2ps->objects_stack);
+  gl2ps->xreflist = (int*)gl2psMalloc(sizeof(int) * gl2ps->objects_stack); 
 
 #if defined(GL2PS_HAVE_ZLIB)
   if(gl2ps->options & GL2PS_COMPRESS){
     gl2psSetupCompress();
   }
-#endif
+#endif    
   gl2ps->xreflist[0] = 0;
   offs += fprintf(gl2ps->stream, "%%PDF-1.4\n");
   gl2ps->xreflist[1] = offs;
-
+  
   offs += gl2psPrintPDFInfo();
   gl2ps->xreflist[2] = offs;
-
+  
   offs += gl2psPrintPDFCatalog();
   gl2ps->xreflist[3] = offs;
-
+  
   offs += gl2psPrintPDFPages();
   gl2ps->xreflist[4] = offs;
-
+  
   offs += gl2psOpenPDFDataStream();
   gl2ps->xreflist[5] = offs; /* finished in gl2psPrintPDFFooter */
   gl2ps->streamlength = gl2psOpenPDFDataStreamWritePreface();
@@ -4050,7 +4044,7 @@
 {
   GL2PSprimitive *prim = *(GL2PSprimitive**)data;
 
-  if((gl2ps->options & GL2PS_OCCLUSION_CULL) && prim->culled)
+  if((gl2ps->options & GL2PS_OCCLUSION_CULL) && prim->culled) 
     return;
 
   prim = gl2psCopyPrimitive(prim); /* deep copy */
@@ -4062,7 +4056,7 @@
 static int gl2psClosePDFDataStream(void)
 {
   int offs = 0;
-
+ 
 #if defined(GL2PS_HAVE_ZLIB)
   if(gl2ps->options & GL2PS_COMPRESS){
     if(Z_OK != gl2psDeflate())
@@ -4070,13 +4064,13 @@
     else
       fwrite(gl2ps->compress->dest, gl2ps->compress->destLen, 1, gl2ps->stream);
     gl2ps->streamlength += gl2ps->compress->destLen;
-
+    
     offs += gl2ps->streamlength;
     gl2psFreeCompress();
   }
-#endif
-
-  offs += fprintf(gl2ps->stream,
+#endif 
+  
+  offs += fprintf(gl2ps->stream, 
                   "endstream\n"
                   "endobj\n");
   return offs;
@@ -4097,27 +4091,27 @@
 static int gl2psPrintPDFOpenPage(void)
 {
   int offs;
-
+  
   /* Write fixed part */
-
-  offs = fprintf(gl2ps->stream,
+  
+  offs = fprintf(gl2ps->stream, 
                  "6 0 obj\n"
-                 "<<\n"
+                 "<<\n" 
                  "/Type /Page\n"
                  "/Parent 3 0 R\n"
                  "/MediaBox [%d %d %d %d]\n",
                  (int)gl2ps->viewport[0], (int)gl2ps->viewport[1],
                  (int)gl2ps->viewport[2], (int)gl2ps->viewport[3]);
-
+  
   if(gl2ps->options & GL2PS_LANDSCAPE)
     offs += fprintf(gl2ps->stream, "/Rotate -90\n");
-
+  
   offs += fprintf(gl2ps->stream,
                   "/Contents 4 0 R\n"
-                  "/Resources\n"
-                  "<<\n"
+                  "/Resources\n" 
+                  "<<\n" 
                   "/ProcSet [/PDF /Text /ImageB /ImageC]  %%/ImageI\n");
-
+  
   return offs;
 
   /* End fixed part, proceeds in gl2psPDFgroupListWriteVariableResources() */
@@ -4126,19 +4120,19 @@
 static int gl2psPDFgroupListWriteVariableResources(void)
 {
   int offs = 0;
-
+  
   /* a) Graphics States for shader alpha masks*/
-  offs += gl2psPDFgroupListWriteGStateResources();
-
-  /* b) Shader and shader masks */
-  offs += gl2psPDFgroupListWriteShaderResources();
-
+  offs += gl2psPDFgroupListWriteGStateResources();  
+  
+  /* b) Shader and shader masks */ 
+  offs += gl2psPDFgroupListWriteShaderResources();  
+ 
   /* c) XObjects (Images & Shader Masks) */
   offs += gl2psPDFgroupListWriteXObjectResources();
-
+  
   /* d) Fonts */
   offs += gl2psPDFgroupListWriteFontResources();
-
+  
   /* End resources and page */
   offs += fprintf(gl2ps->stream,
                   ">>\n"
@@ -4169,10 +4163,10 @@
 
 /* Put vertex' edge flag (8bit) and coordinates (32bit) in shader stream */
 
-static int gl2psPrintPDFShaderStreamDataCoord(GL2PSvertex *vertex,
-                                              size_t (*action)(unsigned long data,
-                                                               size_t size),
-                                              GLfloat dx, GLfloat dy,
+static int gl2psPrintPDFShaderStreamDataCoord(GL2PSvertex *vertex, 
+                                              size_t (*action)(unsigned long data, 
+                                                               size_t size), 
+                                              GLfloat dx, GLfloat dy, 
                                               GLfloat xmin, GLfloat ymin)
 {
   int offs = 0;
@@ -4188,7 +4182,7 @@
 
   /* The Shader stream in PDF requires to be in a 'big-endian'
      order */
-
+    
   if(GL2PS_ZERO(dx * dy)){
     offs += (*action)(0, 4);
     offs += (*action)(0, 4);
@@ -4201,7 +4195,7 @@
       diff = 0.0F;
     imap = (unsigned long)(diff * dmax);
     offs += (*action)(imap, 4);
-
+      
     diff = (vertex->xyz[1] - ymin) / dy;
     if(diff > 1)
       diff = 1.0F;
@@ -4210,14 +4204,14 @@
     imap = (unsigned long)(diff * dmax);
     offs += (*action)(imap, 4);
   }
-
+  
   return offs;
 }
 
 /* Put vertex' rgb value (8bit for every component) in shader stream */
 
 static int gl2psPrintPDFShaderStreamDataRGB(GL2PSvertex *vertex,
-                                            size_t (*action)(unsigned long data,
+                                            size_t (*action)(unsigned long data, 
                                                              size_t size))
 {
   int offs = 0;
@@ -4229,20 +4223,20 @@
 
   imap = (unsigned long)((vertex->rgba[0]) * dmax);
   offs += (*action)(imap, 1);
-
+    
   imap = (unsigned long)((vertex->rgba[1]) * dmax);
   offs += (*action)(imap, 1);
-
+    
   imap = (unsigned long)((vertex->rgba[2]) * dmax);
   offs += (*action)(imap, 1);
-
+  
   return offs;
 }
 
 /* Put vertex' alpha (8/16bit) in shader stream */
 
-static int gl2psPrintPDFShaderStreamDataAlpha(GL2PSvertex *vertex,
-                                              size_t (*action)(unsigned long data,
+static int gl2psPrintPDFShaderStreamDataAlpha(GL2PSvertex *vertex, 
+                                              size_t (*action)(unsigned long data, 
                                                                size_t size),
                                               int sigbyte)
 {
@@ -4255,48 +4249,48 @@
 
   if(sigbyte != 8 && sigbyte != 16)
     sigbyte = 8;
-
+        
   sigbyte /= 8;
-
+  
   imap = (unsigned long)((vertex->rgba[3]) * dmax);
-
+  
   offs += (*action)(imap, sigbyte);
-
+  
   return offs;
 }
 
 /* Put a triangles raw data in shader stream */
 
-static int gl2psPrintPDFShaderStreamData(GL2PStriangle *triangle,
-                                         GLfloat dx, GLfloat dy,
+static int gl2psPrintPDFShaderStreamData(GL2PStriangle *triangle, 
+                                         GLfloat dx, GLfloat dy, 
                                          GLfloat xmin, GLfloat ymin,
-                                         size_t (*action)(unsigned long data,
+                                         size_t (*action)(unsigned long data, 
                                                           size_t size),
                                          int gray)
 {
   int i, offs = 0;
   GL2PSvertex v;
-
+  
   if(gray && gray != 8 && gray != 16)
     gray = 8;
-
+  
   for(i = 0; i < 3; ++i){
     offs += gl2psPrintPDFShaderStreamDataCoord(&triangle->vertex[i], action,
                                                dx, dy, xmin, ymin);
-    if(gray){
+    if(gray){ 
       v = triangle->vertex[i];
-      offs += gl2psPrintPDFShaderStreamDataAlpha(&v, action, gray);
+      offs += gl2psPrintPDFShaderStreamDataAlpha(&v, action, gray); 
     }
     else{
       offs += gl2psPrintPDFShaderStreamDataRGB(&triangle->vertex[i], action);
     }
   }
-
+  
   return offs;
 }
 
-static void gl2psPDFRectHull(GLfloat *xmin, GLfloat *xmax,
-                             GLfloat *ymin, GLfloat *ymax,
+static void gl2psPDFRectHull(GLfloat *xmin, GLfloat *xmax, 
+                             GLfloat *ymin, GLfloat *ymax, 
                              GL2PStriangle *triangles, int cnt)
 {
   int i, j;
@@ -4305,7 +4299,7 @@
   *xmax = triangles[0].vertex[0].xyz[0];
   *ymin = triangles[0].vertex[0].xyz[1];
   *ymax = triangles[0].vertex[0].xyz[1];
-
+  
   for(i = 0; i < cnt; ++i){
     for(j = 0; j < 3; ++j){
       if(*xmin > triangles[i].vertex[j].xyz[0])
@@ -4320,17 +4314,17 @@
   }
 }
 
-/* Writes shaded triangle
+/* Writes shaded triangle 
    gray == 0 means write RGB triangles
    gray == 8             8bit-grayscale (for alpha masks)
    gray == 16            16bit-grayscale (for alpha masks) */
 
-static int gl2psPrintPDFShader(int obj, GL2PStriangle *triangles,
+static int gl2psPrintPDFShader(int obj, GL2PStriangle *triangles, 
                                int size, int gray)
 {
   int i, offs = 0, vertexbytes, done = 0;
   GLfloat xmin, xmax, ymin, ymax;
-
+        
   switch(gray){
   case 0:
     vertexbytes = 1+4+4+1+1+1;
@@ -4346,9 +4340,9 @@
     vertexbytes = 1+4+4+1;
     break;
   }
-
+  
   gl2psPDFRectHull(&xmin, &xmax, &ymin, &ymax, triangles, size);
-
+  
   offs += fprintf(gl2ps->stream,
                   "%d 0 obj\n"
                   "<< "
@@ -4359,18 +4353,18 @@
                   "/BitsPerFlag 8 "
                   "/Decode [%f %f %f %f 0 1 %s] ",
                   obj,
-                  (gray) ? "/DeviceGray" : "/DeviceRGB",
+                  (gray) ? "/DeviceGray" : "/DeviceRGB", 
                   (gray) ? gray : 8,
                   xmin, xmax, ymin, ymax,
                   (gray) ? "" : "0 1 0 1");
-
+  
 #if defined(GL2PS_HAVE_ZLIB)
   if(gl2ps->options & GL2PS_COMPRESS){
     gl2psAllocCompress(vertexbytes * size * 3);
 
     for(i = 0; i < size; ++i)
       gl2psPrintPDFShaderStreamData(&triangles[i],
-                                    xmax-xmin, ymax-ymin, xmin, ymin,
+                                    xmax-xmin, ymax-ymin, xmin, ymin, 
                                     gl2psWriteBigEndianCompress, gray);
 
     if(Z_OK == gl2psDeflate() && 23 + gl2ps->compress->destLen < gl2ps->compress->srcLen){
@@ -4380,8 +4374,8 @@
                       ">>\n"
                       "stream\n",
                       (int)gl2ps->compress->destLen);
-      offs += gl2ps->compress->destLen * fwrite(gl2ps->compress->dest,
-                                                gl2ps->compress->destLen,
+      offs += gl2ps->compress->destLen * fwrite(gl2ps->compress->dest, 
+                                                gl2ps->compress->destLen, 
                                                 1, gl2ps->stream);
       done = 1;
     }
@@ -4402,11 +4396,11 @@
                                             xmax-xmin, ymax-ymin, xmin, ymin,
                                             gl2psWriteBigEndian, gray);
   }
-
+  
   offs += fprintf(gl2ps->stream,
                   "\nendstream\n"
                   "endobj\n");
-
+  
   return offs;
 }
 
@@ -4415,7 +4409,7 @@
 static int gl2psPrintPDFShaderMask(int obj, int childobj)
 {
   int offs = 0, len;
-
+  
   offs += fprintf(gl2ps->stream,
                   "%d 0 obj\n"
                   "<<\n"
@@ -4427,11 +4421,11 @@
                   obj,
                   (int)gl2ps->viewport[0], (int)gl2ps->viewport[1],
                   (int)gl2ps->viewport[2], (int)gl2ps->viewport[3]);
-
-  len = (childobj>0)
+  
+  len = (childobj>0) 
     ? strlen("/TrSh sh\n") + (int)log10((double)childobj)+1
-    : strlen("/TrSh0 sh\n");
-
+    : strlen("/TrSh0 sh\n"); 
+  
   offs += fprintf(gl2ps->stream,
                   "/Length %d\n"
                   ">>\n"
@@ -4443,7 +4437,7 @@
   offs += fprintf(gl2ps->stream,
                   "endstream\n"
                   "endobj\n");
-
+  
   return offs;
 }
 
@@ -4454,16 +4448,16 @@
 static int gl2psPrintPDFShaderExtGS(int obj, int childobj)
 {
   int offs = 0;
-
+  
   offs += fprintf(gl2ps->stream,
                   "%d 0 obj\n"
                   "<<\n",
                   obj);
-
+  
   offs += fprintf(gl2ps->stream,
                   "/SMask << /S /Alpha /G %d 0 R >> ",
                   childobj);
-
+  
   offs += fprintf(gl2ps->stream,
                   ">>\n"
                   "endobj\n");
@@ -4475,7 +4469,7 @@
 static int gl2psPrintPDFShaderSimpleExtGS(int obj, GLfloat alpha)
 {
   int offs = 0;
-
+  
   offs += fprintf(gl2ps->stream,
                   "%d 0 obj\n"
                   "<<\n"
@@ -4489,8 +4483,8 @@
 /* Similar groups of functions for pixmaps and text */
 
 static int gl2psPrintPDFPixmapStreamData(GL2PSimage *im,
-                                         size_t (*action)(unsigned long data,
-                                                          size_t size),
+                                         size_t (*action)(unsigned long data, 
+                                                          size_t size), 
                                          int gray)
 {
   int x, y, shift;
@@ -4503,7 +4497,7 @@
     gray = 8;
 
   gray /= 8;
-
+  
   shift = (sizeof(unsigned long) - 1) * 8;
 
   for(y = 0; y < im->height; ++y){
@@ -4534,10 +4528,10 @@
 
   if(gray && gray !=8 && gray != 16)
     gray = 8;
-
+  
   if(gray)
-    sigbytes = gray / 8;
-
+    sigbytes = gray / 8; 
+  
   offs += fprintf(gl2ps->stream,
                   "%d 0 obj\n"
                   "<<\n"
@@ -4555,13 +4549,13 @@
                     "/SMask %d 0 R\n",
                     childobj);
   }
-
+  
 #if defined(GL2PS_HAVE_ZLIB)
   if(gl2ps->options & GL2PS_COMPRESS){
     gl2psAllocCompress((int)(im->width * im->height * sigbytes));
-
+    
     gl2psPrintPDFPixmapStreamData(im, gl2psWriteBigEndianCompress, gray);
-
+    
     if(Z_OK == gl2psDeflate() && 23 + gl2ps->compress->destLen < gl2ps->compress->srcLen){
       offs += gl2psPrintPDFCompressorType();
       offs += fprintf(gl2ps->stream,
@@ -4576,7 +4570,7 @@
     gl2psFreeCompress();
   }
 #endif
-
+  
   if(!done){
     /* no compression, or too long after compression, or compress error
        -> write non-compressed entry */
@@ -4587,18 +4581,18 @@
                     (int)(im->width * im->height * sigbytes));
     offs += gl2psPrintPDFPixmapStreamData(im, gl2psWriteBigEndian, gray);
   }
-
+  
   offs += fprintf(gl2ps->stream,
                   "\nendstream\n"
                   "endobj\n");
-
+  
   return offs;
 }
 
 static int gl2psPrintPDFText(int obj, GL2PSstring *s, int fontnumber)
 {
   int offs = 0;
-
+  
   offs += fprintf(gl2ps->stream,
                   "%d 0 obj\n"
                   "<<\n"
@@ -4626,9 +4620,9 @@
 
   if(!gl2ps->pdfgrouplist)
     return offs;
-
-  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){
-    gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i);
+  
+  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){  
+    gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i); 
     if(!gl2psListNbr(gro->ptrlist))
       continue;
     p = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, 0);
@@ -4640,7 +4634,7 @@
     case GL2PS_TRIANGLE:
       size = gl2psListNbr(gro->ptrlist);
       triangles = (GL2PStriangle*)gl2psMalloc(sizeof(GL2PStriangle) * size);
-      for(j = 0; j < size; ++j){
+      for(j = 0; j < size; ++j){  
         p = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
         gl2psFillTriangleFromPrimitive(&triangles[j], p, GL_TRUE);
       }
@@ -4682,7 +4676,7 @@
       break;
     default:
       break;
-    }
+    } 
   }
   return offs;
 }
@@ -4693,29 +4687,29 @@
 
 static void gl2psPrintPDFFooter(void)
 {
-  int i, offs;
+  int i, offs;  
 
   gl2psPDFgroupListInit();
   gl2psPDFgroupListWriteMainStream();
-
-  offs = gl2ps->xreflist[5] + gl2ps->streamlength;
+ 
+  offs = gl2ps->xreflist[5] + gl2ps->streamlength; 
   offs += gl2psClosePDFDataStream();
   gl2ps->xreflist[5] = offs;
-
+  
   offs += gl2psPrintPDFDataStreamLength(gl2ps->streamlength);
   gl2ps->xreflist[6] = offs;
   gl2ps->streamlength = 0;
-
+  
   offs += gl2psPrintPDFOpenPage();
   offs += gl2psPDFgroupListWriteVariableResources();
   gl2ps->xreflist = (int*)gl2psRealloc(gl2ps->xreflist,
                                        sizeof(int) * (gl2ps->objects_stack + 1));
   gl2ps->xreflist[7] = offs;
-
+  
   offs += gl2psPrintPDFGSObject();
   gl2ps->xreflist[8] = offs;
-
-  gl2ps->xreflist[gl2ps->objects_stack] =
+  
+  gl2ps->xreflist[gl2ps->objects_stack] = 
     gl2psPDFgroupListWriteObjects(gl2ps->xreflist[8]);
 
   /* Start cross reference table. The file has to been opened in
@@ -4724,13 +4718,13 @@
           "xref\n"
           "0 %d\n"
           "%010d 65535 f \n", gl2ps->objects_stack, 0);
-
+  
   for(i = 1; i < gl2ps->objects_stack; ++i)
     fprintf(gl2ps->stream, "%010d 00000 n \n", gl2ps->xreflist[i]);
-
+  
   fprintf(gl2ps->stream,
           "trailer\n"
-          "<<\n"
+          "<<\n" 
           "/Size %d\n"
           "/Info 1 0 R\n"
           "/Root 2 0 R\n"
@@ -4738,13 +4732,13 @@
           "startxref\n%d\n"
           "%%%%EOF\n",
           gl2ps->objects_stack, gl2ps->xreflist[gl2ps->objects_stack]);
-
-  /* Free auxiliary lists and arrays */
+  
+  /* Free auxiliary lists and arrays */    
   gl2psFree(gl2ps->xreflist);
   gl2psListAction(gl2ps->pdfprimlist, gl2psFreePrimitive);
   gl2psListDelete(gl2ps->pdfprimlist);
   gl2psPDFgroupListDelete();
-
+  
 #if defined(GL2PS_HAVE_ZLIB)
   if(gl2ps->options & GL2PS_COMPRESS){
     gl2psFreeCompress();
@@ -4762,16 +4756,16 @@
   GLint index;
   GLfloat rgba[4];
   int x = viewport[0], y = viewport[1], w = viewport[2], h = viewport[3];
-
+  
   glRenderMode(GL_FEEDBACK);
-
+  
   if(gl2ps->header){
     gl2psPrintPDFHeader();
     gl2ps->header = GL_FALSE;
   }
 
   offs += gl2psPrintf("q\n");
-
+  
   if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
     if(gl2ps->colormode == GL_RGBA || gl2ps->colorsize == 0){
       glGetFloatv(GL_COLOR_CLEAR_VALUE, rgba);
@@ -4791,18 +4785,18 @@
   }
   else{
     offs += gl2psPrintf("%d %d %d %d re\n"
-                        "W\n"
+                        "W\n"   
                         "n\n",
-                        x, y, w, h);
-  }
-
+                        x, y, w, h);            
+  }
+  
   gl2ps->streamlength += offs;
 }
 
 static GLint gl2psPrintPDFEndViewport(void)
 {
   GLint res;
-
+  
   res = gl2psPrintPrimitives();
   gl2ps->streamlength += gl2psPrintf("Q\n");
   return res;
@@ -4825,13 +4819,13 @@
   "Portable Document Format"
 };
 
-/*********************************************************************
+/********************************************************************* 
  *
  * SVG routines
  *
  *********************************************************************/
 
-static void gl2psSVGGetCoordsAndColors(int n, GL2PSvertex *verts,
+static void gl2psSVGGetCoordsAndColors(int n, GL2PSvertex *verts, 
                                        GL2PSxyz *xyz, GL2PSrgba *rgba)
 {
   int i, j;
@@ -4861,9 +4855,9 @@
   int x, y, width, height;
   char col[32];
   time_t now;
-
+  
   time(&now);
-
+  
   if (gl2ps->options & GL2PS_LANDSCAPE){
     x = (int)gl2ps->viewport[1];
     y = (int)gl2ps->viewport[0];
@@ -4876,10 +4870,10 @@
     width = (int)gl2ps->viewport[2];
     height = (int)gl2ps->viewport[3];
   }
-
+  
   /* Compressed SVG files (.svgz) are simply gzipped SVG files */
   gl2psPrintGzipHeader();
-
+  
   gl2psPrintf("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
   gl2psPrintf("<svg xmlns=\"http://www.w3.org/2000/svg\"\n");
   gl2psPrintf("     xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
@@ -4899,9 +4893,9 @@
   if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
     gl2psSVGGetColorString(gl2ps->bgcolor, col);
     gl2psPrintf("<polygon fill=\"%s\" points=\"%d,%d %d,%d %d,%d %d,%d\"/>\n", col,
-                (int)gl2ps->viewport[0], (int)gl2ps->viewport[1],
-                (int)gl2ps->viewport[2], (int)gl2ps->viewport[1],
-                (int)gl2ps->viewport[2], (int)gl2ps->viewport[3],
+                (int)gl2ps->viewport[0], (int)gl2ps->viewport[1], 
+                (int)gl2ps->viewport[2], (int)gl2ps->viewport[1], 
+                (int)gl2ps->viewport[2], (int)gl2ps->viewport[3], 
                 (int)gl2ps->viewport[0], (int)gl2ps->viewport[3]);
   }
 
@@ -4924,52 +4918,52 @@
     gl2psSVGGetColorString(rgba[0], col);
     gl2psPrintf("<polygon fill=\"%s\" ", col);
     if(rgba[0][3] < 1.0F) gl2psPrintf("fill-opacity=\"%g\" ", rgba[0][3]);
-    gl2psPrintf("points=\"%g,%g %g,%g %g,%g\"/>\n", xyz[0][0], xyz[0][1],
+    gl2psPrintf("points=\"%g,%g %g,%g %g,%g\"/>\n", xyz[0][0], xyz[0][1], 
                 xyz[1][0], xyz[1][1], xyz[2][0], xyz[2][1]);
   }
   else{
     /* subdivide into 4 subtriangles */
     for(i = 0; i < 3; i++){
-      xyz2[0][i] = xyz[0][i];
+      xyz2[0][i] = xyz[0][i]; 
       xyz2[1][i] = 0.5F * (xyz[0][i] + xyz[1][i]);
       xyz2[2][i] = 0.5F * (xyz[0][i] + xyz[2][i]);
     }
     for(i = 0; i < 4; i++){
-      rgba2[0][i] = rgba[0][i];
+      rgba2[0][i] = rgba[0][i]; 
       rgba2[1][i] = 0.5F * (rgba[0][i] + rgba[1][i]);
       rgba2[2][i] = 0.5F * (rgba[0][i] + rgba[2][i]);
     }
     gl2psPrintSVGSmoothTriangle(xyz2, rgba2);
     for(i = 0; i < 3; i++){
       xyz2[0][i] = 0.5F * (xyz[0][i] + xyz[1][i]);
-      xyz2[1][i] = xyz[1][i];
+      xyz2[1][i] = xyz[1][i]; 
       xyz2[2][i] = 0.5F * (xyz[1][i] + xyz[2][i]);
     }
     for(i = 0; i < 4; i++){
       rgba2[0][i] = 0.5F * (rgba[0][i] + rgba[1][i]);
-      rgba2[1][i] = rgba[1][i];
+      rgba2[1][i] = rgba[1][i]; 
       rgba2[2][i] = 0.5F * (rgba[1][i] + rgba[2][i]);
     }
     gl2psPrintSVGSmoothTriangle(xyz2, rgba2);
     for(i = 0; i < 3; i++){
       xyz2[0][i] = 0.5F * (xyz[0][i] + xyz[2][i]);
-      xyz2[1][i] = xyz[2][i];
+      xyz2[1][i] = xyz[2][i]; 
       xyz2[2][i] = 0.5F * (xyz[1][i] + xyz[2][i]);
     }
     for(i = 0; i < 4; i++){
       rgba2[0][i] = 0.5F * (rgba[0][i] + rgba[2][i]);
-      rgba2[1][i] = rgba[2][i];
+      rgba2[1][i] = rgba[2][i]; 
       rgba2[2][i] = 0.5F * (rgba[1][i] + rgba[2][i]);
     }
     gl2psPrintSVGSmoothTriangle(xyz2, rgba2);
     for(i = 0; i < 3; i++){
       xyz2[0][i] = 0.5F * (xyz[0][i] + xyz[1][i]);
-      xyz2[1][i] = 0.5F * (xyz[1][i] + xyz[2][i]);
+      xyz2[1][i] = 0.5F * (xyz[1][i] + xyz[2][i]); 
       xyz2[2][i] = 0.5F * (xyz[0][i] + xyz[2][i]);
     }
     for(i = 0; i < 4; i++){
       rgba2[0][i] = 0.5F * (rgba[0][i] + rgba[1][i]);
-      rgba2[1][i] = 0.5F * (rgba[1][i] + rgba[2][i]);
+      rgba2[1][i] = 0.5F * (rgba[1][i] + rgba[2][i]); 
       rgba2[2][i] = 0.5F * (rgba[0][i] + rgba[2][i]);
     }
     gl2psPrintSVGSmoothTriangle(xyz2, rgba2);
@@ -4995,7 +4989,7 @@
 {
   int i;
   if(gl2ps->lastvertex.rgba[0] >= 0.){
-    gl2psPrintf("%g,%g\"/>\n", gl2ps->lastvertex.xyz[0],
+    gl2psPrintf("%g,%g\"/>\n", gl2ps->lastvertex.xyz[0], 
                 gl2ps->viewport[3] - gl2ps->lastvertex.xyz[1]);
     for(i = 0; i < 3; i++)
       gl2ps->lastvertex.xyz[i] = -1.;
@@ -5017,7 +5011,7 @@
      file), we need to encode the pixmap into PNG in memory, then
      encode it into base64. */
 
-  png = gl2psListCreate(pixmap->width * pixmap->height * 3, 1000,
+  png = gl2psListCreate(pixmap->width * pixmap->height * 3, 1000, 
                         sizeof(unsigned char));
   gl2psConvertPixmapToPNG(pixmap, png);
   gl2psListEncodeBase64(png);
@@ -5086,7 +5080,7 @@
     gl2ps->lastfactor = prim->factor;
     if(newline){
       gl2psSVGGetColorString(rgba[0], col);
-      gl2psPrintf("<polyline fill=\"none\" stroke=\"%s\" stroke-width=\"%g\" ",
+      gl2psPrintf("<polyline fill=\"none\" stroke=\"%s\" stroke-width=\"%g\" ", 
                   col, prim->width);
       if(rgba[0][3] < 1.0F) gl2psPrintf("stroke-opacity=\"%g\" ", rgba[0][3]);
       gl2psPrintSVGDash(prim->pattern, prim->factor);
@@ -5112,42 +5106,6 @@
     if(prim->data.text->angle)
       gl2psPrintf("transform=\"rotate(%g, %g, %g)\" ",
                   -prim->data.text->angle, xyz[0][0], xyz[0][1]);
-    switch(prim->data.text->alignment){
-    case GL2PS_TEXT_C:
-      gl2psPrintf("text-anchor=\"middle\" baseline-shift=\"%d\" ",
-                  -prim->data.text->fontsize / 2);
-      break;
-    case GL2PS_TEXT_CL:
-      gl2psPrintf("text-anchor=\"start\" baseline-shift=\"%d\" ",
-                  -prim->data.text->fontsize / 2);
-      break;
-    case GL2PS_TEXT_CR:
-      gl2psPrintf("text-anchor=\"end\" baseline-shift=\"%d\" ",
-                  -prim->data.text->fontsize / 2);
-      break;
-    case GL2PS_TEXT_B:
-      gl2psPrintf("text-anchor=\"middle\" baseline-shift=\"0\" ");
-      break;
-    case GL2PS_TEXT_BR:
-      gl2psPrintf("text-anchor=\"end\" baseline-shift=\"0\" ");
-      break;
-    case GL2PS_TEXT_T:
-      gl2psPrintf("text-anchor=\"middle\" baseline-shift=\"%d\" ",
-                  -prim->data.text->fontsize);
-      break;
-    case GL2PS_TEXT_TL:
-      gl2psPrintf("text-anchor=\"start\" baseline-shift=\"%d\" ",
-                  -prim->data.text->fontsize);
-      break;
-    case GL2PS_TEXT_TR:
-      gl2psPrintf("text-anchor=\"end\" baseline-shift=\"%d\" ",
-                  -prim->data.text->fontsize);
-      break;
-    case GL2PS_TEXT_BL:
-    default: /* same as GL2PS_TEXT_BL */
-      gl2psPrintf("text-anchor=\"start\" baseline-shift=\"0\" ");
-      break;
-    }
     if(!strcmp(prim->data.text->fontname, "Times-Roman"))
       gl2psPrintf("font-family=\"Times\">");
     else if(!strcmp(prim->data.text->fontname, "Times-Bold"))
@@ -5186,8 +5144,8 @@
 static void gl2psPrintSVGFooter(void)
 {
   gl2psPrintf("</g>\n");
-  gl2psPrintf("</svg>\n");
-
+  gl2psPrintf("</svg>\n");  
+  
   gl2psPrintGzipFooter();
 }
 
@@ -5199,7 +5157,7 @@
   int x = viewport[0], y = viewport[1], w = viewport[2], h = viewport[3];
 
   glRenderMode(GL_FEEDBACK);
-
+  
   if(gl2ps->header){
     gl2psPrintSVGHeader();
     gl2ps->header = GL_FALSE;
@@ -5217,18 +5175,18 @@
       rgba[3] = 1.0F;
     }
     gl2psSVGGetColorString(rgba, col);
-    gl2psPrintf("<polygon fill=\"%s\" points=\"%d,%d %d,%d %d,%d %d,%d\"/>\n", col,
-                x, gl2ps->viewport[3] - y,
-                x + w, gl2ps->viewport[3] - y,
-                x + w, gl2ps->viewport[3] - (y + h),
+    gl2psPrintf("<polygon fill=\"%s\" points=\"%d,%d %d,%d %d,%d %d,%d\"/>\n", col, 
+                x, gl2ps->viewport[3] - y, 
+                x + w, gl2ps->viewport[3] - y, 
+                x + w, gl2ps->viewport[3] - (y + h), 
                 x, gl2ps->viewport[3] - (y + h));
   }
 
   gl2psPrintf("<clipPath id=\"cp%d%d%d%d\">\n", x, y, w, h);
-  gl2psPrintf("  <polygon points=\"%d,%d %d,%d %d,%d %d,%d\"/>\n",
-              x, gl2ps->viewport[3] - y,
-              x + w, gl2ps->viewport[3] - y,
-              x + w, gl2ps->viewport[3] - (y + h),
+  gl2psPrintf("  <polygon points=\"%d,%d %d,%d %d,%d %d,%d\"/>\n", 
+              x, gl2ps->viewport[3] - y, 
+              x + w, gl2ps->viewport[3] - y, 
+              x + w, gl2ps->viewport[3] - (y + h), 
               x, gl2ps->viewport[3] - (y + h));
   gl2psPrintf("</clipPath>\n");
   gl2psPrintf("<g clip-path=\"url(#cp%d%d%d%d)\">\n", x, y, w, h);
@@ -5282,7 +5240,7 @@
 
   time(&now);
 
-  fprintf(gl2ps->stream,
+  fprintf(gl2ps->stream, 
           "%% Title: %s\n"
           "%% Creator: GL2PS %d.%d.%d%s, %s\n"
           "%% For: %s\n"
@@ -5336,7 +5294,7 @@
   case GL2PS_TEXT_T  : return "north";
   case GL2PS_TEXT_TL : return "north west";
   case GL2PS_TEXT_TR : return "north east";
-  case GL2PS_TEXT_BL :
+  case GL2PS_TEXT_BL : 
   default            : return "south west";
   }
 }
@@ -5351,7 +5309,7 @@
   case GL2PS_POINT :
     /* Points in openGL are rectangular */
     gl2psPrintPGFColor(prim->verts[0].rgba);
-    fprintf(gl2ps->stream,
+    fprintf(gl2ps->stream, 
             "\\pgfpathrectangle{\\pgfpoint{%fpt}{%fpt}}"
             "{\\pgfpoint{%fpt}{%fpt}}\n\\pgfusepath{fill}\n",
             prim->verts[0].xyz[0]-0.5*prim->width,
@@ -5365,7 +5323,7 @@
       fprintf(gl2ps->stream, "\\pgfsetlinewidth{%fpt}\n", gl2ps->lastlinewidth);
     }
     gl2psPrintPGFDash(prim->pattern, prim->factor);
-    fprintf(gl2ps->stream,
+    fprintf(gl2ps->stream, 
             "\\pgfpathmoveto{\\pgfpoint{%fpt}{%fpt}}\n"
             "\\pgflineto{\\pgfpoint{%fpt}{%fpt}}\n"
             "\\pgfusepath{stroke}\n",
@@ -5378,7 +5336,7 @@
       fprintf(gl2ps->stream, "\\pgfsetlinewidth{0.01pt}\n");
     }
     gl2psPrintPGFColor(prim->verts[0].rgba);
-    fprintf(gl2ps->stream,
+    fprintf(gl2ps->stream, 
             "\\pgfpathmoveto{\\pgfpoint{%fpt}{%fpt}}\n"
             "\\pgflineto{\\pgfpoint{%fpt}{%fpt}}\n"
             "\\pgflineto{\\pgfpoint{%fpt}{%fpt}}\n"
@@ -5447,14 +5405,14 @@
       rgba[3] = 1.0F;
     }
     gl2psPrintPGFColor(rgba);
-    fprintf(gl2ps->stream,
+    fprintf(gl2ps->stream, 
             "\\pgfpathrectangle{\\pgfpoint{%dpt}{%dpt}}"
             "{\\pgfpoint{%dpt}{%dpt}}\n"
             "\\pgfusepath{fill}\n",
             x, y, w, h);
   }
-
-  fprintf(gl2ps->stream,
+  
+  fprintf(gl2ps->stream, 
           "\\pgfpathrectangle{\\pgfpoint{%dpt}{%dpt}}"
           "{\\pgfpoint{%dpt}{%dpt}}\n"
           "\\pgfusepath{clip}\n",
@@ -5486,7 +5444,7 @@
   "PGF Latex Graphics"
 };
 
-/*********************************************************************
+/********************************************************************* 
  *
  * General primitive printing routine
  *
@@ -5521,7 +5479,7 @@
     if(prim->verts[i].xyz[1] > gl2ps->viewport[3])
       gl2ps->viewport[3] = (GLint)(prim->verts[i].xyz[1] + 0.5F);
   }
-}
+}  
 
 static GLint gl2psPrintPrimitives(void)
 {
@@ -5542,7 +5500,7 @@
   gl2psRescaleAndOffset();
 
   if(gl2ps->header){
-    if(gl2psListNbr(gl2ps->primitives) &&
+    if(gl2psListNbr(gl2ps->primitives) && 
        (gl2ps->options & GL2PS_TIGHT_BOUNDING_BOX)){
       gl2ps->viewport[0] = gl2ps->viewport[1] = 100000;
       gl2ps->viewport[2] = gl2ps->viewport[3] = -100000;
@@ -5584,7 +5542,7 @@
                            gl2psAddInImageTree, 1);
       gl2psFreeBspImageTree(&gl2ps->imagetree);
     }
-    gl2psTraverseBspTree(root, eye, GL2PS_EPSILON, gl2psGreater,
+    gl2psTraverseBspTree(root, eye, GL2PS_EPSILON, gl2psGreater, 
                          gl2psbackends[gl2ps->format]->printPrimitive, 0);
     gl2psFreeBspTree(&root);
     /* reallocate the primitive list (it's been deleted by
@@ -5597,13 +5555,13 @@
   return GL2PS_SUCCESS;
 }
 
-/*********************************************************************
+/********************************************************************* 
  *
  * Public routines
  *
  *********************************************************************/
 
-GL2PSDLL_API GLint gl2psBeginPage(const char *title, const char *producer,
+GL2PSDLL_API GLint gl2psBeginPage(const char *title, const char *producer, 
                                   GLint viewport[4], GLint format, GLint sort,
                                   GLint options, GLint colormode,
                                   GLint colorsize, GL2PSrgba *colormap,
@@ -5671,7 +5629,7 @@
 
   if(!gl2ps->viewport[2] || !gl2ps->viewport[3]){
     gl2psMsg(GL2PS_ERROR, "Incorrect viewport (x=%d, y=%d, width=%d, height=%d)",
-             gl2ps->viewport[0], gl2ps->viewport[1],
+             gl2ps->viewport[0], gl2ps->viewport[1], 
              gl2ps->viewport[2], gl2ps->viewport[3]);
     gl2psFree(gl2ps);
     gl2ps = NULL;
@@ -5695,11 +5653,11 @@
   gl2ps->lastfactor = 0;
   gl2ps->imagetree = NULL;
   gl2ps->primitivetoadd = NULL;
-  gl2ps->zerosurfacearea = GL_FALSE;
+  gl2ps->zerosurfacearea = GL_FALSE;  
   gl2ps->pdfprimlist = NULL;
   gl2ps->pdfgrouplist = NULL;
   gl2ps->xreflist = NULL;
-
+  
   /* get default blending mode from current OpenGL state (enabled by
      default for SVG) */
   gl2ps->blending = (gl2ps->format == GL2PS_SVG) ? GL_TRUE : glIsEnabled(GL_BLEND);
@@ -5742,7 +5700,7 @@
     gl2ps->title = (char*)gl2psMalloc((strlen(title)+1)*sizeof(char));
     strcpy(gl2ps->title, title);
   }
-
+    
   if(!producer){
     gl2ps->producer = (char*)gl2psMalloc(sizeof(char));
     gl2ps->producer[0] = '\0';
@@ -5751,7 +5709,7 @@
     gl2ps->producer = (char*)gl2psMalloc((strlen(producer)+1)*sizeof(char));
     strcpy(gl2ps->producer, producer);
   }
-
+  
   if(!filename){
     gl2ps->filename = (char*)gl2psMalloc(sizeof(char));
     gl2ps->filename[0] = '\0';
@@ -5765,7 +5723,7 @@
   gl2ps->auxprimitives = gl2psListCreate(100, 100, sizeof(GL2PSprimitive*));
   gl2ps->feedback = (GLfloat*)gl2psMalloc(gl2ps->buffersize * sizeof(GLfloat));
   glFeedbackBuffer(gl2ps->buffersize, GL_3D_COLOR, gl2ps->feedback);
-  glRenderMode(GL_FEEDBACK);
+  glRenderMode(GL_FEEDBACK);  
 
   return GL2PS_SUCCESS;
 }
@@ -5780,7 +5738,7 @@
 
   if(res != GL2PS_OVERFLOW)
     (gl2psbackends[gl2ps->format]->printFooter)();
-
+  
   fflush(gl2ps->stream);
 
   gl2psListDelete(gl2ps->primitives);
@@ -5802,7 +5760,7 @@
   if(!gl2ps) return GL2PS_UNINITIALIZED;
 
   (gl2psbackends[gl2ps->format]->beginViewport)(viewport);
-
+  
   return GL2PS_SUCCESS;
 }
 
@@ -5820,7 +5778,7 @@
   return res;
 }
 
-GL2PSDLL_API GLint gl2psTextOpt(const char *str, const char *fontname,
+GL2PSDLL_API GLint gl2psTextOpt(const char *str, const char *fontname, 
                                 GLshort fontsize, GLint alignment, GLfloat angle)
 {
   return gl2psAddText(GL2PS_TEXT, str, fontname, fontsize, alignment, angle);
@@ -5838,11 +5796,11 @@
 
 GL2PSDLL_API GLint gl2psDrawPixels(GLsizei width, GLsizei height,
                                    GLint xorig, GLint yorig,
-                                   GLenum format, GLenum type,
+                                   GLenum format, GLenum type, 
                                    const void *pixels)
 {
   int size, i;
-  GLfloat pos[4], *piv, zoom_x, zoom_y;
+  GLfloat pos[4], *piv;
   GL2PSprimitive *prim;
   GLboolean valid;
 
@@ -5862,8 +5820,6 @@
   if(GL_FALSE == valid) return GL2PS_SUCCESS; /* the primitive is culled */
 
   glGetFloatv(GL_CURRENT_RASTER_POSITION, pos);
-  glGetFloatv(GL_ZOOM_X, &zoom_x);
-  glGetFloatv(GL_ZOOM_Y, &zoom_y);
 
   prim = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
   prim->type = GL2PS_PIXMAP;
@@ -5882,8 +5838,6 @@
   prim->data.image = (GL2PSimage*)gl2psMalloc(sizeof(GL2PSimage));
   prim->data.image->width = width;
   prim->data.image->height = height;
-  prim->data.image->zoom_x = zoom_x;
-  prim->data.image->zoom_y = zoom_y;
   prim->data.image->format = format;
   prim->data.image->type = type;
 
@@ -5897,9 +5851,9 @@
       piv = (GLfloat*)pixels;
       for(i = 0; i < size; ++i, ++piv){
         prim->data.image->pixels[i] = *piv;
-        if(!((i + 1) % 3))
+        if(!((i+1)%3))
           ++piv;
-      }
+      }   
     }
     else{
       size = height * width * 4;
@@ -5926,11 +5880,11 @@
                                      const unsigned char *imagemap){
   int size, i;
   int sizeoffloat = sizeof(GLfloat);
-
+  
   if(!gl2ps || !imagemap) return GL2PS_UNINITIALIZED;
 
   if((width <= 0) || (height <= 0)) return GL2PS_ERROR;
-
+  
   size = height + height * ((width - 1) / 8);
   glPassThrough(GL2PS_IMAGEMAP_TOKEN);
   glBegin(GL_POINTS);
@@ -6010,7 +5964,7 @@
 
   glPassThrough(GL2PS_POINT_SIZE_TOKEN);
   glPassThrough(value);
-
+  
   return GL2PS_SUCCESS;
 }
 
--- a/src/gl2ps.h
+++ b/src/gl2ps.h
@@ -139,9 +139,9 @@
 #define GL2PS_BLEND               4
 
 /* Text alignment (o=raster position; default mode is BL):
-   +---+ +---+ +---+ +---+ +---+ +---+ +-o-+ o---+ +---o
-   | o | o   | |   o |   | |   | |   | |   | |   | |   |
-   +---+ +---+ +---+ +-o-+ o---+ +---o +---+ +---+ +---+
+   +---+ +---+ +---+ +---+ +---+ +---+ +-o-+ o---+ +---o 
+   | o | o   | |   o |   | |   | |   | |   | |   | |   | 
+   +---+ +---+ +---+ +-o-+ o---+ +---o +---+ +---+ +---+ 
     C     CL    CR    B     BL    BR    T     TL    TR */
 
 #define GL2PS_TEXT_C  1
@@ -160,10 +160,10 @@
 extern "C" {
 #endif
 
-GL2PSDLL_API GLint gl2psBeginPage(const char *title, const char *producer,
+GL2PSDLL_API GLint gl2psBeginPage(const char *title, const char *producer, 
                                   GLint viewport[4], GLint format, GLint sort,
                                   GLint options, GLint colormode,
-                                  GLint colorsize, GL2PSrgba *colormap,
+                                  GLint colorsize, GL2PSrgba *colormap, 
                                   GLint nr, GLint ng, GLint nb, GLint buffersize,
                                   FILE *stream, const char *filename);
 GL2PSDLL_API GLint gl2psEndPage(void);
@@ -171,9 +171,9 @@
 GL2PSDLL_API GLint gl2psGetOptions(GLint *options);
 GL2PSDLL_API GLint gl2psBeginViewport(GLint viewport[4]);
 GL2PSDLL_API GLint gl2psEndViewport(void);
-GL2PSDLL_API GLint gl2psText(const char *str, const char *fontname,
+GL2PSDLL_API GLint gl2psText(const char *str, const char *fontname, 
                              GLshort fontsize);
-GL2PSDLL_API GLint gl2psTextOpt(const char *str, const char *fontname,
+GL2PSDLL_API GLint gl2psTextOpt(const char *str, const char *fontname, 
                                 GLshort fontsize, GLint align, GLfloat angle);
 GL2PSDLL_API GLint gl2psSpecial(GLint format, const char *str);
 GL2PSDLL_API GLint gl2psDrawPixels(GLsizei width, GLsizei height,
--- a/src/graphics.cc
+++ b/src/graphics.cc
@@ -3172,6 +3172,7 @@
   ticklength.add_constraint (dim_vector (1, 2));
   tightinset.add_constraint (dim_vector (1, 4));
   looseinset.add_constraint (dim_vector (1, 4));
+  update_font ();
 
   x_zlim.resize (1, 2);
 
@@ -3263,13 +3264,119 @@
 void
 axes::properties::sync_positions (void)
 {
+  Matrix ref_linset = looseinset.get ().matrix_value ();
+  if (autopos_tag_is ("subplot"))
+    {
+      graphics_object parent_obj = gh_manager::get_object (get_parent ());
+      if (parent_obj.isa ("figure"))
+        {
+           // FIXME: temporarily changed units should be protected
+           //        from interrupts
+           std::string fig_units = parent_obj.get ("units").string_value ();
+           parent_obj.set ("units", "pixels");
+
+           Matrix ref_outbox = outerposition.get ().matrix_value ();
+           ref_outbox(2) += ref_outbox(0);
+           ref_outbox(3) += ref_outbox(1);
+
+           // Find those subplots that are left, right, bottom and top aligned
+           // with the current subplot
+           Matrix kids = parent_obj.get_properties ().get_children ();
+           std::vector<octave_value> aligned;
+           std::vector<bool> l_aligned, b_aligned, r_aligned, t_aligned;
+           for (octave_idx_type i = 0; i < kids.numel (); i++)
+             {
+               graphics_object go = gh_manager::get_object (kids(i));
+               if (go.isa ("axes"))
+                 {
+                   axes::properties& props =
+                     dynamic_cast<axes::properties&> (go.get_properties ());
+                   if (props.autopos_tag_is("subplot"))
+                     {
+                       Matrix outpos = go.get ("outerposition").matrix_value ();
+                       bool l_align=(std::abs (outpos(0)-ref_outbox(0)) < 1e-15);
+                       bool b_align=(std::abs (outpos(1)-ref_outbox(1)) < 1e-15);
+                       bool r_align=(std::abs (outpos(0)+outpos(2)-ref_outbox(2)) < 1e-15);
+                       bool t_align=(std::abs (outpos(1)+outpos(3)-ref_outbox(3)) < 1e-15);
+                       if (l_align || b_align || r_align || t_align)
+                         {
+                           aligned.push_back(kids(i));
+                           l_aligned.push_back(l_align);
+                           b_aligned.push_back(b_align);
+                           r_aligned.push_back(r_align);
+                           t_aligned.push_back(t_align);
+                           // FIXME: the temporarily deleted tags should be
+                           //        protected from interrupts
+                           props.set_autopos_tag ("none");
+                         }
+                     }
+                 }
+             }
+           // Determine a minimum box which aligns the subplots
+           Matrix ref_box(1, 4, 0.);
+           ref_box(2) = 1.;
+           ref_box(3) = 1.;
+           for (size_t i = 0; i < aligned.size (); i++)
+             {
+               graphics_object go = gh_manager::get_object (aligned[i]);
+               axes::properties& props =
+                 dynamic_cast<axes::properties&> (go.get_properties ());
+               Matrix linset = props.get_looseinset ().matrix_value ();
+               if (l_aligned[i])
+                 linset(0) = std::min (0., linset(0)-0.01);
+               if (b_aligned[i])
+                 linset(1) = std::min (0., linset(1)-0.01);
+               if (r_aligned[i])
+                 linset(2) = std::min (0., linset(2)-0.01);
+               if (t_aligned[i])
+                 linset(3) = std::min (0., linset(3)-0.01);
+               props.set_looseinset (linset);
+               Matrix pos = props.get_position ().matrix_value ();
+               if (l_aligned[i])
+                 ref_box(0) = std::max (ref_box(0), pos(0));
+               if (b_aligned[i])
+                 ref_box(1) = std::max (ref_box(1), pos(1));
+               if (r_aligned[i])
+                 ref_box(2) = std::min (ref_box(2), pos(0)+pos(2));
+               if (t_aligned[i])
+                 ref_box(3) = std::min (ref_box(3), pos(1)+pos(3));
+             }
+           // Set common looseinset values for all aligned subplots and
+           // revert their tag values
+           for (size_t i = 0; i < aligned.size (); i++)
+             {
+               graphics_object go = gh_manager::get_object (aligned[i]);
+               axes::properties& props =
+                 dynamic_cast<axes::properties&> (go.get_properties ());
+               Matrix outpos = props.get_outerposition ().matrix_value ();
+               Matrix linset = props.get_looseinset ().matrix_value ();
+               if (l_aligned[i])
+                 linset(0) = (ref_box(0)-outpos(0))/outpos(2);
+               if (b_aligned[i])
+                 linset(1) = (ref_box(1)-outpos(1))/outpos(3);
+               if (r_aligned[i])
+                 linset(2) = (outpos(0)+outpos(2)-ref_box(2))/outpos(2);
+               if (t_aligned[i])
+                 linset(3) = (outpos(1)+outpos(3)-ref_box(3))/outpos(3);
+               props.set_looseinset (linset);
+               props.set_autopos_tag ("subplot");
+             }
+           parent_obj.set ("units", fig_units);
+        }
+    }
+  else
+    sync_positions (ref_linset);
+}
+
+void
+axes::properties::sync_positions (const Matrix& linset)
+{
   Matrix pos = position.get ().matrix_value ();
   Matrix outpos = outerposition.get ().matrix_value ();
-  Matrix lins = looseinset.get ().matrix_value ();
-  double lratio = lins(0);
-  double bratio = lins(1);
-  double wratio = 1-lins(0)-lins(2);
-  double hratio = 1-lins(1)-lins(3);
+  double lratio = linset(0);
+  double bratio = linset(1);
+  double wratio = 1-linset(0)-linset(2);
+  double hratio = 1-linset(1)-linset(3);
   if (activepositionproperty.is ("outerposition"))
     {
       pos = outpos;
@@ -4223,15 +4330,22 @@
   update_title_position ();
 }
 
+static bool updating_xlabel_position = false;
+
 void
 axes::properties::update_xlabel_position (void)
 {
+  if (updating_xlabel_position)
+    return;
+
   text::properties& xlabel_props = reinterpret_cast<text::properties&>
     (gh_manager::get_object (get_xlabel ()).get_properties ());
 
-  bool is_empty = xlabel_props.get_string ().empty ();
-
-  xlabel_props.set_autopos_tag ("none");
+  bool is_empty = xlabel_props.get_string ().is_empty ();
+
+  unwind_protect frame;
+  frame.protect_var (updating_xlabel_position);
+  updating_xlabel_position = true;
 
   if (! is_empty)
     {
@@ -4305,19 +4419,24 @@
           xlabel_props.set_rotationmode ("auto");
         }
     }
-
-  xlabel_props.set_autopos_tag ("xlabel");
-}
+}
+
+static bool updating_ylabel_position = false;
 
 void
 axes::properties::update_ylabel_position (void)
 {
+  if (updating_ylabel_position)
+    return;
+
   text::properties& ylabel_props = reinterpret_cast<text::properties&>
     (gh_manager::get_object (get_ylabel ()).get_properties ());
 
-  bool is_empty = ylabel_props.get_string ().empty ();
-
-  ylabel_props.set_autopos_tag ("none");
+  bool is_empty = ylabel_props.get_string ().is_empty ();
+
+  unwind_protect frame;
+  frame.protect_var (updating_ylabel_position);
+  updating_ylabel_position = true;
 
   if (! is_empty)
     {
@@ -4391,20 +4510,25 @@
           ylabel_props.set_rotationmode ("auto");
         }
     }
-
-  ylabel_props.set_autopos_tag ("ylabel");
-}
+}
+
+static bool updating_zlabel_position = false;
 
 void
 axes::properties::update_zlabel_position (void)
 {
+  if (updating_zlabel_position)
+    return;
+
   text::properties& zlabel_props = reinterpret_cast<text::properties&>
     (gh_manager::get_object (get_zlabel ()).get_properties ());
 
   bool camAuto = cameraupvectormode_is ("auto");
-  bool is_empty = zlabel_props.get_string ().empty ();
-
-  zlabel_props.set_autopos_tag ("none");
+  bool is_empty = zlabel_props.get_string ().is_empty ();
+
+  unwind_protect frame;
+  frame.protect_var (updating_zlabel_position);
+  updating_zlabel_position = true;
 
   if (! is_empty)
     {
@@ -4499,17 +4623,22 @@
           zlabel_props.set_rotationmode ("auto");
         }
     }
-
-  zlabel_props.set_autopos_tag ("zlabel");
-}
+}
+
+static bool updating_title_position = false;
 
 void
 axes::properties::update_title_position (void)
 {
+  if (updating_title_position)
+    return;
+
   text::properties& title_props = reinterpret_cast<text::properties&>
     (gh_manager::get_object (get_title ()).get_properties ());
 
-  title_props.set_autopos_tag ("none");
+  unwind_protect frame;
+  frame.protect_var (updating_title_position);
+  updating_title_position = true;
 
   if (title_props.positionmode_is ("auto"))
     {
@@ -4523,8 +4652,6 @@
       title_props.set_position (p.extract_n(0, 3).transpose ());
       title_props.set_positionmode ("auto");
     }
-
-  title_props.set_autopos_tag ("title");
 }
 
 void
@@ -4693,6 +4820,19 @@
     }
 }
 
+void
+axes::properties::update_font (void)
+{
+#ifdef HAVE_FREETYPE
+#ifdef HAVE_FONTCONFIG
+  text_renderer.set_font (get ("fontname").string_value (),
+                          get ("fontweight").string_value (),
+                          get ("fontangle").string_value (),
+                          get ("fontsize").double_value ());
+#endif
+#endif
+}
+
 // The INTERNAL flag defines whether position or outerposition is used.
 
 Matrix
@@ -4756,7 +4896,7 @@
 
           Matrix text_pos = text_props.get_position ().matrix_value ();
           text_pos = xform.transform (text_pos(0), text_pos(1), text_pos(2));
-          if (text_props.get_string ().empty ())
+          if (text_props.get_string ().is_empty ())
             {
               ext(0) = std::min (ext(0), text_pos(0));
               ext(1) = std::min (ext(1), text_pos(1));
@@ -5196,14 +5336,7 @@
                                          const string_vector& ticklabels,
                                          const Matrix& limits)
 {
-#ifdef HAVE_FREETYPE
-  //FIXME: text_renderer could be cached
-  ft_render text_renderer;
-  text_renderer.set_font (get ("fontname").string_value (),
-                          get ("fontweight").string_value (),
-                          get ("fontangle").string_value (),
-                          get ("fontsize").double_value ());
-#else
+#ifndef HAVE_FREETYPE
   double fontsize = get ("fontsize").double_value ();
 #endif
 
@@ -5856,11 +5989,9 @@
 }
 
 void
-text::properties::update_text_extent (void)
+text::properties::update_font (void)
 {
 #ifdef HAVE_FREETYPE
-
-  // FIXME: font and color should be set only when modified, for efficiency
 #ifdef HAVE_FONTCONFIG
   renderer.set_font (get ("fontname").string_value (),
                      get ("fontweight").string_value (),
@@ -5868,6 +5999,13 @@
                      get ("fontsize").double_value ());
 #endif
   renderer.set_color (get_color_rgb ());
+#endif
+}
+
+void
+text::properties::update_text_extent (void)
+{
+#ifdef HAVE_FREETYPE
 
   int halign = 0, valign = 0;
 
@@ -5884,11 +6022,17 @@
     valign = 1;
 
   Matrix bbox;
+
   // FIXME: string should be parsed only when modified, for efficiency
-  renderer.text_to_pixels (get_string (), pixels, bbox,
+
+  octave_value string_prop = get_string ();
+
+  string_vector sv = string_prop.all_strings ();
+
+  renderer.text_to_pixels (sv.join ("\n"), pixels, bbox,
                            halign, valign, get_rotation ());
-
   set_extent (bbox);
+
 #endif
 
   if (autopos_tag_is ("xlabel") || autopos_tag_is ("ylabel") ||
@@ -6909,6 +7053,12 @@
 
   if (nargin == 1 || nargin == 2)
     {
+      if (args(0).is_empty())
+        {
+          retval = Matrix ();
+          return retval;
+        }
+
       ColumnVector hcv (args(0).vector_value ());
 
       if (! error_state)
--- a/src/graphics.h.in
+++ b/src/graphics.h.in
@@ -33,6 +33,7 @@
 #include <list>
 #include <map>
 #include <set>
+#include <sstream>
 #include <string>
 
 #include "caseless-str.h"
@@ -692,6 +693,178 @@
 
 // ---------------------------------------------------------------------
 
+class text_label_property : public base_property
+{
+public:
+  enum type { char_t, cellstr_t };
+
+  text_label_property (const std::string& s, const graphics_handle& h,
+                       const std::string& val = "")
+    : base_property (s, h), value (val), stored_type (char_t)
+  { }
+
+  text_label_property (const std::string& s, const graphics_handle& h,
+                       const NDArray& nda)
+    : base_property (s, h), stored_type (char_t)
+  {
+    octave_idx_type nel = nda.numel ();
+
+    value.resize (nel);
+
+    for (octave_idx_type i = 0; i < nel; i++)
+      {
+        std::ostringstream buf;
+        buf << nda(i);
+        value[i] = buf.str ();
+      }
+  }
+
+  text_label_property (const std::string& s, const graphics_handle& h,
+                       const Cell& c)
+    : base_property (s, h), stored_type (cellstr_t)
+  {
+    octave_idx_type nel = c.numel ();
+
+    value.resize (nel);
+
+    for (octave_idx_type i = 0; i < nel; i++)
+      {
+        octave_value tmp = c(i);
+
+        if (tmp.is_string ())
+          value[i] = c(i).string_value ();
+        else
+          {
+            double d = c(i).double_value ();
+
+            if (! error_state)
+              {
+                std::ostringstream buf;
+                buf << d;
+                value[i] = buf.str ();
+              }
+            else
+              break;
+          }
+      }
+  }
+
+  text_label_property (const text_label_property& p)
+    : base_property (p), value (p.value), stored_type (p.stored_type)
+  { }
+
+  bool empty (void) const
+  {
+    octave_value tmp = get ();
+    return tmp.is_empty ();
+  }
+
+  octave_value get (void) const
+  {
+    if (stored_type == char_t)
+      return octave_value (char_value ());
+    else
+      return octave_value (cell_value ());
+  }
+
+  std::string string_value (void) const
+  {
+    return value.empty () ? std::string () : value[0];
+  }
+
+  string_vector string_vector_value (void) const { return value; }
+
+  charMatrix char_value (void) const { return charMatrix (value, ' '); }
+
+  Cell cell_value (void) const {return Cell (value); }
+
+  text_label_property& operator = (const octave_value& val)
+  {
+    set (val);
+    return *this;
+  }
+
+  base_property* clone (void) const { return new text_label_property (*this); }
+
+protected:
+
+  bool do_set (const octave_value& val)
+  {
+    if (val.is_string ())
+      {
+        value = val.all_strings ();
+
+        stored_type = char_t;
+      }
+    else if (val.is_cell ())
+      {
+        Cell c = val.cell_value ();
+
+        octave_idx_type nel = c.numel ();
+
+        value.resize (nel);
+
+        for (octave_idx_type i = 0; i < nel; i++)
+          {
+            octave_value tmp = c(i);
+
+            if (tmp.is_string ())
+              value[i] = c(i).string_value ();
+            else
+              {
+                double d = c(i).double_value ();
+
+                if (! error_state)
+                  {
+                    std::ostringstream buf;
+                    buf << d;
+                    value[i] = buf.str ();
+                  }
+                else
+                  return false;
+              }
+          }
+
+        stored_type = cellstr_t;
+      }
+    else
+      {
+        NDArray nda = val.array_value ();
+
+        if (! error_state)
+          {
+            octave_idx_type nel = nda.numel ();
+
+            value.resize (nel);
+
+            for (octave_idx_type i = 0; i < nel; i++)
+              {
+                std::ostringstream buf;
+                buf << nda(i);
+                value[i] = buf.str ();
+              }
+
+            stored_type = char_t;
+          }
+        else
+          {
+            error ("set: invalid string property value for \"%s\"",
+                   get_name ().c_str ());
+
+            return false;
+          }
+      }
+
+    return true;
+  }
+
+private:
+  string_vector value;
+  type stored_type;
+};
+
+// ---------------------------------------------------------------------
+
 class radio_values
 {
 public:
@@ -3206,6 +3379,11 @@
     bool x2Dtop, y2Dright, layer2Dtop;
     bool xySym, xyzSym, zSign, nearhoriz;
 
+#if HAVE_FREETYPE
+    // freetype renderer, used for calculation of text (tick labels) size
+    ft_render text_renderer;
+#endif
+
     void set_text_child (handle_property& h, const std::string& who,
                          const octave_value& v);
 
@@ -3288,11 +3466,11 @@
       radio_property cameraviewanglemode , "{auto}|manual"
       array_property currentpoint , Matrix (2, 3, 0.0)
       radio_property drawmode , "{normal}|fast"
-      radio_property fontangle , "{normal}|italic|oblique"
-      string_property fontname , OCTAVE_DEFAULT_FONTNAME
-      double_property fontsize , 10
+      radio_property fontangle u , "{normal}|italic|oblique"
+      string_property fontname u , OCTAVE_DEFAULT_FONTNAME
+      double_property fontsize u , 10
       radio_property fontunits SU , "{points}|normalized|inches|centimeters|pixels"
-      radio_property fontweight , "{normal}|light|demi|bold"
+      radio_property fontweight u , "{normal}|light|demi|bold"
       radio_property gridlinestyle , "-|--|{:}|-.|none"
       string_array_property linestyleorder , "-"
       double_property linewidth , 0.5
@@ -3318,6 +3496,8 @@
       row_vector_property zmtick h , Matrix ()
       // hidden properties for inset
       array_property looseinset hu , Matrix (1, 4, 0.0)
+      // hidden properties for alignment of subplots
+      radio_property autopos_tag h , "{none}|subplot"
    END_PROPERTIES
 
   protected:
@@ -3411,7 +3591,15 @@
           calc_ticklabels (ztick, zticklabel, zscale.is ("log"));
       }
 
+    void update_font (void);
+    void update_fontname (void) { update_font (); }
+    void update_fontsize (void) { update_font (); }
+    void update_fontangle (void) { update_font (); }
+    void update_fontweight (void) { update_font (); }
+
+    void sync_positions (const Matrix& linset);
     void sync_positions (void);
+
     void update_outerposition (void)
     {
       set_activepositionproperty ("outerposition");
@@ -3671,7 +3859,7 @@
     // properties declarations.
 
     BEGIN_PROPERTIES (text)
-      string_property string u , ""
+      text_label_property string u , ""
       radio_property units u , "{data}|pixels|normalized|inches|centimeters|points"
       array_property position mu , Matrix (1, 3, 0.0)
       double_property rotation mu , 0
@@ -3712,7 +3900,7 @@
     Matrix get_extent_matrix (void) const;
     const uint8NDArray& get_pixels (void) const { return pixels; }
 #if HAVE_FREETYPE
-    // freetype render, used for text rendering
+    // freetype renderer, used for calculation of text size
     ft_render renderer;
 #endif
 
@@ -3722,6 +3910,7 @@
         position.add_constraint (dim_vector (1, 2));
         position.add_constraint (dim_vector (1, 3));
         cached_units = get_units ();
+        update_font ();
       }
 
   private:
@@ -3757,13 +3946,14 @@
     void update_horizontalalignmentmode (void) { request_autopos (); }
     void update_verticalalignmentmode (void) { request_autopos (); }
 
+    void update_font (void);
     void update_string (void) { request_autopos (); update_text_extent (); }
     void update_rotation (void) { update_text_extent (); }
-    void update_color (void) { update_text_extent (); }
-    void update_fontname (void) { update_text_extent (); }
-    void update_fontsize (void) { update_text_extent (); }
-    void update_fontangle (void) { update_text_extent (); }
-    void update_fontweight (void) { update_text_extent (); }
+    void update_color (void) { update_font (); }
+    void update_fontname (void) { update_font (); update_text_extent (); }
+    void update_fontsize (void) { update_font (); update_text_extent (); }
+    void update_fontangle (void) { update_font (); update_text_extent (); }
+    void update_fontweight (void) { update_font (); update_text_extent (); }
     void update_interpreter (void) { update_text_extent (); }
     void update_horizontalalignment (void) { update_text_extent (); }
     void update_verticalalignment (void) { update_text_extent (); }
--- a/src/help.cc
+++ b/src/help.cc
@@ -749,6 +749,9 @@
   const string_vector bif = symbol_table::built_in_function_names ();
   const int bif_len = bif.length ();
 
+  const string_vector cfl = symbol_table::cmdline_function_names ();
+  const int cfl_len = cfl.length ();
+
   const string_vector lcl = symbol_table::variable_names ();
   const int lcl_len = lcl.length ();
 
@@ -758,7 +761,8 @@
   const string_vector afl = autoloaded_functions ();
   const int afl_len = afl.length ();
 
-  const int total_len = key_len + bif_len + lcl_len + ffl_len + afl_len;
+  const int total_len
+    = key_len + bif_len + cfl_len + lcl_len + ffl_len + afl_len;
 
   string_vector list (total_len);
 
@@ -772,6 +776,9 @@
   for (i = 0; i < bif_len; i++)
     list[j++] = bif[i];
 
+  for (i = 0; i < cfl_len; i++)
+    list[j++] = cfl[i];
+
   for (i = 0; i < lcl_len; i++)
     list[j++] = lcl[i];
 
--- a/src/input.cc
+++ b/src/input.cc
@@ -686,93 +686,88 @@
   frame.protect_var (VPS1);
   VPS1 = prompt;
 
-  if (stdin_is_tty)
+  if (! (interactive || forced_interactive)
+      || (reading_fcn_file
+          || reading_classdef_file
+          || reading_script_file
+          || get_input_from_eval_string
+          || input_from_startup_file
+          || input_from_command_line_file))
     {
-      if (! (interactive || forced_interactive)
-          || (reading_fcn_file
-              || reading_classdef_file
-              || reading_script_file
-              || get_input_from_eval_string
-              || input_from_startup_file
-              || input_from_command_line_file))
-        {
-          frame.protect_var (forced_interactive);
-          forced_interactive = true;
+      frame.protect_var (forced_interactive);
+      forced_interactive = true;
+
+      frame.protect_var (reading_fcn_file);
+      reading_fcn_file = false;
+
+      frame.protect_var (reading_classdef_file);
+      reading_classdef_file = false;
+
+      frame.protect_var (reading_script_file);
+      reading_script_file = false;
 
-          frame.protect_var (reading_fcn_file);
-          reading_fcn_file = false;
+      frame.protect_var (input_from_startup_file);
+      input_from_startup_file = false;
+
+      frame.protect_var (input_from_command_line_file);
+      input_from_command_line_file = false;
 
-          frame.protect_var (reading_classdef_file);
-          reading_classdef_file = false;
+      frame.protect_var (get_input_from_eval_string);
+      get_input_from_eval_string = false;
+
+      YY_BUFFER_STATE old_buf = current_buffer ();
+      YY_BUFFER_STATE new_buf = create_buffer (get_input_from_stdin ());
+
+      // FIXME: are these safe?
+      frame.add_fcn (switch_to_buffer, old_buf);
+      frame.add_fcn (delete_buffer, new_buf);
 
-          frame.protect_var (reading_script_file);
-          reading_script_file = false;
+      switch_to_buffer (new_buf);
+    }
+
+  while (Vdebugging)
+    {
+      reset_error_handler ();
+
+      reset_parser ();
 
-          frame.protect_var (input_from_startup_file);
-          input_from_startup_file = false;
+      // Save current value of global_command.
+      frame.protect_var (global_command);
+
+      global_command = 0;
 
-          frame.protect_var (input_from_command_line_file);
-          input_from_command_line_file = false;
+      // Do this with an unwind-protect cleanup function so that the
+      // forced variables will be unmarked in the event of an interrupt.
+      symbol_table::scope_id scope = symbol_table::top_scope ();
+      frame.add_fcn (symbol_table::unmark_forced_variables, scope);
 
-          frame.protect_var (get_input_from_eval_string);
-          get_input_from_eval_string = false;
+      // This is the same as yyparse in parse.y.
+      int retval = octave_parse ();
 
-          YY_BUFFER_STATE old_buf = current_buffer ();
-          YY_BUFFER_STATE new_buf = create_buffer (get_input_from_stdin ());
+      if (retval == 0 && global_command)
+        {
+          global_command->accept (*current_evaluator);
 
-          // FIXME: are these safe?
-          frame.add_fcn (switch_to_buffer, old_buf);
-          frame.add_fcn (delete_buffer, new_buf);
+          // FIXME -- To avoid a memory leak, global_command should be
+          // deleted, I think.  But doing that here causes trouble if
+          // an error occurs while executing a debugging command
+          // (dbstep, for example). It's not clear to me why that
+          // happens.
+          //
+          // delete global_command;
+          //
+          // global_command = 0;
 
-          switch_to_buffer (new_buf);
+          if (octave_completion_matches_called)
+            octave_completion_matches_called = false;
         }
 
-      while (Vdebugging)
-        {
-          reset_error_handler ();
-
-          reset_parser ();
-
-          // Save current value of global_command.
-          frame.protect_var (global_command);
-
-          global_command = 0;
-
-          // Do this with an unwind-protect cleanup function so that the
-          // forced variables will be unmarked in the event of an interrupt.
-          symbol_table::scope_id scope = symbol_table::top_scope ();
-          frame.add_fcn (symbol_table::unmark_forced_variables, scope);
-
-          // This is the same as yyparse in parse.y.
-          int retval = octave_parse ();
-
-          if (retval == 0 && global_command)
-            {
-              global_command->accept (*current_evaluator);
+      // Unmark forced variables.
+      // Restore previous value of global_command.
+      frame.run_top (2);
 
-              // FIXME -- To avoid a memory leak, global_command should be
-              // deleted, I think.  But doing that here causes trouble if
-              // an error occurs while executing a debugging command
-              // (dbstep, for example). It's not clear to me why that
-              // happens.
-              //
-              // delete global_command;
-              //
-              // global_command = 0;
-
-              if (octave_completion_matches_called)
-                octave_completion_matches_called = false;
-            }
-
-          // Unmark forced variables.
-          // Restore previous value of global_command.
-          frame.run_top (2);
-
-          octave_quit ();
-        }
+      octave_quit ();
     }
-  else
-    warning ("invalid attempt to debug script read from stdin");
 }
 
 // If the user simply hits return, this will produce an empty matrix.
@@ -956,14 +951,11 @@
 
   unwind_protect frame;
 
-  // FIXME -- we shouldn't need both the
-  // command_history object and the
-  // Vsaving_history variable...
+  frame.add_fcn (command_history::ignore_entries,
+                 command_history::ignoring_entries ());
+
   command_history::ignore_entries (false);
 
-  frame.add_fcn (command_history::ignore_entries, ! Vsaving_history);
-
-  frame.protect_var (Vsaving_history);
   frame.protect_var (Vdebugging);
 
   frame.add_fcn (octave_call_stack::restore_frame,
@@ -975,7 +967,6 @@
   // tree_print_code tpc (octave_stdout);
   // stmt.accept (tpc);
 
-  Vsaving_history = true;
   Vdebugging = true;
 
   std::string prompt = "debug> ";
--- a/src/lex.ll
+++ b/src/lex.ll
@@ -164,13 +164,13 @@
     } \
   while (0)
 
-#define BIN_OP_RETURN(tok, convert, bos) \
+#define BIN_OP_RETURN_INTERNAL(tok, convert, bos, qit) \
   do \
     { \
       yylval.tok_val = new token (input_line_number, current_input_column); \
       token_stack.push (yylval.tok_val); \
       current_input_column += yyleng; \
-      lexer_flags.quote_is_transpose = false; \
+      lexer_flags.quote_is_transpose = qit; \
       lexer_flags.convert_spaces_to_comma = convert; \
       lexer_flags.looking_for_object_index = false; \
       lexer_flags.at_beginning_of_statement = bos; \
@@ -178,6 +178,21 @@
     } \
   while (0)
 
+#define XBIN_OP_RETURN_INTERNAL(tok, convert, bos, qit) \
+  do \
+    { \
+      gripe_matlab_incompatible_operator (yytext); \
+      BIN_OP_RETURN_INTERNAL (tok, convert, bos, qit); \
+    } \
+  while (0)
+
+#define BIN_OP_RETURN(tok, convert, bos) \
+  do \
+    { \
+      BIN_OP_RETURN_INTERNAL (tok, convert, bos, false); \
+    } \
+  while (0)
+
 #define XBIN_OP_RETURN(tok, convert, bos) \
   do \
     { \
@@ -896,8 +911,8 @@
 ".^"    { LEXER_DEBUG (".^"); BIN_OP_RETURN (EPOW, false, false); }
 ".**"   { LEXER_DEBUG (".**"); XBIN_OP_RETURN (EPOW, false, false); }
 ".'"    { LEXER_DEBUG (".'"); do_comma_insert_check (); BIN_OP_RETURN (TRANSPOSE, true, false); }
-"++"    { LEXER_DEBUG ("++"); do_comma_insert_check (); XBIN_OP_RETURN (PLUS_PLUS, true, false); }
-"--"    { LEXER_DEBUG ("--"); do_comma_insert_check (); XBIN_OP_RETURN (MINUS_MINUS, true, false); }
+"++"    { LEXER_DEBUG ("++"); do_comma_insert_check (); XBIN_OP_RETURN_INTERNAL (PLUS_PLUS, true, false, true); }
+"--"    { LEXER_DEBUG ("--"); do_comma_insert_check (); XBIN_OP_RETURN_INTERNAL (MINUS_MINUS, true, false, true); }
 "<="    { LEXER_DEBUG ("<="); BIN_OP_RETURN (EXPR_LE, false, false); }
 "=="    { LEXER_DEBUG ("=="); BIN_OP_RETURN (EXPR_EQ, false, false); }
 "~="    { LEXER_DEBUG ("~="); BIN_OP_RETURN (EXPR_NE, false, false); }
@@ -3435,6 +3450,14 @@
   return retval;
 }
 
+/*
+
+%!assert (iskeyword ("for"))
+%!assert (iskeyword ("fort"), false)
+%!assert (iskeyword ("fft"), false)
+
+*/
+
 void
 prep_lexer_for_script_file (void)
 {
new file mode 100644
--- /dev/null
+++ b/src/link-deps.mk
@@ -0,0 +1,38 @@
+include ../liboctave/link-deps.mk
+
+if AMCOND_ENABLE_DYNAMIC_LINKING
+  LIBOCTINTERP_LINK_DEPS =
+else
+  LIBOCTINTERP_LINK_DEPS = $(DLD_FUNCTIONS_LIBS)
+endif
+
+LIBOCTINTERP_LINK_DEPS += \
+  $(GRAPHICS_LIBS) \
+  $(FT2_LIBS) \
+  $(HDF5_LIBS) \
+  $(Z_LIBS) \
+  $(OPENGL_LIBS) \
+  $(X11_LIBS) \
+  $(CARBON_LIBS)
+
+LIBOCTINTERP_LINK_OPTS = \
+  $(GRAPHICS_LDFLAGS) \
+  $(FT2_LDFLAGS) \
+  $(HDF5_LDFLAGS) \
+  $(Z_LDFLAGS) \
+  $(REGEX_LDFLAGS)
+
+OCT_LINK_DEPS =
+
+OCT_LINK_OPTS = $(LDFLAGS)
+
+if AMCOND_LINK_ALL_DEPS
+  LIBOCTINTERP_LINK_DEPS += $(LIBOCTAVE_LINK_DEPS)
+  LIBOCTINTERP_LINK_OPTS += $(LIBOCTAVE_LINK_OPTS)
+
+  OCTAVE_LINK_DEPS = $(LIBOCTINTERP_LINK_DEPS)
+  OCTAVE_LINK_OPTS = $(LIBOCTINTERP_LINK_OPTS)
+
+  OCT_LINK_DEPS += $(LIBOCTINTERP_LINK_DEPS)
+  OCT_LINK_OPTS += $(LIBOCTINTERP_LINK_OPTS)
+endif
--- a/src/load-save.cc
+++ b/src/load-save.cc
@@ -545,6 +545,9 @@
 @deftypefnx {Command} {} load options file\n\
 @deftypefnx {Command} {} load options file v1 v2 @dots{}\n\
 @deftypefnx {Command} {S =} load (\"options\", \"file\", \"v1\", \"v2\", @dots{})\n\
+@deftypefnx {Command} {} load file options\n\
+@deftypefnx {Command} {} load file options v1 v2 @dots{}\n\
+@deftypefnx {Command} {S =} load (\"file\", \"options\", \"v1\", \"v2\", @dots{})\n\
 Load the named variables @var{v1}, @var{v2}, @dots{}, from the file\n\
 @var{file}.  If no variables are specified then all variables found in the\n\
 file will be loaded.  As with @code{save}, the list of variables to extract\n\
@@ -642,6 +645,16 @@
   if (error_state)
     return retval;
 
+  int i = 1;
+  std::string orig_fname = "";
+
+  // Function called with Matlab-style ["filename", options] syntax
+  if (argv[1].at(0) != '-')
+    {
+      orig_fname = argv[1];
+      i++;
+    }
+
   // It isn't necessary to have the default load format stored in a
   // user preference variable since we can determine the type of file
   // as we are reading.
@@ -651,8 +664,8 @@
   bool list_only = false;
   bool verbose = false;
 
-  int i;
-  for (i = 1; i < argc; i++)
+  //for (i; i < argc; i++)
+  for (; i < argc; i++)
     {
       if (argv[i] == "-force" || argv[i] == "-f")
         {
@@ -710,19 +723,24 @@
         break;
     }
 
-  if (i == argc)
+  if (orig_fname == "")
     {
-      print_usage ();
-      return retval;
+      if (i == argc)
+        {
+          print_usage ();
+          return retval;
+        }
+      else
+        orig_fname = argv[i];
     }
-
-  std::string orig_fname = argv[i];
+  else
+    i--;
 
   oct_mach_info::float_format flt_fmt = oct_mach_info::flt_fmt_unknown;
 
   bool swap = false;
 
-  if (argv[i] == "-")
+  if (orig_fname == "-")
     {
       i++;
 
@@ -747,7 +765,7 @@
     }
   else
     {
-      std::string fname = file_ops::tilde_expand (argv[i]);
+      std::string fname = file_ops::tilde_expand (orig_fname);
 
       fname = find_file_to_load (fname, orig_fname);
 
--- a/src/ls-mat5.cc
+++ b/src/ls-mat5.cc
@@ -1225,21 +1225,29 @@
             else
               {
                 octave_class* cls = new octave_class (m, classname);
-                cls->reconstruct_exemplar ();
-
-                if (! cls->reconstruct_parents ())
-                  warning ("load: unable to reconstruct object inheritance");
-
-                tc = cls;
-                if (load_path::find_method (classname, "loadobj") !=
-                    std::string())
+
+                if (cls->reconstruct_exemplar ())
                   {
-                    octave_value_list tmp = feval ("loadobj", tc, 1);
-
-                    if (! error_state)
-                      tc = tmp(0);
-                    else
-                      goto data_read_error;
+
+                    if (! cls->reconstruct_parents ())
+                      warning ("load: unable to reconstruct object inheritance");
+
+                    tc = cls;
+                    if (load_path::find_method (classname, "loadobj") !=
+                        std::string())
+                      {
+                        octave_value_list tmp = feval ("loadobj", tc, 1);
+
+                        if (! error_state)
+                          tc = tmp(0);
+                        else
+                          goto data_read_error;
+                      }
+                  }
+                else
+                  {
+                    tc = m;
+                    warning ("load: element has been converted to a structure");
                   }
               }
           }
--- a/src/mkoctfile.cc.in
+++ b/src/mkoctfile.cc.in
@@ -219,7 +219,6 @@
   vars["DL_LD"] = get_variable ("DL_LD", %OCTAVE_CONF_DL_LD%);
   vars["DL_LDFLAGS"] = get_variable ("DL_LDFLAGS", %OCTAVE_CONF_MKOCTFILE_DL_LDFLAGS%);
 
-  vars["RLD_FLAG"] = get_variable ("RLD_FLAG", %OCTAVE_CONF_RLD_FLAG%);
   vars["RDYNAMIC_FLAG"] = get_variable ("RDYNAMIC_FLAG", %OCTAVE_CONF_RDYNAMIC_FLAG%);
   vars["LIBOCTAVE"] = "-loctave";
   vars["LIBOCTINTERP"] = "-loctinterp";
@@ -233,6 +232,10 @@
   vars["FFTW3F_LIBS"] = get_variable ("FFTW3F_LIBS", %OCTAVE_CONF_FFTW3F_LIBS%);
   vars["LIBS"] = get_variable ("LIBS", %OCTAVE_CONF_LIBS%);
   vars["FLIBS"] = get_variable ("FLIBS", %OCTAVE_CONF_FLIBS%);
+  vars["OCTAVE_LINK_DEPS"] = get_variable ("FLIBS", %OCTAVE_CONF_OCTAVE_LINK_DEPS%);
+  vars["OCT_LINK_DEPS"] = get_variable ("FLIBS", %OCTAVE_CONF_OCT_LINK_DEPS%);
+  vars["FLIBS"] = get_variable ("FLIBS", %OCTAVE_CONF_FLIBS%);
+
   vars["LD_CXX"] = get_variable ("LD_CXX", %OCTAVE_CONF_LD_CXX%);
   vars["LDFLAGS"] = get_variable ("LDFLAGS", %OCTAVE_CONF_LDFLAGS%);
   vars["LD_STATIC_FLAG"] = get_variable ("LD_STATIC_FLAG", %OCTAVE_CONF_LD_STATIC_FLAG%);
@@ -296,25 +299,30 @@
 "  -p VAR, --print VAR     Print configuration variable VAR.  Recognized\n"
 "                          variables are:\n"
 "\n"
-"                           ALL_CFLAGS                FLIBS\n"
-"                           ALL_CXXFLAGS              FPICFLAG\n"
-"                           ALL_FFLAGS                INCFLAGS\n"
-"                           ALL_LDFLAGS               LAPACK_LIBS\n"
-"                           BLAS_LIBS                 LDFLAGS\n"
-"                           CC                        LD_CXX\n"
-"                           CFLAGS                    LD_STATIC_FLAG\n"
-"                           CPICFLAG                  LFLAGS\n"
-"                           CPPFLAGS                  LIBCRUFT\n"
-"                           CXX                       LIBOCTAVE\n"
-"                           CXXFLAGS                  LIBOCTINTERP\n"
-"                           CXXPICFLAG                LIBS\n"
-"                           DEPEND_EXTRA_SED_PATTERN  OCTAVE_LIBS\n"
-"                           DEPEND_FLAGS              RDYNAMIC_FLAG\n"
-"                           DL_LD                     READLINE_LIBS\n"
-"                           DL_LDFLAGS                RLD_FLAG\n"
-"                           F77                       SED\n"
-"                           FFLAGS                    XTRA_CFLAGS\n"
-"                           FFTW_LIBS                 XTRA_CXXFLAGS\n"
+"                            ALL_CFLAGS                FLIBS\n"
+"                            ALL_CXXFLAGS              FPICFLAG\n"
+"                            ALL_FFLAGS                INCFLAGS\n"
+"                            ALL_LDFLAGS               LAPACK_LIBS\n"
+"                            BLAS_LIBS                 LDFLAGS\n"
+"                            CC                        LD_CXX\n"
+"                            CFLAGS                    LD_STATIC_FLAG\n"
+"                            CPICFLAG                  LFLAGS\n"
+"                            CPPFLAGS                  LIBCRUFT\n"
+"                            CXX                       LIBOCTAVE\n"
+"                            CXXFLAGS                  LIBOCTINTERP\n"
+"                            CXXPICFLAG                LIBS\n"
+"                            DEPEND_EXTRA_SED_PATTERN  OCTAVE_LIBS\n"
+"                            DEPEND_FLAGS              OCTAVE_LINK_DEPS\n"
+"                            DL_LD                     OCTAVE_LINK_OPTS\n"
+"                            DL_LDFLAGS                OCT_LINK_DEPS\n"
+"                            EXEEXT                    OCT_LINK_OPTS\n"
+"                            F77                       RDYNAMIC_FLAG\n"
+"                            F77_INTEGER_8_FLAG        READLINE_LIBS\n"
+"                            FFLAGS                    SED\n"
+"                            FFTW3_LDFLAGS             XTRA_CFLAGS\n"
+"                            FFTW3_LIBS                XTRA_CXXFLAGS\n"
+"                            FFTW3F_LDFLAGS\n"
+"                            FFTW3F_LIBS\n"
 "\n"
 "  --link-stand-alone      Link a stand-alone executable file.\n"
 "\n"
@@ -742,11 +750,10 @@
                 + vars["ALL_CXXFLAGS"] + " " + vars["RDYNAMIC_FLAG"]
                 + " " + vars["ALL_LDFLAGS"] + " " +  pass_on_options
                 + " " + output_option + " " + objfiles + " " + libfiles
-                + " " + ldflags + " " + vars["LFLAGS"] + " "
-                + vars["RLD_FLAG"] + " " + vars["OCTAVE_LIBS"] + " "
-                + vars["LAPACK_LIBS"] + " " + vars["BLAS_LIBS"] + " "
-                + vars["FFTW_LIBS"] + " " + vars["READLINE_LIBS"] + " "
-                + vars["LIBS"] + " " + vars["FLIBS"];
+                + " " + ldflags + " " + vars["LFLAGS"]
+                + " -loctinterp -loctave -lcruft "
+                + " " + vars["OCT_LINK_OPTS"]
+                + " " + vars["OCTAVE_LINK_DEPS"];
               result = run_command (cmd);
             }
           else
@@ -758,12 +765,11 @@
         }
       else
         {
-          string LINK_DEPS = vars["LFLAGS"] + " " + vars["OCTAVE_LIBS"]
-            + " " + vars["LDFLAGS"] + " " + vars["BLAS_LIBS"] + " "
-            + vars["FFTW_LIBS"] + " " + vars["LIBS"] + " " + vars["FLIBS"];
           string cmd = vars["DL_LD"] + " " + vars["DL_LDFLAGS"] + " "
             + pass_on_options + " -o " + octfile + " " + objfiles + " "
-            + libfiles + " " + ldflags + " " + LINK_DEPS;
+            + libfiles + " " + ldflags + " " + vars["LFLAGS"]
+            + " -loctinterp -loctave -lcruft "
+            + vars["OCT_LINK_OPTS"] + " " + vars["OCT_LINK_DEPS"];
           result = run_command (cmd);
         }
 
--- a/src/mkoctfile.in
+++ b/src/mkoctfile.in
@@ -85,7 +85,6 @@
 : ${DL_LD=%OCTAVE_CONF_DL_LD%}
 : ${DL_LDFLAGS=%OCTAVE_CONF_MKOCTFILE_DL_LDFLAGS%}
 
-: ${RLD_FLAG=%OCTAVE_CONF_RLD_FLAG%}
 : ${RDYNAMIC_FLAG=%OCTAVE_CONF_RDYNAMIC_FLAG%}
 : ${LIBOCTAVE=-loctave}
 : ${LIBOCTINTERP=-loctinterp}
@@ -99,6 +98,10 @@
 : ${FFTW3F_LIBS=%OCTAVE_CONF_FFTW3F_LIBS%}
 : ${LIBS=%OCTAVE_CONF_LIBS%}
 : ${FLIBS=%OCTAVE_CONF_FLIBS%}
+: ${OCTAVE_LINK_DEPS=%OCTAVE_CONF_OCTAVE_LINK_DEPS%}
+: ${OCTAVE_LINK_DEPS=%OCTAVE_CONF_OCTAVE_LINK_OPTS%}
+: ${OCT_LINK_DEPS=%OCTAVE_CONF_MKOCTFILE_OCT_LINK_DEPS%}
+: ${OCT_LINK_DEPS=%OCTAVE_CONF_MKOCTFILE_OCT_LINK_OPTS%}
 : ${LD_CXX=%OCTAVE_CONF_LD_CXX%}
 : ${LDFLAGS=%OCTAVE_CONF_LDFLAGS%}
 : ${LD_STATIC_FLAG=%OCTAVE_CONF_LD_STATIC_FLAG%}
@@ -221,7 +224,7 @@
 
   -s, --strip             Strip output file.
 
-  --mex                   Create a MEX file.  
+  --mex                   Create a MEX file.
                           Set the default output extension to ".mex".
 
   -o FILE, --output FILE  Output file name.  Default extension is .oct
@@ -231,28 +234,29 @@
   -p VAR, --print VAR     Print configuration variable VAR.  Recognized
                           variables are:
 
-                            ALL_CFLAGS                FFTW3F_LDFLAGS
-                            ALL_CXXFLAGS              FFTW3F_LIBS
-                            ALL_FFLAGS                FLIBS
-                            ALL_LDFLAGS               FPICFLAG
-                            BLAS_LIBS                 INCFLAGS
-                            CC                        LAPACK_LIBS
-                            CFLAGS                    LDFLAGS
-                            CPICFLAG                  LD_CXX
-                            CPPFLAGS                  LD_STATIC_FLAG
-                            CXX                       LFLAGS
-                            CXXFLAGS                  LIBCRUFT
-                            CXXPICFLAG                LIBOCTAVE
-                            DEPEND_EXTRA_SED_PATTERN  LIBOCTINTERP
-                            DEPEND_FLAGS              LIBS
-                            DL_LD                     OCTAVE_LIBS
-                            DL_LDFLAGS                RDYNAMIC_FLAG
-                            EXEEXT                    READLINE_LIBS
-                            F77                       RLD_FLAG
+                            ALL_CFLAGS                FFTW3F_LIBS
+                            ALL_CXXFLAGS              FLIBS
+                            ALL_FFLAGS                FPICFLAG
+                            ALL_LDFLAGS               INCFLAGS
+                            BLAS_LIBS                 LAPACK_LIBS
+                            CC                        LDFLAGS
+                            CFLAGS                    LD_CXX
+                            CPICFLAG                  LD_STATIC_FLAG
+                            CPPFLAGS                  LFLAGS
+                            CXX                       LIBCRUFT
+                            CXXFLAGS                  LIBOCTAVE
+                            CXXPICFLAG                LIBOCTINTERP
+                            DEPEND_EXTRA_SED_PATTERN  LIBS
+                            DEPEND_FLAGS              OCTAVE_LIBS
+                            DL_LD                     OCTAVE_LINK_DEPS
+                            DL_LDFLAGS                OCT_LINK_DEPS
+                            EXEEXT                    RDYNAMIC_FLAG
+                            F77                       READLINE_LIBS
                             F77_INTEGER_8_FLAG        SED
                             FFLAGS                    XTRA_CFLAGS
                             FFTW3_LDFLAGS             XTRA_CXXFLAGS
                             FFTW3_LIBS
+                            FFTW3F_LDFLAGS
 
   -v, --verbose           Echo commands as they are executed.
 
@@ -529,7 +533,7 @@
 if $link && [ -n "$objfiles" ]; then
   if $link_stand_alone; then
     if [ -n "$LD_CXX" ]; then
-      cmd="$LD_CXX $CPPFLAGS $ALL_CXXFLAGS $RDYNAMIC_FLAG $ALL_LDFLAGS $pass_on_options $output_option $objfiles $libfiles $ldflags $LFLAGS $RLD_FLAG $OCTAVE_LIBS $LAPACK_LIBS $BLAS_LIBS $FFTW_LIBS $READLINE_LIBS $LIBS $FLIBS"
+      cmd="$LD_CXX $CPPFLAGS $ALL_CXXFLAGS $RDYNAMIC_FLAG $ALL_LDFLAGS $pass_on_options $output_option $objfiles $libfiles $ldflags $LFLAGS -loctinterp -loctave -lcruft $OCTAVE_LINK_OPTS $OCTAVE_LINK_DEPS"
       $dbg $cmd
       eval $cmd
     else
@@ -537,8 +541,7 @@
       exit 1
     fi
   else
-    LINK_DEPS="$LFLAGS $OCTAVE_LIBS $LDFLAGS $LAPACK_LIBS $BLAS_LIBS $FFTW_LIBS $LIBS $FLIBS"
-    cmd="$DL_LD $DL_LDFLAGS $pass_on_options -o $octfile $objfiles $libfiles $ldflags $LINK_DEPS"
+    cmd="$DL_LD $DL_LDFLAGS $pass_on_options -o $octfile $objfiles $libfiles $ldflags $LFLAGS -loctinterp -loctave -lcruft $OCT_LINK_OPTS $OCT_LINK_DEPS"
     $dbg $cmd
     eval $cmd
   fi
--- a/src/oct-conf.h.in
+++ b/src/oct-conf.h.in
@@ -376,6 +376,14 @@
 #define OCTAVE_CONF_MKOCTFILE_DL_LDFLAGS %OCTAVE_CONF_MKOCTFILE_DL_LDFLAGS%
 #endif
 
+#ifndef OCTAVE_CONF_OCTAVE_LINK_DEPS
+#define OCTAVE_CONF_OCTAVE_LINK_DEPS %OCTAVE_CONF_OCTAVE_LINK_DEPS%
+#endif
+
+#ifndef OCTAVE_CONF_OCTAVE_LINK_OPTS
+#define OCTAVE_CONF_OCTAVE_LINK_OPTS %OCTAVE_CONF_OCTAVE_LINK_OPTS%
+#endif
+
 #ifndef OCTAVE_CONF_OCTINCLUDEDIR
 #define OCTAVE_CONF_OCTINCLUDEDIR %OCTAVE_CONF_OCTINCLUDEDIR%
 #endif
@@ -384,6 +392,14 @@
 #define OCTAVE_CONF_OCTLIBDIR %OCTAVE_CONF_OCTLIBDIR%
 #endif
 
+#ifndef OCTAVE_CONF_OCT_LINK_DEPS
+#define OCTAVE_CONF_OCT_LINK_DEPS %OCTAVE_CONF_OCT_LINK_DEPS%
+#endif
+
+#ifndef OCTAVE_CONF_OCT_LINK_OPTS
+#define OCTAVE_CONF_OCT_LINK_OPTS %OCTAVE_CONF_OCT_LINK_OPTS%
+#endif
+
 #ifndef OCTAVE_CONF_OPENGL_LIBS
 #define OCTAVE_CONF_OPENGL_LIBS %OCTAVE_CONF_OPENGL_LIBS%
 #endif
@@ -440,10 +456,6 @@
 #define OCTAVE_CONF_REGEX_LIBS %OCTAVE_CONF_REGEX_LIBS%
 #endif
 
-#ifndef OCTAVE_CONF_RLD_FLAG
-#define OCTAVE_CONF_RLD_FLAG %OCTAVE_CONF_RLD_FLAG%
-#endif
-
 #ifndef OCTAVE_CONF_SED
 #define OCTAVE_CONF_SED %OCTAVE_CONF_SED%
 #endif
--- a/src/oct-hist.cc
+++ b/src/oct-hist.cc
@@ -88,9 +88,6 @@
   return file;
 }
 
-// Where history is saved.
-static std::string Vhistory_file = default_history_file ();
-
 static int
 default_history_size (void)
 {
@@ -109,27 +106,6 @@
   return size;
 }
 
-// The number of lines to keep in the history file.
-static int Vhistory_size = default_history_size ();
-
-static std::string
-default_history_control (void)
-{
-  std::string retval;
-
-  std::string env_histcontrol = octave_env::getenv ("OCTAVE_HISTCONTROL");
-
-  if (! env_histcontrol.empty ())
-    {
-      return env_histcontrol;
-    }
-
-  return retval;
-}
-
-// The number of lines to keep in the history file.
-static std::string Vhistory_control = default_history_control ();
-
 static std::string
 default_history_timestamp_format (void)
 {
@@ -146,9 +122,6 @@
 static std::string Vhistory_timestamp_format_string
   = default_history_timestamp_format ();
 
-// TRUE if we are saving history.
-bool Vsaving_history = true;
-
 // Display, save, or load history.  Stolen and modified from bash.
 //
 // Arg of -w FILENAME means write file, arg of -r FILENAME
@@ -160,6 +133,10 @@
 {
   int numbered_output = 1;
 
+  unwind_protect frame;
+
+  frame.add_fcn (command_history::set_file, command_history::file ());
+
   int i;
   for (i = 1; i < argc; i++)
     {
@@ -537,8 +514,10 @@
 void
 initialize_history (bool read_history_file)
 {
-  command_history::initialize (read_history_file, Vhistory_file, Vhistory_size,
-                               Vhistory_control);
+  command_history::initialize (read_history_file,
+                               default_history_file (),
+                               default_history_size (),
+                               octave_env::getenv ("OCTAVE_HISTCONTROL"));
 }
 
 void
@@ -691,12 +670,15 @@
 @seealso{history_file, history_size, history_timestamp_format_string, saving_history}\n\
 @end deftypefn")
 {
-  std::string saved_history_control = Vhistory_control;
+  std::string old_history_control = command_history::histcontrol ();
+
+  std::string tmp = old_history_control;
 
-  octave_value retval = SET_INTERNAL_VARIABLE (history_control);
+  octave_value retval = set_internal_variable (tmp, args, nargout,
+                                               "history_control");
 
-  if (Vhistory_control != saved_history_control)
-    command_history::process_histcontrol (Vhistory_control);
+  if (tmp != old_history_control)
+    command_history::process_histcontrol (tmp);
 
   return retval;
 }
@@ -711,13 +693,15 @@
 @seealso{history_file, history_timestamp_format_string, saving_history}\n\
 @end deftypefn")
 {
-  int saved_history_size = Vhistory_size;
+  int old_history_size = command_history::size ();
+
+  int tmp = old_history_size;
 
-  octave_value retval
-    = SET_INTERNAL_VARIABLE_WITH_LIMITS (history_size, -1, INT_MAX);
+  octave_value retval = set_internal_variable (tmp, args, nargout,
+                                               "history_size", -1, INT_MAX);
 
-  if (Vhistory_size != saved_history_size)
-    command_history::set_size (Vhistory_size);
+  if (tmp != old_history_size)
+    command_history::set_size (tmp);
 
   return retval;
 }
@@ -733,12 +717,15 @@
 @seealso{history_size, saving_history, history_timestamp_format_string}\n\
 @end deftypefn")
 {
-  std::string saved_history_file = Vhistory_file;
+  std::string old_history_file = command_history::file ();
+
+  std::string tmp = old_history_file;
 
-  octave_value retval = SET_INTERNAL_VARIABLE (history_file);
+  octave_value retval = set_internal_variable (tmp, args, nargout,
+                                               "history_file");
 
-  if (Vhistory_file != saved_history_file)
-    command_history::set_file (Vhistory_file);
+  if (tmp != old_history_file)
+    command_history::set_file (tmp);
 
   return retval;
 }
@@ -770,9 +757,15 @@
 @seealso{history_control, history_file, history_size, history_timestamp_format_string}\n\
 @end deftypefn")
 {
-  octave_value retval = SET_INTERNAL_VARIABLE (saving_history);
+  bool old_saving_history = ! command_history::ignoring_entries ();
+
+  bool tmp = old_saving_history;
 
-  command_history::ignore_entries (! Vsaving_history);
+  octave_value retval = set_internal_variable (tmp, args, nargout,
+                                               "saving_history");
+
+  if (tmp != old_saving_history)
+    command_history::ignore_entries (! tmp);
 
   return retval;
 }
--- a/src/oct-hist.h
+++ b/src/oct-hist.h
@@ -35,7 +35,4 @@
 // TRUE means input is coming from temporary history file.
 extern bool input_from_tmp_history_file;
 
-// TRUE if we are saving history.
-extern bool Vsaving_history;
-
 #endif
--- a/src/oct-parse.yy
+++ b/src/oct-parse.yy
@@ -471,7 +471,7 @@
 %type <tree_matrix_type> matrix_rows matrix_rows1
 %type <tree_cell_type> cell_rows cell_rows1
 %type <tree_expression_type> matrix cell
-%type <tree_expression_type> primary_expr postfix_expr prefix_expr binary_expr
+%type <tree_expression_type> primary_expr oper_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
@@ -514,7 +514,6 @@
 %type <dummy_type> class_body
 
 // Precedence and associativity.
-%left ';' ',' '\n'
 %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
 %left EXPR_OR_OR
 %left EXPR_AND_AND
@@ -525,8 +524,9 @@
 %left ':'
 %left '-' '+' EPLUS EMINUS
 %left '*' '/' LEFTDIV EMUL EDIV ELEFTDIV
-%left UNARY PLUS_PLUS MINUS_MINUS EXPR_NOT
+%right UNARY EXPR_NOT
 %left POW EPOW QUOTE TRANSPOSE
+%right PLUS_PLUS MINUS_MINUS
 %left '(' '.' '{'
 
 // Where to start.
@@ -796,69 +796,61 @@
                   { lexer_flags.looking_at_indirect_ref = true; }
                 ;
 
-postfix_expr    : primary_expr
+oper_expr       : primary_expr
                   { $$ = $1; }
-                | postfix_expr '(' ')'
+                | oper_expr PLUS_PLUS
+                  { $$ = make_postfix_op (PLUS_PLUS, $1, $2); }
+                | oper_expr MINUS_MINUS
+                  { $$ = make_postfix_op (MINUS_MINUS, $1, $2); }
+                | oper_expr '(' ')'
                   { $$ = make_index_expression ($1, 0, '('); }
-                | postfix_expr '(' arg_list ')'
+                | oper_expr '(' arg_list ')'
                   { $$ = make_index_expression ($1, $3, '('); }
-                | postfix_expr '{' '}'
+                | oper_expr '{' '}'
                   { $$ = make_index_expression ($1, 0, '{'); }
-                | postfix_expr '{' arg_list '}'
+                | oper_expr '{' arg_list '}'
                   { $$ = make_index_expression ($1, $3, '{'); }
-                | postfix_expr PLUS_PLUS
-                  { $$ = make_postfix_op (PLUS_PLUS, $1, $2); }
-                | postfix_expr MINUS_MINUS
-                  { $$ = make_postfix_op (MINUS_MINUS, $1, $2); }
-                | postfix_expr QUOTE
+                | oper_expr QUOTE
                   { $$ = make_postfix_op (QUOTE, $1, $2); }
-                | postfix_expr TRANSPOSE
+                | oper_expr TRANSPOSE
                   { $$ = make_postfix_op (TRANSPOSE, $1, $2); }
-                | postfix_expr indirect_ref_op STRUCT_ELT
+                | oper_expr indirect_ref_op STRUCT_ELT
                   { $$ = make_indirect_ref ($1, $3->text ()); }
-                | postfix_expr indirect_ref_op '(' expression ')'
+                | oper_expr indirect_ref_op '(' expression ')'
                   { $$ = make_indirect_ref ($1, $4); }
-                ;
-
-prefix_expr     : postfix_expr
-                  { $$ = $1; }
-                | binary_expr
-                  { $$ = $1; }
-                | PLUS_PLUS prefix_expr %prec UNARY
+                | PLUS_PLUS oper_expr %prec UNARY
                   { $$ = make_prefix_op (PLUS_PLUS, $2, $1); }
-                | MINUS_MINUS prefix_expr %prec UNARY
+                | MINUS_MINUS oper_expr %prec UNARY
                   { $$ = make_prefix_op (MINUS_MINUS, $2, $1); }
-                | EXPR_NOT prefix_expr %prec UNARY
+                | EXPR_NOT oper_expr %prec UNARY
                   { $$ = make_prefix_op (EXPR_NOT, $2, $1); }
-                | '+' prefix_expr %prec UNARY
+                | '+' oper_expr %prec UNARY
                   { $$ = make_prefix_op ('+', $2, $1); }
-                | '-' prefix_expr %prec UNARY
+                | '-' oper_expr %prec UNARY
                   { $$ = make_prefix_op ('-', $2, $1); }
-                ;
-
-binary_expr     : prefix_expr POW prefix_expr
+                | oper_expr POW oper_expr
                   { $$ = make_binary_op (POW, $1, $2, $3); }
-                | prefix_expr EPOW prefix_expr
+                | oper_expr EPOW oper_expr
                   { $$ = make_binary_op (EPOW, $1, $2, $3); }
-                | prefix_expr '+' prefix_expr
+                | oper_expr '+' oper_expr
                   { $$ = make_binary_op ('+', $1, $2, $3); }
-                | prefix_expr '-' prefix_expr
+                | oper_expr '-' oper_expr
                   { $$ = make_binary_op ('-', $1, $2, $3); }
-                | prefix_expr '*' prefix_expr
+                | oper_expr '*' oper_expr
                   { $$ = make_binary_op ('*', $1, $2, $3); }
-                | prefix_expr '/' prefix_expr
+                | oper_expr '/' oper_expr
                   { $$ = make_binary_op ('/', $1, $2, $3); }
-                | prefix_expr EPLUS prefix_expr
+                | oper_expr EPLUS oper_expr
                   { $$ = make_binary_op ('+', $1, $2, $3); }
-                | prefix_expr EMINUS prefix_expr
+                | oper_expr EMINUS oper_expr
                   { $$ = make_binary_op ('-', $1, $2, $3); }
-                | prefix_expr EMUL prefix_expr
+                | oper_expr EMUL oper_expr
                   { $$ = make_binary_op (EMUL, $1, $2, $3); }
-                | prefix_expr EDIV prefix_expr
+                | oper_expr EDIV oper_expr
                   { $$ = make_binary_op (EDIV, $1, $2, $3); }
-                | prefix_expr LEFTDIV prefix_expr
+                | oper_expr LEFTDIV oper_expr
                   { $$ = make_binary_op (LEFTDIV, $1, $2, $3); }
-                | prefix_expr ELEFTDIV prefix_expr
+                | oper_expr ELEFTDIV oper_expr
                   { $$ = make_binary_op (ELEFTDIV, $1, $2, $3); }
                 ;
 
@@ -866,9 +858,9 @@
                   { $$ = finish_colon_expression ($1); }
                 ;
 
-colon_expr1     : prefix_expr
+colon_expr1     : oper_expr
                   { $$ = new tree_colon_expression ($1); }
-                | colon_expr1 ':' prefix_expr
+                | colon_expr1 ':' oper_expr
                   {
                     if (! ($$ = $1->append ($3)))
                       ABORT_PARSE;
@@ -2908,6 +2900,7 @@
     }
 
   fcn->stash_function_name (id_name);
+  fcn->stash_fcn_location (input_line_number, current_input_column);
 
   if (! help_buf.empty () && current_function_depth == 1
       && ! parsing_subfunctions)
@@ -3348,11 +3341,10 @@
           break;
 
         case '\n':
-          current_input_column = 0;
+          current_input_column = 1;
           break;
 
         default:
-          current_input_column--;
           reader.ungetc (c);
           goto done;
         }
@@ -3479,18 +3471,11 @@
   parsing_subfunctions = false;
   endfunction_found = false;
 
-  // The next four lines must be in this order.
-  frame.add_fcn (command_history::ignore_entries, ! Vsaving_history);
-
-  // FIXME -- we shouldn't need both the
-  // command_history object and the
-  // Vsaving_history variable...
+  frame.add_fcn (command_history::ignore_entries,
+                 command_history::ignoring_entries ());
+
   command_history::ignore_entries ();
 
-  frame.protect_var (Vsaving_history);
-
-  Vsaving_history = false;
-
   FILE *ffile = get_input_from_file (ff, 0);
 
   frame.add_fcn (safe_fclose, ffile);
--- a/src/oct-stream.cc
+++ b/src/oct-stream.cc
@@ -1227,158 +1227,9 @@
 
         if (c1 != EOF)
           {
-            if (c1 == 'N')
-              {
-                int c2 = is.get ();
-
-                if (c2 != EOF)
-                  {
-                    if (c2 == 'A')
-                      {
-                        int c3 = is.get ();
-
-                        if (c3 != EOF)
-                          {
-                            is.putback (c3);
-
-                            if (isspace (c3) || ispunct (c3))
-                              ref = octave_NA;
-                            else
-                              {
-                                is.putback (c2);
-                                is.putback (c1);
-
-                                is >> ref;
-                              }
-                          }
-                        else
-                          {
-                            is.clear ();
-
-                            ref = octave_NA;
-                          }
-                      }
-                    else if (c2 == 'a')
-                      {
-                        int c3 = is.get ();
-
-                        if (c3 != EOF)
-                          {
-                            if (c3 == 'N')
-                              {
-                                int c4 = is.get ();
-
-                                if (c4 != EOF)
-                                  {
-                                    is.putback (c4);
-
-                                    if (isspace (c4) || ispunct (c4))
-                                      ref = octave_NaN;
-                                    else
-                                      {
-                                        is.putback (c3);
-                                        is.putback (c2);
-                                        is.putback (c1);
-
-                                        is >> ref;
-                                      }
-                                  }
-                                else
-                                  {
-                                    is.clear ();
-
-                                    ref = octave_NaN;
-                                  }
-                              }
-                            else
-                              {
-                                is.putback (c3);
-                                is.putback (c2);
-                                is.putback (c1);
-
-                                is >> ref;
-                              }
-                          }
-                      }
-                    else
-                      {
-                        is.putback (c2);
-                        is.putback (c1);
-
-                        is >> ref;
-                      }
-                  }
-              }
-            else if (c1 == 'I')
-              {
-                int c2 = is.get ();
-
-                if (c2 != EOF)
-                  {
-                    if (c2 == 'n')
-                      {
-                        int c3 = is.get ();
-
-                        if (c3 != EOF)
-                          {
-                            if (c3 == 'f')
-                              {
-                                int c4 = is.get ();
-
-                                if (c4 != EOF)
-                                  {
-                                    is.putback (c4);
-
-                                    if (isspace (c4) || ispunct (c4))
-                                      ref = octave_Inf;
-                                    else
-                                      {
-                                        is.putback (c3);
-                                        is.putback (c2);
-                                        is.putback (c1);
-
-                                        is >> ref;
-                                      }
-                                  }
-                                else
-                                  {
-                                    is.clear ();
-
-                                    ref = octave_Inf;
-                                  }
-                              }
-                            else
-                              {
-                                is.putback (c3);
-                                is.putback (c2);
-                                is.putback (c1);
-                                
-                                is >> ref;
-                              }
-                          }
-                        else
-                          {
-                            is.putback (c2);
-                            is.putback (c1);
-                            
-                            is >> ref;
-                          }
-                      }
-                    else
-                      {
-                        is.putback (c2);
-                        is.putback (c1);
-                        
-                        is >> ref;
-                      }
-                  }
-              }
-            else
-              {
-                is.putback (c1);
-
-                is >> ref;
-              }
+            is.putback (c1);
+
+            ref = octave_read_value<double> (is);
           }
       }
       break;
@@ -3011,38 +2862,60 @@
     {
       clearerr ();
 
+      // Find current position so we can return to it if needed.
+
       long orig_pos = rep->tell ();
 
-      status = rep->seek (offset, origin);
+      // Move to end of file.  If successful, find the offset of the end.
+
+      status = rep->seek (0, SEEK_END);
 
       if (status == 0)
         {
-          long save_pos = rep->tell ();
-
-          rep->seek (0, SEEK_END);
-
-          long pos_eof = rep->tell ();
-
-          // I don't think save_pos can be less than zero, but we'll
-          // check anyway...
-
-          if (save_pos > pos_eof || save_pos < 0)
+          long eof_pos = rep->tell ();
+
+          if (origin == SEEK_CUR)
+            {
+              // Move back to original position, otherwise we will be
+              // seeking from the end of file which is probably not the
+              // original location.
+
+              rep->seek (orig_pos, SEEK_SET);
+            }
+
+          // Attempt to move to desired position; may be outside bounds
+          // of existing file.
+
+          status = rep->seek (offset, origin);
+
+          if (status == 0)
             {
-              // Seek outside bounds of file.  Failure should leave
-              // position unchanged.
+              // Where are we after moving to desired position?
+
+              long desired_pos = rep->tell ();
+
+              // I don't think save_pos can be less than zero, but we'll
+              // check anyway...
+
+              if (desired_pos > eof_pos || desired_pos < 0)
+                {
+                  // Seek outside bounds of file.  Failure should leave
+                  // position unchanged.
+
+                  rep->seek (orig_pos, SEEK_SET);
+
+                  status = -1;
+                }
+            }
+          else
+            {
+              // Seeking to the desired position failed.  Move back to
+              // original position and return failure status.
 
               rep->seek (orig_pos, SEEK_SET);
 
               status = -1;
             }
-          else
-            {
-              // Is it possible for this to fail?  We are just
-              // returning to a position after the first successful
-              // seek.
-
-              rep->seek (save_pos, SEEK_SET);
-            }
         }
     }
 
--- a/src/octave.cc
+++ b/src/octave.cc
@@ -971,6 +971,11 @@
   return retval;
 }
 
+/*
+%!error argv (1);
+%!assert (iscellstr (argv ()));
+*/
+
 DEFUN (program_invocation_name, args, ,
   "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} program_invocation_name ()\n\
@@ -993,6 +998,11 @@
   return retval;
 }
 
+/*
+%!error program_invocation_name (1);
+%!assert (ischar (program_invocation_name ()));
+*/
+
 DEFUN (program_name, args, ,
   "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} program_name ()\n\
@@ -1010,3 +1020,8 @@
 
   return retval;
 }
+
+/*
+%!error program_name (1);
+%!assert (ischar (program_name ()));
+*/
--- a/src/ov-base.cc
+++ b/src/ov-base.cc
@@ -1548,3 +1548,16 @@
 {
   return SET_INTERNAL_VARIABLE (sparse_auto_mutate);
 }
+
+/*
+
+%!test
+ s = speye(3);
+ sparse_auto_mutate (false);
+ s(:, 1) = 1;
+ assert (typeinfo (s), "sparse matrix");
+ sparse_auto_mutate (true);
+ s(1, :) = 1;
+ assert (typeinfo (s), "matrix");
+
+*/
--- a/src/ov-builtin.cc
+++ b/src/ov-builtin.cc
@@ -29,6 +29,7 @@
 #include "oct-obj.h"
 #include "ov-builtin.h"
 #include "ov.h"
+#include "profiler.h"
 #include "toplev.h"
 #include "unwind-prot.h"
 
@@ -125,6 +126,8 @@
 
       try
         {
+          BEGIN_PROFILER_BLOCK (profiler_name ())
+
           retval = (*f) (args, nargout);
           // Do not allow null values to be returned from functions.
           // FIXME -- perhaps true builtins should be allowed?
@@ -137,6 +140,8 @@
           // the idiom is very common, so we solve that here.
           if (retval.length () == 1 && retval.xelem (0).is_undefined ())
             retval.clear ();
+
+          END_PROFILER_BLOCK
         }
       catch (octave_execution_exception)
         {
--- a/src/ov-fcn.h
+++ b/src/ov-fcn.h
@@ -60,6 +60,9 @@
   virtual bool is_system_fcn_file (void) const { return false; }
 
   virtual std::string fcn_file_name (void) const { return std::string (); }
+  
+  // The name to show in the profiler (also used as map-key).
+  virtual std::string profiler_name (void) const { return name (); }
 
   virtual std::string parent_fcn_name (void) const { return std::string (); }
 
--- a/src/ov-flt-re-mat.cc
+++ b/src/ov-flt-re-mat.cc
@@ -839,3 +839,32 @@
 
   return octave_value ();
 }
+
+/*
+
+%!assert (class (single(1)), "single")
+%!assert (class (single(1 + i)), "single")
+%!assert (class (single (int8 (1))), "single")
+%!assert (class (single (uint8 (1))), "single")
+%!assert (class (single (int16 (1))), "single")
+%!assert (class (single (uint16 (1))), "single")
+%!assert (class (single (int32 (1))), "single")
+%!assert (class (single (uint32 (1))), "single")
+%!assert (class (single (int64 (1))), "single")
+%!assert (class (single (uint64 (1))), "single")
+%!assert (class (single (true)), "single")
+%!assert (class (single ("A")), "single")
+%!error (single (sparse (1)))
+%!test
+%! x = diag ([1 3 2]);
+%! y = single (x);
+%! assert (class (x), "double");
+%! assert (class (y), "single");
+%!test
+%! x = diag ([i 3 2]);
+%! y = single (x);
+%! assert (class (x), "double");
+%! assert (class (y), "single");
+
+*/
+
--- a/src/ov-int16.cc
+++ b/src/ov-int16.cc
@@ -82,3 +82,15 @@
 {
   OCTAVE_TYPE_CONV_BODY (int16);
 }
+
+/*
+
+%!assert (class (int16 (1)), "int16")
+%!assert (int16 (1.25), int16 (1))
+%!assert (int16 (1.5), int16 (2))
+%!assert (int16 (-1.5), int16 (-2))
+%!assert (int16 (2^17), int16 (2^16-1))
+%!assert (int16 (-2^17), int16 (-2^16))
+
+*/
+
--- a/src/ov-int32.cc
+++ b/src/ov-int32.cc
@@ -82,3 +82,15 @@
 {
   OCTAVE_TYPE_CONV_BODY (int32);
 }
+
+/*
+
+%!assert (class (int32 (1)), "int32")
+%!assert (int32 (1.25), int32 (1))
+%!assert (int32 (1.5), int32 (2))
+%!assert (int32 (-1.5), int32 (-2))
+%!assert (int32 (2^33), int32 (2^32-1))
+%!assert (int32 (-2^33), int32 (-2^32))
+
+*/
+
--- a/src/ov-int64.cc
+++ b/src/ov-int64.cc
@@ -82,3 +82,15 @@
 {
   OCTAVE_TYPE_CONV_BODY (int64);
 }
+
+/*
+
+%!assert (class (int64 (1)), "int64")
+%!assert (int64 (1.25), int64 (1))
+%!assert (int64 (1.5), int64 (2))
+%!assert (int64 (-1.5), int64 (-2))
+%!assert (int64 (2^65), int64 (2^64-1))
+%!assert (int64 (-2^65), int64 (-2^64))
+
+*/
+
--- a/src/ov-int8.cc
+++ b/src/ov-int8.cc
@@ -82,3 +82,14 @@
 {
   OCTAVE_TYPE_CONV_BODY (int8);
 }
+
+/*
+
+%!assert (class (int8 (1)), "int8")
+%!assert (int8 (1.25), int8 (1))
+%!assert (int8 (1.5), int8 (2))
+%!assert (int8 (-1.5), int8 (-2))
+%!assert (int8 (2^9), int8 (2^8-1))
+%!assert (int8 (-2^9), int8 (-2^8))
+
+*/
--- a/src/ov-mex-fcn.cc
+++ b/src/ov-mex-fcn.cc
@@ -33,6 +33,7 @@
 #include "oct-obj.h"
 #include "ov-mex-fcn.h"
 #include "ov.h"
+#include "profiler.h"
 #include "toplev.h"
 #include "unwind-prot.h"
 
@@ -147,7 +148,9 @@
 
       try
         {
+          BEGIN_PROFILER_BLOCK (profiler_name ())
           retval = call_mex (have_fmex, mex_fcn_ptr, args, nargout, this);
+          END_PROFILER_BLOCK
         }
       catch (octave_execution_exception)
         {
--- a/src/ov-null-mat.cc
+++ b/src/ov-null-mat.cc
@@ -118,3 +118,17 @@
   return retval;
 }
 
+/*
+
+%!assert (isnull ([]), true)
+%!assert (isnull ([1]), false)
+%!assert (isnull (zeros (0,3)), false)
+%!assert (isnull (""), true)
+%!assert (isnull ("A"), false)
+%!assert (isnull (''), true)
+%!assert (isnull ('A'), false)
+%!test
+%! x = [];
+%! assert (isnull (x), false);
+
+*/
--- a/src/ov-range.cc
+++ b/src/ov-range.cc
@@ -655,3 +655,16 @@
 {
   return SET_INTERNAL_VARIABLE (allow_noninteger_range_as_index);
 }
+
+/*
+%!test
+%! x = 0:10;
+%! save = allow_noninteger_range_as_index (0);
+%! fail ('x(2.1:5)');
+%! assert (x(2:5), 1:4);
+%! allow_noninteger_range_as_index (1);
+%! assert (x(2.49:5), 1:3);
+%! assert (x(2.5:5), 2:4);
+%! assert (x(2.51:5), 2:4);
+%! allow_noninteger_range_as_index (save);
+*/
--- a/src/ov-re-mat.cc
+++ b/src/ov-re-mat.cc
@@ -979,3 +979,36 @@
 
   return octave_value ();
 }
+
+/*
+
+%!assert (class (double (single (1))), "double")
+%!assert (class (double (single (1 + i))), "double")
+%!assert (class (double (int8 (1))), "double")
+%!assert (class (double (uint8 (1))), "double")
+%!assert (class (double (int16 (1))), "double")
+%!assert (class (double (uint16 (1))), "double")
+%!assert (class (double (int32 (1))), "double")
+%!assert (class (double (uint32 (1))), "double")
+%!assert (class (double (int64 (1))), "double")
+%!assert (class (double (uint64 (1))), "double")
+%!assert (class (double (true)), "double")
+%!assert (class (double ("A")), "double")
+%!test
+%! x = sparse (logical ([1 0; 0 1]));
+%! y = double (x);
+%! assert (class (x), "logical");
+%! assert (class (y), "double");
+%! assert (issparse (y));
+%!test
+%! x = diag (single ([1 3 2]));
+%! y = double (x);
+%! assert (class (x), "single");
+%! assert (class (y), "double");
+%!test
+%! x = diag (single ([i 3 2]));
+%! y = double (x);
+%! assert (class (x), "single");
+%! assert (class (y), "double");
+
+*/
--- a/src/ov-uint16.cc
+++ b/src/ov-uint16.cc
@@ -82,3 +82,15 @@
 {
   OCTAVE_TYPE_CONV_BODY (uint16);
 }
+
+/*
+
+%!assert (class (uint16 (1)), "uint16")
+%!assert (uint16 (1.25), uint16 (1))
+%!assert (uint16 (1.5), uint16 (2))
+%!assert (uint16 (-1.5), uint16 (0))
+%!assert (uint16 (2^17), uint16 (2^16-1))
+%!assert (uint16 (-2^17), uint16 (0))
+
+*/
+
--- a/src/ov-uint32.cc
+++ b/src/ov-uint32.cc
@@ -82,3 +82,14 @@
 {
   OCTAVE_TYPE_CONV_BODY (uint32);
 }
+
+/*
+
+%!assert (class (uint32 (1)), "uint32")
+%!assert (uint32 (1.25), uint32 (1))
+%!assert (uint32 (1.5), uint32 (2))
+%!assert (uint32 (-1.5), uint32 (0))
+%!assert (uint32 (2^33), uint32 (2^32-1))
+%!assert (uint32 (-2^33), uint32 (0))
+
+*/
--- a/src/ov-uint64.cc
+++ b/src/ov-uint64.cc
@@ -82,3 +82,14 @@
 {
   OCTAVE_TYPE_CONV_BODY (uint64);
 }
+
+/*
+
+%!assert (class (uint64 (1)), "uint64")
+%!assert (uint64 (1.25), uint64 (1))
+%!assert (uint64 (1.5), uint64 (2))
+%!assert (uint64 (-1.5), uint64 (0))
+%!assert (uint64 (2^65), uint64 (2^64-1))
+%!assert (uint64 (-2^65), uint64 (0))
+
+*/
--- a/src/ov-uint8.cc
+++ b/src/ov-uint8.cc
@@ -82,3 +82,14 @@
 {
   OCTAVE_TYPE_CONV_BODY (uint8);
 }
+
+/*
+
+%!assert (class (uint8 (1)), "uint8")
+%!assert (uint8 (1.25), uint8 (1))
+%!assert (uint8 (1.5), uint8 (2))
+%!assert (uint8 (-1.5), uint8 (0))
+%!assert (uint8 (2^9), uint8 (2^8-1))
+%!assert (uint8 (-2^9), uint8 (0))
+
+*/
--- a/src/ov-usr-fcn.cc
+++ b/src/ov-usr-fcn.cc
@@ -24,6 +24,8 @@
 #include <config.h>
 #endif
 
+#include <sstream>
+
 #include "str-vec.h"
 
 #include <defaults.h>
@@ -47,6 +49,7 @@
 #include "unwind-prot.h"
 #include "utils.h"
 #include "parse.h"
+#include "profiler.h"
 #include "variables.h"
 
 // Whether to optimize subsasgn method calls.
@@ -131,7 +134,9 @@
                   frame.protect_var (tree_evaluator::statement_context);
                   tree_evaluator::statement_context = tree_evaluator::script;
 
+                  BEGIN_PROFILER_BLOCK (profiler_name ())
                   cmd_list->accept (*current_evaluator);
+                  END_PROFILER_BLOCK
 
                   if (tree_return_command::returning)
                     tree_return_command::returning = 0;
@@ -176,6 +181,7 @@
   : octave_user_code (std::string (), std::string ()),
     param_list (pl), ret_list (rl), cmd_list (cl),
     lead_comm (), trail_comm (), file_name (),
+    location_line (0), location_column (0),
     parent_name (), t_parsed (static_cast<time_t> (0)),
     t_checked (static_cast<time_t> (0)),
     system_fcn_file (false), call_depth (-1),
@@ -217,6 +223,22 @@
   file_name = nm;
 }
 
+std::string
+octave_user_function::profiler_name (void) const
+{
+  std::ostringstream result;
+
+  if (is_inline_function ())
+    result << "anonymous@" << fcn_file_name ()
+           << ":" << location_line << ":" << location_column;
+  else if (is_subfunction ())
+    result << parent_fcn_name () << ">" << name ();
+  else
+    result << name ();
+
+  return result.str ();
+}
+
 void
 octave_user_function::mark_as_system_fcn_file (void)
 {
@@ -431,6 +453,8 @@
   bool special_expr = (is_inline_function ()
                        || cmd_list->is_anon_function_body ());
 
+  BEGIN_PROFILER_BLOCK (profiler_name ())
+
   if (special_expr)
     {
       assert (cmd_list->length () == 1);
@@ -448,6 +472,8 @@
   else
     cmd_list->accept (*current_evaluator);
 
+  END_PROFILER_BLOCK
+
   if (echo_commands)
     print_code_function_trailer ();
 
--- a/src/ov-usr-fcn.h
+++ b/src/ov-usr-fcn.h
@@ -189,6 +189,12 @@
 
   void stash_fcn_file_name (const std::string& nm);
 
+  void stash_fcn_location (int line, int col)
+    {
+      location_line = line;
+      location_column = col;
+    }
+
   void stash_parent_fcn_name (const std::string& p) { parent_name = p; }
 
   void stash_parent_fcn_scope (symbol_table::scope_id ps) { parent_scope = ps; }
@@ -207,6 +213,8 @@
 
   std::string fcn_file_name (void) const { return file_name; }
 
+  std::string profiler_name (void) const;
+
   std::string parent_fcn_name (void) const { return parent_name; }
 
   symbol_table::scope_id parent_fcn_scope (void) const { return parent_scope; }
@@ -344,6 +352,10 @@
   // The name of the file we parsed.
   std::string file_name;
 
+  // Location where this function was defined.
+  int location_line;
+  int location_column;
+
   // The name of the parent function, if any.
   std::string parent_name;
 
new file mode 100644
--- /dev/null
+++ b/src/profiler.cc
@@ -0,0 +1,416 @@
+/*
+
+Copyright (C) 2011 Daniel Kraft
+
+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 <cstddef>
+#include <iostream>
+
+#include "defun.h"
+#include "oct-time.h"
+#include "ov-struct.h"
+#include "pager.h"
+#include "profiler.h"
+
+profile_data_accumulator::enter::enter (profile_data_accumulator& a,
+                                        const std::string& f)
+  : acc (a)
+{
+  if (acc.is_active ())
+    {
+      fcn = f;
+      acc.enter_function (fcn);
+    }
+  else
+    fcn = "";
+}
+
+profile_data_accumulator::enter::~enter ()
+{
+  if (fcn != "")
+    acc.exit_function (fcn);
+}
+
+profile_data_accumulator::stats::stats ()
+  : time (0.0), calls (0), recursive (false),
+    parents (), children ()
+{}
+
+octave_value
+profile_data_accumulator::stats::function_set_value (const function_set& list)
+{
+  const octave_idx_type n = list.size ();
+
+  RowVector retval (n);
+  octave_idx_type i = 0;
+  for (function_set::const_iterator p = list.begin (); p != list.end (); ++p)
+    {
+      retval(i) = *p;
+      ++i;
+    }
+  assert (i == n);
+
+  return retval;
+}
+
+profile_data_accumulator::tree_node::tree_node (tree_node* p, octave_idx_type f)
+  : parent (p), fcn_id (f), children (), time (0.0), calls (0)
+{}
+
+profile_data_accumulator::tree_node::~tree_node ()
+{
+  for (child_map::iterator i = children.begin (); i != children.end (); ++i)
+    delete i->second;
+}
+
+profile_data_accumulator::tree_node*
+profile_data_accumulator::tree_node::enter (octave_idx_type fcn)
+{
+  tree_node* retval;
+
+  child_map::iterator pos = children.find (fcn);
+  if (pos == children.end ())
+    {
+      retval = new tree_node (this, fcn);
+      children[fcn] = retval;
+    }
+  else
+    retval = pos->second;
+
+  ++retval->calls;
+  return retval;
+}
+
+profile_data_accumulator::tree_node*
+profile_data_accumulator::tree_node::exit (octave_idx_type fcn)
+{
+  assert (parent);
+  assert (fcn_id == fcn);
+
+  return parent;
+}
+
+void
+profile_data_accumulator::tree_node::build_flat (flat_profile& data) const
+{
+  // If this is not the top-level node, update profile entry for this function.
+  if (fcn_id != 0)
+    {
+      stats& entry = data[fcn_id - 1];
+      
+      entry.time += time;
+      entry.calls += calls;
+
+      assert (parent);
+      if (parent->fcn_id != 0)
+        {
+          entry.parents.insert (parent->fcn_id);
+          data[parent->fcn_id - 1].children.insert (fcn_id);
+        }
+
+      if (!entry.recursive)
+        for (const tree_node* i = parent; i; i = i->parent)
+          if (i->fcn_id == fcn_id)
+            {
+              entry.recursive = true;
+              break;
+            }
+    }
+
+  // Recurse on children.
+  for (child_map::const_iterator i = children.begin ();
+       i != children.end (); ++i)
+    i->second->build_flat (data);
+}
+
+octave_value
+profile_data_accumulator::tree_node::get_hierarchical (void) const
+{
+  /* Note that we don't generate the entry just for this node, but rather
+     a struct-array with entries for all children.  This way, the top-node
+     (for which we don't want a real entry) generates already the final
+     hierarchical profile data.  */
+
+  const octave_idx_type n = children.size ();
+
+  Cell rv_indices (n, 1);
+  Cell rv_times (n, 1);
+  Cell rv_calls (n, 1);
+  Cell rv_children (n, 1);
+
+  octave_idx_type i = 0;
+  for (child_map::const_iterator p = children.begin ();
+       p != children.end (); ++p)
+    {
+      const tree_node& entry = *p->second;
+
+      rv_indices(i) = octave_value (p->first);
+      rv_times(i) = octave_value (entry.time);
+      rv_calls(i) = octave_value (entry.calls);
+      rv_children(i) = entry.get_hierarchical ();
+
+      ++i;
+    }
+  assert (i == n);
+
+  Octave_map retval;
+
+  retval.assign ("Index", rv_indices);
+  retval.assign ("SelfTime", rv_times);
+  retval.assign ("NumCalls", rv_calls);
+  retval.assign ("Children", rv_children);
+
+  return retval;
+}
+
+profile_data_accumulator::profile_data_accumulator ()
+  : known_functions (), fcn_index (),
+    enabled (false), call_tree (NULL), last_time (-1.0)
+{}
+
+profile_data_accumulator::~profile_data_accumulator ()
+{
+  if (call_tree)
+    delete call_tree;
+}
+
+void
+profile_data_accumulator::set_active (bool value)
+{
+  if (value)
+    {
+      // Create a call-tree top-node if there isn't yet one.
+      if (!call_tree)
+        call_tree = new tree_node (NULL, 0);
+
+      // Let the top-node be the active one.  This ensures we have a clean
+      // fresh start collecting times.
+      active_fcn = call_tree;
+    }
+  else
+    {
+      // Make sure we start with fresh timing if we're re-enabled later.
+      last_time = -1.0;
+    }
+
+  enabled = value;
+}
+
+void
+profile_data_accumulator::enter_function (const std::string& fcn)
+{
+  // The enter class will check and only call us if the profiler is active.
+  assert (is_active ());
+  assert (call_tree);
+
+  // If there is already an active function, add to its time before
+  // pushing the new one.
+  if (active_fcn != call_tree)
+    add_current_time ();
+
+  // Map the function's name to its index.
+  octave_idx_type fcn_idx;
+  fcn_index_map::iterator pos = fcn_index.find (fcn);
+  if (pos == fcn_index.end ())
+    {
+      known_functions.push_back (fcn);
+      fcn_idx = known_functions.size ();
+      fcn_index[fcn] = fcn_idx;
+    }
+  else
+    fcn_idx = pos->second;
+
+  active_fcn = active_fcn->enter (fcn_idx);
+  last_time = query_time ();
+}
+
+void
+profile_data_accumulator::exit_function (const std::string& fcn)
+{
+  assert (call_tree);
+  assert (active_fcn != call_tree);
+
+  // Usually, if we are disabled this function is not even called.  But the
+  // call disabling the profiler is an exception.  So also check here
+  // and only record the time if enabled.
+  if (is_active ())
+    add_current_time ();
+
+  fcn_index_map::iterator pos = fcn_index.find (fcn);
+  assert (pos != fcn_index.end ());
+  active_fcn = active_fcn->exit (pos->second);
+
+  // If this was an "inner call", we resume executing the parent function
+  // up the stack.  So note the start-time for this!
+  last_time = query_time ();
+}
+
+void
+profile_data_accumulator::reset (void)
+{
+  if (is_active ())
+    {
+      error ("Can't reset active profiler.");
+      return;
+    }
+
+  known_functions.clear ();
+  fcn_index.clear ();
+
+  if (call_tree)
+    {
+      delete call_tree;
+      call_tree = NULL;
+    }
+
+  last_time = -1.0;
+}
+
+octave_value
+profile_data_accumulator::get_flat (void) const
+{
+  const octave_idx_type n = known_functions.size ();
+
+  flat_profile flat (n);
+  assert (call_tree);
+  call_tree->build_flat (flat);
+
+  Cell rv_names (n, 1);
+  Cell rv_times (n, 1);
+  Cell rv_calls (n, 1);
+  Cell rv_recursive (n, 1);
+  Cell rv_parents (n, 1);
+  Cell rv_children (n, 1);
+
+  for (octave_idx_type i = 0; i != n; ++i)
+    {
+      rv_names(i) = octave_value (known_functions[i]);
+      rv_times(i) = octave_value (flat[i].time);
+      rv_calls(i) = octave_value (flat[i].calls);
+      rv_recursive(i) = octave_value (flat[i].recursive);
+      rv_parents(i) = stats::function_set_value (flat[i].parents);
+      rv_children(i) = stats::function_set_value (flat[i].children);
+    }
+
+  Octave_map retval;
+
+  retval.assign ("FunctionName", rv_names);
+  retval.assign ("TotalTime", rv_times);
+  retval.assign ("NumCalls", rv_calls);
+  retval.assign ("IsRecursive", rv_recursive);
+  retval.assign ("Parents", rv_parents);
+  retval.assign ("Children", rv_children);
+
+  return retval;
+}
+
+octave_value
+profile_data_accumulator::get_hierarchical (void) const
+{
+  assert (call_tree);
+  return call_tree->get_hierarchical ();
+}
+
+double
+profile_data_accumulator::query_time (void) const
+{
+  octave_time now;
+  return now.double_value ();
+}
+
+void
+profile_data_accumulator::add_current_time (void)
+{
+  const double t = query_time ();
+  assert (last_time >= 0.0 && last_time <= t);
+
+  assert (call_tree && active_fcn != call_tree);
+  active_fcn->add_time (t - last_time);
+}
+
+profile_data_accumulator profiler;
+
+// Enable or disable the profiler data collection.
+DEFUN (__profiler_enable__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Function File} __profiler_enable ()\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value_list retval;
+
+  const int nargin = args.length ();
+  if (nargin > 0)
+    {
+      if (nargin > 1)
+        {
+          print_usage ();
+          return retval;
+        }
+
+      profiler.set_active (args(0).bool_value ());
+    }
+
+  retval(0) = profiler.is_active ();
+
+  return retval;
+}
+
+// Clear all collected profiling data.
+DEFUN (__profiler_reset__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Function File} __profiler_reset ()\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value_list retval;
+  const int nargin = args.length ();
+
+  if (nargin > 0)
+    warning ("profiler_reset: ignoring extra arguments");
+
+  profiler.reset ();
+
+  return retval;
+}
+
+// Query the timings collected by the profiler.
+DEFUN (__profiler_data__, args, nargout,
+  "-*- texinfo -*-\n\
+@deftypefn {Function File} __profiler_data ()\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value_list retval;
+  const int nargin = args.length ();
+
+  if (nargin > 0)
+    warning ("profiler_data: ignoring extra arguments");
+
+  retval(0) = profiler.get_flat ();
+  if (nargout > 1)
+    retval(1) = profiler.get_hierarchical ();
+
+  return retval;
+}
new file mode 100644
--- /dev/null
+++ b/src/profiler.h
@@ -0,0 +1,185 @@
+/*
+
+Copyright (C) 2011 Daniel Kraft
+
+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_profiler_h)
+#define octave_profiler_h 1
+
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+class octave_value;
+
+class
+OCTAVE_API
+profile_data_accumulator
+{
+public:
+
+  // This is a utility class that can be used to call the enter/exit
+  // functions in a manner protected from stack unwinding.
+  class enter
+  {
+  private:
+
+    profile_data_accumulator& acc;
+    std::string fcn;
+
+  public:
+
+    enter (profile_data_accumulator&, const std::string&);
+    virtual ~enter (void);
+
+  private:
+
+    // No copying!
+    enter (const enter&);
+    enter& operator = (const enter&);
+  };
+
+  profile_data_accumulator (void);
+  virtual ~profile_data_accumulator ();
+
+  bool is_active (void) const { return enabled; }
+  void set_active (bool);
+
+  void reset (void);
+
+  octave_value get_flat (void) const;
+  octave_value get_hierarchical (void) const;
+
+private:
+
+  // One entry in the flat profile (i.e., a collection of data for a single
+  // function).  This is filled in when building the flat profile from the
+  // hierarchical call tree.
+  struct stats
+  {
+    stats ();
+
+    double time;
+    unsigned calls;
+
+    bool recursive;
+
+    typedef std::set<octave_idx_type> function_set;
+    function_set parents;
+    function_set children;
+
+    // Convert a function_set list to an Octave array of indices.
+    static octave_value function_set_value (const function_set&);
+  };
+
+  typedef std::vector<stats> flat_profile;
+  
+  // Store data for one node in the call-tree of the hierarchical profiler
+  // data we collect.
+  class tree_node
+  {
+  public:
+
+    tree_node (tree_node*, octave_idx_type);
+    virtual ~tree_node ();
+
+    void add_time (double dt) { time += dt; }
+
+    // Enter a child function.  It is created in the list of children if it
+    // wasn't already there.  The now-active child node is returned.
+    tree_node* enter (octave_idx_type);
+
+    // Exit function.  As a sanity-check, it is verified that the currently
+    // active function actually is the one handed in here.  Returned is the
+    // then-active node, which is our parent.
+    tree_node* exit (octave_idx_type);
+
+    void build_flat (flat_profile&) const;
+    octave_value get_hierarchical (void) const;
+
+  private:
+
+    tree_node* parent;
+    octave_idx_type fcn_id;
+
+    typedef std::map<octave_idx_type, tree_node*> child_map;
+    child_map children;
+
+    // This is only time spent *directly* on this level, excluding children!
+    double time;
+
+    unsigned calls;
+
+    // No copying!
+    tree_node (const tree_node&);
+    tree_node& operator = (const tree_node&);
+  };
+
+  // Each function we see in the profiler is given a unique index (which
+  // simply counts starting from 1).  We thus have to map profiler-names to
+  // those indices.  For all other stuff, we identify functions by their index.
+
+  typedef std::vector<std::string> function_set;
+  typedef std::map<std::string, octave_idx_type> fcn_index_map;
+
+  function_set known_functions;
+  fcn_index_map fcn_index;
+
+  bool enabled;
+
+  tree_node* call_tree;
+  tree_node* active_fcn;
+
+  // Store last timestamp we had, when the currently active function was called.
+  double last_time;
+
+  // These are private as only the unwind-protecting inner class enter
+  // should be allowed to call them.
+  void enter_function (const std::string&);
+  void exit_function (const std::string&);
+
+  // Query a timestamp, used for timing calls (obviously).
+  // This is not static because in the future, maybe we want a flag
+  // in the profiler or something to choose between cputime, wall-time,
+  // user-time, system-time, ...
+  double query_time () const;
+
+  // Add the time elapsed since last_time to the function we're currently in.
+  // This is called from two different positions, thus it is useful to have
+  // it as a seperate function.
+  void add_current_time (void);
+
+  // No copying!
+  profile_data_accumulator (const profile_data_accumulator&);
+  profile_data_accumulator& operator = (const profile_data_accumulator&);
+};
+
+// The instance used.
+extern profile_data_accumulator profiler;
+
+// Helper macro to profile a block of code.
+#define BEGIN_PROFILER_BLOCK(name) \
+  { \
+    profile_data_accumulator::enter pe (profiler, (name));
+#define END_PROFILER_BLOCK \
+  }
+
+#endif
--- a/src/pt-binop.cc
+++ b/src/pt-binop.cc
@@ -28,6 +28,7 @@
 #include "defun.h"
 #include "oct-obj.h"
 #include "ov.h"
+#include "profiler.h"
 #include "pt-binop.h"
 #include "pt-bp.h"
 #include "pt-walk.h"
@@ -120,10 +121,20 @@
 
           if (! error_state && b.is_defined ())
             {
+              BEGIN_PROFILER_BLOCK ("binary " + oper ())
+
+              // Note: The profiler does not catch the braindead
+              // short-circuit evaluation code above, but that should be
+              // ok. The evaluation of operands and the operator itself
+              // is entangled and it's not clear where to start/stop
+              // timing the operator to make it reasonable.
+
               retval = ::do_binary_op (etype, a, b);
 
               if (error_state)
                 retval = octave_value ();
+
+              END_PROFILER_BLOCK
             }
         }
     }
@@ -183,6 +194,11 @@
 
   bool result = false;
 
+  // This evaluation is not caught by the profiler, since we can't find
+  // a reasonable place where to time. Note that we don't want to
+  // include evaluation of LHS or RHS into the timing, but this is
+  // entangled together with short-circuit evaluation here.
+
   if (op_lhs)
     {
       octave_value a = op_lhs->rvalue1 ();
@@ -279,3 +295,19 @@
 {
   return SET_INTERNAL_VARIABLE (do_braindead_shortcircuit_evaluation);
 }
+
+/*
+
+%!test
+%! x = 0;
+%! do_braindead_shortcircuit_evaluation (0);
+%! if (1 | (x = 1)) 
+%! endif
+%! assert (x, 1);
+%! do_braindead_shortcircuit_evaluation (1);
+%! if (1 | (x = 0)) 
+%! endif
+%! assert (x, 1);
+
+*/
+
--- a/src/pt-eval.cc
+++ b/src/pt-eval.cc
@@ -1202,6 +1202,17 @@
   return SET_INTERNAL_VARIABLE (max_recursion_depth);
 }
 
+/*
+%!error (max_recursion_depth (1, 2));
+%!test
+%! orig_val = max_recursion_depth ();
+%! old_val = max_recursion_depth (2*orig_val);
+%! assert (orig_val, old_val);
+%! assert (max_recursion_depth (), 2*orig_val);
+%! max_recursion_depth (orig_val);
+%! assert (max_recursion_depth (), orig_val);
+*/
+
 DEFUN (silent_functions, args, nargout,
   "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {@var{val} =} silent_functions ()\n\
@@ -1214,3 +1225,14 @@
 {
   return SET_INTERNAL_VARIABLE (silent_functions);
 }
+
+/*
+%!error (silent_functions (1, 2));
+%!test
+%! orig_val = silent_functions ();
+%! old_val = silent_functions (! orig_val);
+%! assert (orig_val, old_val);
+%! assert (silent_functions (), ! orig_val);
+%! silent_functions (orig_val);
+%! assert (silent_functions (), orig_val);
+*/
--- a/src/pt-fcn-handle.cc
+++ b/src/pt-fcn-handle.cc
@@ -127,6 +127,7 @@
     }
 
   uf->mark_as_inline_function ();
+  uf->stash_fcn_location (line (), column ());
 
   octave_value ov_fcn (uf);
 
--- a/src/pt-mat.cc
+++ b/src/pt-mat.cc
@@ -1146,3 +1146,18 @@
 {
   return SET_INTERNAL_VARIABLE (string_fill_char);
 }
+
+/*
+%!error (string_fill_char (1, 2));
+%% string_fill_char() function call must be outside of %!test block
+%% due to the way a %!test block is wrapped inside a function
+%!shared orig_val, old_val
+%! orig_val = string_fill_char ();
+%! old_val  = string_fill_char ("X");
+%!test
+%! assert (orig_val, old_val);
+%! assert (string_fill_char (), "X");
+%! assert (["these"; "are"; "strings"], ["theseXX"; "areXXXX"; "strings"]);
+%! string_fill_char (orig_val);
+%! assert (string_fill_char (), orig_val);
+*/
--- a/src/pt-unop.cc
+++ b/src/pt-unop.cc
@@ -28,6 +28,7 @@
 #include "oct-obj.h"
 #include "oct-lvalue.h"
 #include "ov.h"
+#include "profiler.h"
 #include "pt-bp.h"
 #include "pt-unop.h"
 #include "pt-walk.h"
@@ -72,10 +73,14 @@
 
           if (! error_state)
             {
+              BEGIN_PROFILER_BLOCK ("prefix " + oper ())
+              
               ref.do_unary_op (etype);
 
               if (! error_state)
                 retval = ref.value ();
+
+              END_PROFILER_BLOCK
             }
         }
       else
@@ -84,6 +89,8 @@
 
           if (! error_state && val.is_defined ())
             {
+              BEGIN_PROFILER_BLOCK ("prefix " + oper ())
+
               // Attempt to do the operation in-place if it is unshared
               // (a temporary expression).
               if (val.get_count () == 1)
@@ -93,6 +100,8 @@
 
               if (error_state)
                 retval = octave_value ();
+
+              END_PROFILER_BLOCK
             }
         }
     }
@@ -153,7 +162,9 @@
             {
               retval = ref.value ();
 
+              BEGIN_PROFILER_BLOCK ("postfix " + oper ())
               ref.do_unary_op (etype);
+              END_PROFILER_BLOCK
             }
         }
       else
@@ -162,10 +173,14 @@
 
           if (! error_state && val.is_defined ())
             {
+              BEGIN_PROFILER_BLOCK ("postfix " + oper ())
+
               retval = ::do_unary_op (etype, val);
 
               if (error_state)
                 retval = octave_value ();
+
+              END_PROFILER_BLOCK
             }
         }
     }
--- a/src/sighandlers.cc
+++ b/src/sighandlers.cc
@@ -945,6 +945,12 @@
   return retval;
 }
 
+/*
+%!error SIG (1);
+%!assert (isstruct (SIG ()));
+%!assert (! isempty (SIG ()));
+*/
+
 DEFUN (debug_on_interrupt, args, nargout,
   "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {@var{val} =} debug_on_interrupt ()\n\
@@ -958,6 +964,17 @@
   return SET_INTERNAL_VARIABLE (debug_on_interrupt);
 }
 
+/*
+%!error (debug_on_interrupt (1, 2));
+%!test
+%! orig_val = debug_on_interrupt ();
+%! old_val = debug_on_interrupt (! orig_val);
+%! assert (orig_val, old_val);
+%! assert (debug_on_interrupt (), ! orig_val);
+%! debug_on_interrupt (orig_val);
+%! assert (debug_on_interrupt (), orig_val);
+*/
+
 DEFUN (sighup_dumps_octave_core, args, nargout,
   "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {@var{val} =} sighup_dumps_octave_core ()\n\
@@ -970,6 +987,17 @@
   return SET_INTERNAL_VARIABLE (sighup_dumps_octave_core);
 }
 
+/*
+%!error (sighup_dumps_octave_core (1, 2));
+%!test
+%! orig_val = sighup_dumps_octave_core ();
+%! old_val = sighup_dumps_octave_core (! orig_val);
+%! assert (orig_val, old_val);
+%! assert (sighup_dumps_octave_core (), ! orig_val);
+%! sighup_dumps_octave_core (orig_val);
+%! assert (sighup_dumps_octave_core (), orig_val);
+*/
+
 DEFUN (sigterm_dumps_octave_core, args, nargout,
   "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {@var{val} =} sigterm_dumps_octave_core ()\n\
@@ -981,3 +1009,14 @@
 {
   return SET_INTERNAL_VARIABLE (sigterm_dumps_octave_core);
 }
+
+/*
+%!error (sigterm_dumps_octave_core (1, 2));
+%!test
+%! orig_val = sigterm_dumps_octave_core ();
+%! old_val = sigterm_dumps_octave_core (! orig_val);
+%! assert (orig_val, old_val);
+%! assert (sigterm_dumps_octave_core (), ! orig_val);
+%! sigterm_dumps_octave_core (orig_val);
+%! assert (sigterm_dumps_octave_core (), orig_val);
+*/
--- a/src/symtab.h
+++ b/src/symtab.h
@@ -790,6 +790,11 @@
       return rep->built_in_function;
     }
 
+    octave_value find_cmdline_function (void) const
+    {
+      return rep->cmdline_function;
+    }
+
     octave_value find_autoload (void)
     {
       return rep->find_autoload ();
@@ -1787,6 +1792,25 @@
     return retval;
   }
 
+  static std::list<std::string> cmdline_function_names (void)
+  {
+    std::list<std::string> retval;
+
+    for (fcn_table_const_iterator p = fcn_table.begin ();
+         p != fcn_table.end (); p++)
+      {
+        octave_value fcn = p->second.find_cmdline_function ();
+
+        if (fcn.is_defined ())
+          retval.push_back (p->first);
+      }
+
+    if (! retval.empty ())
+      retval.sort ();
+
+    return retval;
+  }
+
   static bool is_local_variable (const std::string& name)
   {
     if (xcurrent_scope == xglobal_scope)
--- a/src/sysdep.cc
+++ b/src/sysdep.cc
@@ -586,8 +586,16 @@
 
   return retval;
 }
+
 DEFALIAS (setenv, putenv);
 
+/*
+%!assert (ischar (getenv ("OCTAVE_HOME")));
+%!test
+%! setenv ("dummy_variable_that_cannot_matter", "foobar");
+%! assert (getenv ("dummy_variable_that_cannot_matter"), "foobar");
+*/
+
 // FIXME -- perhaps kbhit should also be able to print a prompt?
 
 DEFUN (kbhit, args, ,
@@ -695,6 +703,12 @@
   return retval;
 }
 
+/*
+%!error (pause (1, 2));
+%!test
+%! pause (1);
+*/
+
 DEFUN (sleep, args, ,
   "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} sleep (@var{seconds})\n\
@@ -724,6 +738,13 @@
   return retval;
 }
 
+/*
+%!error (sleep ());
+%!error (sleep (1, 2));
+%!test
+%! sleep (1);
+*/
+
 DEFUN (usleep, args, ,
   "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} usleep (@var{microseconds})\n\
@@ -760,6 +781,13 @@
   return retval;
 }
 
+/*
+%!error (usleep ());
+%!error (usleep (1, 2));
+%!test
+%! usleep (1000);
+*/
+
 // FIXME -- maybe this should only return 1 if IEEE floating
 // point functions really work.
 
@@ -776,6 +804,10 @@
                        || flt_fmt == oct_mach_info::flt_fmt_ieee_big_endian);
 }
 
+/*
+%!assert (islogical (isieee ()));
+*/
+
 DEFUN (native_float_format, , ,
   "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} native_float_format ()\n\
@@ -787,6 +819,10 @@
   return octave_value (oct_mach_info::float_format_as_string (flt_fmt));
 }
 
+/*
+%!assert (ischar (native_float_format ()));
+*/
+
 DEFUN (tilde_expand, args, ,
   "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} tilde_expand (@var{string})\n\
@@ -835,3 +871,14 @@
 
   return retval;
 }
+
+/*
+%!test
+%! if (isempty (getenv ("HOME")))
+%!   setenv ("HOME", "foobar");
+%! endif
+%! home = getenv ("HOME");
+%! assert (tilde_expand ("~/foobar"), fullfile (home, "foobar"));
+%! assert (tilde_expand ("/foo/bar"), "/foo/bar");
+%! assert (tilde_expand ("foo/bar"), "foo/bar");
+*/
--- a/src/toplev.cc
+++ b/src/toplev.cc
@@ -39,6 +39,7 @@
 #include <unistd.h>
 
 #include "cmd-edit.h"
+#include "cmd-hist.h"
 #include "file-ops.h"
 #include "lo-error.h"
 #include "lo-mappers.h"
@@ -1001,6 +1002,20 @@
 
 DEFALIAS (shell_cmd, system);
 
+/*
+%!error (system ());
+%!error (system (1, 2, 3));
+%!test
+%! if (ispc ())
+%!   cmd = "dir";
+%! else
+%!   cmd = "ls";
+%! endif
+%! [status, output] = system (cmd);
+%! assert (ischar (output));
+%! assert (! isempty (output));
+*/
+
 // FIXME -- this should really be static, but that causes
 // problems on some systems.
 std::list<std::string> octave_atexit_functions;
@@ -1039,7 +1054,7 @@
 
       SAFE_CALL (octave_history_write_timestamp, ())
 
-      if (Vsaving_history)
+      if (! command_history::ignoring_entries ())
         SAFE_CALL (command_history::clean_up_and_save, ())
 
       SAFE_CALL (close_files, ())
@@ -1285,6 +1300,10 @@
       { false, "MAGICK_LDFLAGS", OCTAVE_CONF_MAGICK_LDFLAGS },
       { false, "MAGICK_LIBS", OCTAVE_CONF_MAGICK_LIBS },
       { false, "MKOCTFILE_DL_LDFLAGS", OCTAVE_CONF_MKOCTFILE_DL_LDFLAGS },
+      { false, "OCTAVE_LINK_DEPS", OCTAVE_CONF_OCTAVE_LINK_DEPS },
+      { false, "OCTAVE_LINK_OPTS", OCTAVE_CONF_OCTAVE_LINK_OPTS },
+      { false, "OCT_LINK_DEPS", OCTAVE_CONF_OCT_LINK_DEPS },
+      { false, "OCT_LINK_OPTS", OCTAVE_CONF_OCT_LINK_OPTS },
       { false, "OPENGL_LIBS", OCTAVE_CONF_OPENGL_LIBS },
       { false, "PTHREAD_CFLAGS", OCTAVE_CONF_PTHREAD_CFLAGS },
       { false, "PTHREAD_LIBS", OCTAVE_CONF_PTHREAD_LIBS },
@@ -1298,7 +1317,6 @@
       { false, "RDYNAMIC_FLAG", OCTAVE_CONF_RDYNAMIC_FLAG },
       { false, "READLINE_LIBS", OCTAVE_CONF_READLINE_LIBS },
       { false, "REGEX_LIBS", OCTAVE_CONF_REGEX_LIBS },
-      { false, "RLD_FLAG", OCTAVE_CONF_RLD_FLAG },
       { false, "SED", OCTAVE_CONF_SED },
       { false, "SHARED_LIBS", OCTAVE_CONF_SHARED_LIBS },
       { false, "SHLEXT", OCTAVE_CONF_SHLEXT },
@@ -1439,6 +1457,15 @@
   return retval;
 }
 
+/*
+%!error octave_config_info (1, 2);
+%!assert (ischar (octave_config_info ("version")));
+%!test
+%! x = octave_config_info ();
+%! assert (isstruct (x));
+%! assert (! isempty (x));
+*/
+
 #if defined (__GNUG__) && defined (DEBUG_NEW_DELETE)
 
 int debug_new_delete = 0;
--- a/src/txt-eng-ft.cc
+++ b/src/txt-eng-ft.cc
@@ -202,7 +202,8 @@
 
 ft_render::ft_render (void)
     : text_processor (), face (0), bbox (1, 4, 0.0),
-      xoffset (0), yoffset (0), mode (MODE_BBOX),
+      xoffset (0), yoffset (0), multiline_halign (0), 
+      multiline_align_xoffsets(), mode (MODE_BBOX),
       red (0), green (0), blue (0)
 {
 }
@@ -270,15 +271,23 @@
 {
   if (face)
     {
+      int line_index = 0;
+      FT_UInt box_line_width = 0;
       std::string str = e.string_value ();
       FT_UInt glyph_index, previous = 0;
 
+      if (mode == MODE_BBOX)
+        multiline_align_xoffsets.clear();
+      else if (mode == MODE_RENDER)
+        xoffset += multiline_align_xoffsets[line_index];
+
       for (size_t i = 0; i < str.length (); i++)
         {
           glyph_index = FT_Get_Char_Index (face, str[i]);
 
-          if (! glyph_index
-              || FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT))
+          if (str[i] != '\n' 
+              && (! glyph_index
+              || FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT)))
             ::warning ("ft_render: skipping missing glyph for character `%c'",
                        str[i]);
           else
@@ -286,7 +295,21 @@
               switch (mode)
                 {
                 case MODE_RENDER:
-                  if (FT_Render_Glyph (face->glyph, FT_RENDER_MODE_NORMAL))
+                  if (str[i] == '\n')
+                    {
+                    glyph_index = FT_Get_Char_Index(face, ' ');
+                    if (!glyph_index || FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT))
+                      {
+                        ::warning ("ft_render: skipping missing glyph for character ` '");
+                      } 
+                    else 
+                      {
+                        line_index++;
+                        xoffset = multiline_align_xoffsets[line_index];
+                        yoffset -= (face->size->metrics.height >> 6);
+                      }
+                  } 
+                  else if (FT_Render_Glyph (face->glyph, FT_RENDER_MODE_NORMAL))
                     ::warning ("ft_render: unable to render glyph for character `%c'",
                                str[i]);
                   else
@@ -304,6 +327,14 @@
 
                       x0 = xoffset+face->glyph->bitmap_left;
                       y0 = yoffset+face->glyph->bitmap_top;
+
+                      // 'w' seems to have a negative -1
+                      // face->glyph->bitmap_left, this is so we don't
+                      // index out of bound, and assumes we we allocated
+                      // the right amount of horizontal space in the bbox.
+                      if (x0 < 0)
+                        x0 = 0;
+
                       for (int r = 0; r < bitmap.rows; r++)
                         for (int c = 0; c < bitmap.width; c++)
                           {
@@ -327,43 +358,89 @@
                   break;
 
                 case MODE_BBOX:
-                  // width
-                  if (previous)
+                  if (str[i] == '\n')
                     {
-                      FT_Vector delta;
-
-                      FT_Get_Kerning (face, previous, glyph_index, FT_KERNING_DEFAULT, &delta);
-                      bbox(2) += (delta.x >> 6);
-                    }
-                  bbox(2) += (face->glyph->advance.x >> 6);
-
-                  int asc, desc;
-
-                  if (false /*tight*/)
+                      glyph_index = FT_Get_Char_Index(face, ' ');
+                      if (! glyph_index
+                          || FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT))
+                      {
+                        ::warning ("ft_render: skipping missing glyph for character ` '");
+                      }
+                    else
+                      {
+                        multiline_align_xoffsets.push_back(box_line_width);
+                        // Reset the pixel width for this newline, so we don't
+                        // allocate a bounding box larger than the horizontal
+                        // width of the multi-line
+                        box_line_width = 0; 
+                        bbox(1) -= (face->size->metrics.height >> 6);
+                      }
+                    } 
+                  else 
                     {
-                      desc = face->glyph->metrics.horiBearingY - face->glyph->metrics.height;
-                      asc = face->glyph->metrics.horiBearingY;
-                    }
-                  else
-                    {
-                      asc = face->size->metrics.ascender;
-                      desc = face->size->metrics.descender;
-                    }
+                    // width
+                    if (previous)
+                      {
+                        FT_Vector delta;
+
+                        FT_Get_Kerning (face, previous, glyph_index,
+                                        FT_KERNING_DEFAULT, &delta);
+
+                        box_line_width += (delta.x >> 6);
+                      }
+
+                    box_line_width += (face->glyph->advance.x >> 6);
+
+                    int asc, desc;
 
-                  asc = yoffset + (asc >> 6);
-                  desc = yoffset + (desc >> 6);
+                    if (false /*tight*/)
+                      {
+                        desc = face->glyph->metrics.horiBearingY - face->glyph->metrics.height;
+                        asc = face->glyph->metrics.horiBearingY;
+                      }
+                    else
+                      {
+                        asc = face->size->metrics.ascender;
+                        desc = face->size->metrics.descender;
+                      }
 
-                  if (desc < bbox(1))
-                    {
-                      bbox(3) += (bbox(1) - desc);
-                      bbox(1) = desc;
-                    }
-                  if (asc > (bbox(3)+bbox(1)))
-                    bbox(3) = asc-bbox(1);
+                    asc = yoffset + (asc >> 6);
+                    desc = yoffset + (desc >> 6);
+
+                    if (desc < bbox(1))
+                      {
+                        bbox(3) += (bbox(1) - desc);
+                        bbox(1) = desc;
+                      }
+                    if (asc > (bbox(3)+bbox(1)))
+                      bbox(3) = asc-bbox(1);
+                    if (bbox(2) < box_line_width)
+                      bbox(2) = box_line_width;
+                  }
                   break;
                 }
+                if (str[i] == '\n')
+                  previous = 0;
+                else
+                  previous = glyph_index;
+            }
+        }
+      if (mode == MODE_BBOX)
+        {
+          /* Push last the width associated with the last line */ 
+          multiline_align_xoffsets.push_back(box_line_width);
 
-              previous = glyph_index;
+          for (unsigned int i = 0; i < multiline_align_xoffsets.size(); i++)
+            {
+            /* Center align */
+            if (multiline_halign == 1) 
+              multiline_align_xoffsets[i] = (bbox(2) - multiline_align_xoffsets[i])/2;
+            /* Right align */
+            else if (multiline_halign == 2)
+              multiline_align_xoffsets[i] = (bbox(2) - multiline_align_xoffsets[i]);
+            /* Left align */
+            else 
+              multiline_align_xoffsets[i] = 0;
             }
         }
     }
@@ -506,6 +583,8 @@
 {
   // FIXME: clip "rotation" between 0 and 360
   int rot_mode = rotation_to_mode (rotation);
+  
+  multiline_halign = halign;
 
   text_element *elt = text_parser_none ().parse (txt);
   pixels_ = render (elt, box, rot_mode);
--- a/src/txt-eng-ft.h
+++ b/src/txt-eng-ft.h
@@ -25,6 +25,8 @@
 
 #if HAVE_FREETYPE
 
+#include <vector>
+
 #include <ft2build.h>
 #include FT_FREETYPE_H
 
@@ -94,6 +96,8 @@
   uint8NDArray pixels;
   int xoffset;
   int yoffset;
+  int multiline_halign;
+  std::vector<int> multiline_align_xoffsets;
   int mode;
   uint8_t red, green, blue;
 };
--- a/src/variables.cc
+++ b/src/variables.cc
@@ -1043,11 +1043,12 @@
                  const std::string& expr_str = std::string (),
                  const octave_value& expr_val = octave_value ())
       : name (expr_str.empty () ? sr.name () : expr_str),
+        varval (expr_val.is_undefined () ? sr.varval () : expr_val),
         is_automatic (sr.is_automatic ()),
+        is_complex (varval.is_complex_type ()),
         is_formal (sr.is_formal ()),
         is_global (sr.is_global ()),
-        is_persistent (sr.is_persistent ()),
-        varval (expr_val.is_undefined () ? sr.varval () : expr_val)
+        is_persistent (sr.is_persistent ())
     { }
 
     void display_line (std::ostream& os,
@@ -1117,13 +1118,14 @@
                 {
                 case 'a':
                   {
-                    char tmp[5];
+                    char tmp[6];
 
                     tmp[0] = (is_automatic ? 'a' : ' ');
-                    tmp[1] = (is_formal ? 'f' : ' ');
-                    tmp[2] = (is_global ? 'g' : ' ');
-                    tmp[3] = (is_persistent ? 'p' : ' ');
-                    tmp[4] = 0;
+                    tmp[1] = (is_complex ? 'c' : ' ');
+                    tmp[2] = (is_formal ? 'f' : ' ');
+                    tmp[3] = (is_global ? 'g' : ' ');
+                    tmp[4] = (is_persistent ? 'p' : ' ');
+                    tmp[5] = 0;
 
                     os << tmp;
                   }
@@ -1172,11 +1174,12 @@
     }
 
     std::string name;
+    octave_value varval;
     bool is_automatic;
+    bool is_complex;
     bool is_formal;
     bool is_global;
     bool is_persistent;
-    octave_value varval;
   };
 
 public:
@@ -1333,6 +1336,9 @@
     for (size_t i = 0; i < param_string.length (); i++)
       param_length(i) = param_names(i) . length ();
 
+    // The attribute column needs size 5.
+    param_length(pos_a) = 5;
+
     // Calculating necessary spacing for name column,
     // bytes column, elements column and class column
 
@@ -1798,6 +1804,9 @@
 Automatic variable.  An automatic variable is one created by the\n\
 interpreter, for example @code{argn}.\n\
 \n\
+@item @code{c}\n\
+Variable of complex type.\n\
+\n\
 @item @code{f}\n\
 Formal parameter (function argument).\n\
 \n\
--- a/src/xpow.cc
+++ b/src/xpow.cc
@@ -49,6 +49,8 @@
 #include "utils.h"
 #include "xpow.h"
 
+#include "bsxfun.h"
+
 #ifdef _OPENMP
 #include <omp.h>
 #endif
@@ -1243,8 +1245,21 @@
 
   if (a_dims != b_dims)
     {
-      gripe_nonconformant ("operator .^", a_dims, b_dims);
-      return octave_value ();
+      if (is_valid_bsxfun (a_dims, b_dims))
+        {
+          //Potentially complex results
+          NDArray xa = octave_value_extract<NDArray> (a);
+          NDArray xb = octave_value_extract<NDArray> (b);
+          if (! xb.all_integers () && xa.any_element_is_negative ())
+            return octave_value (bsxfun_pow (ComplexNDArray (xa), xb));
+          else
+            return octave_value (bsxfun_pow (xa, xb));
+        }
+      else
+        {
+          gripe_nonconformant ("operator .^", a_dims, b_dims);
+          return octave_value ();
+        }
     }
 
   int len = a.length ();
@@ -1318,8 +1333,15 @@
 
   if (a_dims != b_dims)
     {
-      gripe_nonconformant ("operator .^", a_dims, b_dims);
-      return octave_value ();
+      if (is_valid_bsxfun (a_dims, b_dims))
+        {
+          return bsxfun_pow (a, b);
+        }
+      else
+        {
+          gripe_nonconformant ("operator .^", a_dims, b_dims);
+          return octave_value ();
+        }
     }
 
   ComplexNDArray result (a_dims);
@@ -1410,8 +1432,15 @@
 
   if (a_dims != b_dims)
     {
-      gripe_nonconformant ("operator .^", a_dims, b_dims);
-      return octave_value ();
+      if (is_valid_bsxfun (a_dims, b_dims))
+        {
+          return bsxfun_pow (a, b);
+        }
+      else
+        {
+          gripe_nonconformant ("operator .^", a_dims, b_dims);
+          return octave_value ();
+        }
     }
 
   ComplexNDArray result (a_dims);
@@ -1453,8 +1482,15 @@
 
   if (a_dims != b_dims)
     {
-      gripe_nonconformant ("operator .^", a_dims, b_dims);
-      return octave_value ();
+      if (is_valid_bsxfun (a_dims, b_dims))
+        {
+          return bsxfun_pow (a, b);
+        }
+      else
+        {
+          gripe_nonconformant ("operator .^", a_dims, b_dims);
+          return octave_value ();
+        }
     }
 
   ComplexNDArray result (a_dims);
@@ -2562,8 +2598,21 @@
 
   if (a_dims != b_dims)
     {
-      gripe_nonconformant ("operator .^", a_dims, b_dims);
-      return octave_value ();
+      if (is_valid_bsxfun (a_dims, b_dims))
+        {
+          //Potentially complex results
+          FloatNDArray xa = octave_value_extract<FloatNDArray> (a);
+          FloatNDArray xb = octave_value_extract<FloatNDArray> (b);
+          if (! xb.all_integers () && xa.any_element_is_negative ())
+            return octave_value (bsxfun_pow (FloatComplexNDArray (xa), xb));
+          else
+            return octave_value (bsxfun_pow (xa, xb));
+        }
+      else
+        {
+          gripe_nonconformant ("operator .^", a_dims, b_dims);
+          return octave_value ();
+        }
     }
 
   int len = a.length ();
@@ -2637,8 +2686,15 @@
 
   if (a_dims != b_dims)
     {
-      gripe_nonconformant ("operator .^", a_dims, b_dims);
-      return octave_value ();
+      if (is_valid_bsxfun (a_dims, b_dims))
+        {
+          return bsxfun_pow (a, b);
+        }
+      else
+        {
+          gripe_nonconformant ("operator .^", a_dims, b_dims);
+          return octave_value ();
+        }
     }
 
   FloatComplexNDArray result (a_dims);
@@ -2729,8 +2785,15 @@
 
   if (a_dims != b_dims)
     {
-      gripe_nonconformant ("operator .^", a_dims, b_dims);
-      return octave_value ();
+      if (is_valid_bsxfun (a_dims, b_dims))
+        {
+          return bsxfun_pow (a, b);
+        }
+      else
+        {
+          gripe_nonconformant ("operator .^", a_dims, b_dims);
+          return octave_value ();
+        }
     }
 
   FloatComplexNDArray result (a_dims);
@@ -2772,8 +2835,15 @@
 
   if (a_dims != b_dims)
     {
-      gripe_nonconformant ("operator .^", a_dims, b_dims);
-      return octave_value ();
+      if (is_valid_bsxfun (a_dims, b_dims))
+        {
+          return bsxfun_pow (a, b);
+        }
+      else
+        {
+          gripe_nonconformant ("operator .^", a_dims, b_dims);
+          return octave_value ();
+        }
     }
 
   FloatComplexNDArray result (a_dims);
--- a/test/fntests.m
+++ b/test/fntests.m
@@ -97,6 +97,17 @@
   endif
 endfunction
 
+function retval = has_demos (f)
+  fid = fopen (f);
+  if (fid >= 0)
+    str = fread (fid, "*char")';
+    fclose (fid);
+    retval = ! isempty (regexp (str, '^%!demo', "lineanchors"));
+  else
+    error ("fopen failed: %s", f);
+  endif
+endfunction
+
 function [dp, dn, dxf, dsk] = run_test_dir (fid, d);
   global files_with_tests;
   global files_with_no_tests;
@@ -113,6 +124,8 @@
         [p, n, xf, sk] = test (nm(1:(end-2)), "quiet", fid);
         print_pass_fail (n, p);
         files_with_tests(end+1) = ffnm;
+      elseif (has_demos (ffnm))
+        files_with_tests(end+1) = ffnm;
       else
         files_with_no_tests(end+1) = ffnm;
       endif
@@ -164,6 +177,8 @@
         dxf += xf;
         dsk += sk;
         files_with_tests(end+1) = f;
+      elseif (has_demos (f))
+        files_with_tests(end+1) = f;
       elseif (has_functions (f))
         ## To reduce the list length, only mark .cc files that contain
         ## DEFUN definitions.
@@ -192,20 +207,15 @@
 endfunction
 
 function n = num_elts_matching_pattern (lst, pat)
-  n = 0;
-  for i = 1:length (lst)
-    if (! isempty (regexp (lst{i}, pat, "once")))
-      n++;
-    endif
-  endfor
+  n = sum (cellfun (@(x) !isempty (x), regexp (lst, pat, 'once')));
 endfunction
 
 function report_files_with_no_tests (with, without, typ)
-  pat = cstrcat ("\\", typ, "$");
+  pat = cstrcat ('\', typ, "$");
   n_with = num_elts_matching_pattern (with, pat);
   n_without = num_elts_matching_pattern (without, pat);
   n_tot = n_with + n_without;
-  printf ("\n%d (of %d) %s files have no tests.\n", n_without, n_tot, typ);
+  printf ("\n%d (of %d) %s files have no tests or demos.\n", n_without, n_tot, typ);
 endfunction
 
 pso = page_screen_output ();
@@ -258,6 +268,12 @@
     puts ("because the needed libraries were not present when Octave was built.\n");
   endif
 
+  ## Weed out deprecated and private functions
+  weed_idx = cellfun (@isempty, regexp (files_with_tests, '\bdeprecated\b|\bprivate\b', 'once'));
+  files_with_tests = files_with_tests(weed_idx);
+  weed_idx = cellfun (@isempty, regexp (files_with_no_tests, '\bdeprecated\b|\bprivate\b', '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, ".cc");
 
--- a/test/test_io.m
+++ b/test/test_io.m
@@ -245,6 +245,27 @@
 %!assert (sscanf ('123456', '%10c'), '123456')
 %!assert (sscanf ('123456', '%10s'), '123456')
 
+%!test
+%! [val, count, msg, pos] = sscanf ("3I2", "%f");
+%! assert (val, 3);
+%! assert (count, 1);
+%! assert (msg, "");
+%! assert (pos, 2);
+
+%!test
+%! [val, count, msg, pos] = sscanf ("3In2", "%f");
+%! assert (val, 3);
+%! assert (count, 1);
+%! assert (msg, "");
+%! assert (pos, 2);
+
+%!test
+%! [val, count, msg, pos] = sscanf ("3Inf2", "%f");
+%! assert (val, [3; Inf; 2]);
+%! assert (count, 3);
+%! assert (msg, "");
+%! assert (pos, 6);
+
 %% test/octave.test/io/sscanf-1.m
 %!test
 %! [a, b, c] = sscanf ("1.2 3 foo", "%f%d%s", "C");
--- a/test/test_parser.m
+++ b/test/test_parser.m
@@ -28,142 +28,222 @@
 %!assert ({1 2,{3,4}}, {1,2,{3,4}})
 %!assert ({1,2,{3 4}}, {1,2,{3,4}})
 
-%# Tests for operator precedence as documented in section 8.8 of manual
-%# There are 11 levels of precedence from "exponentiation" (highest) down to
-%# "statement operators" (lowest).
-%#
-%# Level 11 (exponentiation) overrides all others
+## 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).
+##
+## Level 13 (parentheses and indexing)
+## Overrides all other levels
+%!test
+%!  a.b = 1;
+%!  assert (a. b++, 1)
+%!  assert (a.b, 2)
+%!  clear a;
+%!  a.b = [0 1];
+%!  b = 2;
+%!  assert (a.b', [0;1])
+%!  assert (!a .b, logical ([1 0]))
+%!  assert (3*a .b, [0 3])
+%!  assert (a. b-1, [-1 0])
+%!  assert (a. b:3, 0:3)
+%!  assert (a. b>0.5, logical ([0 1]))
+%!  assert (a. b&0, logical ([0 0]))
+%!  assert (a. b|0, logical ([0 1]))
+%!  a.b = [1 2];
+%!  assert (a. b&&0, false)
+%!  assert (a. b||0, true)
+%!  a.b += a. b*2;
+%!  assert (a.b, [3 6])
+## Level 12 (postfix increment and decrement)
 %!test
-%!  assert (-2^2, -4)
-%!  assert (!0^0, false);
-# FIXME: This test is failing.  Transpose mistakenly has higher priority.
-%!#  assert ([2 3].^2', [4; 9])
-%!  assert (2*3^2, 18)
-%!  assert (2+3^2, 11)
-%!  assert ([1:10](1:2^2), [1 2 3 4])
-%!  assert (3 > 2^2, false)
-%!  assert (1 & 0^0, true)
-%!  assert (1 && 0^0, true)
+%!  a = [3 5];
+%!  assert (2.^a ++, [8 32])
+%!  assert (a, [4 6])
+%!  assert (a--', [4; 6])
+%!  assert (a, [3 5])
+%!  a = 0;
+%!  assert (!a --, true)
+%!  assert (-a ++, 1)
+%!  assert (3*a ++, 0)
+%!  assert (a++-2, -1)
+%!  assert (1:a ++, 1:2)
+%!  assert (4>a++, true)
+%!  a = [0 -1];
+%!  assert ([1 1] & a++, logical ([0 1]))
+%!  assert ([0 0] | a++, logical ([1 0]))
+%!  a = 0;
+%!  assert (1 && a ++, false)
+%!  assert (0 || a --, true)
+%!  a = 5; b = 2;
+%!  b +=a ++;
+%!  assert (b, 7)
+
+## Level 11 (transpose and exponentiation)
+%!test
+%!  assert (-2 ^2, -4)
+%!  assert (!0 ^0, false)
+%!  assert (2*3 ^2, 18)
+%!  assert (2+3 ^2, 11)
+%!  assert ([1:10](1:2 ^2), [1 2 3 4])
+%!  assert (3>2 ^2, false)
+%!  assert (1&0 ^0, true)
+%!  assert (0|0 ^0, true)
+%!  assert (1&&0 ^0, true)
+%!  assert (0||0 ^0, true)
 %!  a = 3;
-%!  a *= 0^0;
+%!  a *= 0 ^0;
 %!  assert (a, 3)
-%# Level 10 (unary plus, increment, not)
+## Level 10 (unary plus/minus, prefix increment/decrement, not)
 %!test
-# FIXME: No test for increment and transpose that I can think of.
 %!  a = 2;
-%!  assert (++a*3, 9)
-%!  assert (a++-2, 1)
-%!  assert (a, 4)
-%!  assert ([1:10](1:++a), [1:5])
-%!  assert (5 == a++, true)
-%!  assert (7 == ++a, true)
+%!  assert (++ a*3, 9)
+%!  assert (-- a-2, 0)
+%!  assert (a, 2)
+%!  assert (! a-2, -2)
+%!  assert ([1:10](++ a:5), 3:5)
+%!  a = [1 0];
+%!  assert (! a>=[1 0], [false true])
 %!  a = 0;
-%!  assert (1 & a++, false)
-%!  assert (a, 1)
-%!  assert (1 && --a, false)
+%!  assert (++ a&1, true)
+%!  assert (-- a|0, false)
+%!  assert (-- a&&1, true)
+%!  assert (++ a||0, false)
 %!  a = 3;
-%!  a *= a++;
-%!  assert (a, 12)
-%# Level 9 (transpose)
+%!  a *= ++a;
+%!  assert (a, 16)
+## Level 9 (multiply, divide)
 %!test
-%!  assert ([1 2]*[3 4]', 11)
-%!  assert ([1 2]'+[3 4]', [4; 6])
-%!  assert (1:5', 1:5)
-%!  assert ([1; 2] == [1 2]', [true; true])
-%!  assert ([1; 0] & [1 0]', [true; false])
-# FIXME: No test for transpose and short-circuit operator that I can think of.
-%!  a = [1 2];
-%!  a *= [3 4]';
-%!  assert (a, 11)
-%# Level 8 (multiply, divide)
-%!test
-%!  assert (3 + 4 * 5, 23)
-%!  assert (3 + 4 * 5, 23)
-%!  assert (5*1:6, [5 6])
-%!  assert (3 > 1 * 5, false)
-%!  assert (1 & 1 * 0, false)
-%!  assert (1 && 1 * 0, false)
+%!  assert (3+4 * 5, 23)
+%!  assert (5 * 1:6, [5 6])
+%!  assert (3>1 * 5, false)
+%!  assert (1&1 * 0, false)
+%!  assert (1|1 * 0, true)
+%!  assert (1&&1 * 0, false)
+%!  assert (1||1 * 0, true)
 %!  a = 3;
 %!  a /= a * 2;
 %!  assert (a, 0.5)
-%# Level 7 (add, subtract)
+## Level 8 (add, subtract)
 %!test
 %!  assert ([2 + 1:6], 3:6)
-%!  assert (3 > 1 + 5, false)
-%!  assert (1 & 1 - 1, false)
-%!  assert (1 && 1 - 1, false)
+%!  assert (3>1 + 5, false)
+%!  assert (1&1 - 1, false)
+%!  assert (0|1 - 2, true)
+%!  assert (1&&1 - 1, false)
+%!  assert (0||1 - 2, true)
 %!  a = 3;
 %!  a *= 1 + 1;
 %!  assert (a, 6)
-%# Level 6 (colon)
+## Level 7 (colon)
 %!test
-%!  assert (5:-1: 3 > 4, [true false false])
-%!  assert (1: 3 & 1, [true true true])
-%!  assert (-1: 3 && 1, false)
+%!  assert (5:-1: 3>4, [true false false])
+%!  assert (1: 3&1, [true true true])
+%!  assert (1: 3|0, [true true true])
+%!  assert (-1: 3&&1, false)
+%!  assert (-1: 3||0, false)
 %!  a = [1:3];
 %!  a += 3 : 5;
 %!  assert (a, [4 6 8])
-%# Level 5 (relational)
+## Level 6 (relational)
 %!test
-%!  assert (0 == -1 & 0, false)
-%!  assert (0 == -1 && 0, false)
+%!  assert (0 == -1&0, false)
+%!  assert (1 == -1|0, false)
+%!  assert (0 == -1&&0, false)
+%!  assert (1 == -1||0, false)
 %!  a = 2;
 %!  a *= 3 > 1;
 %!  assert (a, 2)
-%# Level 4 (element-wise and, or)
+## Level 5 (element-wise and)
 %!test
-%!  assert (0 & 1 || 1, true)
-%!  assert (0 == -1 && 0, false)
+%!  assert (0 & 1|1, true)
+%!  assert ([0 1] & 1&&1, false)
+%!  assert (0 & 1||1, true)
 %!  a = 2;
 %!  a *= 3 & 1;
 %!  assert (a, 2)
-%# Level 3 (logical and, or)
+## Level 4 (element-wise or)
 %!test
+%!  assert ([0 1] | 1&&0, false)
+%!  assert ([0 1] | 1||0, true)
+%!  a = 2;
+%!  a *= 0 | 1;
+%!  assert (a, 2)
+## Level 3 (logical and)
+%!test
+%!  assert (0 && 1||1, true)
 %!  a = 2;
 %!  a *= 3 && 1;
 %!  assert (a, 2)
+## Level 2 (logical or)
+%!test
+%!  a = 2;
+%!  a *= 0 || 1;
+%!  assert (a, 2)
 
-%# Tests for operator precedence within each level where ordering should
-%# be left to right except for exponents and assignments.
-%# Level 11 (exponentiation)
+## Tests for operator precedence within each level where ordering should
+## be left to right except for postfix and assignment operators.
+
+## Level 13 (parentheses and indexing)
 %!test
-%# FIXME : Exponentiation seems to work left to right, despite the 
-%#         documentation and ordinary mathematical rules of precedence.
-%!#  assert (2^3**2, 512)
-%# Level 10 (unary plus, increment, not)
+%!  a.b1 = 2;
+%!  assert (a.(strcat('b','1'))++, 2)
+%!  assert (a.b1, 3)
+%!  b = {1 2 3 4 5};
+%!  assert (b{(a. b1 + 1)}, 4)
+%!  b = 1:5;
+%!  assert (b(a. b1 + 1), 4)
+%!  assert ([2 3].^2', [4; 9])
+## Level 12 (postfix increment and decrement)
+## No tests possible since a++-- is not valid
+## Level 11 (transpose and exponentiation)
+## Note: Exponentiation works left to right for compatibility with Matlab.
+%!  assert (2^3**2, 64)
+%!  assert ([2 3].^2.', [4;9])
+%!  assert ([2 3].'.^2, [4;9])
+%!  assert (3*4i'.', 0 - 12i)
+%!  assert (3*4i.'.', 0 + 12i)
+## Level 10 (unary plus/minus, prefix increment/decrement, not)
 %!test
 %!  assert (+-+1, -1)
-%!  a = 0;
-%# FIXME : Should we test for this corner case at all?
-%#         (unary minus)(auto-decrement operator)
-%!#  assert (---a, 1);
 %!  a = -1;
 %!  assert (!++a, true)
 %!  assert (a, 0)
 %!  assert (-~a, -1)
-%!  assert (!~a++, false)
-%!  assert (a, 1)
-%# Level 9 (transpose)
+%!  assert (!~--a, true)
+%!  assert (a, -1)
+## Level 9 (multiply, divide)
 %!test
-%!  assert (3*4i'.', 0 - 12i)
-%!  assert (3*4i.'.', 0 + 12i)
-%# Level 8 (multiply, divide)
+%!  assert (3 * 4 / 5, 2.4)
+%!  assert (3 ./ 4 .* 5, 3.75)
+%!  assert (2 * 4 \ 6, 0.75)
+%!  assert (2 .\ 4 .* 6, 12)
+## Level 8 (add, subtract)
 %!test
-%!assert (3 * 4 / 5, 2.4)
-%!assert (3 ./ 4 .* 5, 3.75)
-%# Level 7 (add, subtract)
-%!test
-%!assert (-3 - 4 + 1 + 3 * 2, 0)
-%# Level 5 (relational)
+%!  assert (-3 - 4 + 1 + 3 * 2, 0)
+## Level 7 (colon)
+## No tests possible because colon operator can't be combined with second colon operator
+## Level 6 (relational)
 %!test
 %!  assert (0 < 1 <= 0.5 == 0 >= 0.5 > 0, true)
 %!  assert (1 < 1 == 0 != 0, true)
 %!  assert (1 < 1 == 0 ~= 0, true)
-%# Level 4 (element-wise and, or)
+## Level 5 (element-wise and)
+## No tests possible.  Only one operator (&) at this precedence level and operation is associative.
+## Level 4 (element-wise or)
+## No tests possible.  Only one operator (|) at this precedence level and operation is associative.
+## Level 3 (logical and)
 %!test
-%!  assert ([ 1 0] & [0 1] | [1 0], [true false])
-%# Level 2 (assignment)
+%!  a = 1;
+%!  assert (1 && 0 && ++a, false)
+%!  assert (a, 1)
+## Level 2 (logical or)
+%!test
+%!  a = 1;
+%!  assert (0 || 1 || ++a, true)
+%!  assert (a, 1)
+## Level 1 (assignment)
 %!test
 %! a = 2; b = 5; c = 7;
 %! assert (a += b *= c += 1, 42)
 %! assert (b == 40 && c == 8)
+