changeset 25766:0c087066a9a1

maint: Merge stable to default.
author Kai T. Ohlhus <k.ohlhus@gmail.com>
date Fri, 10 Aug 2018 09:09:51 +0200
parents 826b45c1c427 (diff) 66caa6dc6701 (current diff)
children 785eef952919
files
diffstat 597 files changed, 31255 insertions(+), 31555 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Fri Aug 10 09:08:33 2018 +0200
+++ b/.hgignore	Fri Aug 10 09:09:51 2018 +0200
@@ -1,53 +1,121 @@
 syntax: regexp
-# The recurrent (^|/) idiom in the regexps below should be understood
-# to mean "at any directory" while the ^ idiom means "from the
-# project's top-level directory".
+## The recurrent (^|/) idiom in the regexps below should be understood
+## to mean "at any directory" while the ^ idiom means "from the
+## project's top-level directory".
 
-# gnulib makes these silly backup files
+## gnulib related files
+# gnulib makes these silly backup files.
 .~$
-
 # This directory gets created by gnulib during the build.
 # It contains no Octave files.
-^libgnu($|/)
+(^|/)libgnu($|/)
 
+## m4 related files
 # This directory mostly contains cruft during build time, but it does
-# contain some Octave code, so we gotta be a bit more careful about
-# what we ignore here
+# contain some Octave code, so be more careful about what we ignore here.
 ^m4/(?!ax_).+\.m4$
 
-# Emacs tools create these
+## Autoconf, Automake automatically generated files
+^aclocal\.m4$
+^autom4te\.cache($|/)
+^config\.in\.h$
+^configure$
+(^|/)config.cache$
+(^|/)config.h$
+(^|/)config.log$
+(^|/)config.status$
+
+^Makefile\.in$
+^INSTALL$
+
+## Emacs associated files
 (^|/)TAGS$
 (^|/)semantic.cache$
 
-(/|^)Makefile\.in$
-^INSTALL$
-
-^aclocal\.m4$
-^autom4te\.cache($|/)
+## Scripts associated with building Octave
 ^build-aux/config\.(guess|rpath|sub)$
+(^|/)build-aux/check-subst-vars\.sh$
 ^build-aux/depcomp$
 ^build-aux/install-sh$
 ^build-aux/ltmain\.sh$
 ^build-aux/mdate-sh$
 ^build-aux/missing$
 ^build-aux/move-if-change$
+(^|/)build-aux/subst-config-vals\.sh$
+(^|/)build-aux/subst-cross-config-vals\.sh$
+(^|/)build-aux/subst-script-vals\.sh$
 ^build-aux/texinfo\.tex$
 ^build-aux/ylwrap$
-^config\.in\.h$
-^configure$
+
+## Mercurial associated files
+(^|/)HG-ID$
+
+## Timestamp files used in build process
+.*/\.dirstamp$
+.*/\.octave-dirstamp$
+
+## Intermediate compilation results for libraries
+.*\.la$
+.*/\.libs/
+.*\.Plo$
+.*\.Po$
+
+
+## DLDFCN associated files
+^libinterp/dldfcn/module\.mk$
+(^|/)libinterp/dldfcn/PKG_ADD$
+(^|/)libinterp/dldfcn/.*\.oct$
 
-# e.g. doc/faq/OctaveFAQ.info
-#      doc/interpreter/octave.info-4
+## liboctave/ directory associated patterns
+# E.g., liboctave/operators/smx-op-inc.mk
+^liboctave/operators/\w+-op-\w+\.mk$
+
+## scripts/ directory associated patterns
+# Package files
+(^|/)scripts/.*/PKG_ADD$
+# Java files
+(^|/)scripts/java/octave\.jar$
+(^|/)scripts/java/org/octave/.*\.class$
+
+## libgui/ associated patterns
+# Files generated by moc tool
+(^|/)libgui/.*/moc-.*\.(cc|h)$
+(^|/)libgui/languages/.*\.qm$
+
+## Ignore patterns associated with documentation
+# Info generated files
+# E.g., doc/faq/OctaveFAQ.info, doc/interpreter/octave.info-4
 ^doc/\w+/\w+\.info(-\d+)?$
 
+# Texinfo created temporary directories
+(^|/)doc/(interpreter|liboctave)/(octave|liboctave)\.t2(d|p)/
+# Texinfo created files
+(^|/)doc/interpreter/.*\.texi$
+
+# DOCSTRINGS files built in the source tree
+(^|/)(libinterp|scripts)/DOCSTRINGS$
+
+# Generated HTML directories
+(^|/)doc/interpreter/octave\.html/
+(^|/)doc/liboctave/liboctave\.html/
+
+# Miscellaneous auto-generated files 
+(^|/)doc/interpreter/octave\.dvi$
+(^|/)doc/interpreter/octave\.ps$
+(^|/)doc/interpreter/doc-cache$
+(^|/)doc/interpreter/octave_interpreter\.q(ch|hc)$
+
+# Images and scripts for documentation
+^doc/interpreter/images\.mk$
+(^|/)doc/interpreter/.*\.eps$
+(^|/)doc/interpreter/.*\.pdf$
+(^|/)doc/interpreter/.*\.png$
+(^|/)doc/interpreter/.*\.txt$
+
+# timestamps for doc directory
 ^doc/\w+/stamp-(vti|\d+)$
 ^doc/\w+/version-\w+\.texi$
-^doc/interpreter/images\.mk$
-
-# e.g. liboctave/operators/smx-op-inc.mk
-^liboctave/operators/\w+-op-\w+\.mk$
 
-^libinterp/dldfcn/module\.mk$
+## Test associated patterns
+.*-tst$
 
-# DOCSTRINGS files are built in the source tree
-^(libinterp|scripts)/DOCSTRINGS$
--- a/Makefile.am	Fri Aug 10 09:08:33 2018 +0200
+++ b/Makefile.am	Fri Aug 10 09:09:51 2018 +0200
@@ -43,7 +43,7 @@
 
 # C compiler flags.
 
-AM_CFLAGS = ${CPICFLAG} ${XTRA_CFLAGS}
+AM_CFLAGS = ${CPICFLAG} ${XTRA_CFLAGS} ${WARN_CFLAGS}
 
 # ifeq (${INCLUDE_DEPS},no)
 #   omit_deps = true;
@@ -51,7 +51,7 @@
 
 # C++ compiler flags.
 
-AM_CXXFLAGS = ${CXXPICFLAG} ${XTRA_CXXFLAGS}
+AM_CXXFLAGS = ${CXXPICFLAG} ${XTRA_CXXFLAGS} ${WARN_CXXFLAGS}
 
 FFTW_XCPPFLAGS = @FFTW_XCPPFLAGS@
 FFTW_XLDFLAGS = @FFTW_XLDFLAGS@
@@ -148,6 +148,7 @@
 info_TEXINFOS =
 BUILT_SOURCES =
 TEST_FILES =
+noinst_TEST_FILES =
 
 DOC_IMAGES_SRC =
 BUILT_DOC_IMAGES =
@@ -183,6 +184,8 @@
 octinclude_HEADERS =
 nodist_octinclude_HEADERS =
 
+pkgconfig_DATA =
+
 DIST_SRC =
 
 ALL_LOCAL_TARGETS =
@@ -208,7 +211,6 @@
 include src/module.mk
 include scripts/module.mk
 include doc/module.mk
-include doc/interpreter/images.mk
 include etc/module.mk
 include examples/module.mk
 include m4/module.mk
@@ -220,6 +222,7 @@
   docs-dist-hook \
   fix-file-perms-dist-hook \
   hg-id-dist-hook \
+  appdata-dist-hook \
   icons-dist-hook \
   scripts-dist-hook
 
@@ -458,38 +461,6 @@
   mv $@-t $@
 endef
 
-define subst-bison-api-decls
-  case "${BISON_API_PREFIX_DECL_STYLE}" in \
-    *api*) \
-      case "${BISON_API_PREFIX_DECL_STYLE}" in \
-       *brace*) \
-         api_prefix_decl='%define api.prefix {$(1)}'; ;; \
-       *) \
-         api_prefix_decl='%define api.prefix "$(1)"'; ;; \
-       esac; \
-      ;; \
-    *name*) \
-      case "${BISON_API_PREFIX_DECL_STYLE}" in \
-        *brace*) \
-          api_prefix_decl='%name-prefix {$(1)}'; ;; \
-        *) \
-          api_prefix_decl='%name-prefix="$(1)"'; ;; \
-      esac; \
-    ;; \
-  esac; \
-  case "${BISON_PUSH_PULL_DECL_STYLE}" in \
-    *quote*) quote='"' ;; \
-    *) quote="" ;; \
-  esac; \
-  case "${BISON_PUSH_PULL_DECL_STYLE}" in \
-    *dash*) push_pull_decl="%define api.push-pull $${quote}both$${quote}"; ;; \
-    *underscore*) push_pull_decl="%define api.push_pull $${quote}both$${quote}"; ;; \
-  esac; \
-  ${SED} -e "s/%PUSH_PULL_DECL%/$$push_pull_decl/" \
-         -e "s/%API_PREFIX_DECL%/$$api_prefix_decl/" $< > $@-t && \
-  mv $@-t $@
-endef
-
 define gdbinit-install-rule
   if [ -f $@ ] && ! cmp -s $< $@; then \
     echo "refusing to overwrite $@ with newer version from $<" 1>&2; \
--- a/NEWS	Fri Aug 10 09:08:33 2018 +0200
+++ b/NEWS	Fri Aug 10 09:09:51 2018 +0200
@@ -1,962 +1,102 @@
-Summary of important user-visible changes for version 4.4 (2018-04-30):
+Summary of important user-visible changes for version 5.0 (yyyy-mm-dd):
 ----------------------------------------------------------------------
 
- ** A graphical Variable Editor has been added to the GUI interface.
-    It uses a spreadsheet-like interface for quick, intuitive editing
-    of variables.  The Variable Editor is launched by double-clicking
-    on a variable name in the Workspace Window or by typing
-    "openvar VARIABLE_NAME" in the Command Window.
-
- ** On systems with 64-bit pointers, --enable-64 is now the default and
-    Octave always uses 64-bit indexing.  However, if the configure
-    script determines that the BLAS library uses 32-bit integers, then
-    operations using the following libraries are limited to arrays with
-    dimensions that are smaller than 2^31 elements:
-
-      BLAS  LAPACK  QRUPDATE  SuiteSparse  ARPACK
-
-    Additionally, the following libraries use "int" internally, so
-    maximum problem sizes are always limited:
-
-      glpk  Qhull
-
- ** The octave command no longer starts the GUI by default.  Most users
-    starting Octave from a shell were expecting the command line
-    interface, and desktop launchers already required the `--force-gui'
-    option.  With this change, desktop launchers should be modified to
-    use the new option `--gui'.  The previous `--force-gui' option will
-    continue to work, and maps to `--gui', but it will be removed in
-    Octave 6.
-
- ** A known bug in Qt (https://bugreports.qt.io/browse/QTBUG-55357) is
-    addressed by limiting GUI sub-panel relocation capabilities for Qt
-    versions in the range >= 5.6.1 and < 5.7.1.  However, this may not
-    thoroughly avoid issues on all platforms.
+ ** The functions issymmetric and ishermitian accept an option "nonskew"
+    or "skew" to calculate the symmetric or skew-symmetric property
+    of a matrix.  Performance has also been increased.
 
- ** A new container data type--containers.Map--is available.  Map is a
-    key/value storage container (a.k.a, a hash) that efficiently allows
-    storing and retrieving values by name, rather than by position which
-    is how arrays work.
-
- ** The bareword "import" is now recognized in scripts and functions.
-    However, the functionality to import functions and classes from
-    other namespaces into the local scope has not yet been implemented.
-    Attempting to use "import" will provoke an error message.
-
- ** hex2num and num2hex now work for integer and char types and num2hex
-    may optionally return a cell array of strings instead of a character
-    array.  If given a cell array of strings, hex2num now returns a
-    numeric array of the same size as the input cell array.  Previously,
-    hex2num would accept a cell array of strings of arbitrary dimension
-    but would always return a column vector.
+ ** The issorted function now uses a direction option of "ascend" or
+    "descend" to make it compatible with both the sort function and
+    with Matlab.  Change all uses of "ascending" and "descending" in
+    existing code to the new options.
 
- ** New special functions cosint, sinint, and gammaincinv have been added.
-
- ** Special functions in Octave have been rewritten for larger input
-    domains, better accuracy, and additional options.
-    * gammainc now accepts negative real values for X.
-    * improved accuracy for gammainc, betainc, betaincinv, expint.
-    * gammainc has new options "scaledlower" and "scaledupper".
-    * betainc, betaincinv have new option "upper".
+ ** The strncmp and strncmpi functions now return true if the two input
+    strings match, even though the number of characters specified by N
+    exceeds the string length.  This behavior more closely matches
+    common sense and is Matlab compatible.  Example:
 
- ** The "names" option used in regular expressions now returns a struct
-    array, rather than a struct with a cell array for each field.  This
-    change was made for Matlab compatibility.
-
- ** The quadcc function now uses both absolute tolerance and relative
-    tolerance to determine the stopping criteria for an integration.
-    To be compatible with other quadXXX functions, such as quadgk, the
-    calling syntax has changed to
+      Octave 5.0 : strncmp ("abc", "abc", 100) => true
+      Previously : strncmp ("abc", "abc", 100) => false
 
-      quadcc (f, a, b, [AbsTol, [RelTol]])
-
-    To update existing code, change instances of RelTol to [0, RelTol].
-
-      quadcc (f, a, b, tol) => quadcc (f, a, b, [0, tol])
-
-    A warning that a single tolerance input is now interpreted as an
-    absolute tolerance will be issued in Octave versions 4.4 and 5,
-    after which it will be removed.  The warning has ID
-    "Octave:quadcc:RelTol-conversion" and can be disabled with
-
-      warning ("off", "Octave:quadcc:RelTol-conversion")
-
- ** The qr function now returns a standard factorization unless
-    explicitly instructed to perform an economy factorization by using a
-    final argument of 0.
-
- ** The Qt graphics toolkit now supports offscreen printing without osmesa
-    if Octave was built with Qt >= 5.1.
-
- ** The built-in pager for display of large data is now disabled by
-    default.  To re-enable it for every Octave session add the following
-    to your .octaverc file:
-
-      more on;
-
- ** The FLTK toolkit is no longer prioritized for development.  The
-    number of Octave Maintainers is too small to support three different
-    graphic toolkits.  New development will target the Qt toolkit.
-    While no longer prioritized, the FLTK toolkit is not deprecated and
-    there is no schedule for its removal.
-
- ** The graphic object property "PickableParts" has been implemented
-    which controls whether an object can accept mouse clicks.
+ ** The fsolve function has been tweaked to use larger step sizes when
+    calculating the Jacobian of a function with finite differences.
+    This leads to faster convergence.  The default solver options have
+    also changed to be Matlab compatible.  This *may* result in existing
+    code producing different results.
 
- ** The graphic object property "Interruptible" has been fully
-    implemented which controls whether a running callback function can
-    be interrupted by another callback function.
-
- ** The graphic object property "HitTest" has been updated to be fully
-    compatible with Matlab.
-
- ** Text objects now implement the properties "BackgroundColor",
-    "EdgeColor", "LineStyle", "LineWidth", and "Margin".
-
- ** An initial implementation of alpha transparency has been made for
-    patch and surface objects.  Printing to svg and pdf is supported.
+          Option     |  New Default   |  Old Default
+      ------------------------------------------------
+        FinDiffType  |   "forward"    |   "central"
+        MaxFunEvals  | 100*length(x0) |     Inf
+        TolFun       |     1e-6       |     1e-7
+        TolX         |     1e-6       |     1e-7
+        Updating     |     "off"      |     "on"
 
- ** ishandle now returns true for both graphics handle objects and
-    Java objects.  The latter change was made for Matlab compatibility.
-    Use ishghandle or isgraphics if it is important not to include Java
-    objects.
-
- ** The pkg command now accepts a URL as an argument, allowing a valid
-    Octave package to be installed from any remote host with one command,
-    for example
-
-      pkg install https://example.org/download/example-package.tar.gz
-
- ** The following statistical functions have been moved from core
-    Octave to the statistics package available from Octave Forge.
-
-    BASE
-      cloglog
-      logit
-      prctile
-      probit
-      qqplot
-      table  (renamed to crosstab)
+ ** The fminsearch function has changed default solver options for
+    Matlab compatibility.  The accuracy option TolFun is now 1e-4 rather
+    than 1e-7.  This *may* result in existing code producing different
+    results.
 
-    DISTRIBUTIONS
-      betacdf
-      betainv
-      betapdf
-      betarnd
-      binocdf
-      binoinv
-      binopdf
-      binornd
-      cauchy_cdf
-      cauchy_inv
-      cauchy_pdf
-      cauchy_rnd
-      chi2cdf
-      chi2inv
-      chi2pdf
-      chi2rnd
-      expcdf
-      expinv
-      exppdf
-      exprnd
-      fcdf
-      finv
-      fpdf
-      frnd
-      gamcdf
-      gaminv
-      gampdf
-      gamrnd
-      geocdf
-      geoinv
-      geopdf
-      geornd
-      hygecdf
-      hygeinv
-      hygepdf
-      hygernd
-      kolmogorov_smirnov_cdf
-      laplace_cdf
-      laplace_inv
-      laplace_pdf
-      laplace_rnd
-      logistic_cdf
-      logistic_inv
-      logistic_pdf
-      logistic_rnd
-      logncdf
-      logninv
-      lognpdf
-      lognrnd
-      nbincdf
-      nbininv
-      nbinpdf
-      nbinrnd
-      normcdf
-      norminv
-      normpdf
-      normrnd
-      poisscdf
-      poissinv
-      poisspdf
-      poissrnd
-      stdnormal_cdf
-      stdnormal_inv
-      stdnormal_pdf
-      stdnormal_rnd
-      tcdf
-      tinv
-      tpdf
-      trnd
-      unidcdf
-      unidinv
-      unidpdf
-      unidrnd
-      unifcdf
-      unifinv
-      unifpdf
-      unifrnd
-      wblcdf
-      wblinv
-      wblpdf
-      wblrnd
-      wienrnd
+ ** The fminbnd function has changed defaults for Matlab compatibility.
+    This *may* result in existing code producing different results.
+
+          Option     |  New Default   |  Old Default
+      ------------------------------------------------
+        MaxFunEvals  |      500       |     Inf
+        MaxIter      |      500       |     Inf
+        TolX         |     1e-4       |     1e-8
+
+ ** Figure graphic objects have a new property "Number" which is
+    read-only and will return the handle (number) of the figure.
+    However, if the property "IntegerHandle" has been set to "off" then
+    the property will return an empty matrix ([]).
 
-    MODELS
-      logistic_regression
+ ** Printing using the -dtiff output device will now create compressed
+    images using lzw compression.  This change was made for Matlab
+    compatibility.  To produce uncompressed images use the -dtiffn
+    device.
 
-    TESTS
-      anova
-      bartlett_test
-      chisquare_test_homogeneity
-      chisquare_test_independence
-      cor_test
-      f_test_regression
-      hotelling_test
-      hotelling_test_2
-      kolmogorov_smirnov_test
-      kolmogorov_smirnov_test_2
-      kruskal_wallis_test
-      manova
-      mcnemar_test
-      prop_test_2
-      run_test
-      sign_test
-      t_test
-      t_test_2
-      t_test_regression
-      u_test
-      var_test
-      welch_test
-      wilcoxon_test
-      z_test
-      z_test_2
-
- ** The following image functions have been moved from core Octave to
-    the image package available from Octave Forge.
-
-      ntsc2rgb
-      rgb2ntsc
-
- ** Other new functions added in 4.4:
+ ** The FFTW library is now required to perform FFT calculations.  The
+    FFTPACK sources have been removed from Octave.
 
-      bounds
-      camlookat
-      camorbit
-      campos
-      camroll
-      camtarget
-      camup
-      camva
-      camzoom
-      corrcoef
-      cosint
-      decic
-      erase
-      gammaincinv
-      getframe
-      groot
-      gsvd
-      hgtransform
-      humps
-      integral
-      integral2
-      integral3
-      isgraphics
-      isstring
-      mad
-      ode15i
-      ode15s
-      openvar
-      quad2d
-      repelem
-      rgb2gray
-      rticks
-      sinint
-      tfqmr
-      thetaticks
-      vecnorm
-      winqueryreg
-      xticklabels
-      xticks
-      yticklabels
-      yticks
-      zticklabels
-      zticks
+ ** The OSMesa library is no longer used.  To print invisible figures
+    when using OpenGL graphics, the Qt QOFFSCREENSURFACE feature must be
+    available and you must use the qt graphics toolkit.
+
+ ** New functions added in 5.0:
 
- ** Deprecated functions.
+      ordeig
+
+ ** Legacy functions.
 
-    The following functions have been deprecated in Octave 4.4 and will
-    be removed from Octave 6 (or whatever version is the second major
-    release after 4.4):
+    The following functions have been declared legacy functions which
+    means they are obsolete and should not be used in any new code.
+    Unlike deprecated functions, however, their removal from Octave has
+    not yet been scheduled.
 
       Function             | Replacement
       ---------------------|------------------
-      chop                 | sprintf for visual results
-      desktop              | isguirunning
-      tmpnam               | tempname
-      toascii              | double
-      java2mat             | __java2mat__
-
-
- ** The following functions were deprecated in Octave 4.0 and have been
-    removed from Octave 4.4.
-
-      allow_noninteger_range_as_index
-      bicubic
-      delaunay3
-      do_braindead_shortcircuit_evaluation
-      dump_prefs
-      find_dir_in_path
-      finite
-      fmod
-      fnmatch
-      gmap40
-      loadaudio
-      luinc
-      mouse_wheel_zoom
-      nfields
-      octave_tmp_file_name
-      playaudio
-      saveaudio
-      setaudio
-      syl
-      usage
-
- ** The "Octave:undefined-return-values" warning ID is obsolete.  Octave
-    now throws an error for any attempts to assign undefined values that
-    might be returned from functions.
-
- ** Deprecated graphics properties.
-
-    The following properties or allowed corresponding values have been
-    deprecated in Octave 4.4 and will be removed from Octave 6 (or whatever
-    version is the second major release after 4.4):
-
-      Object               | Property                | Value
-      ---------------------|-------------------------|-------------------
-      figure               | doublebuffer            |
-                           | mincolormap             |
-                           | wvisual                 |
-                           | wvisualmode             |
-                           | xdisplay                |
-                           | xvisual                 |
-                           | xvisualmode             |
-      axes                 | drawmode                |
-      annotation           | edgecolor ("rectangle") |
-      text                 | fontweight              | "demi" and "light"
-      uicontrol            | fontweight              | "demi" and "light"
-      uipanel              | fontweight              | "demi" and "light"
-      uibuttongroup        | fontweight              | "demi" and "light"
-
- ** The rectangle and ellipse annotation property "edgecolor" has been
-    deprecated and will be removed from Octave 6 (or whatever version
-    is the second major release after 4.4).  Use the property "color"
-    instead.
-
- ** The header file oct-alloc.h has been removed along with the macros
-    that it defined (DECLARE_OCTAVE_ALLOCATOR, DEFINE_OCTAVE_ALLOCATOR,
-    and DEFINE_OCTAVE_ALLOCATOR2).
-
-
-Summary of bugs fixed for version 4.2.2 (2018-03-13):
-----------------------------------------------------
-
-Using the bug numbers listed below, find bug reports on the web using
-the URL https://savannah.gnu.org/bugs/?NNNNN
-
- ** make leftdiv work for scalar \ int-matrix (bug #51682)
-
- ** inputdlg.m: Avoid crash when prompt and defaults sizes differ (bug #53209)
-
- ** tie octave_classdef::numel method to "numel" user override method
-    (bug #46571)
-
- ** fix performance of Sparse fsolve for complex sparse matrices (bug #53140)
-
- ** fix performance of Sparse fsolve (bug #53140)
-
- ** octave.desktop.in: No repetition of Name in Comment field and start I10n
-    (bug #53078)
-
- ** don't create partially invalid graphic objects (bug #52904)
-
- ** test for incorrect regexprep on ARM platforms (bug #52810)
-
- ** fix incorrect regexprep on ARM platforms (bug #52810)
-
- ** correctly handle reading of characters >127 in scanf family (bug #52681)
-
- ** fix addpath for UNC paths on Windows (bug #51268)
-
- ** protect being-deleted objects on figure list from second deletion
-    (bug #52666)
-
- ** dlmwrite.m: Close fid if filename is only one char long (bug #52679)
-
- ** set gnuplot color data to half output range when autoscaling zero input
-    range (bug #52624)
-
- ** add polarplot() to the list of unimplemented functions (bug #52643)
-
- ** configure.ac: Fix test for Java version (bug #52617)
-
- ** for gnuplot toolkit, do not map TrueColor data to colormap size (bug #52599)
-
- ** make wheel scroll behave more consistently in pan mode (bug #52588)
-
- ** make gnuplot color have three components for interpolated edge color
-    (bug #52595)
-
- ** simplify gnuplot toolkit scripts for image/non-image data plots (bug #52589)
-
- ** fix concatenation of empty char matrices with other strings (bug #52542)
-
- ** build: Fix compiling OCTAVE_ARPACK_OK_2 Fortran code (bug #52425)
-
- ** trisurf.m, trimesh.m: Fix input validation (bug #48109)
-
- ** allow uncommenting in editor when line begins with whitespace (bug #52406)
-
- ** do not extend selection when indenting/commenting in editor (bug #45610)
-
- ** remove all delimiters from whitespace list in textscan function (bug #52479)
-
- ** calculate 1-norm of matrices to assess whether NaN or Inf are present
-    (bug #39000)
-
- ** prevent extra ampersand under KDE in cd-or-add-to-path dialog (bug #52423)
-
- ** plotyy.m: Fix error when using FUN2 argument (bug #48115)
-
- ** check ARPACK library for buggy behavior in configure (bug #52425)
-
- ** fix printing integer type images (bug #51558)
-
- ** fix segfault in delaunayn when Qhull memory is not properly cleared
-    (bug #52410)
-
- ** fix segfault with CHOLMOD library and empty matrices (bug #52365)
-
- ** tag global and persistent symbols as variables when parsing (bug #52363)
-
- ** properly restore the input stream pointer at end of textscan (bug #52116 et
-    al.)
-
- ** fix building with Qt4 for Windows (bug #52237)
-
- ** ensure numeric values are passed for the axes "clim" property (bug #52053)
-
- ** avoid abort on exit from GUI (bug #50664)
-
- ** correct auto limits on log axes with negative and zero values (bug #51861)
-
- ** fix warning in quadgk with zero size interval (bug #51867)
-
- ** sparse: correctly handle scalar column index (bug #51880)
-
- ** fix segfault in ichol under certain conditions (bug #51736)
-
- ** configure: ensure empty pkg-config results are actually empty (bug #51680)
-
- ** fix 'legend hide' for gnuplot (bug #50483)
-
- ** qqplot.m: Fix typo in input validation (bug #51458)
-
- ** add possible '\r' to smartindent regex exprepression (Bug #51279)
-
- ** make strncmp case sensitive again (bug #51384)
-
- ** fix possible infinite loop in normest1.m (bug #51241)
-
- ** also run unwind protect cleanup code on interrupt exceptions (bug #51209)
-
- ** fix crash when inverting complex matrices with NaNs (bug #51198)
-
- ** improve accuracy of residue for inputs with very different magnitudes
-    (bug #51148)
-
- ** publish.m: Fix corruption of results for some code inputs (bug #51178)
-
- ** residue.m: Remove code that filters out small return values (bug #34266, bug
-    #49291)
-
- ** avoid possible double free at interpreter exit (bug #51088)
-
- ** show stack trace for errors in command line and startup files (bug #49346)
-
- ** interp1.m: Return NA for all columns which are out of bounds (bug #51030)
-
- ** use idx_type for dimensions instead of int (bug #50934)
-
- ** show stack trace for wrong type arg errors (bug #50894)
-
- ** let mouse selection of Qt figures update "currentfigure" (bug #50666)
-
- ** disable qscintilla editor drag and drop so parent will handle it (Bug
-    #50559)
-
- ** quadgk.m: Correct error messages which point to quadv (bug #50604)
-
- ** set version on AppUserModelId (Bug #50428)
-
- ** version-rcfile: Don't try to execute startup directory, only startup.m
-    (bug #50593)
-
- ** dlmread: Return empty matrix when requested range is outside data
-    (bug #50102)
-
- ** fix eigs for generalized nonsymmetric and shift-invert problems (bug #39573)
-
- ** fix eigs for the generalized eigenvalue problem (bug #50546)
-
- ** datetick.m: Fix uneven range bugs (bug #50493)
-
- ** datenum.m: Correct calculation for fractional leap years (bug #50508)
-
- ** datenum.m: Allow horizontal vectors of dates with fractional months
-    (bug #50508)
-
- ** datenum.m: Accept legal input of vectors with fractional months (bug #50508)
-
- ** fix the anchor position in the info text of the doc browser (bug #50422)
-
- ** fix order of legend labels with plotyy axes (bug #50497)
-
- ** correct hggroup plot legends for gnuplot toolkit, add legend demo 17 items
-    (bug #49341)
-
- ** for gnuplot graphics toolkit, show only one key entry for errorbars
-    (bug #49260)
-
- ** fix compilation of jit caused by cset d0562b3159c7 (bug #50398)
-
- ** remove inline keyword on file_stat destructor which breaks MacOS compilation
-    (bug #50234)
-
-Documentation bugs fixed:
-
- ** playblocking.m: Correct documentation about start and limits inputs
-    (bug #51217)
-
- ** fix eig output argument description (bug #50524)
-
- ** remove backslashes before double quotes in m-file docstrings (bug #52870)
-
- ** tweaks to use single quotes instead of double quotes (bug #52870)
-
- ** correct fieldname of returned struct in ver (bug #52845)
-
- ** cleanup @code example in Appendix on test functions (bug #52852)
-
- ** fixes for signal, image, audio, and OOP chapters (bug #52844)
-
- ** fix issues in geometry, polynomial, and interpolation chapters (bug #52835)
-
- ** fix TeX documentation for qp and clarify size of inputs (bug #52829)
-
- ** correct errors in Diagonal matrix chapter of manual (bug #52814)
-
- ** replace @math{1e^{XXX}} sequences with raw 1eXXX (bug #52827)
-
- ** use '...' rather than deprecated '\' for line continuation (bug #52828)
-
- ** make documentation Sec 26.1 more consistent and Sec 25.4 clearer
-    (bug #52685)
-
- ** documentation fixes for linspace, logspace, lookup (bug #52785)
-
- ** atan2d.m: Correct documentation to match atan docstring (bug #52786)
-
- ** small tweaks to fplot and surfnorm docstrings (bug #52761)
-
- ** rewrite documentation for Advanced Indexing (bug #52723)
-
- ** delete extra ']' in scanf docstring (bug #52742)
-
- ** fix mistaken use of space between function and '(' in documentation
-    (bug #52723)
-
- ** fix various inconsistencies in manual (bug #52712)
-
- ** fix typo in cset 8354b505ad6b (bug #52702)
-
- ** fix inconsistencies with char, strvcat, strread docstrings (bug #52702.
-
- ** explain Matlab compatibility of fopen modes (bug #52644)
-
- ** update documentation for keywords to include classdef statements
-    (bug #52591)
-
- ** fix documentation of third input to lsode() (bug #52664)
-
- ** clarify quiver/quiver3 documentation when a linestyle is given (bug #52608)
-
- ** new section about classdef classes with example (bug #44590)
-
- ** correct surface plot explanation of  meshgridded results of 1 input
-    (bug #52536)
-
- ** fix definition of Delaunay triangulation in docstrings (bug #52416)
-
- ** accumarray.m: Add '@' to function handles in docstring (bug #52418)
-
- ** update manual to explain \deg and \circ symbols (bug #52287)
-
- ** correct documentation for randg (bug #52118)
-
- ** add documentation about PCRE library regexp stack overflow (bug #51589)
-
- ** play.m: Correct documentation about start and limits inputs (bug #51217)
-
- ** redo docstring for qz (bug #50846)
-
- ** describe optional install dependencies PortAudio and SUNDIALS (bug #50513)
-
- ** update CITATION date, version, and permalink to manual (bug #47058)
-
-
-Summary of bugs fixed for version 4.2.1 (2017-02-22):
-----------------------------------------------------
-
-Using the bug numbers listed below, find bug reports on the web using
-the URL https://savannah.gnu.org/bugs/?NNNNN
-
- ** guarantee returning std::string from tilde_expand functions (bug #50234)
-
- ** workaround segfault in file_stat (bug #50234)
-
- ** genpropdoc.m: document more graphics properties (bug #50337)
-
- ** always fork and exec when starting the gui (bug #49609)
-
- ** print.m: fix regression with -append option (bug #50318)
-
- ** don't display legend, colorbar, and annotation axes coordinates
-    (bug #50272)
-
- ** qp.m: Fix regression with incorrect vector dimensions (bug #50067)
-
- ** prevent infinite loop in global documentation search (bug #50177)
-
- ** connect execute command signal in editor constructor (bug #50171)
-
- ** connect editors execute command signal to the required slot (bug #50171)
-
- ** check if input is class method before declaring it unimplemented
-    (patch #9238) (bug #49694)
-
- ** workaround segfault when an error occurs while printing (bug #49779)
-
- ** axis.m: Do not set plotboxaspectratio to 0 (bug #49755)
-
- ** don't rethrow exception in destructor (bug #49304)
-
- ** rethrow octave::exit_exception (bug #49304)
-
- ** update appdata.xml to follow conventions (bug #49952)
-
- ** mexproto.h (mxAssert, mxAssertS): ensure operator precedence (bug #50050)
-
- ** calculate error in solution for ode solvers correctly (bug #49950)
-
- ** use GetModuleFileName for getting octave path in windows (bug #48671)
-
- ** use C++ updaters for labels color (bug #49980)
-
- ** distinguish elements vs. bytes in fread (bug #49699)
-
- ** move frame2im and im2frame to image/ directory (bug #49939)
-
- ** fix undefined return argument for more than 2 outputs from ode solver
-    (bug #49890)
-
- ** fix inv for hermitian matrices (bug #49904)
-
- ** fix gzip for certain types of gzip files (bug #49760)
-
- ** fix typo in liboctave version info (bug #49860)
-
- ** initialize ODE Event function with start time (bug #49846)
-
- ** allow configure test to succeed without implicit fcn decls (bug #49782)
-
- ** allow external docstrings from .oct files to be found again (bug #49687)
-
- ** don't require semicolon between property list elements (bug #49819)
-
- ** display.m: Correctly display output for non-class objects
-    (bug #49753, #49794)
-
- ** don't run publish.tst unless OSMESA or gnuplot are available (bug #49767)
-
- ** find help for function aliases again (bug #49687)
-
- ** legend.m: backport cset 7184b4516a68 (bug #49675)
-
- ** preserve lasterror info on rethrow (bug #49642)
-
- ** norm: fix error in input argument validation leading to segfault
-    (bug #49634)
-
-Documentation bugs fixed:
-
- ** overhaul Java interface description (bug #50299)
-
- ** add documentation for hex and binary prefix and _ separator
-    (bug #50305, #50334)
-
- ** fix build of docs broken in sub2ind (bug #50348)
-
- ** version.m: document that "-release" returns an empty string (bug #50294)
-
- ** remove trailing "\n\" from sleep and usleep docstrings (bug #50301)
-
- ** expand documentation for cast() (bug #50201)
-
- ** correct two entries in Table 34.1 (bug #50203)
-
- ** oop.txi: Improve table formatting (bug #50203)
-
- ** fix '##' in middle of docstring/comment lines (bug #50145)
-
- ** reword documentation about subplots in 15.2.4 (bug #50148)
-
- ** update unimplemented list of functions and where to find them
-    (bug #50098)
-
- ** compare_plot_demos: fix HTML syntax, simplify output, remove
-    external deps (bug #49709)
-
- ** add more depth to explanation of '~' function argument (bug #49444)
-
- ** correct documentation for javaclasspath file (bug #49873)
-
- ** small fixes to docstrings (bug #49733)
-
- ** change text describing demo plots to reflect new ColorOrder (bug #49288)
-
-Other bugs fixed:
-
- ** add missing classdef test files (bug #49819)
-
-
-Summary of important user-visible changes for version 4.2 (2016-11-13):
-----------------------------------------------------------------------
-
- ** The parser has been extended to accept, but ignore, underscore
-    characters in numbers.  This facilitates writing more legible code
-    by using '_' as a thousands separator or to group nibbles into bytes
-    in hex constants.
-
-    Examples: 1_000_000 == 1e6  or  0xDE_AD_BE_EF
-
- ** The parser has been extended to understand binary numbers which
-    begin with the prefix '0b' or '0B'.  The value returned is Octave's
-    default numeric class of double, not at unsigned integer class.
-    Therefore numbers greater than flintmax, i.e., 2^53, will lose some
-    precision.
-
-    Examples: 0b101 == 5  or  0B1100_0001 == 0xC1
-
- ** gnuplot 4.4 is now the minimum version supported by Octave.
-
- ** The default set of colors used to plot lines has been updated to be
-    compatible with Matlab's new default color scheme.  The line plot
-    color scheme can be set with the axes property "ColorOrder".
-
- ** The default colormap is now set to "viridis" which is also the
-    default colormap in matplotlib.  This new colormap fixes some of the
-    main issues with the old default colormap "jet" such as its bad
-    "luminance profile" and is also more similar to Matlab's new default
-    colormap "parula".
-
- ** The colormap function no longer supports the input argument "list"
-    to show built-in colormaps.  Use "help colormap" to find the
-    built-in colormaps.
-
- ** The graphics command "hold on" now ensures that each new plot added
-    to an existing plot has a different color or linestyle according to
-    the "ColorOrder" and/or "LineStyleOrder" properties.  This is
-    equivalent to the old command "hold all" and was made for Matlab
-    compatibility.  Existing code *may* produce differently colored
-    plots if it did not specify the color for a plot and relied on each
-    new plot having the default first color in the "ColorOrder"
-    property.
-
- ** When starting, Octave now looks in the function path for a file
-    startup.m and executes any commands found there.  This change was
-    made to accommodate Matlab users.  Octave has it's own configuration
-    system based on the file .octaverc which is preferred.
-
- ** Octal ('\NNN') and hex ('\xNN') escape sequences in single quoted
-    strings are now interpreted by the function do_string_escapes().
-    The *printf family of functions now supports octal and hex escape
-    sequences in single-quoted strings for Matlab compatibility.
-
- ** Special octal and hex escape sequences for the pattern and
-    replacement strings in regular expressions are now interpreted for
-    Matlab compatibility.
-
-    octal: '\oNNN' or '\o{NNN}'
-    hex  : '\xNN'  or '\x{NN}'
-
- ** Unknown escape sequences in the replacement string for regexprep are
-    now substituted with their unescaped version and no warning is
-    emitted.  This change was made for Matlab compatibility.
-
-    Example: regexprep ('a', 'a', 'x\yz')
-             => 'xyz'
-
- ** mkfifo now interprets the MODE argument as an octal, not decimal,
-    integer.  This is consistent with the equivalent shell command.
-
- ** linspace now returns an empty matrix if the number of requested
-    points is 0 or a negative number.  This change was made to be
-    compatible with Matlab releases newer than 2011.  In addition,
-    Octave no longer supports matrix inputs for A or B.
-
- ** The cov function now returns the complex conjugate of the result
-    from previous versions of Octave.  This change was made for
-    compatibility with Matlab.
-
- ** condest now works with a normest1 compatible syntax.
-
- ** The griddata function no longer plots the interpolated mesh if no
-    output argument is requested, instead the vector or array of
-    interpolated values is always returned for Matlab compatibility.
-
- ** The new function "light" and the corresponding graphics object
-    provide light and shadow effects for patch and surface objects.
-
- ** The surfnorm function now returns unnormalized (magnitude != 1)
-    normal vectors for compatibility with Matlab.
-
- ** The normal vectors returned from isonormals have been reversed to
-    point towards smaller values for compatibility with Matlab.
-
- ** The quadl function now uses an absolute, rather than relative,
-    tolerance for Matlab compatibility.  The default tolerance is 1e-6
-    which may result in lower precision results than previous versions
-    of Octave which used eps as the relative tolerance.  The quadl
-    function has also been extended to return a second output with the
-    total number of function evaluations.
-
- ** The textscan function is now built-in and is much faster and much
-    more Matlab-compatible than the previous m-file version.
-
- ** Dialog boxes--errordlg, helpdlg, inputdlg, listdlg, msgbox,
-    questdlg, and warndlg--now exclusively use Qt for rendering.
-    Java based versions have been removed.
-
- ** The axes properties "TitleFontSizeMultiplier" and "TitleFontWeight"
-    are now implemented which control the default appearance of text
-    created with title().
-    The axes property "LabelFontSizeMultiplier" is now implemented
-    which controls the default appearance of text created with
-    xlabel(), ylabel(), or zlabel().
-
- ** The graphics property "box" for axes now defaults to "off".
-    To obtain equivalent plots to previous versions of Octave use
-      set (0, "DefaultAxesBox", "on");
-    in your .octaverc file.
-
- ** The graphics property "boxstyle" has been implemented.  The default
-    is "back" which draws only the back planes in a 3-D view.  If the
-    option is "full" then all planes are drawn.
-
- ** The graphics property "erasemode" has been hidden, and will
-    eventually be removed.  This property has also been removed
-    from Matlab, and was never implemented in Octave.
-
- ** The graphics property "graphicssmoothing" for figures now controls
-    whether anti-aliasing will be used for lines.  The default is "on".
-
- ** The value "zero" for the axes properties "xaxislocation" and
-    "yaxislocation" has been deprecated and will be removed from
-    Octave 5.  Use "origin" instead.
-
- ** The publish function allows easy publication of Octave script files
-    in HTML or other formats, including figures and output created by
-    this script.  It comes with its counterpart grabcode, which lets one
-    literally grab the HTML published code from a remote website, for
-    example.
-
- ** The value of the MEX variable TrapFlag now defaults to 0, which will
-    cause Octave to abort execution of a MEX file and return to the
-    prompt if an error is encountered in mexCallMATLAB.
-
- ** The MEX API now includes the function mexCallMATLABWithTrap.  This
-    function will not abort if an error occurs during mexCallMATLAB, but
-    instead will return execution to the MEX function for error
-    handling.
-
- ** The MEX API functions for input validation that begin with "mxIs"
-    (e.g., mxIsDouble, mxIsEmpty, etc.) now return type bool rather than
-    type int.
-
- ** The functions mxAssert and mxAssertS for checking assertions have
-    been added.  In order to avoid a performance penalty they are only
-    compiled in to debug versions of a MEX file, i.e., that are produced
-    when the '-g' option is given to mex or mkoctfile.
-
- ** Other new MEX API functions include mexEvalStringWithTrap,
-    mxIsScalar, mxCreateUninitNumericArray, mxCreateUninitNumericMatrix.
-
- ** Other new functions added in 4.2:
-
-      audioformats
-      camlight
-      condeig
-      deg2rad
-      dialog
-      evalc
-      hash
-      im2double
-      isocaps
-      lighting
-      localfunctions
-      material
-      normest1
-      ode23
-      ode45
-      odeget
-      odeplot
-      odeset
-      padecoef
-      profexport
-      psi
-      rad2deg
-      reducepatch
-      reducevolume
-      smooth3
-      uibuttongroup
+      findstr              | strfind
+      flipdim              | flip
+      isequalwithequalnans | isequaln
+      isstr                | ischar
+      setstr               | char
+      strmatch             | strncmp or strcmp
+      strread              | textscan
+      textread             | textscan
 
  ** Deprecated functions.
 
-    The following functions have been deprecated in Octave 4.2 and will
-    be removed from Octave 5 (or whatever version is the second major
-    release after 4.2):
+    The following functions have been deprecated in Octave 5.0 and will
+    be removed from Octave 7 (or whatever version is the second major
+    release after 5.0):
+
+      Function             | Replacement
+      ---------------------|------------------
+                           |
+
+ ** The following functions were deprecated in Octave 4.2 and have been
+    removed from Octave 5.0.
 
       Function             | Replacement
       ---------------------|------------------
@@ -970,381 +110,26 @@
       wavread              | audioread
       wavwrite             | audiowrite
 
- ** The following functions were deprecated in Octave 3.8 and have been
-    removed from Octave 4.2.
-
-      default_save_options    java_new
-      gen_doc_cache           java_unsigned_conversion
-      interp1q                javafields
-      isequalwithequalnans    javamethods
-      java_convert_matrix     re_read_readline_init_file
-      java_debug              read_readline_init_file
-      java_invoke             saving_history
-
- ** The global error_state variable in Octave's C++ API has been
-    deprecated and will be removed in a future version.  Now the error
-    and print_usage functions throw an exception
-    (octave::execution_exception) after displaying the error message.
-    This makes the error and print_usage functions in C++ work more like
-    the corresponding functions in the scripting language.
-
- ** The default error handlers in liboctave have been updated to use
-    exceptions.  After displaying an error message they no longer return
-    control to the calling program.  The error handler function can be
-    customized through the global variables
-    "current_liboctave_error_handler" and
-    "current_liboctave_error_with_id_handler".  If a programmer has
-    installed their own custom error handling routines when directly
-    linking with liboctave then these must be updated to throw an
-    exception and not return to the calling program.
-
- ** The system for common errors and warnings has been renamed from
-    gripe_XXX to either err_XXX if error is called or warn_XXX if
-    warning is called.  The gripe_XXX functions are deprecated and will
-    be removed in version 5.
-
- ** New configure option, --enable-address-sanitizer-flags, to build
-    Octave with memory allocator checks (similar to those in valgrind)
-    built in.
-
-Summary of important user-visible changes for version 4.0 (2015-05-23):
-----------------------------------------------------------------------
-
- ** A graphical user interface is now the default when running Octave
-    interactively.  The start-up option --no-gui will run the familiar
-    command line interface, and still allows use of the GUI dialogs and
-    qt plotting toolkit.  The option --no-gui-libs runs a minimalist
-    command line interface that does not link with the Qt libraries and
-    uses the fltk toolkit for plotting.
-
- ** Octave now uses OpenGL graphics with Qt widgets by default.  If
-    OpenGL libraries are not available when Octave is built, gnuplot is
-    used.  You may choose to use the fltk or gnuplot toolkit for
-    graphics by executing the command
-
-      graphics_toolkit ("fltk")
-        OR
-      graphics_toolkit ("gnuplot")
-
-    Adding such a command to your ~/.octaverc file will set the default
-    for each session.
-
- ** A new syntax for object oriented programming termed classdef has
-    been introduced.  See the manual for more extensive documentation of
-    the classdef interface.
-
-    New keywords:
-
-      classdef      endclassdef
-      enumeration   endenumeration
-      events        endevents
-      methods       endmethods
-      properties    endproperties
-
- ** New audio functions and classes:
-
-      audiodevinfo  audioread      sound
-      audioinfo     audiorecorder  soundsc
-      audioplayer   audiowrite
-
- ** Other new classes in Octave 4.0:
-
-      audioplayer    inputParser
-      audiorecorder
-
- ** Optional stricter Matlab compatibility for ranges, diagonal
-    matrices, and permutation matrices.
-
-    Octave has internal optimizations which use space-efficient storage
-    for the three data types above.  Three new functions have been added
-    which control whether the optimizations are used (default), or
-    whether the data types are stored as full matrices.
-
-    disable_range   disable_diagonal_matrix   disable_permutation_matrix
+ ** Deprecated graphics properties.
 
-    All three optimizations are disabled if Octave is started with the
-    --braindead command line option.
-
- ** The preference
-
-      do_braindead_shortcircuit_evaluation
-
-    is now enabled by default.
-
- ** The preference
-
-      allow_noninteger_range_as_index
-
-    is now enabled by default and the warning ID
-
-      Octave:noninteger-range-as-index
-
-    is now set to "on" by default instead of "error" by default and "on"
-    for --traditional.
-
- ** The "backtrace" warning option is now enabled by default.  This
-    change was made for Matlab compatibility.
-
- ** For compatibility with Matlab, the "ismatrix (x)" function now only
-    checks the dimension of "x".  The old behavior of "ismatrix" is
-    obtained by "isnumeric (x) || islogical (x) || ischar (x)".
-
- ** The nextpow2 function behavior has been changed for vector inputs.
-    Instead of computing `nextpow2 (length (x))', it will now compute
-    nextpow2 for each element of the input.  This change is Matlab
-    compatible, and also prevents bugs for "vectors" of length 1.
-
- ** polyeig now returns a row vector of eigenvalues rather than a matrix
-    with the eigenvalues on the diagonal.  This change was made for
-    Matlab compatibility.
-
- ** Interpolation function changes for Matlab compatibility
-
-    The interpolation method 'cubic' is now equivalent to 'pchip' for
-    interp1, interp2, and interp3.  Previously, 'cubic' was equivalent
-    to 'spline' for interp2.  This may produce different results as
-    'spline' has continuous 1st and 2nd derivatives while 'pchip' only
-    has a continuous 1st derivative.  The methods 'next' and 'previous'
-    have been added to interp1 for compatibility.
+    The following properties or allowed corresponding values have been
+    deprecated in Octave 5.0 and will be removed from Octave 7 (or whatever
+    version is the second major release after 5.0):
 
- ** The delaunay function has been extended to accept 3-D inputs for
-    Matlab compatibility.  The delaunay function no longer plots the
-    triangulation if no output argument is requested, instead, the
-    triangulation is always returned.  The delaunay3 function which
-    handles 3-D inputs has been deprecated in favor of delaunay.
-
- ** The trigonometric functions asin and acos return different phase
-    values from previous versions of Octave when the input is outside
-    the principal branch ([-1, 1]).  If the real portion of the input is
-    greater than 1 then the limit from below is taken.  If the real
-    portion is less than 1 then the limit from above is taken.  This
-    criteria is consistent with several other numerical analysis
-    software packages.
-
- ** The hyperbolic function acosh now returns values with a phase in the
-    range [-pi/2, +pi/2].  Previously Octave returned values in the
-    range [0, pi].  This is consistent with several other numerical
-    analysis software packages.
-
- ** strfind changes when using empty pattern ("") for Matlab
-    compatibility
-
-    strfind now returns an empty array when the pattern itself is empty.
-    In previous versions of Octave, strfind matched at every character
-    location when the pattern was empty.
-
-      NEW
-      strfind ("abc", "") => []
-      OLD
-      strfind ("abc", "") => [1, 2, 3, 4]
-
- ** Integer formats used in the printf family of functions now work for
-    64-bit integers and are more compatible with Matlab when printing
-    non-integer values.  Now instead of truncating, Octave will switch
-    the effective format to '%g' in the following circumstances:
-
-      * the value of an integer type (int8, uint32, etc.) value exceeds
-        the maximum for the format specifier.  For '%d', the limit is
-        intmax ('int64') and for '%u' it is intmax ('uint64').
-
-      * round(x) != x or the value is outside the range allowed by the
-        integer format specifier.
-
-    There is still one difference: Matlab switches to '%e' and Octave
-    switches to '%g'.
-
- ** The functions intersect, setdiff, setxor, and union now return a
-    column vector as output unless the input was a row vector.  This
-    change was made for Matlab compatibility.
+      Object               | Property                | Value
+      ---------------------|-------------------------|-------------------
+                           |                         |
 
- ** The inpolygon function now returns true for points that are within
-    the polygon OR on it's edge.  This change was made for Matlab
-    compatibility.
-
- ** The archive family of functions (bzip2, gzip, zip, tar) and their
-    unpacking routines (bunzip2, gunzip, unzip, untar, unpack) have been
-    recoded.  Excepting unpack, the default is now to place files in the
-    same directory as the archive (on unpack) or as the original files
-    (on archiving).
-
- ** Qt and FLTK graphics toolkits now support offscreen rendering on
-    Linux.  In other words, print will work even when the figure
-    visibility is "off".
-
- ** Z-order stacking issues with patches, grid lines, and line object
-    plot markers for on screen display and printing have all been
-    resolved.  For 2-D plots the axis grid lines can be placed on top of
-    the plot with set (gca, "layer", "top").
-
- ** The patch graphic object has been overhauled.  It now produces
-    visual results equivalent to Matlab even for esoteric combinations
-    of faces/vertices/cdata.
-
- ** The polar() plot function now draws a circular theta axis and radial
-    rho axis rather than using a rectangular x/y axis.
-
- ** linkprop has been completely re-coded for performance and Matlab
-    compatibility.  It now returns a linkprop object which must be
-    stored in a variable for as long as the graphic objects should
-    remain linked.  To unlink properties use 'clear hlink' where hlink
-    is the variable containing the linkprop object.
-
- ** isprime has been extended to operate on negative and complex inputs.
-
- ** xor has been extended to accept more than two arguments in which
-    case it performs cumulative XOR reduction.
-
- ** The following functions now support N-dimensional arrays:
-
-      fliplr   flipud   rot90   rectint
-
- ** The new warning ID "Octave:data-file-in-path" replaces the three
-    previous separate warning IDs "Octave:fopen-file-in-path",
-    "Octave:load-file-in-path", and "Octave:md5sum-file-in-path".
-
- ** The warning ID Octave:singular-matrix-div has been replaced by
-    Octave:nearly-singular-matrix and Octave:singular-matrix.
-
- ** The warning ID Octave:matlab-incompatible has been replaced by
-    Octave:language-extension to better reflect its meaning.
-
- ** The warning ID Octave:broadcast has been removed.  Instead automatic
-    broadcasting will throw an Octave:language-extension warning.  This
-    warning ID is used for broadcasting as well as other features not
-    available in Matlab.
-
- ** Other new functions added in 4.0:
-
-      annotation
-      bandwidth
-      cubehelix
-      dir_in_loadpath
-      flip
-      frame2im
-      get_home_directory
-      hgload
-      hgsave
-      ichol
-      ilu
-      im2frame
-      isbanded
-      isdiag
-      isstudent
-      istril
-      istriu
-      javachk
-      jit_failcnt
-      linkaxes
-      lscov
-      metaclass
-      numfields
-      open
-      ordschur
-      pan
-      qmr
-      rotate
-      rotate3d
-      sylvester
-      unsetenv
-      validateattributes
-      zoom
-
- ** inline() scheduled for eventual deprecation by Matlab
+ ** The following properties or allowed corresponding values were
+    deprecated in Octave 4.2 and have been removed from Octave 5.0:
 
-    Functions created through the use of inline are scheduled for
-    deprecation by Matlab.  When this occurs Octave will continue to
-    support inline functions for an indeterminate amount of time before
-    also removing support.  All new code should use anonymous functions
-    in place of inline functions.
-
- ** Deprecated functions.
-
-    The following functions have been deprecated in Octave 4.0 and will
-    be removed from Octave 4.4 (or whatever version is the second major
-    release after 4.0):
-
-      Function             | Replacement
-      ---------------------|------------------
-      bicubic              | interp2
-      delaunay3            | delaunay
-      dump_prefs           | individual preference get/set routines
-      find_dir_in_path     | dir_in_loadpath
-      finite               | isfinite
-      fmod                 | rem
-      fnmatch              | glob or regexp
-      gmap40               | ----
-      loadaudio            | audioread
-      luinc                | ilu or ichol
-      mouse_wheel_zoom     | mousewheelzoom axes property
-      nfields              | numfields
-      octave_tmp_file_name | tempname
-      playaudio            | audioplayer
-      saveaudio            | audiowrite
-      syl                  | sylvester
-      usage                | print_usage
-
-      allow_noninteger_range_as_index
-      do_braindead_shortcircuit_evaluation
-      setaudio
-
- ** The following functions were deprecated in Octave 3.8 and will be
-    removed from Octave 4.2 (or whatever version is the second major
-    release after 3.8):
-
-      default_save_options    java_new
-      gen_doc_cache           java_unsigned_conversion
-      interp1q                javafields
-      isequalwithequalnans    javamethods
-      java_convert_matrix     re_read_readline_init_file
-      java_debug              read_readline_init_file
-      java_invoke             saving_history
-
- ** The following functions were deprecated in Octave 3.6 and have been
-    removed from Octave 4.0.
-
-      cut                polyderiv
-      cor                shell_cmd
-      corrcoef           studentize
-      __error_text__     sylvester_matrix
-      error_text
-
- ** The following keywords were deprecated in Octave 3.8 and have been
-    removed from Octave 4.0
-
-      static
-
- ** The following configuration variables were deprecated in Octave 3.8
-    and have been removed from Octave 4.0
-
-      CC_VERSION  (now GCC_VERSION)
-      CXX_VERSION (now GXX_VERSION)
-
- ** The internal function atan2 of the sparse matrix class has been
-    deprecated in Octave 4.0 and will be removed from Octave 4.4 (or
-    whatever version is the second major release after 4.0).  Use the
-    Fatan2 function with sparse inputs as a replacement.
-
- ** The internal class Octave_map was deprecated in Octave 3.8 and has
-    been removed from Octave 4.0.  Replacement classes are octave_map
-    (struct array) or octave_scalar_map for a single structure.
-
- ** Octave now has OpenMP enabled by default if the system provides a
-    working OpenMP implementation.  This allows oct-file modules to take
-    advantage of OpenMP if desired.  This can be disabled when building
-    Octave with the configure option --disable-openmp.
-
- ** Octave now automatically truncates intermediate calculations done
-    with floating point values to 64 bits.  Some hardware math
-    co-processors, such as the x87, maintain extra precision, but this
-    leads to disagreements in calculations when compared to reference
-    implementations in software using the IEEE standard for double
-    precision.  There was no measurable performance impact to this
-    change, but it may be disabled with the configure option
-    --disable-float-truncate.  MinGW and Cygwin platforms, as well as
-    GCC compilers >= 5.0 require this feature.  Non-x87 hardware, or
-    hardware using SSE options exclusively, can disable float truncation
-    if desired.
+      Object               | Property                | Value
+      ---------------------|-------------------------|-------------------
+      axes                 | xaxislocation           | "zero"
+                           | yaxislocation           | "zero"
+      patch                | normalmode              |
+      surface              | normalmode              |
 
 ---------------------------------------------------------
 
-See NEWS.3 for old news.
+See NEWS.4 for old news.
--- a/bootstrap.conf	Fri Aug 10 09:08:33 2018 +0200
+++ b/bootstrap.conf	Fri Aug 10 09:09:51 2018 +0200
@@ -59,6 +59,7 @@
   mkdir
   mkfifo
   mkostemp
+  mkostemps
   mktime
   nanosleep
   nproc
@@ -91,9 +92,26 @@
   tempname
   tmpfile
   uname
+  unicase/u8-tolower
+  unicase/u8-toupper
   uniconv/u8-conv-from-enc
   uniconv/u8-conv-to-enc
+  unictype/ctype-alnum
+  unictype/ctype-alpha
+  unictype/ctype-blank
+  unictype/ctype-cntrl
+  unictype/ctype-digit
+  unictype/ctype-graph
+  unictype/ctype-lower
+  unictype/ctype-print
+  unictype/ctype-punct
+  unictype/ctype-space
+  unictype/ctype-upper
+  unictype/ctype-xdigit
   unistd
+  unistr/u8-strmblen
+  unistr/u8-strmbtouc
+  unistr/u8-to-u32
   unlink
   unsetenv
   vasprintf
--- a/build-aux/mk-opts.pl	Fri Aug 10 09:08:33 2018 +0200
+++ b/build-aux/mk-opts.pl	Fri Aug 10 09:09:51 2018 +0200
@@ -512,7 +512,8 @@
 // this file.
 
 #include <iomanip>
-#include <iostream>
+#include <ostream>
+#include <sstream>
 
 #include "$header"
 
@@ -745,7 +746,7 @@
     {
       $iftok = "else if" if ($i > 0);
 
-      print "  $iftok (keyword_almost_match (list[$i].kw_tok, list[$i].min_len,
+      print "  $iftok (octave::keyword_almost_match (list[$i].kw_tok, list[$i].min_len,
            keyword, list[$i].min_toks_to_match, MAX_TOKENS))
     {\n";
 
@@ -814,7 +815,7 @@
     {
       $iftok = "else if" if ($i > 0);
 
-      print "  $iftok (keyword_almost_match (list[$i].kw_tok, list[$i].min_len,
+      print "  $iftok (octave::keyword_almost_match (list[$i].kw_tok, list[$i].min_len,
            keyword, list[$i].min_toks_to_match, MAX_TOKENS))
     {\n";
 
--- a/build-aux/module.mk	Fri Aug 10 09:08:33 2018 +0200
+++ b/build-aux/module.mk	Fri Aug 10 09:09:51 2018 +0200
@@ -14,14 +14,12 @@
   %reldir%/stl_algo.h-fixed \
   %reldir%/subst-config-vals.in.sh \
   %reldir%/subst-cross-config-vals.in.sh \
-  %reldir%/subst-default-vals.in.sh \
   %reldir%/subst-script-vals.in.sh \
   %reldir%/update-bug-status.sh
 
 GEN_CONFIG_SHELL += \
   %reldir%/subst-config-vals.sh \
   %reldir%/subst-cross-config-vals.sh \
-  %reldir%/subst-default-vals.sh \
   %reldir%/subst-script-vals.sh
 
 $(GEN_CONFIG_SHELL) : %.sh : %.in.sh config.status
--- a/build-aux/subst-config-vals.in.sh	Fri Aug 10 09:08:33 2018 +0200
+++ b/build-aux/subst-config-vals.in.sh	Fri Aug 10 09:09:51 2018 +0200
@@ -20,15 +20,55 @@
 
 : ${SED=@SED@}
 
+canonical_host_type="@canonical_host_type@"
+DEFAULT_PAGER="@DEFAULT_PAGER@"
+EXEEXT="@EXEEXT@"
+man1ext="@man1ext@"
+api_version="@OCTAVE_API_VERSION@"
+OCTAVE_RELEASE=""
+version="@PACKAGE_VERSION@"
+
 prefix="@prefix@"
 exec_prefix="@exec_prefix@"
 
+archlibdir=`echo "@archlibdir@" | sed "s|^${exec_prefix}/||"`
 bindir=`echo "@bindir@" | sed "s|^${exec_prefix}/||"`
 libdir=`echo "@libdir@" | sed "s|^${exec_prefix}/||"`
+libexecdir=`echo "@libexecdir@" | sed "s|^${exec_prefix}/||"`
+localapiarchlibdir=`echo "@localapiarchlibdir@" | sed "s|^${exec_prefix}/||"`
+localapioctfiledir=`echo "@localapioctfiledir@" | sed "s|^${exec_prefix}/||"`
+localarchlibdir=`echo "@localarchlibdir@" | sed "s|^${exec_prefix}/||"`
+localoctfiledir=`echo "@localoctfiledir@" | sed "s|^${exec_prefix}/||"`
+localverarchlibdir=`echo "@localverarchlibdir@" | sed "s|^${exec_prefix}/||"`
+localveroctfiledir=`echo "@localveroctfiledir@" | sed "s|^${exec_prefix}/||"`
+octfiledir=`echo "@octfiledir@" | sed "s|^${exec_prefix}/||"`
 octlibdir=`echo "@octlibdir@" | sed "s|^${exec_prefix}/||"`
 
+datadir=`echo "@datadir@" | sed "s|^${prefix}/||"`
+datarootdir=`echo "@datarootdir@" | sed "s|^${prefix}/||"`
+doc_cache_file=`echo "@doc_cache_file@" | sed "s|^${prefix}/||"`
+exec_prefix=`echo "@exec_prefix@" | sed "s|^${prefix}/||"`
+fcnfiledir=`echo "@fcnfiledir@" | sed "s|^${prefix}/||"`
+imagedir=`echo "@imagedir@" | sed "s|^${prefix}/||"`
 includedir=`echo "@includedir@" | sed "s|^${prefix}/||"`
+infodir=`echo "@infodir@" | sed "s|^${prefix}/||"`
+infofile=`echo "@infofile@" | sed "s|^${prefix}/||"`
+localapifcnfiledir=`echo "@localapifcnfiledir@" | sed "s|^${prefix}/||"`
+localfcnfiledir=`echo "@localfcnfiledir@" | sed "s|^${prefix}/||"`
+localstartupfiledir=`echo "@localstartupfiledir@" | sed "s|^${prefix}/||"`
+localapiarchlibdir=`echo "@localapiarchlibdir@" | sed "s|^${prefix}/||"`
+localverfcnfiledir=`echo "@localverfcnfiledir@" | sed "s|^${prefix}/||"`
+man1dir=`echo "@man1dir@" | sed "s|^${prefix}/||"`
+mandir=`echo "@mandir@" | sed "s|^${prefix}/||"`
+octdatadir=`echo "@octdatadir@" | sed "s|^${prefix}/||"`
+octdocdir=`echo "@octdocdir@" | sed "s|^${prefix}/||"`
+octetcdir=`echo "@octetcdir@" | sed "s|^${prefix}/||"`
+octfontsdir=`echo "@octfontsdir@" | sed "s|^${prefix}/||"`
 octincludedir=`echo "@octincludedir@" | sed "s|^${prefix}/||"`
+octlocaledir=`echo "@octlocaledir@" | sed "s|^${prefix}/||"`
+octtestsdir=`echo "@octtestsdir@" | sed "s|^${prefix}/||"`
+startupfiledir=`echo "@startupfiledir@" | sed "s|^${prefix}/||"`
+texi_macros_file=`echo "@texi_macros_file@" | sed "s|^${prefix}/||"`
 
 srcdir="@srcdir@"
 top_srcdir="@top_srcdir@"
@@ -196,7 +236,11 @@
 $SED \
   -e "s|%NO_EDIT_WARNING%|DO NOT EDIT!  Generated automatically by subst-config-vals.|" \
   -e "s|%NO_OCT_FILE_STRIP%|${NO_OCT_FILE_STRIP}|" \
+  -e "s|%OCTAVE_API_VERSION%|\"${api_version}\"|" \
+  -e "s|%OCTAVE_ARCHLIBDIR%|\"${archlibdir}\"|" \
   -e "s|%OCTAVE_BINDIR%|\"${bindir}\"|" \
+  -e "s|%OCTAVE_BINDIR%|\"${bindir}\"|" \
+  -e "s|%OCTAVE_CANONICAL_HOST_TYPE%|\"${canonical_host_type}\"|" \
   -e "s|%OCTAVE_CONF_AMD_CPPFLAGS%|\"${AMD_CPPFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_AMD_LDFLAGS%|\"${AMD_LDFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_AMD_LIBS%|\"${AMD_LIBS}\"|" \
@@ -235,25 +279,23 @@
   -e "s|%OCTAVE_CONF_CXXPICFLAG%|\"${CXXPICFLAG}\"|" \
   -e "s|%OCTAVE_CONF_DEFAULT_PAGER%|\"${DEFAULT_PAGER}\"|" \
   -e "s|%OCTAVE_CONF_DEFS%|\"${DEFS}\"|" \
+  -e "s|%OCTAVE_CONF_DEPEND_EXTRA_SED_PATTERN%|\"${DEPEND_EXTRA_SED_PATTERN}\"|" \
   -e "s|%OCTAVE_CONF_DEPEND_FLAGS%|\"${DEPEND_FLAGS}\"|" \
-  -e "s|%OCTAVE_CONF_DEPEND_EXTRA_SED_PATTERN%|\"${DEPEND_EXTRA_SED_PATTERN}\"|" \
   -e "s|%OCTAVE_CONF_DL_LD%|\"${DL_LD}\"|" \
   -e "s|%OCTAVE_CONF_DL_LDFLAGS%|\"${DL_LDFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_DL_LIBS%|\"${DL_LIBS}\"|" \
   -e "s|%OCTAVE_CONF_EXEC_PREFIX%|\"${exec_prefix}\"|" \
   -e "s|%OCTAVE_CONF_EXEEXT%|\"${EXEEXT}\"|" \
-  -e "s|%OCTAVE_CONF_GCC_VERSION%|\"${GCC_VERSION}\"|" \
-  -e "s|%OCTAVE_CONF_GXX_VERSION%|\"${GXX_VERSION}\"|" \
   -e "s|%OCTAVE_CONF_F77%|\"${F77}\"|" \
   -e "s|%OCTAVE_CONF_F77_FLOAT_STORE_FLAG%|\"${F77_FLOAT_STORE_FLAG}\"|" \
   -e "s|%OCTAVE_CONF_F77_INTEGER_8_FLAG%|\"${F77_INTEGER_8_FLAG}\"|" \
   -e "s|%OCTAVE_CONF_FFLAGS%|\"${FFLAGS}\"|" \
+  -e "s|%OCTAVE_CONF_FFTW3F_CPPFLAGS%|\"${FFTW3F_CPPFLAGS}\"|" \
+  -e "s|%OCTAVE_CONF_FFTW3F_LDFLAGS%|\"${FFTW3F_LDFLAGS}\"|" \
+  -e "s|%OCTAVE_CONF_FFTW3F_LIBS%|\"${FFTW3F_LIBS}\"|" \
   -e "s|%OCTAVE_CONF_FFTW3_CPPFLAGS%|\"${FFTW3_CPPFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_FFTW3_LDFLAGS%|\"${FFTW3_LDFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_FFTW3_LIBS%|\"${FFTW3_LIBS}\"|" \
-  -e "s|%OCTAVE_CONF_FFTW3F_CPPFLAGS%|\"${FFTW3F_CPPFLAGS}\"|" \
-  -e "s|%OCTAVE_CONF_FFTW3F_LDFLAGS%|\"${FFTW3F_LDFLAGS}\"|" \
-  -e "s|%OCTAVE_CONF_FFTW3F_LIBS%|\"${FFTW3F_LIBS}\"|" \
   -e "s|%OCTAVE_CONF_FLIBS%|\"${FLIBS}\"|" \
   -e "s|%OCTAVE_CONF_FLTK_CPPFLAGS%|\"${FLTK_CPPFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_FLTK_LDFLAGS%|\"${FLTK_LDFLAGS}\"|" \
@@ -261,22 +303,25 @@
   -e "s|%OCTAVE_CONF_FONTCONFIG_CPPFLAGS%|\"${FONTCONFIG_CPPFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_FONTCONFIG_LIBS%|\"${FONTCONFIG_LIBS}\"|" \
   -e "s|%OCTAVE_CONF_FPICFLAG%|\"${FPICFLAG}\"|" \
-  -e "s|%OCTAVE_CONF_FT2_CPPFLAGS%|\"${FT2_CPPFLAGS}\"|" \
+  -e "s|%OCTAVE_CONF_FT2_CPPFLAGS%|\"${FT2_CPPFLAGS}\"|" | \
+  $SED \
   -e "s|%OCTAVE_CONF_FT2_LIBS%|\"${FT2_LIBS}\"|" \
+  -e "s|%OCTAVE_CONF_GCC_VERSION%|\"${GCC_VERSION}\"|" \
   -e "s|%OCTAVE_CONF_GLPK_CPPFLAGS%|\"${GLPK_CPPFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_GLPK_LDFLAGS%|\"${GLPK_LDFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_GLPK_LIBS%|\"${GLPK_LIBS}\"|" \
   -e "s|%OCTAVE_CONF_GNUPLOT%|\"${GNUPLOT}\"|" \
-  -e "s|%OCTAVE_CONF_HDF5_CPPFLAGS%|\"${HDF5_CPPFLAGS}\"|" | \
-  $SED -e "s|%OCTAVE_CONF_HDF5_LDFLAGS%|\"${HDF5_LDFLAGS}\"|" \
+  -e "s|%OCTAVE_CONF_GXX_VERSION%|\"${GXX_VERSION}\"|" \
+  -e "s|%OCTAVE_CONF_HDF5_CPPFLAGS%|\"${HDF5_CPPFLAGS}\"|" \
+  -e "s|%OCTAVE_CONF_HDF5_LDFLAGS%|\"${HDF5_LDFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_HDF5_LIBS%|\"${HDF5_LIBS}\"|" \
   -e "s|%OCTAVE_CONF_INCLUDEDIR%|\"${includedir}\"|" \
   -e "s|%OCTAVE_CONF_KLU_CPPFLAGS%|\"${KLU_CPPFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_KLU_LDFLAGS%|\"${KLU_LDFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_KLU_LIBS%|\"${KLU_LIBS}\"|" \
   -e "s|%OCTAVE_CONF_LAPACK_LIBS%|\"${LAPACK_LIBS}\"|" \
+  -e "s|%OCTAVE_CONF_LDFLAGS%|\"${LDFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_LD_CXX%|\"${LD_CXX}\"|" \
-  -e "s|%OCTAVE_CONF_LDFLAGS%|\"${LDFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_LD_STATIC_FLAG%|\"${LD_STATIC_FLAG}\"|" \
   -e "s|%OCTAVE_CONF_LEX%|\"${LEX}\"|" \
   -e "s|%OCTAVE_CONF_LEXLIB%|\"${LEXLIB}\"|" \
@@ -299,9 +344,9 @@
   -e "s|%OCTAVE_CONF_MKOCTFILE_DL_LDFLAGS%|\"${MKOCTFILE_DL_LDFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_MKOCTFILE_F77%|\"${MKOCTFILE_F77}\"|" \
   -e "s|%OCTAVE_CONF_MKOCTFILE_LD_CXX%|\"${MKOCTFILE_LD_CXX}\"|" \
-  -e "s|%OCTAVE_CONF_MKOCTFILE_RANLIB%|\"${MKOCTFILE_RANLIB}\"|" \
   -e "s|%OCTAVE_CONF_MKOCTFILE_OCTAVE_LINK_DEPS%|\"${MKOCTFILE_OCTAVE_LINK_DEPS}\"|" \
   -e "s|%OCTAVE_CONF_MKOCTFILE_OCT_LINK_DEPS%|\"${MKOCTFILE_OCT_LINK_DEPS}\"|" \
+  -e "s|%OCTAVE_CONF_MKOCTFILE_RANLIB%|\"${MKOCTFILE_RANLIB}\"|" \
   -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}\"|" \
@@ -329,7 +374,8 @@
   -e "s|%OCTAVE_CONF_QT_LIBS%|\"${QT_LIBS}\"|" \
   -e "s|%OCTAVE_CONF_RANLIB%|\"${RANLIB}\"|" \
   -e "s|%OCTAVE_CONF_RDYNAMIC_FLAG%|\"${RDYNAMIC_FLAG}\"|" \
-  -e "s|%OCTAVE_CONF_READLINE_LIBS%|\"${READLINE_LIBS}\"|" \
+  -e "s|%OCTAVE_CONF_READLINE_LIBS%|\"${READLINE_LIBS}\"|" | \
+  $SED \
   -e "s|%OCTAVE_CONF_SED%|\"${SED}\"|" \
   -e "s|%OCTAVE_CONF_SHARED_LIBS%|\"${SHARED_LIBS}\"|" \
   -e "s|%OCTAVE_CONF_SH_LD%|\"${SH_LD}\"|" \
@@ -358,4 +404,45 @@
   -e "s|%OCTAVE_CONF_Z_CPPFLAGS%|\"${Z_CPPFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_Z_LDFLAGS%|\"${Z_LDFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_Z_LIBS%|\"${Z_LIBS}\"|" \
-  -e "s|%OCTAVE_CONF_config_opts%|\"${config_opts}\"|"
+  -e "s|%OCTAVE_CONF_config_opts%|\"${config_opts}\"|" \
+  -e "s|%OCTAVE_DATADIR%|\"${datadir}\"|" \
+  -e "s|%OCTAVE_DATAROOTDIR%|\"${datarootdir}\"|" \
+  -e "s|%OCTAVE_DEFAULT_PAGER%|\"${DEFAULT_PAGER}\"|" \
+  -e "s|%OCTAVE_DOCDIR%|\"${docdir}\"|" \
+  -e "s|%OCTAVE_DOC_CACHE_FILE%|\"${doc_cache_file}\"|" \
+  -e "s|%OCTAVE_EXEC_PREFIX%|\"${exec_prefix}\"|" \
+  -e "s|%OCTAVE_EXEEXT%|\"${EXEEXT}\"|" \
+  -e "s|%OCTAVE_FCNFILEDIR%|\"${fcnfiledir}\"|" \
+  -e "s|%OCTAVE_IMAGEDIR%|\"${imagedir}\"|" \
+  -e "s|%OCTAVE_INCLUDEDIR%|\"${includedir}\"|" \
+  -e "s|%OCTAVE_INFODIR%|\"${infodir}\"|" \
+  -e "s|%OCTAVE_INFOFILE%|\"${infofile}\"|" \
+  -e "s|%OCTAVE_LIBDIR%|\"${libdir}\"|" \
+  -e "s|%OCTAVE_LIBEXECDIR%|\"${libexecdir}\"|" \
+  -e "s|%OCTAVE_LOCALAPIARCHLIBDIR%|\"${localapiarchlibdir}\"|" \
+  -e "s|%OCTAVE_LOCALAPIFCNFILEDIR%|\"${localapifcnfiledir}\"|" \
+  -e "s|%OCTAVE_LOCALAPIOCTFILEDIR%|\"${localapioctfiledir}\"|" \
+  -e "s|%OCTAVE_LOCALARCHLIBDIR%|\"${localarchlibdir}\"|" \
+  -e "s|%OCTAVE_LOCALFCNFILEDIR%|\"${localfcnfiledir}\"|" \
+  -e "s|%OCTAVE_LOCALOCTFILEDIR%|\"${localoctfiledir}\"|" \
+  -e "s|%OCTAVE_LOCALSTARTUPFILEDIR%|\"${localstartupfiledir}\"|" \
+  -e "s|%OCTAVE_LOCALVERARCHLIBDIR%|\"${localverarchlibdir}\"|" \
+  -e "s|%OCTAVE_LOCALVERFCNFILEDIR%|\"${localverfcnfiledir}\"|" \
+  -e "s|%OCTAVE_LOCALVEROCTFILEDIR%|\"${localveroctfiledir}\"|" \
+  -e "s|%OCTAVE_MAN1DIR%|\"${man1dir}\"|" \
+  -e "s|%OCTAVE_MAN1EXT%|\"${man1ext}\"|" \
+  -e "s|%OCTAVE_MANDIR%|\"${mandir}\"|" \
+  -e "s|%OCTAVE_OCTDATADIR%|\"${octdatadir}\"|" \
+  -e "s|%OCTAVE_OCTDOCDIR%|\"${octdocdir}\"|" \
+  -e "s|%OCTAVE_OCTETCDIR%|\"${octetcdir}\"|" \
+  -e "s|%OCTAVE_OCTFILEDIR%|\"${octfiledir}\"|" \
+  -e "s|%OCTAVE_OCTFONTSDIR%|\"${octfontsdir}\"|" \
+  -e "s|%OCTAVE_OCTINCLUDEDIR%|\"${octincludedir}\"|" \
+  -e "s|%OCTAVE_OCTLIBDIR%|\"${octlibdir}\"|" \
+  -e "s|%OCTAVE_OCTLOCALEDIR%|\"${octlocaledir}\"|" \
+  -e "s|%OCTAVE_OCTTESTSDIR%|\"${octtestsdir}\"|" \
+  -e "s|%OCTAVE_PREFIX%|\"${prefix}\"|" \
+  -e "s|%OCTAVE_RELEASE%|\"${OCTAVE_RELEASE}\"|" \
+  -e "s|%OCTAVE_STARTUPFILEDIR%|\"${startupfiledir}\"|" \
+  -e "s|%OCTAVE_TEXI_MACROS_FILE%|\"${texi_macros_file}\"|" \
+  -e "s|%OCTAVE_VERSION%|\"${version}\"|"
--- a/build-aux/subst-cross-config-vals.in.sh	Fri Aug 10 09:08:33 2018 +0200
+++ b/build-aux/subst-cross-config-vals.in.sh	Fri Aug 10 09:09:51 2018 +0200
@@ -32,15 +32,55 @@
 ##   OCTAVE_CONF_MKOCTFILE_LD_CXX
 ##   OCTAVE_CONF_MKOCTFILE_RANLIB
 
+canonical_host_type="@canonical_host_type@"
+DEFAULT_PAGER="@DEFAULT_PAGER@"
+EXEEXT="@EXEEXT@"
+man1ext="@man1ext@"
+api_version="@OCTAVE_API_VERSION@"
+OCTAVE_RELEASE=""
+version="@PACKAGE_VERSION@"
+
 prefix="@prefix@"
 exec_prefix="@exec_prefix@"
 
+archlibdir=`echo "@archlibdir@" | sed "s|^${exec_prefix}/||"`
 bindir=`echo "@bindir@" | sed "s|^${exec_prefix}/||"`
 libdir=`echo "@libdir@" | sed "s|^${exec_prefix}/||"`
+libexecdir=`echo "@libexecdir@" | sed "s|^${exec_prefix}/||"`
+localapiarchlibdir=`echo "@localapiarchlibdir@" | sed "s|^${exec_prefix}/||"`
+localapioctfiledir=`echo "@localapioctfiledir@" | sed "s|^${exec_prefix}/||"`
+localarchlibdir=`echo "@localarchlibdir@" | sed "s|^${exec_prefix}/||"`
+localoctfiledir=`echo "@localoctfiledir@" | sed "s|^${exec_prefix}/||"`
+localverarchlibdir=`echo "@localverarchlibdir@" | sed "s|^${exec_prefix}/||"`
+localveroctfiledir=`echo "@localveroctfiledir@" | sed "s|^${exec_prefix}/||"`
+octfiledir=`echo "@octfiledir@" | sed "s|^${exec_prefix}/||"`
 octlibdir=`echo "@octlibdir@" | sed "s|^${exec_prefix}/||"`
 
+datadir=`echo "@datadir@" | sed "s|^${prefix}/||"`
+datarootdir=`echo "@datarootdir@" | sed "s|^${prefix}/||"`
+doc_cache_file=`echo "@doc_cache_file@" | sed "s|^${prefix}/||"`
+exec_prefix=`echo "@exec_prefix@" | sed "s|^${prefix}/||"`
+fcnfiledir=`echo "@fcnfiledir@" | sed "s|^${prefix}/||"`
+imagedir=`echo "@imagedir@" | sed "s|^${prefix}/||"`
 includedir=`echo "@includedir@" | sed "s|^${prefix}/||"`
+infodir=`echo "@infodir@" | sed "s|^${prefix}/||"`
+infofile=`echo "@infofile@" | sed "s|^${prefix}/||"`
+localapifcnfiledir=`echo "@localapifcnfiledir@" | sed "s|^${prefix}/||"`
+localfcnfiledir=`echo "@localfcnfiledir@" | sed "s|^${prefix}/||"`
+localstartupfiledir=`echo "@localstartupfiledir@" | sed "s|^${prefix}/||"`
+localapiarchlibdir=`echo "@localapiarchlibdir@" | sed "s|^${prefix}/||"`
+localverfcnfiledir=`echo "@localverfcnfiledir@" | sed "s|^${prefix}/||"`
+man1dir=`echo "@man1dir@" | sed "s|^${prefix}/||"`
+mandir=`echo "@mandir@" | sed "s|^${prefix}/||"`
+octdatadir=`echo "@octdatadir@" | sed "s|^${prefix}/||"`
+octdocdir=`echo "@octdocdir@" | sed "s|^${prefix}/||"`
+octetcdir=`echo "@octetcdir@" | sed "s|^${prefix}/||"`
+octfontsdir=`echo "@octfontsdir@" | sed "s|^${prefix}/||"`
 octincludedir=`echo "@octincludedir@" | sed "s|^${prefix}/||"`
+octlocaledir=`echo "@octlocaledir@" | sed "s|^${prefix}/||"`
+octtestsdir=`echo "@octtestsdir@" | sed "s|^${prefix}/||"`
+startupfiledir=`echo "@startupfiledir@" | sed "s|^${prefix}/||"`
+texi_macros_file=`echo "@texi_macros_file@" | sed "s|^${prefix}/||"`
 
 srcdir="@srcdir@"
 top_srcdir="@top_srcdir@"
@@ -198,9 +238,13 @@
 config_opts="@config_opts@"
 
 $SED \
-  -e "s|%NO_EDIT_WARNING%|DO NOT EDIT!  Generated automatically by subst-config-vals.|" \
+  -e "s|%NO_EDIT_WARNING%|DO NOT EDIT!  Generated automatically by subst-cross-config-vals.|" \
   -e "s|%NO_OCT_FILE_STRIP%|${NO_OCT_FILE_STRIP}|" \
+  -e "s|%OCTAVE_API_VERSION%|\"${api_version}\"|" \
+  -e "s|%OCTAVE_ARCHLIBDIR%|\"${archlibdir}\"|" \
   -e "s|%OCTAVE_BINDIR%|\"${bindir}\"|" \
+  -e "s|%OCTAVE_BINDIR%|\"${bindir}\"|" \
+  -e "s|%OCTAVE_CANONICAL_HOST_TYPE%|\"${canonical_host_type}\"|" \
   -e "s|%OCTAVE_CONF_AMD_CPPFLAGS%|\"${AMD_CPPFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_AMD_LDFLAGS%|\"${AMD_LDFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_AMD_LIBS%|\"${AMD_LIBS}\"|" \
@@ -239,25 +283,23 @@
   -e "s|%OCTAVE_CONF_CXXPICFLAG%|\"${CXXPICFLAG}\"|" \
   -e "s|%OCTAVE_CONF_DEFAULT_PAGER%|\"${DEFAULT_PAGER}\"|" \
   -e "s|%OCTAVE_CONF_DEFS%|\"${DEFS}\"|" \
+  -e "s|%OCTAVE_CONF_DEPEND_EXTRA_SED_PATTERN%|\"${DEPEND_EXTRA_SED_PATTERN}\"|" \
   -e "s|%OCTAVE_CONF_DEPEND_FLAGS%|\"${DEPEND_FLAGS}\"|" \
-  -e "s|%OCTAVE_CONF_DEPEND_EXTRA_SED_PATTERN%|\"${DEPEND_EXTRA_SED_PATTERN}\"|" \
   -e "s|%OCTAVE_CONF_DL_LD%|\"${DL_LD}\"|" \
   -e "s|%OCTAVE_CONF_DL_LDFLAGS%|\"${DL_LDFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_DL_LIBS%|\"${DL_LIBS}\"|" \
   -e "s|%OCTAVE_CONF_EXEC_PREFIX%|\"${exec_prefix}\"|" \
   -e "s|%OCTAVE_CONF_EXEEXT%|\"${EXEEXT}\"|" \
-  -e "s|%OCTAVE_CONF_GCC_VERSION%|\"${GCC_VERSION}\"|" \
-  -e "s|%OCTAVE_CONF_GXX_VERSION%|\"${GXX_VERSION}\"|" \
   -e "s|%OCTAVE_CONF_F77%|\"${F77}\"|" \
   -e "s|%OCTAVE_CONF_F77_FLOAT_STORE_FLAG%|\"${F77_FLOAT_STORE_FLAG}\"|" \
   -e "s|%OCTAVE_CONF_F77_INTEGER_8_FLAG%|\"${F77_INTEGER_8_FLAG}\"|" \
   -e "s|%OCTAVE_CONF_FFLAGS%|\"${FFLAGS}\"|" \
+  -e "s|%OCTAVE_CONF_FFTW3F_CPPFLAGS%|\"${FFTW3F_CPPFLAGS}\"|" \
+  -e "s|%OCTAVE_CONF_FFTW3F_LDFLAGS%|\"${FFTW3F_LDFLAGS}\"|" \
+  -e "s|%OCTAVE_CONF_FFTW3F_LIBS%|\"${FFTW3F_LIBS}\"|" \
   -e "s|%OCTAVE_CONF_FFTW3_CPPFLAGS%|\"${FFTW3_CPPFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_FFTW3_LDFLAGS%|\"${FFTW3_LDFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_FFTW3_LIBS%|\"${FFTW3_LIBS}\"|" \
-  -e "s|%OCTAVE_CONF_FFTW3F_CPPFLAGS%|\"${FFTW3F_CPPFLAGS}\"|" \
-  -e "s|%OCTAVE_CONF_FFTW3F_LDFLAGS%|\"${FFTW3F_LDFLAGS}\"|" \
-  -e "s|%OCTAVE_CONF_FFTW3F_LIBS%|\"${FFTW3F_LIBS}\"|" \
   -e "s|%OCTAVE_CONF_FLIBS%|\"${FLIBS}\"|" \
   -e "s|%OCTAVE_CONF_FLTK_CPPFLAGS%|\"${FLTK_CPPFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_FLTK_LDFLAGS%|\"${FLTK_LDFLAGS}\"|" \
@@ -265,22 +307,25 @@
   -e "s|%OCTAVE_CONF_FONTCONFIG_CPPFLAGS%|\"${FONTCONFIG_CPPFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_FONTCONFIG_LIBS%|\"${FONTCONFIG_LIBS}\"|" \
   -e "s|%OCTAVE_CONF_FPICFLAG%|\"${FPICFLAG}\"|" \
-  -e "s|%OCTAVE_CONF_FT2_CPPFLAGS%|\"${FT2_CPPFLAGS}\"|" \
+  -e "s|%OCTAVE_CONF_FT2_CPPFLAGS%|\"${FT2_CPPFLAGS}\"|" | \
+  $SED \
   -e "s|%OCTAVE_CONF_FT2_LIBS%|\"${FT2_LIBS}\"|" \
+  -e "s|%OCTAVE_CONF_GCC_VERSION%|\"${GCC_VERSION}\"|" \
   -e "s|%OCTAVE_CONF_GLPK_CPPFLAGS%|\"${GLPK_CPPFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_GLPK_LDFLAGS%|\"${GLPK_LDFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_GLPK_LIBS%|\"${GLPK_LIBS}\"|" \
   -e "s|%OCTAVE_CONF_GNUPLOT%|\"${GNUPLOT}\"|" \
-  -e "s|%OCTAVE_CONF_HDF5_CPPFLAGS%|\"${HDF5_CPPFLAGS}\"|" | \
-  $SED -e "s|%OCTAVE_CONF_HDF5_LDFLAGS%|\"${HDF5_LDFLAGS}\"|" \
+  -e "s|%OCTAVE_CONF_GXX_VERSION%|\"${GXX_VERSION}\"|" \
+  -e "s|%OCTAVE_CONF_HDF5_CPPFLAGS%|\"${HDF5_CPPFLAGS}\"|" \
+  -e "s|%OCTAVE_CONF_HDF5_LDFLAGS%|\"${HDF5_LDFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_HDF5_LIBS%|\"${HDF5_LIBS}\"|" \
   -e "s|%OCTAVE_CONF_INCLUDEDIR%|\"${includedir}\"|" \
   -e "s|%OCTAVE_CONF_KLU_CPPFLAGS%|\"${KLU_CPPFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_KLU_LDFLAGS%|\"${KLU_LDFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_KLU_LIBS%|\"${KLU_LIBS}\"|" \
   -e "s|%OCTAVE_CONF_LAPACK_LIBS%|\"${LAPACK_LIBS}\"|" \
+  -e "s|%OCTAVE_CONF_LDFLAGS%|\"${LDFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_LD_CXX%|\"${LD_CXX}\"|" \
-  -e "s|%OCTAVE_CONF_LDFLAGS%|\"${LDFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_LD_STATIC_FLAG%|\"${LD_STATIC_FLAG}\"|" \
   -e "s|%OCTAVE_CONF_LEX%|\"${LEX}\"|" \
   -e "s|%OCTAVE_CONF_LEXLIB%|\"${LEXLIB}\"|" \
@@ -303,9 +348,9 @@
   -e "s|%OCTAVE_CONF_MKOCTFILE_DL_LDFLAGS%|\"${DL_LDFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_MKOCTFILE_F77%|\"${F77}\"|" \
   -e "s|%OCTAVE_CONF_MKOCTFILE_LD_CXX%|\"${LD_CXX}\"|" \
-  -e "s|%OCTAVE_CONF_MKOCTFILE_RANLIB%|\"${RANLIB}\"|" \
   -e "s|%OCTAVE_CONF_MKOCTFILE_OCTAVE_LINK_DEPS%|\"${MKOCTFILE_OCTAVE_LINK_DEPS}\"|" \
   -e "s|%OCTAVE_CONF_MKOCTFILE_OCT_LINK_DEPS%|\"${MKOCTFILE_OCT_LINK_DEPS}\"|" \
+  -e "s|%OCTAVE_CONF_MKOCTFILE_RANLIB%|\"${RANLIB}\"|" \
   -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}\"|" \
@@ -333,7 +378,8 @@
   -e "s|%OCTAVE_CONF_QT_LIBS%|\"${QT_LIBS}\"|" \
   -e "s|%OCTAVE_CONF_RANLIB%|\"${RANLIB}\"|" \
   -e "s|%OCTAVE_CONF_RDYNAMIC_FLAG%|\"${RDYNAMIC_FLAG}\"|" \
-  -e "s|%OCTAVE_CONF_READLINE_LIBS%|\"${READLINE_LIBS}\"|" \
+  -e "s|%OCTAVE_CONF_READLINE_LIBS%|\"${READLINE_LIBS}\"|" | \
+  $SED \
   -e "s|%OCTAVE_CONF_SED%|\"${SED}\"|" \
   -e "s|%OCTAVE_CONF_SHARED_LIBS%|\"${SHARED_LIBS}\"|" \
   -e "s|%OCTAVE_CONF_SH_LD%|\"${SH_LD}\"|" \
@@ -362,4 +408,45 @@
   -e "s|%OCTAVE_CONF_Z_CPPFLAGS%|\"${Z_CPPFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_Z_LDFLAGS%|\"${Z_LDFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_Z_LIBS%|\"${Z_LIBS}\"|" \
-  -e "s|%OCTAVE_CONF_config_opts%|\"${config_opts}\"|"
+  -e "s|%OCTAVE_CONF_config_opts%|\"${config_opts}\"|" \
+  -e "s|%OCTAVE_DATADIR%|\"${datadir}\"|" \
+  -e "s|%OCTAVE_DATAROOTDIR%|\"${datarootdir}\"|" \
+  -e "s|%OCTAVE_DEFAULT_PAGER%|\"${DEFAULT_PAGER}\"|" \
+  -e "s|%OCTAVE_DOCDIR%|\"${docdir}\"|" \
+  -e "s|%OCTAVE_DOC_CACHE_FILE%|\"${doc_cache_file}\"|" \
+  -e "s|%OCTAVE_EXEC_PREFIX%|\"${exec_prefix}\"|" \
+  -e "s|%OCTAVE_EXEEXT%|\"${EXEEXT}\"|" \
+  -e "s|%OCTAVE_FCNFILEDIR%|\"${fcnfiledir}\"|" \
+  -e "s|%OCTAVE_IMAGEDIR%|\"${imagedir}\"|" \
+  -e "s|%OCTAVE_INCLUDEDIR%|\"${includedir}\"|" \
+  -e "s|%OCTAVE_INFODIR%|\"${infodir}\"|" \
+  -e "s|%OCTAVE_INFOFILE%|\"${infofile}\"|" \
+  -e "s|%OCTAVE_LIBDIR%|\"${libdir}\"|" \
+  -e "s|%OCTAVE_LIBEXECDIR%|\"${libexecdir}\"|" \
+  -e "s|%OCTAVE_LOCALAPIARCHLIBDIR%|\"${localapiarchlibdir}\"|" \
+  -e "s|%OCTAVE_LOCALAPIFCNFILEDIR%|\"${localapifcnfiledir}\"|" \
+  -e "s|%OCTAVE_LOCALAPIOCTFILEDIR%|\"${localapioctfiledir}\"|" \
+  -e "s|%OCTAVE_LOCALARCHLIBDIR%|\"${localarchlibdir}\"|" \
+  -e "s|%OCTAVE_LOCALFCNFILEDIR%|\"${localfcnfiledir}\"|" \
+  -e "s|%OCTAVE_LOCALOCTFILEDIR%|\"${localoctfiledir}\"|" \
+  -e "s|%OCTAVE_LOCALSTARTUPFILEDIR%|\"${localstartupfiledir}\"|" \
+  -e "s|%OCTAVE_LOCALVERARCHLIBDIR%|\"${localverarchlibdir}\"|" \
+  -e "s|%OCTAVE_LOCALVERFCNFILEDIR%|\"${localverfcnfiledir}\"|" \
+  -e "s|%OCTAVE_LOCALVEROCTFILEDIR%|\"${localveroctfiledir}\"|" \
+  -e "s|%OCTAVE_MAN1DIR%|\"${man1dir}\"|" \
+  -e "s|%OCTAVE_MAN1EXT%|\"${man1ext}\"|" \
+  -e "s|%OCTAVE_MANDIR%|\"${mandir}\"|" \
+  -e "s|%OCTAVE_OCTDATADIR%|\"${octdatadir}\"|" \
+  -e "s|%OCTAVE_OCTDOCDIR%|\"${octdocdir}\"|" \
+  -e "s|%OCTAVE_OCTETCDIR%|\"${octetcdir}\"|" \
+  -e "s|%OCTAVE_OCTFILEDIR%|\"${octfiledir}\"|" \
+  -e "s|%OCTAVE_OCTFONTSDIR%|\"${octfontsdir}\"|" \
+  -e "s|%OCTAVE_OCTINCLUDEDIR%|\"${octincludedir}\"|" \
+  -e "s|%OCTAVE_OCTLIBDIR%|\"${octlibdir}\"|" \
+  -e "s|%OCTAVE_OCTLOCALEDIR%|\"${octlocaledir}\"|" \
+  -e "s|%OCTAVE_OCTTESTSDIR%|\"${octtestsdir}\"|" \
+  -e "s|%OCTAVE_PREFIX%|\"${prefix}\"|" \
+  -e "s|%OCTAVE_RELEASE%|\"${OCTAVE_RELEASE}\"|" \
+  -e "s|%OCTAVE_STARTUPFILEDIR%|\"${startupfiledir}\"|" \
+  -e "s|%OCTAVE_TEXI_MACROS_FILE%|\"${texi_macros_file}\"|" \
+  -e "s|%OCTAVE_VERSION%|\"${version}\"|"
--- a/build-aux/subst-default-vals.in.sh	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,119 +0,0 @@
-#! /bin/sh
-#
-# Copyright (C) 2016-2018 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
-# <https://www.gnu.org/licenses/>.
-
-: ${SED=@SED@}
-
-canonical_host_type="@canonical_host_type@"
-DEFAULT_PAGER="@DEFAULT_PAGER@"
-EXEEXT="@EXEEXT@"
-man1ext="@man1ext@"
-api_version="@OCTAVE_API_VERSION@"
-OCTAVE_RELEASE=""
-version="@PACKAGE_VERSION@"
-
-prefix="@prefix@"
-exec_prefix="@exec_prefix@"
-
-archlibdir=`echo "@archlibdir@" | sed "s|^${exec_prefix}/||"`
-bindir=`echo "@bindir@" | sed "s|^${exec_prefix}/||"`
-libdir=`echo "@libdir@" | sed "s|^${exec_prefix}/||"`
-libexecdir=`echo "@libexecdir@" | sed "s|^${exec_prefix}/||"`
-localapiarchlibdir=`echo "@localapiarchlibdir@" | sed "s|^${exec_prefix}/||"`
-localapioctfiledir=`echo "@localapioctfiledir@" | sed "s|^${exec_prefix}/||"`
-localarchlibdir=`echo "@localarchlibdir@" | sed "s|^${exec_prefix}/||"`
-localoctfiledir=`echo "@localoctfiledir@" | sed "s|^${exec_prefix}/||"`
-localverarchlibdir=`echo "@localverarchlibdir@" | sed "s|^${exec_prefix}/||"`
-localveroctfiledir=`echo "@localveroctfiledir@" | sed "s|^${exec_prefix}/||"`
-octfiledir=`echo "@octfiledir@" | sed "s|^${exec_prefix}/||"`
-octlibdir=`echo "@octlibdir@" | sed "s|^${exec_prefix}/||"`
-
-datadir=`echo "@datadir@" | sed "s|^${prefix}/||"`
-datarootdir=`echo "@datarootdir@" | sed "s|^${prefix}/||"`
-doc_cache_file=`echo "@doc_cache_file@" | sed "s|^${prefix}/||"`
-exec_prefix=`echo "@exec_prefix@" | sed "s|^${prefix}/||"`
-fcnfiledir=`echo "@fcnfiledir@" | sed "s|^${prefix}/||"`
-imagedir=`echo "@imagedir@" | sed "s|^${prefix}/||"`
-includedir=`echo "@includedir@" | sed "s|^${prefix}/||"`
-infodir=`echo "@infodir@" | sed "s|^${prefix}/||"`
-infofile=`echo "@infofile@" | sed "s|^${prefix}/||"`
-localapifcnfiledir=`echo "@localapifcnfiledir@" | sed "s|^${prefix}/||"`
-localfcnfiledir=`echo "@localfcnfiledir@" | sed "s|^${prefix}/||"`
-localstartupfiledir=`echo "@localstartupfiledir@" | sed "s|^${prefix}/||"`
-localapiarchlibdir=`echo "@localapiarchlibdir@" | sed "s|^${prefix}/||"`
-localverfcnfiledir=`echo "@localverfcnfiledir@" | sed "s|^${prefix}/||"`
-man1dir=`echo "@man1dir@" | sed "s|^${prefix}/||"`
-mandir=`echo "@mandir@" | sed "s|^${prefix}/||"`
-octdatadir=`echo "@octdatadir@" | sed "s|^${prefix}/||"`
-octdocdir=`echo "@octdocdir@" | sed "s|^${prefix}/||"`
-octetcdir=`echo "@octetcdir@" | sed "s|^${prefix}/||"`
-octfontsdir=`echo "@octfontsdir@" | sed "s|^${prefix}/||"`
-octincludedir=`echo "@octincludedir@" | sed "s|^${prefix}/||"`
-octlocaledir=`echo "@octlocaledir@" | sed "s|^${prefix}/||"`
-octtestsdir=`echo "@octtestsdir@" | sed "s|^${prefix}/||"`
-startupfiledir=`echo "@startupfiledir@" | sed "s|^${prefix}/||"`
-texi_macros_file=`echo "@texi_macros_file@" | sed "s|^${prefix}/||"`
-
-$SED \
-  -e "s|%NO_EDIT_WARNING%|DO NOT EDIT!  Generated automatically by subst-default-vals.|" \
-  -e "s|%OCTAVE_ARCHLIBDIR%|\"${archlibdir}\"|" \
-  -e "s|%OCTAVE_BINDIR%|\"${bindir}\"|" \
-  -e "s|%OCTAVE_CANONICAL_HOST_TYPE%|\"${canonical_host_type}\"|" \
-  -e "s|%OCTAVE_DATADIR%|\"${datadir}\"|" \
-  -e "s|%OCTAVE_DATAROOTDIR%|\"${datarootdir}\"|" \
-  -e "s|%OCTAVE_DOCDIR%|\"${docdir}\"|" \
-  -e "s|%OCTAVE_DEFAULT_PAGER%|\"${DEFAULT_PAGER}\"|" \
-  -e "s|%OCTAVE_DOC_CACHE_FILE%|\"${doc_cache_file}\"|" \
-  -e "s|%OCTAVE_EXEC_PREFIX%|\"${exec_prefix}\"|" \
-  -e "s|%OCTAVE_EXEEXT%|\"${EXEEXT}\"|" \
-  -e "s|%OCTAVE_FCNFILEDIR%|\"${fcnfiledir}\"|" \
-  -e "s|%OCTAVE_IMAGEDIR%|\"${imagedir}\"|" \
-  -e "s|%OCTAVE_INCLUDEDIR%|\"${includedir}\"|" \
-  -e "s|%OCTAVE_INFODIR%|\"${infodir}\"|" \
-  -e "s|%OCTAVE_INFOFILE%|\"${infofile}\"|" \
-  -e "s|%OCTAVE_LIBDIR%|\"${libdir}\"|" \
-  -e "s|%OCTAVE_LIBEXECDIR%|\"${libexecdir}\"|" \
-  -e "s|%OCTAVE_LOCALAPIFCNFILEDIR%|\"${localapifcnfiledir}\"|" \
-  -e "s|%OCTAVE_LOCALAPIOCTFILEDIR%|\"${localapioctfiledir}\"|" \
-  -e "s|%OCTAVE_LOCALARCHLIBDIR%|\"${localarchlibdir}\"|" \
-  -e "s|%OCTAVE_LOCALFCNFILEDIR%|\"${localfcnfiledir}\"|" \
-  -e "s|%OCTAVE_LOCALOCTFILEDIR%|\"${localoctfiledir}\"|" \
-  -e "s|%OCTAVE_LOCALSTARTUPFILEDIR%|\"${localstartupfiledir}\"|" \
-  -e "s|%OCTAVE_LOCALAPIARCHLIBDIR%|\"${localapiarchlibdir}\"|" \
-  -e "s|%OCTAVE_LOCALVERARCHLIBDIR%|\"${localverarchlibdir}\"|" \
-  -e "s|%OCTAVE_LOCALVERFCNFILEDIR%|\"${localverfcnfiledir}\"|" \
-  -e "s|%OCTAVE_LOCALVEROCTFILEDIR%|\"${localveroctfiledir}\"|" \
-  -e "s|%OCTAVE_MAN1DIR%|\"${man1dir}\"|" \
-  -e "s|%OCTAVE_MAN1EXT%|\"${man1ext}\"|" \
-  -e "s|%OCTAVE_MANDIR%|\"${mandir}\"|" \
-  -e "s|%OCTAVE_OCTDATADIR%|\"${octdatadir}\"|" \
-  -e "s|%OCTAVE_OCTDOCDIR%|\"${octdocdir}\"|" \
-  -e "s|%OCTAVE_OCTETCDIR%|\"${octetcdir}\"|" \
-  -e "s|%OCTAVE_OCTFILEDIR%|\"${octfiledir}\"|" \
-  -e "s|%OCTAVE_OCTFONTSDIR%|\"${octfontsdir}\"|" \
-  -e "s|%OCTAVE_OCTINCLUDEDIR%|\"${octincludedir}\"|" \
-  -e "s|%OCTAVE_OCTLIBDIR%|\"${octlibdir}\"|" \
-  -e "s|%OCTAVE_OCTLOCALEDIR%|\"${octlocaledir}\"|" \
-  -e "s|%OCTAVE_OCTTESTSDIR%|\"${octtestsdir}\"|" \
-  -e "s|%OCTAVE_STARTUPFILEDIR%|\"${startupfiledir}\"|" \
-  -e "s|%OCTAVE_PREFIX%|\"${prefix}\"|" \
-  -e "s|%OCTAVE_API_VERSION%|\"${api_version}\"|" \
-  -e "s|%OCTAVE_RELEASE%|\"${OCTAVE_RELEASE}\"|" \
-  -e "s|%OCTAVE_TEXI_MACROS_FILE%|\"${texi_macros_file}\"|" \
-  -e "s|%OCTAVE_VERSION%|\"${version}\"|"
--- a/configure.ac	Fri Aug 10 09:08:33 2018 +0200
+++ b/configure.ac	Fri Aug 10 09:09:51 2018 +0200
@@ -20,7 +20,7 @@
 
 ### Initialize Autoconf
 AC_PREREQ([2.65])
-AC_INIT([GNU Octave], [4.4.1-rc2], [https://octave.org/bugs.html], [octave],
+AC_INIT([GNU Octave], [5.0.0], [https://octave.org/bugs.html], [octave],
         [https://www.gnu.org/software/octave/])
 
 ### Declare version numbers
@@ -28,9 +28,13 @@
 dnl Note that the version number is duplicated here and in AC_INIT because
 dnl AC_INIT requires it to be static, not computed from shell variables.
 
-OCTAVE_MAJOR_VERSION=4
-OCTAVE_MINOR_VERSION=4
-OCTAVE_PATCH_VERSION=1-rc2
+## The description of the Octave version number in the etc/HACKING.md
+## explains how to update these numbers for release and development
+## versions.
+
+OCTAVE_MAJOR_VERSION=5
+OCTAVE_MINOR_VERSION=0
+OCTAVE_PATCH_VERSION=0
 
 dnl PACKAGE_VERSION is set by the AC_INIT VERSION argument.
 OCTAVE_VERSION="$PACKAGE_VERSION"
@@ -52,7 +56,7 @@
 dnl FIXME: Since we also set libtool versions for liboctave and libinterp,
 dnl perhaps we should be computing the "api version" from those versions numbers
 dnl in some way instead of setting it independently here.
-OCTAVE_API_VERSION="api-v52"
+OCTAVE_API_VERSION="api-v52+"
 
 AC_SUBST(OCTAVE_MAJOR_VERSION)
 AC_SUBST(OCTAVE_MINOR_VERSION)
@@ -188,6 +192,10 @@
 ## Programs used in configuring Octave.
 dnl Find pkg-config executable (sets $PKG_CONFIG)
 PKG_PROG_PKG_CONFIG
+## And where we will install our own .pc files.
+PKG_INSTALLDIR
+AC_SUBST([liboctave_pkgconfigdir], [$pkgconfigdir])
+AC_SUBST([libinterp_pkgconfigdir], [$pkgconfigdir])
 
 ## Programs used in Makefiles.
 AC_PROG_AWK
@@ -1398,7 +1406,6 @@
     [(EXPERIMENTAL) enable JIT compiler])],
   [if test "$enableval" = yes; then ENABLE_JIT=yes; fi], [])
 
-LLVM_CXXFLAGS=
 LLVM_CPPFLAGS=
 LLVM_LDFLAGS=
 LLVM_LIBS=
@@ -1416,7 +1423,6 @@
     warn_llvm="LLVM was not found or is to old.  JIT compiler is disabled."
 
     save_CPPFLAGS="$CPPFLAGS"
-    save_CXXFLAGS="$CXXFLAGS"
     save_LDFLAGS="$LDFLAGS"
 
     dnl Use -isystem if available because we don't want to see warnings in LLVM
@@ -1427,7 +1433,6 @@
 
     dnl Use -isystem so we don't get warnings from llvm headers
     LLVM_CPPFLAGS="$LLVM_INCLUDE_FLAG `$LLVM_CONFIG --includedir`"
-    LLVM_CXXFLAGS=
     LLVM_LDFLAGS="-L`$LLVM_CONFIG --libdir`"
 
     LDFLAGS="$LDFLAGS $LLVM_LDFLAGS"
@@ -1439,7 +1444,6 @@
     dnl Ideally we should get these from llvm-config, but llvm-config isn't
     dnl very helpful.
     CPPFLAGS="-D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS $LLVM_CPPFLAGS $CPPFLAGS"
-    CXXFLAGS="$LLVM_CXXFLAGS $CXXFLAGS"
     AC_LANG_PUSH(C++)
     AC_CHECK_HEADER([llvm/Support/TargetSelect.h], [warn_llvm=""])
 
@@ -1472,7 +1476,6 @@
     OCTAVE_LLVM_LEGACY_PASSMANAGER_API
     AC_LANG_POP(C++)
     CPPFLAGS="$save_CPPFLAGS"
-    CXXFLAGS="$save_CXXFLAGS"
     LDFLAGS="$save_LDFLAGS"
   fi
 
@@ -1481,7 +1484,6 @@
   else
     ENABLE_JIT=no
     LLVM_CPPFLAGS=
-    LLVM_CXXFLAGS=
     LLVM_LDFLAGS=
     LLVM_LIBS=
     OCTAVE_CONFIGURE_WARNING([warn_llvm])
@@ -1497,7 +1499,6 @@
 fi
 
 AC_SUBST(LLVM_CPPFLAGS)
-AC_SUBST(LLVM_CXXFLAGS)
 AC_SUBST(LLVM_LDFLAGS)
 AC_SUBST(LLVM_LIBS)
 AM_CONDITIONAL([AMCOND_HAVE_LLVM], [test -z "$warn_llvm"])
@@ -1909,76 +1910,6 @@
 AC_SUBST(DEFAULT_TERMINAL_FONT)
 AC_SUBST(DEFAULT_TERMINAL_FONT_SIZE)
 
-### Check for OSMesa.
-## Library is needed for offscreen rendering with Qt < 5.1 or FLTK.
-use_osmesa=auto
-AC_ARG_WITH([osmesa],
-  [AS_HELP_STRING([--with-osmesa],
-    [use OSMesa library for offscreen rendering of invisible figures])],
-  [if test x"$withval" = xyes; then
-     use_osmesa=yes
-   else
-     use_osmesa=no
-   fi])
-
-dnl If no argument given, only use OSMesa when Qt is too old
-if test $use_osmesa = auto; then
-  ## Quote $octave_cv_qt_opengl_os_ok because it will only be set if
-  ## Qt is found.
-  if test "$octave_cv_qt_opengl_os_ok" = yes; then
-    use_osmesa=no
-  else
-    use_osmesa=yes
-  fi
-fi
-
-if test $use_osmesa = yes; then
-  dnl Pre-declare warning message, and unset if library is found
-  ## Quote $octave_cv_qt_opengl_os_ok because it will only be set if
-  ## Qt is found.
-  if test "$octave_cv_qt_opengl_os_ok" = no; then
-    warn_osmesa="OSMesa library not found and Qt < 5.1.  Offscreen rendering with OpenGL will be disabled."
-  else
-    warn_osmesa="OSMesa library not found.  Offscreen rendering with FLTK will be disabled."
-  fi
-
-  OSMESA_LIBS="-lOSMesa"
-  save_CPPFLAGS="$CPPFLAGS"
-  save_LDFLAGS="$LDFLAGS"
-  save_LIBS="$LIBS"
-  CPPFLAGS="$OSMESA_CPPFLAGS $CPPFLAGS"
-  LDFLAGS="$OSMESA_LDFLAGS $LDFLAGS"
-  LIBS="$OSMESA_LIBS $LIBS"
-  AC_LANG_PUSH(C++)
-  ac_octave_osmesa_check_for_lib=no
-  AC_CHECK_HEADERS([osmesa.h GL/osmesa.h],
-                   [ac_octave_osmesa_check_for_lib=yes; break])
-  if test $ac_octave_osmesa_check_for_lib = yes; then
-    AC_CACHE_CHECK([for OSMesaCreateContext in OSMesa],
-      octave_cv_lib_osmesa,
-      [AC_LINK_IFELSE([AC_LANG_CALL([], [OSMesaCreateContext])],
-        [octave_cv_lib_osmesa=yes], [octave_cv_lib_osmesa=no])
-    ])
-    if test $octave_cv_lib_osmesa = yes; then
-      warn_osmesa=
-      AC_DEFINE(HAVE_OSMESA, 1, [Define to 1 if OSMesa is available.])
-    fi
-  fi
-  AC_LANG_POP(C++)
-  CPPFLAGS="$save_CPPFLAGS"
-  LDFLAGS="$save_LDFLAGS"
-  LIBS="$save_LIBS"
-
-  if test -n "$warn_osmesa"; then
-    OCTAVE_CONFIGURE_WARNING([warn_osmesa])
-    OSMESA_LIBS=
-  fi
-fi
-
-AC_SUBST(OSMESA_CPPFLAGS)
-AC_SUBST(OSMESA_LDFLAGS)
-AC_SUBST(OSMESA_LIBS)
-
 ### Check for FLTK library
 
 check_fltk=yes
@@ -2635,7 +2566,7 @@
      OCTAVE_CONFIGURE_WARNING([warn_docs])
    fi], [])
 if test $ENABLE_DOCS = yes; then
-  if test $opengl_graphics = no || { test "$have_qt_opengl_offscreen" = no && test -n "$warn_osmesa"; }; then
+  if test $opengl_graphics = no || test "$have_qt_opengl_offscreen" = no; then
     if test -n "$warn_gnuplot"; then
       ENABLE_DOCS=no
       warn_docs_graphics="building documentation disabled because no suitable graphics toolkit is available; make dist will fail."
@@ -2860,7 +2791,9 @@
 OCT_LINK_DEPS=""
 OCT_LINK_OPTS="$LDFLAGS"
 
-if test $link_all_deps = yes || test -n "$QT_LDFLAGS"; then
+if test $link_all_deps = yes; then
+  OCT_LINK_DEPS="libinterp/liboctinterp.la liboctave/liboctave.la"
+
   MKOCTFILE_OCTAVE_LINK_DEPS="$LIBOCTINTERP_LINK_DEPS $MKOCTFILE_LIBOCTAVE_LINK_DEPS"
   MKOCTFILE_OCT_LINK_DEPS="$OCT_LINK_DEPS $MKOCTFILE_LIBOCTINTERP_LINK_DEPS"
 
@@ -2869,9 +2802,12 @@
 
   OCTAVE_LINK_DEPS="$LIBOCTINTERP_LINK_DEPS"
   OCTAVE_LINK_OPTS="$LIBOCTINTERP_LINK_OPTS"
-
-  OCT_LINK_DEPS="$OCT_LINK_DEPS $LIBOCTINTERP_LINK_DEPS"
-  OCT_LINK_OPTS="$OCT_LINK_OPTS $LIBOCTINTERP_LINK_OPTS"
+else
+  case $host_os in
+    mingw* | msdosmsvc)
+      OCT_LINK_DEPS="libinterp/liboctinterp.la liboctave/liboctave.la"
+    ;;
+  esac
 fi
 
 AC_SUBST(LIBOCTINTERP_LINK_DEPS)
@@ -3019,7 +2955,9 @@
   Makefile
   build-aux/check-subst-vars.sh:build-aux/check-subst-vars.in.sh
   doc/doxyhtml/Doxyfile
-  libgnu/Makefile])
+  libgnu/Makefile
+  liboctave/octave.pc:liboctave/octave.in.pc
+  libinterp/octinterp.pc:libinterp/octinterp.in.pc])
 
 dnl We use a .in.h file for oct-conf-post.h simply to copy it to the build tree
 dnl so that we don't have to add the -I${top_srcdir} to any CPPFLAGS variables.
@@ -3031,11 +2969,10 @@
 OCTAVE_CONFIG_MOVE_IF_CHANGE_FILES([
   libgui/mk-default-qt-settings.sh
   liboctave/external/mk-f77-def.sh
+  liboctave/mk-version-h.sh
   libinterp/corefcn/mk-mxarray-h.sh
-  libinterp/mk-version-h.sh
   build-aux/subst-config-vals.sh
   build-aux/subst-cross-config-vals.sh
-  build-aux/subst-default-vals.sh
   build-aux/subst-script-vals.sh])
 
 AC_OUTPUT
--- a/doc/interpreter/genpropdoc.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/doc/interpreter/genpropdoc.m	Fri Aug 10 09:09:51 2018 +0200
@@ -1372,8 +1372,18 @@
 the vertices). @qcode{\"phong\"} is deprecated and has the same effect as \
 @qcode{\"gouraud\"}.";
 
+      case "facenormals"
+        s.doc = "Face normals are used for lighting the edges or faces if the \
+@code{edgelighting} or @code{facelighting} properties are set to \
+@qcode{\"flat\"}.  __modemsg__";
+
+      case "facenormalsmode"
+        s.doc = "If this property is set to @qcode{\"auto\"}, \
+@code{facenormals} are automatically calculated if the @code{edgelighting} or \
+@code{facelighting} property are set to @qcode{\"flat\"} and at least one \
+@code{light} object is present and visible in the same axes.";
+
       case "faces"
-      case "xdata"
         s.valid = valid_vecmat;
 
       case "facevertexalphadata"
@@ -1401,7 +1411,6 @@
         s.doc = "@xref{XREFlinemarkersize, , @w{line markersize property}}.";
         s.valid = "scalar";
 
-      case "normalmode"
       case "specularcolorreflectance"
         s.doc = "Reflectance for specular color.  Value between 0.0 (color \
 of underlying face) and 1.0 (color of light source).";
@@ -1418,6 +1427,16 @@
         s.valid = "scalar";
 
       case "vertexnormals"
+        s.doc = "Vertex normals are used for lighting the edges or faces if \
+the @code{edgelighting} or @code{facelighting} properties are set to \
+@qcode{\"gouraud\"}.  __modemsg__";
+
+      case "vertexnormalsmode"
+        s.doc = "If this property is set to @qcode{\"auto\"}, \
+@code{vertexnormals} are automatically calculated if the @code{edgelighting} \
+or @code{facelighting} property are set to @qcode{\"gouraud\"} and at least \
+one @code{light} object is present and visible in the same axes.";
+
       case "vertices"
         s.valid = valid_vecmat;
 
@@ -1745,7 +1764,7 @@
   def = get (h, field);
 
   ## Don't print default values for graphics handles
-  if (isscalar (def) && def != 0 && ishghandle (def))
+  if (ishghandle (def) && isscalar (def) && def != 0)
     def = "";
   else
     if (ischar (def))
--- a/doc/interpreter/linalg.txi	Fri Aug 10 09:08:33 2018 +0200
+++ b/doc/interpreter/linalg.txi	Fri Aug 10 09:09:51 2018 +0200
@@ -183,6 +183,8 @@
 
 @DOCSTRING(ordschur)
 
+@DOCSTRING(ordeig)
+
 @DOCSTRING(subspace)
 
 @DOCSTRING(svd)
--- a/doc/interpreter/module.mk	Fri Aug 10 09:08:33 2018 +0200
+++ b/doc/interpreter/module.mk	Fri Aug 10 09:09:51 2018 +0200
@@ -27,55 +27,57 @@
   mv $@-t $@
 endef
 
-%reldir%/plot-axesproperties.texi: %reldir%/genpropdoc.m
+GRAPHICS_PROPS_SRC = libinterp/corefcn/graphics.in.h libinterp/corefcn/genprops.awk
+
+%reldir%/plot-axesproperties.texi: %reldir%/genpropdoc.m $(GRAPHICS_PROPS_SRC)
 	$(AM_V_GEN)$(call gen-propdoc-texi,axes)
 
-%reldir%/plot-figureproperties.texi: %reldir%/genpropdoc.m
+%reldir%/plot-figureproperties.texi: %reldir%/genpropdoc.m $(GRAPHICS_PROPS_SRC)
 	$(AM_V_GEN)$(call gen-propdoc-texi,figure)
 
-%reldir%/plot-imageproperties.texi: %reldir%/genpropdoc.m
+%reldir%/plot-imageproperties.texi: %reldir%/genpropdoc.m $(GRAPHICS_PROPS_SRC)
 	$(AM_V_GEN)$(call gen-propdoc-texi,image)
 
-%reldir%/plot-lightproperties.texi: %reldir%/genpropdoc.m
+%reldir%/plot-lightproperties.texi: %reldir%/genpropdoc.m $(GRAPHICS_PROPS_SRC)
 	$(AM_V_GEN)$(call gen-propdoc-texi,light)
 
-%reldir%/plot-lineproperties.texi: %reldir%/genpropdoc.m
+%reldir%/plot-lineproperties.texi: %reldir%/genpropdoc.m $(GRAPHICS_PROPS_SRC)
 	$(AM_V_GEN)$(call gen-propdoc-texi,line)
 
-%reldir%/plot-patchproperties.texi: %reldir%/genpropdoc.m
+%reldir%/plot-patchproperties.texi: %reldir%/genpropdoc.m $(GRAPHICS_PROPS_SRC)
 	$(AM_V_GEN)$(call gen-propdoc-texi,patch)
 
-%reldir%/plot-rootproperties.texi: %reldir%/genpropdoc.m
+%reldir%/plot-rootproperties.texi: %reldir%/genpropdoc.m $(GRAPHICS_PROPS_SRC)
 	$(AM_V_GEN)$(call gen-propdoc-texi,root)
 
-%reldir%/plot-surfaceproperties.texi: %reldir%/genpropdoc.m
+%reldir%/plot-surfaceproperties.texi: %reldir%/genpropdoc.m $(GRAPHICS_PROPS_SRC)
 	$(AM_V_GEN)$(call gen-propdoc-texi,surface)
 
-%reldir%/plot-textproperties.texi: %reldir%/genpropdoc.m
+%reldir%/plot-textproperties.texi: %reldir%/genpropdoc.m $(GRAPHICS_PROPS_SRC)
 	$(AM_V_GEN)$(call gen-propdoc-texi,text)
 
-%reldir%/plot-uimenuproperties.texi: %reldir%/genpropdoc.m
+%reldir%/plot-uimenuproperties.texi: %reldir%/genpropdoc.m $(GRAPHICS_PROPS_SRC)
 	$(AM_V_GEN)$(call gen-propdoc-texi,uimenu)
 
-%reldir%/plot-uibuttongroupproperties.texi: %reldir%/genpropdoc.m
+%reldir%/plot-uibuttongroupproperties.texi: %reldir%/genpropdoc.m $(GRAPHICS_PROPS_SRC)
 	$(AM_V_GEN)$(call gen-propdoc-texi,uibuttongroup)
 
-%reldir%/plot-uicontextmenuproperties.texi: %reldir%/genpropdoc.m
+%reldir%/plot-uicontextmenuproperties.texi: %reldir%/genpropdoc.m $(GRAPHICS_PROPS_SRC)
 	$(AM_V_GEN)$(call gen-propdoc-texi,uicontextmenu)
 
-%reldir%/plot-uipanelproperties.texi: %reldir%/genpropdoc.m
+%reldir%/plot-uipanelproperties.texi: %reldir%/genpropdoc.m $(GRAPHICS_PROPS_SRC)
 	$(AM_V_GEN)$(call gen-propdoc-texi,uipanel)
 
-%reldir%/plot-uicontrolproperties.texi: %reldir%/genpropdoc.m
+%reldir%/plot-uicontrolproperties.texi: %reldir%/genpropdoc.m $(GRAPHICS_PROPS_SRC)
 	$(AM_V_GEN)$(call gen-propdoc-texi,uicontrol)
 
-%reldir%/plot-uitoolbarproperties.texi: %reldir%/genpropdoc.m
+%reldir%/plot-uitoolbarproperties.texi: %reldir%/genpropdoc.m $(GRAPHICS_PROPS_SRC)
 	$(AM_V_GEN)$(call gen-propdoc-texi,uitoolbar)
 
-%reldir%/plot-uipushtoolproperties.texi: %reldir%/genpropdoc.m
+%reldir%/plot-uipushtoolproperties.texi: %reldir%/genpropdoc.m $(GRAPHICS_PROPS_SRC)
 	$(AM_V_GEN)$(call gen-propdoc-texi,uipushtool)
 
-%reldir%/plot-uitoggletoolproperties.texi: %reldir%/genpropdoc.m
+%reldir%/plot-uitoggletoolproperties.texi: %reldir%/genpropdoc.m $(GRAPHICS_PROPS_SRC)
 	$(AM_V_GEN)$(call gen-propdoc-texi,uitoggletool)
 
 dist_man_MANS = \
@@ -323,6 +325,7 @@
 if AMCOND_BUILD_QT_DOCS
 DOC_TARGETS += \
   $(OCTAVE_QTHELP_FILES)
+
 endif
 
 ## Distribute both OCTAVE_CSS and HTMLDIR_CSS so that the rules for
@@ -422,6 +425,13 @@
 
 endif
 
+## These actions should happen even if we are not building docs
+
+include doc/interpreter/images.mk
+
+$(srcdir)/%reldir%/images.mk: $(srcdir)/%reldir%/config-images.sh $(srcdir)/%reldir%/images.awk $(srcdir)/%reldir%/images
+	$(AM_V_GEN)$(SHELL) $(srcdir)/%reldir%/config-images.sh $(top_srcdir)
+
 DIRSTAMP_FILES += %reldir%/$(octave_dirstamp)
 
 ## The doc-cache file can be built without TeX but it does require
@@ -443,19 +453,19 @@
 
 %reldir%/undocumented_list:
 	rm -f $@-t $@
-	-cd $(srcdir)/doc/interpreter; $(PERL) ./doccheck/mk_undocumented_list > $(@F)-t
+	-cd $(srcdir)/%reldir%; $(PERL) ./doccheck/mk_undocumented_list > $(@F)-t
 	mv $@-t $@
 .PHONY: %reldir%/undocumented_list
 
 SPELLCHECK_FILES = $(MUNGED_TEXI_SRC:.texi=.scheck)
 
 %.scheck: %.texi | %reldir%/$(octave_dirstamp)
-	cd $(srcdir)/doc/interpreter; ./doccheck/spellcheck $(<F) > $(@F)-t
+	cd $(srcdir)/%reldir%; ./doccheck/spellcheck $(<F) > $(@F)-t
 	mv $@-t $@
 	[ -s $@ ] || rm -f $@
 
 spellcheck: $(SPELLCHECK_FILES)
-	@cd $(srcdir)/doc/interpreter ; \
+	@cd $(srcdir)/%reldir% ; \
 	if ls *.scheck >/dev/null 2>&1 ; then \
 		echo "Spellcheck failed"; \
 		echo "Review the following files:"; \
--- a/doc/interpreter/octave.texi	Fri Aug 10 09:08:33 2018 +0200
+++ b/doc/interpreter/octave.texi	Fri Aug 10 09:09:51 2018 +0200
@@ -93,7 +93,7 @@
 @c        is automatically generated by Automake in version-octave.texi.
 @c        Need to use sed to strip off MINOR.PATCH numbers and place
 @c        the results in a new file, and then @include that new file.
-@subtitle Edition 4 for Octave version @value{VERSION}
+@subtitle Edition 5 for Octave version @value{VERSION}
 @subtitle @value{UPDATED-MONTH}
 @sp 2
 @multitable @columnfractions 0.4 0.025 0.65
--- a/doc/interpreter/strings.txi	Fri Aug 10 09:08:33 2018 +0200
+++ b/doc/interpreter/strings.txi	Fri Aug 10 09:09:51 2018 +0200
@@ -53,6 +53,9 @@
 produces the string whose contents are @samp{foobarbaz}.  @xref{Numeric Data
 Types}, for more information about creating matrices.
 
+While strings can in principal store arbitrary content, most functions expect
+them to be UTF-8 encoded Unicode strings.
+
 @menu
 * Escape Sequences in String Constants::
 * Character Arrays::
@@ -468,6 +471,8 @@
 
 @DOCSTRING(untabify)
 
+@DOCSTRING(unicode_idx)
+
 @node String Conversions
 @section String Conversions
 
--- a/doc/refcard/module.mk	Fri Aug 10 09:08:33 2018 +0200
+++ b/doc/refcard/module.mk	Fri Aug 10 09:09:51 2018 +0200
@@ -44,9 +44,6 @@
 %reldir%/refcard-letter.ps: %reldir%/refcard-letter.dvi
 	-$(AM_V_DVIPS)$(DVIPS) $(AM_V_texinfo) -T 11in,8.5in -o $@ $<
 
-$(srcdir)/doc/interpreter/images.mk: $(srcdir)/doc/interpreter/config-images.sh $(srcdir)/doc/interpreter/images.awk $(srcdir)/doc/interpreter/images
-	$(AM_V_GEN)$(SHELL) $(srcdir)/doc/interpreter/config-images.sh $(top_srcdir)
-
 $(refcard_DVI) : %.dvi : %.tex | %reldir%/$(octave_dirstamp)
 	-$(AM_V_TEX)cd $(@D) && \
 	TEXINPUTS="$(abs_top_srcdir)/doc/refcard:$(TEXINPUTS):" \
--- a/etc/HACKING.md	Fri Aug 10 09:08:33 2018 +0200
+++ b/etc/HACKING.md	Fri Aug 10 09:09:51 2018 +0200
@@ -297,6 +297,94 @@
   - `fntests.m`
        script to run function tests embedded in C++ and .m files.
 
+Release Numbering
+-----------------
+
+Since version 5, Octave uses the following rules for release numbering:
+
+  Version Dev Phase       When
+
+  5.0.0   (experimental)  active development of Octave 5 on default branch
+  5.0.1   (pre-release)   stabilization period of Octave 5 on stable branch
+  6.0.0   (experimental)  active development of Octave 6 on default branch
+  5.1.0   (release)       first release of Octave 5 from stable branch
+  5.1.1   (pre-release)   bug fixing on stable branch after 5.1.0 release
+  5.2.0   (release)       second release of Octave 5 from stable branch
+  5.2.1   (pre-release)   bug fixing on stable branch after 5.2.0 release
+  ...
+
+To summarize, the first release of Octave 5 will be Octave 5.1.0 while
+development snapshots will be Octave 5.0.0 and snapshots from the
+release branch Octave 5.n.1.
+
+With this numbering scheme:
+
+  * Any version X.0.0 means "this is an experimental development
+    version".
+
+  * Any version X.Y.1 means, "this is a pre-release version meant
+    for bug fixing and testing".
+
+  * Any version X.Y.0 with Y != 0 means "this is a released version".
+
+Shared Library Versioning
+-------------------------
+
+Version numbers for the liboctave, liboctinterp, and liboctgui shared
+libraries are set in the module.mk files in the top-level directory for
+each library using the variables
+
+  %canon_reldir%_%canon_reldir%_current
+  %canon_reldir%_%canon_reldir%_revision
+  %canon_reldir%_%canon_reldir%_age
+
+The rules for updating these version numbers are:
+
+  * Start with version information of ‘0:0:0’ for each libtool library.
+
+  * Update the version information only immediately before a public
+    release of your software.  More frequent updates are unnecessary,
+    and only guarantee that the current interface number gets larger
+    faster.
+
+  * If the library source code has changed at all since the last update,
+    then increment revision (‘c:r:a’ becomes ‘c:r+1:a’).
+
+  * If any interfaces have been added, removed, or changed since the
+    last update, increment current, and set revision to 0.
+
+  * If any interfaces have been added since the last public release,
+    then increment age.
+
+  * If any interfaces have been removed or changed since the last public
+    release, then set age to 0.
+
+Never try to set the interface numbers so that they correspond to the
+Octave version number.  This is an abuse that only fosters
+misunderstanding of the purpose of library versions.
+
+The following explanation may help to understand the above rules a bit
+better: consider that there are three possible kinds of reactions from
+users of your library to changes in a shared library:
+
+  * Programs using the previous version may use the new version as
+    drop-in replacement, and programs using the new version can also
+    work with the previous one.  In other words, no recompiling nor
+    relinking is needed.  In this case, bump revision only, don’t touch
+    current nor age.
+
+  * Programs using the previous version may use the new version as
+    drop-in replacement, but programs using the new version may use APIs
+    not present in the previous one.  In other words, a program linking
+    against the new version may fail with unresolved symbols if linking
+    against the old version at runtime: set revision to 0, bump current
+    and age.
+
+  * Programs may need to be changed, recompiled, and relinked in order
+    to use the new version.  Bump current, set revision and age to 0.
+
+These guidelines also appear in the automake manual.
+
 
 ################################################################################
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/etc/NEWS.4	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,1350 @@
+Summary of important user-visible changes for version 4.4 (2018-04-30):
+----------------------------------------------------------------------
+
+ ** A graphical Variable Editor has been added to the GUI interface.
+    It uses a spreadsheet-like interface for quick, intuitive editing
+    of variables.  The Variable Editor is launched by double-clicking
+    on a variable name in the Workspace Window or by typing
+    "openvar VARIABLE_NAME" in the Command Window.
+
+ ** On systems with 64-bit pointers, --enable-64 is now the default and
+    Octave always uses 64-bit indexing.  However, if the configure
+    script determines that the BLAS library uses 32-bit integers, then
+    operations using the following libraries are limited to arrays with
+    dimensions that are smaller than 2^31 elements:
+
+      BLAS  LAPACK  QRUPDATE  SuiteSparse  ARPACK
+
+    Additionally, the following libraries use "int" internally, so
+    maximum problem sizes are always limited:
+
+      glpk  Qhull
+
+ ** The octave command no longer starts the GUI by default.  Most users
+    starting Octave from a shell were expecting the command line
+    interface, and desktop launchers already required the `--force-gui'
+    option.  With this change, desktop launchers should be modified to
+    use the new option `--gui'.  The previous `--force-gui' option will
+    continue to work, and maps to `--gui', but it will be removed in
+    Octave 6.
+
+ ** A known bug in Qt (https://bugreports.qt.io/browse/QTBUG-55357) is
+    addressed by limiting GUI sub-panel relocation capabilities for Qt
+    versions in the range >= 5.6.1 and < 5.7.1.  However, this may not
+    thoroughly avoid issues on all platforms.
+
+ ** A new container data type--containers.Map--is available.  Map is a
+    key/value storage container (a.k.a, a hash) that efficiently allows
+    storing and retrieving values by name, rather than by position which
+    is how arrays work.
+
+ ** The bareword "import" is now recognized in scripts and functions.
+    However, the functionality to import functions and classes from
+    other namespaces into the local scope has not yet been implemented.
+    Attempting to use "import" will provoke an error message.
+
+ ** hex2num and num2hex now work for integer and char types and num2hex
+    may optionally return a cell array of strings instead of a character
+    array.  If given a cell array of strings, hex2num now returns a
+    numeric array of the same size as the input cell array.  Previously,
+    hex2num would accept a cell array of strings of arbitrary dimension
+    but would always return a column vector.
+
+ ** New special functions cosint, sinint, and gammaincinv have been added.
+
+ ** Special functions in Octave have been rewritten for larger input
+    domains, better accuracy, and additional options.
+    * gammainc now accepts negative real values for X.
+    * improved accuracy for gammainc, betainc, betaincinv, expint.
+    * gammainc has new options "scaledlower" and "scaledupper".
+    * betainc, betaincinv have new option "upper".
+
+ ** The "names" option used in regular expressions now returns a struct
+    array, rather than a struct with a cell array for each field.  This
+    change was made for Matlab compatibility.
+
+ ** The quadcc function now uses both absolute tolerance and relative
+    tolerance to determine the stopping criteria for an integration.
+    To be compatible with other quadXXX functions, such as quadgk, the
+    calling syntax has changed to
+
+      quadcc (f, a, b, [AbsTol, [RelTol]])
+
+    To update existing code, change instances of RelTol to [0, RelTol].
+
+      quadcc (f, a, b, tol) => quadcc (f, a, b, [0, tol])
+
+    A warning that a single tolerance input is now interpreted as an
+    absolute tolerance will be issued in Octave versions 4.4 and 5,
+    after which it will be removed.  The warning has ID
+    "Octave:quadcc:RelTol-conversion" and can be disabled with
+
+      warning ("off", "Octave:quadcc:RelTol-conversion")
+
+ ** The qr function now returns a standard factorization unless
+    explicitly instructed to perform an economy factorization by using a
+    final argument of 0.
+
+ ** The Qt graphics toolkit now supports offscreen printing without osmesa
+    if Octave was built with Qt >= 5.1.
+
+ ** The built-in pager for display of large data is now disabled by
+    default.  To re-enable it for every Octave session add the following
+    to your .octaverc file:
+
+      more on;
+
+ ** The FLTK toolkit is no longer prioritized for development.  The
+    number of Octave Maintainers is too small to support three different
+    graphic toolkits.  New development will target the Qt toolkit.
+    While no longer prioritized, the FLTK toolkit is not deprecated and
+    there is no schedule for its removal.
+
+ ** The graphic object property "PickableParts" has been implemented
+    which controls whether an object can accept mouse clicks.
+
+ ** The graphic object property "Interruptible" has been fully
+    implemented which controls whether a running callback function can
+    be interrupted by another callback function.
+
+ ** The graphic object property "HitTest" has been updated to be fully
+    compatible with Matlab.
+
+ ** Text objects now implement the properties "BackgroundColor",
+    "EdgeColor", "LineStyle", "LineWidth", and "Margin".
+
+ ** An initial implementation of alpha transparency has been made for
+    patch and surface objects.  Printing to svg and pdf is supported.
+
+ ** ishandle now returns true for both graphics handle objects and
+    Java objects.  The latter change was made for Matlab compatibility.
+    Use ishghandle or isgraphics if it is important not to include Java
+    objects.
+
+ ** The pkg command now accepts a URL as an argument, allowing a valid
+    Octave package to be installed from any remote host with one command,
+    for example
+
+      pkg install https://example.org/download/example-package.tar.gz
+
+ ** The following statistical functions have been moved from core
+    Octave to the statistics package available from Octave Forge.
+
+    BASE
+      cloglog
+      logit
+      prctile
+      probit
+      qqplot
+      table  (renamed to crosstab)
+
+    DISTRIBUTIONS
+      betacdf
+      betainv
+      betapdf
+      betarnd
+      binocdf
+      binoinv
+      binopdf
+      binornd
+      cauchy_cdf
+      cauchy_inv
+      cauchy_pdf
+      cauchy_rnd
+      chi2cdf
+      chi2inv
+      chi2pdf
+      chi2rnd
+      expcdf
+      expinv
+      exppdf
+      exprnd
+      fcdf
+      finv
+      fpdf
+      frnd
+      gamcdf
+      gaminv
+      gampdf
+      gamrnd
+      geocdf
+      geoinv
+      geopdf
+      geornd
+      hygecdf
+      hygeinv
+      hygepdf
+      hygernd
+      kolmogorov_smirnov_cdf
+      laplace_cdf
+      laplace_inv
+      laplace_pdf
+      laplace_rnd
+      logistic_cdf
+      logistic_inv
+      logistic_pdf
+      logistic_rnd
+      logncdf
+      logninv
+      lognpdf
+      lognrnd
+      nbincdf
+      nbininv
+      nbinpdf
+      nbinrnd
+      normcdf
+      norminv
+      normpdf
+      normrnd
+      poisscdf
+      poissinv
+      poisspdf
+      poissrnd
+      stdnormal_cdf
+      stdnormal_inv
+      stdnormal_pdf
+      stdnormal_rnd
+      tcdf
+      tinv
+      tpdf
+      trnd
+      unidcdf
+      unidinv
+      unidpdf
+      unidrnd
+      unifcdf
+      unifinv
+      unifpdf
+      unifrnd
+      wblcdf
+      wblinv
+      wblpdf
+      wblrnd
+      wienrnd
+
+    MODELS
+      logistic_regression
+
+    TESTS
+      anova
+      bartlett_test
+      chisquare_test_homogeneity
+      chisquare_test_independence
+      cor_test
+      f_test_regression
+      hotelling_test
+      hotelling_test_2
+      kolmogorov_smirnov_test
+      kolmogorov_smirnov_test_2
+      kruskal_wallis_test
+      manova
+      mcnemar_test
+      prop_test_2
+      run_test
+      sign_test
+      t_test
+      t_test_2
+      t_test_regression
+      u_test
+      var_test
+      welch_test
+      wilcoxon_test
+      z_test
+      z_test_2
+
+ ** The following image functions have been moved from core Octave to
+    the image package available from Octave Forge.
+
+      ntsc2rgb
+      rgb2ntsc
+
+ ** Other new functions added in 4.4:
+
+      bounds
+      camlookat
+      camorbit
+      campos
+      camroll
+      camtarget
+      camup
+      camva
+      camzoom
+      corrcoef
+      cosint
+      decic
+      erase
+      gammaincinv
+      getframe
+      groot
+      gsvd
+      hgtransform
+      humps
+      integral
+      integral2
+      integral3
+      isgraphics
+      isstring
+      mad
+      ode15i
+      ode15s
+      openvar
+      quad2d
+      repelem
+      rgb2gray
+      rticks
+      sinint
+      tfqmr
+      thetaticks
+      vecnorm
+      winqueryreg
+      xticklabels
+      xticks
+      yticklabels
+      yticks
+      zticklabels
+      zticks
+
+ ** Deprecated functions.
+
+    The following functions have been deprecated in Octave 4.4 and will
+    be removed from Octave 6 (or whatever version is the second major
+    release after 4.4):
+
+      Function             | Replacement
+      ---------------------|------------------
+      chop                 | sprintf for visual results
+      desktop              | isguirunning
+      tmpnam               | tempname
+      toascii              | double
+      java2mat             | __java2mat__
+
+
+ ** The following functions were deprecated in Octave 4.0 and have been
+    removed from Octave 4.4.
+
+      allow_noninteger_range_as_index
+      bicubic
+      delaunay3
+      do_braindead_shortcircuit_evaluation
+      dump_prefs
+      find_dir_in_path
+      finite
+      fmod
+      fnmatch
+      gmap40
+      loadaudio
+      luinc
+      mouse_wheel_zoom
+      nfields
+      octave_tmp_file_name
+      playaudio
+      saveaudio
+      setaudio
+      syl
+      usage
+
+ ** The "Octave:undefined-return-values" warning ID is obsolete.  Octave
+    now throws an error for any attempts to assign undefined values that
+    might be returned from functions.
+
+ ** Deprecated graphics properties.
+
+    The following properties or allowed corresponding values have been
+    deprecated in Octave 4.4 and will be removed from Octave 6 (or whatever
+    version is the second major release after 4.4):
+
+      Object               | Property                | Value
+      ---------------------|-------------------------|-------------------
+      figure               | doublebuffer            |
+                           | mincolormap             |
+                           | wvisual                 |
+                           | wvisualmode             |
+                           | xdisplay                |
+                           | xvisual                 |
+                           | xvisualmode             |
+      axes                 | drawmode                |
+      annotation           | edgecolor ("rectangle") |
+      text                 | fontweight              | "demi" and "light"
+      uicontrol            | fontweight              | "demi" and "light"
+      uipanel              | fontweight              | "demi" and "light"
+      uibuttongroup        | fontweight              | "demi" and "light"
+
+ ** The rectangle and ellipse annotation property "edgecolor" has been
+    deprecated and will be removed from Octave 6 (or whatever version
+    is the second major release after 4.4).  Use the property "color"
+    instead.
+
+ ** The header file oct-alloc.h has been removed along with the macros
+    that it defined (DECLARE_OCTAVE_ALLOCATOR, DEFINE_OCTAVE_ALLOCATOR,
+    and DEFINE_OCTAVE_ALLOCATOR2).
+
+
+Summary of bugs fixed for version 4.2.2 (2018-03-13):
+----------------------------------------------------
+
+Using the bug numbers listed below, find bug reports on the web using
+the URL https://savannah.gnu.org/bugs/?NNNNN
+
+ ** make leftdiv work for scalar \ int-matrix (bug #51682)
+
+ ** inputdlg.m: Avoid crash when prompt and defaults sizes differ (bug #53209)
+
+ ** tie octave_classdef::numel method to "numel" user override method
+    (bug #46571)
+
+ ** fix performance of Sparse fsolve for complex sparse matrices (bug #53140)
+
+ ** fix performance of Sparse fsolve (bug #53140)
+
+ ** octave.desktop.in: No repetition of Name in Comment field and start I10n
+    (bug #53078)
+
+ ** don't create partially invalid graphic objects (bug #52904)
+
+ ** test for incorrect regexprep on ARM platforms (bug #52810)
+
+ ** fix incorrect regexprep on ARM platforms (bug #52810)
+
+ ** correctly handle reading of characters >127 in scanf family (bug #52681)
+
+ ** fix addpath for UNC paths on Windows (bug #51268)
+
+ ** protect being-deleted objects on figure list from second deletion
+    (bug #52666)
+
+ ** dlmwrite.m: Close fid if filename is only one char long (bug #52679)
+
+ ** set gnuplot color data to half output range when autoscaling zero input
+    range (bug #52624)
+
+ ** add polarplot() to the list of unimplemented functions (bug #52643)
+
+ ** configure.ac: Fix test for Java version (bug #52617)
+
+ ** for gnuplot toolkit, do not map TrueColor data to colormap size (bug #52599)
+
+ ** make wheel scroll behave more consistently in pan mode (bug #52588)
+
+ ** make gnuplot color have three components for interpolated edge color
+    (bug #52595)
+
+ ** simplify gnuplot toolkit scripts for image/non-image data plots (bug #52589)
+
+ ** fix concatenation of empty char matrices with other strings (bug #52542)
+
+ ** build: Fix compiling OCTAVE_ARPACK_OK_2 Fortran code (bug #52425)
+
+ ** trisurf.m, trimesh.m: Fix input validation (bug #48109)
+
+ ** allow uncommenting in editor when line begins with whitespace (bug #52406)
+
+ ** do not extend selection when indenting/commenting in editor (bug #45610)
+
+ ** remove all delimiters from whitespace list in textscan function (bug #52479)
+
+ ** calculate 1-norm of matrices to assess whether NaN or Inf are present
+    (bug #39000)
+
+ ** prevent extra ampersand under KDE in cd-or-add-to-path dialog (bug #52423)
+
+ ** plotyy.m: Fix error when using FUN2 argument (bug #48115)
+
+ ** check ARPACK library for buggy behavior in configure (bug #52425)
+
+ ** fix printing integer type images (bug #51558)
+
+ ** fix segfault in delaunayn when Qhull memory is not properly cleared
+    (bug #52410)
+
+ ** fix segfault with CHOLMOD library and empty matrices (bug #52365)
+
+ ** tag global and persistent symbols as variables when parsing (bug #52363)
+
+ ** properly restore the input stream pointer at end of textscan (bug #52116 et
+    al.)
+
+ ** fix building with Qt4 for Windows (bug #52237)
+
+ ** ensure numeric values are passed for the axes "clim" property (bug #52053)
+
+ ** avoid abort on exit from GUI (bug #50664)
+
+ ** correct auto limits on log axes with negative and zero values (bug #51861)
+
+ ** fix warning in quadgk with zero size interval (bug #51867)
+
+ ** sparse: correctly handle scalar column index (bug #51880)
+
+ ** fix segfault in ichol under certain conditions (bug #51736)
+
+ ** configure: ensure empty pkg-config results are actually empty (bug #51680)
+
+ ** fix 'legend hide' for gnuplot (bug #50483)
+
+ ** qqplot.m: Fix typo in input validation (bug #51458)
+
+ ** add possible '\r' to smartindent regex exprepression (Bug #51279)
+
+ ** make strncmp case sensitive again (bug #51384)
+
+ ** fix possible infinite loop in normest1.m (bug #51241)
+
+ ** also run unwind protect cleanup code on interrupt exceptions (bug #51209)
+
+ ** fix crash when inverting complex matrices with NaNs (bug #51198)
+
+ ** improve accuracy of residue for inputs with very different magnitudes
+    (bug #51148)
+
+ ** publish.m: Fix corruption of results for some code inputs (bug #51178)
+
+ ** residue.m: Remove code that filters out small return values (bug #34266, bug
+    #49291)
+
+ ** avoid possible double free at interpreter exit (bug #51088)
+
+ ** show stack trace for errors in command line and startup files (bug #49346)
+
+ ** interp1.m: Return NA for all columns which are out of bounds (bug #51030)
+
+ ** use idx_type for dimensions instead of int (bug #50934)
+
+ ** show stack trace for wrong type arg errors (bug #50894)
+
+ ** let mouse selection of Qt figures update "currentfigure" (bug #50666)
+
+ ** disable qscintilla editor drag and drop so parent will handle it (Bug
+    #50559)
+
+ ** quadgk.m: Correct error messages which point to quadv (bug #50604)
+
+ ** set version on AppUserModelId (Bug #50428)
+
+ ** version-rcfile: Don't try to execute startup directory, only startup.m
+    (bug #50593)
+
+ ** dlmread: Return empty matrix when requested range is outside data
+    (bug #50102)
+
+ ** fix eigs for generalized nonsymmetric and shift-invert problems (bug #39573)
+
+ ** fix eigs for the generalized eigenvalue problem (bug #50546)
+
+ ** datetick.m: Fix uneven range bugs (bug #50493)
+
+ ** datenum.m: Correct calculation for fractional leap years (bug #50508)
+
+ ** datenum.m: Allow horizontal vectors of dates with fractional months
+    (bug #50508)
+
+ ** datenum.m: Accept legal input of vectors with fractional months (bug #50508)
+
+ ** fix the anchor position in the info text of the doc browser (bug #50422)
+
+ ** fix order of legend labels with plotyy axes (bug #50497)
+
+ ** correct hggroup plot legends for gnuplot toolkit, add legend demo 17 items
+    (bug #49341)
+
+ ** for gnuplot graphics toolkit, show only one key entry for errorbars
+    (bug #49260)
+
+ ** fix compilation of jit caused by cset d0562b3159c7 (bug #50398)
+
+ ** remove inline keyword on file_stat destructor which breaks MacOS compilation
+    (bug #50234)
+
+Documentation bugs fixed:
+
+ ** playblocking.m: Correct documentation about start and limits inputs
+    (bug #51217)
+
+ ** fix eig output argument description (bug #50524)
+
+ ** remove backslashes before double quotes in m-file docstrings (bug #52870)
+
+ ** tweaks to use single quotes instead of double quotes (bug #52870)
+
+ ** correct fieldname of returned struct in ver (bug #52845)
+
+ ** cleanup @code example in Appendix on test functions (bug #52852)
+
+ ** fixes for signal, image, audio, and OOP chapters (bug #52844)
+
+ ** fix issues in geometry, polynomial, and interpolation chapters (bug #52835)
+
+ ** fix TeX documentation for qp and clarify size of inputs (bug #52829)
+
+ ** correct errors in Diagonal matrix chapter of manual (bug #52814)
+
+ ** replace @math{1e^{XXX}} sequences with raw 1eXXX (bug #52827)
+
+ ** use '...' rather than deprecated '\' for line continuation (bug #52828)
+
+ ** make documentation Sec 26.1 more consistent and Sec 25.4 clearer
+    (bug #52685)
+
+ ** documentation fixes for linspace, logspace, lookup (bug #52785)
+
+ ** atan2d.m: Correct documentation to match atan docstring (bug #52786)
+
+ ** small tweaks to fplot and surfnorm docstrings (bug #52761)
+
+ ** rewrite documentation for Advanced Indexing (bug #52723)
+
+ ** delete extra ']' in scanf docstring (bug #52742)
+
+ ** fix mistaken use of space between function and '(' in documentation
+    (bug #52723)
+
+ ** fix various inconsistencies in manual (bug #52712)
+
+ ** fix typo in cset 8354b505ad6b (bug #52702)
+
+ ** fix inconsistencies with char, strvcat, strread docstrings (bug #52702.
+
+ ** explain Matlab compatibility of fopen modes (bug #52644)
+
+ ** update documentation for keywords to include classdef statements
+    (bug #52591)
+
+ ** fix documentation of third input to lsode() (bug #52664)
+
+ ** clarify quiver/quiver3 documentation when a linestyle is given (bug #52608)
+
+ ** new section about classdef classes with example (bug #44590)
+
+ ** correct surface plot explanation of  meshgridded results of 1 input
+    (bug #52536)
+
+ ** fix definition of Delaunay triangulation in docstrings (bug #52416)
+
+ ** accumarray.m: Add '@' to function handles in docstring (bug #52418)
+
+ ** update manual to explain \deg and \circ symbols (bug #52287)
+
+ ** correct documentation for randg (bug #52118)
+
+ ** add documentation about PCRE library regexp stack overflow (bug #51589)
+
+ ** play.m: Correct documentation about start and limits inputs (bug #51217)
+
+ ** redo docstring for qz (bug #50846)
+
+ ** describe optional install dependencies PortAudio and SUNDIALS (bug #50513)
+
+ ** update CITATION date, version, and permalink to manual (bug #47058)
+
+
+Summary of bugs fixed for version 4.2.1 (2017-02-22):
+----------------------------------------------------
+
+Using the bug numbers listed below, find bug reports on the web using
+the URL https://savannah.gnu.org/bugs/?NNNNN
+
+ ** guarantee returning std::string from tilde_expand functions (bug #50234)
+
+ ** workaround segfault in file_stat (bug #50234)
+
+ ** genpropdoc.m: document more graphics properties (bug #50337)
+
+ ** always fork and exec when starting the gui (bug #49609)
+
+ ** print.m: fix regression with -append option (bug #50318)
+
+ ** don't display legend, colorbar, and annotation axes coordinates
+    (bug #50272)
+
+ ** qp.m: Fix regression with incorrect vector dimensions (bug #50067)
+
+ ** prevent infinite loop in global documentation search (bug #50177)
+
+ ** connect execute command signal in editor constructor (bug #50171)
+
+ ** connect editors execute command signal to the required slot (bug #50171)
+
+ ** check if input is class method before declaring it unimplemented
+    (patch #9238) (bug #49694)
+
+ ** workaround segfault when an error occurs while printing (bug #49779)
+
+ ** axis.m: Do not set plotboxaspectratio to 0 (bug #49755)
+
+ ** don't rethrow exception in destructor (bug #49304)
+
+ ** rethrow octave::exit_exception (bug #49304)
+
+ ** update appdata.xml to follow conventions (bug #49952)
+
+ ** mexproto.h (mxAssert, mxAssertS): ensure operator precedence (bug #50050)
+
+ ** calculate error in solution for ode solvers correctly (bug #49950)
+
+ ** use GetModuleFileName for getting octave path in windows (bug #48671)
+
+ ** use C++ updaters for labels color (bug #49980)
+
+ ** distinguish elements vs. bytes in fread (bug #49699)
+
+ ** move frame2im and im2frame to image/ directory (bug #49939)
+
+ ** fix undefined return argument for more than 2 outputs from ode solver
+    (bug #49890)
+
+ ** fix inv for hermitian matrices (bug #49904)
+
+ ** fix gzip for certain types of gzip files (bug #49760)
+
+ ** fix typo in liboctave version info (bug #49860)
+
+ ** initialize ODE Event function with start time (bug #49846)
+
+ ** allow configure test to succeed without implicit fcn decls (bug #49782)
+
+ ** allow external docstrings from .oct files to be found again (bug #49687)
+
+ ** don't require semicolon between property list elements (bug #49819)
+
+ ** display.m: Correctly display output for non-class objects
+    (bug #49753, #49794)
+
+ ** don't run publish.tst unless OSMESA or gnuplot are available (bug #49767)
+
+ ** find help for function aliases again (bug #49687)
+
+ ** legend.m: backport cset 7184b4516a68 (bug #49675)
+
+ ** preserve lasterror info on rethrow (bug #49642)
+
+ ** norm: fix error in input argument validation leading to segfault
+    (bug #49634)
+
+Documentation bugs fixed:
+
+ ** overhaul Java interface description (bug #50299)
+
+ ** add documentation for hex and binary prefix and _ separator
+    (bug #50305, #50334)
+
+ ** fix build of docs broken in sub2ind (bug #50348)
+
+ ** version.m: document that "-release" returns an empty string (bug #50294)
+
+ ** remove trailing "\n\" from sleep and usleep docstrings (bug #50301)
+
+ ** expand documentation for cast() (bug #50201)
+
+ ** correct two entries in Table 34.1 (bug #50203)
+
+ ** oop.txi: Improve table formatting (bug #50203)
+
+ ** fix '##' in middle of docstring/comment lines (bug #50145)
+
+ ** reword documentation about subplots in 15.2.4 (bug #50148)
+
+ ** update unimplemented list of functions and where to find them
+    (bug #50098)
+
+ ** compare_plot_demos: fix HTML syntax, simplify output, remove
+    external deps (bug #49709)
+
+ ** add more depth to explanation of '~' function argument (bug #49444)
+
+ ** correct documentation for javaclasspath file (bug #49873)
+
+ ** small fixes to docstrings (bug #49733)
+
+ ** change text describing demo plots to reflect new ColorOrder (bug #49288)
+
+Other bugs fixed:
+
+ ** add missing classdef test files (bug #49819)
+
+
+Summary of important user-visible changes for version 4.2 (2016-11-13):
+----------------------------------------------------------------------
+
+ ** The parser has been extended to accept, but ignore, underscore
+    characters in numbers.  This facilitates writing more legible code
+    by using '_' as a thousands separator or to group nibbles into bytes
+    in hex constants.
+
+    Examples: 1_000_000 == 1e6  or  0xDE_AD_BE_EF
+
+ ** The parser has been extended to understand binary numbers which
+    begin with the prefix '0b' or '0B'.  The value returned is Octave's
+    default numeric class of double, not at unsigned integer class.
+    Therefore numbers greater than flintmax, i.e., 2^53, will lose some
+    precision.
+
+    Examples: 0b101 == 5  or  0B1100_0001 == 0xC1
+
+ ** gnuplot 4.4 is now the minimum version supported by Octave.
+
+ ** The default set of colors used to plot lines has been updated to be
+    compatible with Matlab's new default color scheme.  The line plot
+    color scheme can be set with the axes property "ColorOrder".
+
+ ** The default colormap is now set to "viridis" which is also the
+    default colormap in matplotlib.  This new colormap fixes some of the
+    main issues with the old default colormap "jet" such as its bad
+    "luminance profile" and is also more similar to Matlab's new default
+    colormap "parula".
+
+ ** The colormap function no longer supports the input argument "list"
+    to show built-in colormaps.  Use "help colormap" to find the
+    built-in colormaps.
+
+ ** The graphics command "hold on" now ensures that each new plot added
+    to an existing plot has a different color or linestyle according to
+    the "ColorOrder" and/or "LineStyleOrder" properties.  This is
+    equivalent to the old command "hold all" and was made for Matlab
+    compatibility.  Existing code *may* produce differently colored
+    plots if it did not specify the color for a plot and relied on each
+    new plot having the default first color in the "ColorOrder"
+    property.
+
+ ** When starting, Octave now looks in the function path for a file
+    startup.m and executes any commands found there.  This change was
+    made to accommodate Matlab users.  Octave has it's own configuration
+    system based on the file .octaverc which is preferred.
+
+ ** Octal ('\NNN') and hex ('\xNN') escape sequences in single quoted
+    strings are now interpreted by the function do_string_escapes().
+    The *printf family of functions now supports octal and hex escape
+    sequences in single-quoted strings for Matlab compatibility.
+
+ ** Special octal and hex escape sequences for the pattern and
+    replacement strings in regular expressions are now interpreted for
+    Matlab compatibility.
+
+    octal: '\oNNN' or '\o{NNN}'
+    hex  : '\xNN'  or '\x{NN}'
+
+ ** Unknown escape sequences in the replacement string for regexprep are
+    now substituted with their unescaped version and no warning is
+    emitted.  This change was made for Matlab compatibility.
+
+    Example: regexprep ('a', 'a', 'x\yz')
+             => 'xyz'
+
+ ** mkfifo now interprets the MODE argument as an octal, not decimal,
+    integer.  This is consistent with the equivalent shell command.
+
+ ** linspace now returns an empty matrix if the number of requested
+    points is 0 or a negative number.  This change was made to be
+    compatible with Matlab releases newer than 2011.  In addition,
+    Octave no longer supports matrix inputs for A or B.
+
+ ** The cov function now returns the complex conjugate of the result
+    from previous versions of Octave.  This change was made for
+    compatibility with Matlab.
+
+ ** condest now works with a normest1 compatible syntax.
+
+ ** The griddata function no longer plots the interpolated mesh if no
+    output argument is requested, instead the vector or array of
+    interpolated values is always returned for Matlab compatibility.
+
+ ** The new function "light" and the corresponding graphics object
+    provide light and shadow effects for patch and surface objects.
+
+ ** The surfnorm function now returns unnormalized (magnitude != 1)
+    normal vectors for compatibility with Matlab.
+
+ ** The normal vectors returned from isonormals have been reversed to
+    point towards smaller values for compatibility with Matlab.
+
+ ** The quadl function now uses an absolute, rather than relative,
+    tolerance for Matlab compatibility.  The default tolerance is 1e-6
+    which may result in lower precision results than previous versions
+    of Octave which used eps as the relative tolerance.  The quadl
+    function has also been extended to return a second output with the
+    total number of function evaluations.
+
+ ** The textscan function is now built-in and is much faster and much
+    more Matlab-compatible than the previous m-file version.
+
+ ** Dialog boxes--errordlg, helpdlg, inputdlg, listdlg, msgbox,
+    questdlg, and warndlg--now exclusively use Qt for rendering.
+    Java based versions have been removed.
+
+ ** The axes properties "TitleFontSizeMultiplier" and "TitleFontWeight"
+    are now implemented which control the default appearance of text
+    created with title().
+    The axes property "LabelFontSizeMultiplier" is now implemented
+    which controls the default appearance of text created with
+    xlabel(), ylabel(), or zlabel().
+
+ ** The graphics property "box" for axes now defaults to "off".
+    To obtain equivalent plots to previous versions of Octave use
+      set (0, "DefaultAxesBox", "on");
+    in your .octaverc file.
+
+ ** The graphics property "boxstyle" has been implemented.  The default
+    is "back" which draws only the back planes in a 3-D view.  If the
+    option is "full" then all planes are drawn.
+
+ ** The graphics property "erasemode" has been hidden, and will
+    eventually be removed.  This property has also been removed
+    from Matlab, and was never implemented in Octave.
+
+ ** The graphics property "graphicssmoothing" for figures now controls
+    whether anti-aliasing will be used for lines.  The default is "on".
+
+ ** The value "zero" for the axes properties "xaxislocation" and
+    "yaxislocation" has been deprecated and will be removed from
+    Octave 5.  Use "origin" instead.
+
+ ** The publish function allows easy publication of Octave script files
+    in HTML or other formats, including figures and output created by
+    this script.  It comes with its counterpart grabcode, which lets one
+    literally grab the HTML published code from a remote website, for
+    example.
+
+ ** The value of the MEX variable TrapFlag now defaults to 0, which will
+    cause Octave to abort execution of a MEX file and return to the
+    prompt if an error is encountered in mexCallMATLAB.
+
+ ** The MEX API now includes the function mexCallMATLABWithTrap.  This
+    function will not abort if an error occurs during mexCallMATLAB, but
+    instead will return execution to the MEX function for error
+    handling.
+
+ ** The MEX API functions for input validation that begin with "mxIs"
+    (e.g., mxIsDouble, mxIsEmpty, etc.) now return type bool rather than
+    type int.
+
+ ** The functions mxAssert and mxAssertS for checking assertions have
+    been added.  In order to avoid a performance penalty they are only
+    compiled in to debug versions of a MEX file, i.e., that are produced
+    when the '-g' option is given to mex or mkoctfile.
+
+ ** Other new MEX API functions include mexEvalStringWithTrap,
+    mxIsScalar, mxCreateUninitNumericArray, mxCreateUninitNumericMatrix.
+
+ ** Other new functions added in 4.2:
+
+      audioformats
+      camlight
+      condeig
+      deg2rad
+      dialog
+      evalc
+      hash
+      im2double
+      isocaps
+      lighting
+      localfunctions
+      material
+      normest1
+      ode23
+      ode45
+      odeget
+      odeplot
+      odeset
+      padecoef
+      profexport
+      psi
+      rad2deg
+      reducepatch
+      reducevolume
+      smooth3
+      uibuttongroup
+
+ ** Deprecated functions.
+
+    The following functions have been deprecated in Octave 4.2 and will
+    be removed from Octave 5 (or whatever version is the second major
+    release after 4.2):
+
+      Function             | Replacement
+      ---------------------|------------------
+      bitmax               | flintmax
+      mahalanobis          | mahal in Octave-Forge statistics pkg
+      md5sum               | hash
+      octave_config_info   | __octave_config_info__
+      onenormest           | normest1
+      sleep                | pause
+      usleep               | pause
+      wavread              | audioread
+      wavwrite             | audiowrite
+
+ ** The following functions were deprecated in Octave 3.8 and have been
+    removed from Octave 4.2.
+
+      default_save_options    java_new
+      gen_doc_cache           java_unsigned_conversion
+      interp1q                javafields
+      isequalwithequalnans    javamethods
+      java_convert_matrix     re_read_readline_init_file
+      java_debug              read_readline_init_file
+      java_invoke             saving_history
+
+ ** The global error_state variable in Octave's C++ API has been
+    deprecated and will be removed in a future version.  Now the error
+    and print_usage functions throw an exception
+    (octave::execution_exception) after displaying the error message.
+    This makes the error and print_usage functions in C++ work more like
+    the corresponding functions in the scripting language.
+
+ ** The default error handlers in liboctave have been updated to use
+    exceptions.  After displaying an error message they no longer return
+    control to the calling program.  The error handler function can be
+    customized through the global variables
+    "current_liboctave_error_handler" and
+    "current_liboctave_error_with_id_handler".  If a programmer has
+    installed their own custom error handling routines when directly
+    linking with liboctave then these must be updated to throw an
+    exception and not return to the calling program.
+
+ ** The system for common errors and warnings has been renamed from
+    gripe_XXX to either err_XXX if error is called or warn_XXX if
+    warning is called.  The gripe_XXX functions are deprecated and will
+    be removed in version 5.
+
+ ** New configure option, --enable-address-sanitizer-flags, to build
+    Octave with memory allocator checks (similar to those in valgrind)
+    built in.
+
+Summary of important user-visible changes for version 4.0 (2015-05-23):
+----------------------------------------------------------------------
+
+ ** A graphical user interface is now the default when running Octave
+    interactively.  The start-up option --no-gui will run the familiar
+    command line interface, and still allows use of the GUI dialogs and
+    qt plotting toolkit.  The option --no-gui-libs runs a minimalist
+    command line interface that does not link with the Qt libraries and
+    uses the fltk toolkit for plotting.
+
+ ** Octave now uses OpenGL graphics with Qt widgets by default.  If
+    OpenGL libraries are not available when Octave is built, gnuplot is
+    used.  You may choose to use the fltk or gnuplot toolkit for
+    graphics by executing the command
+
+      graphics_toolkit ("fltk")
+        OR
+      graphics_toolkit ("gnuplot")
+
+    Adding such a command to your ~/.octaverc file will set the default
+    for each session.
+
+ ** A new syntax for object oriented programming termed classdef has
+    been introduced.  See the manual for more extensive documentation of
+    the classdef interface.
+
+    New keywords:
+
+      classdef      endclassdef
+      enumeration   endenumeration
+      events        endevents
+      methods       endmethods
+      properties    endproperties
+
+ ** New audio functions and classes:
+
+      audiodevinfo  audioread      sound
+      audioinfo     audiorecorder  soundsc
+      audioplayer   audiowrite
+
+ ** Other new classes in Octave 4.0:
+
+      audioplayer    inputParser
+      audiorecorder
+
+ ** Optional stricter Matlab compatibility for ranges, diagonal
+    matrices, and permutation matrices.
+
+    Octave has internal optimizations which use space-efficient storage
+    for the three data types above.  Three new functions have been added
+    which control whether the optimizations are used (default), or
+    whether the data types are stored as full matrices.
+
+    disable_range   disable_diagonal_matrix   disable_permutation_matrix
+
+    All three optimizations are disabled if Octave is started with the
+    --braindead command line option.
+
+ ** The preference
+
+      do_braindead_shortcircuit_evaluation
+
+    is now enabled by default.
+
+ ** The preference
+
+      allow_noninteger_range_as_index
+
+    is now enabled by default and the warning ID
+
+      Octave:noninteger-range-as-index
+
+    is now set to "on" by default instead of "error" by default and "on"
+    for --traditional.
+
+ ** The "backtrace" warning option is now enabled by default.  This
+    change was made for Matlab compatibility.
+
+ ** For compatibility with Matlab, the "ismatrix (x)" function now only
+    checks the dimension of "x".  The old behavior of "ismatrix" is
+    obtained by "isnumeric (x) || islogical (x) || ischar (x)".
+
+ ** The nextpow2 function behavior has been changed for vector inputs.
+    Instead of computing `nextpow2 (length (x))', it will now compute
+    nextpow2 for each element of the input.  This change is Matlab
+    compatible, and also prevents bugs for "vectors" of length 1.
+
+ ** polyeig now returns a row vector of eigenvalues rather than a matrix
+    with the eigenvalues on the diagonal.  This change was made for
+    Matlab compatibility.
+
+ ** Interpolation function changes for Matlab compatibility
+
+    The interpolation method 'cubic' is now equivalent to 'pchip' for
+    interp1, interp2, and interp3.  Previously, 'cubic' was equivalent
+    to 'spline' for interp2.  This may produce different results as
+    'spline' has continuous 1st and 2nd derivatives while 'pchip' only
+    has a continuous 1st derivative.  The methods 'next' and 'previous'
+    have been added to interp1 for compatibility.
+
+ ** The delaunay function has been extended to accept 3-D inputs for
+    Matlab compatibility.  The delaunay function no longer plots the
+    triangulation if no output argument is requested, instead, the
+    triangulation is always returned.  The delaunay3 function which
+    handles 3-D inputs has been deprecated in favor of delaunay.
+
+ ** The trigonometric functions asin and acos return different phase
+    values from previous versions of Octave when the input is outside
+    the principal branch ([-1, 1]).  If the real portion of the input is
+    greater than 1 then the limit from below is taken.  If the real
+    portion is less than 1 then the limit from above is taken.  This
+    criteria is consistent with several other numerical analysis
+    software packages.
+
+ ** The hyperbolic function acosh now returns values with a phase in the
+    range [-pi/2, +pi/2].  Previously Octave returned values in the
+    range [0, pi].  This is consistent with several other numerical
+    analysis software packages.
+
+ ** strfind changes when using empty pattern ("") for Matlab
+    compatibility
+
+    strfind now returns an empty array when the pattern itself is empty.
+    In previous versions of Octave, strfind matched at every character
+    location when the pattern was empty.
+
+      NEW
+      strfind ("abc", "") => []
+      OLD
+      strfind ("abc", "") => [1, 2, 3, 4]
+
+ ** Integer formats used in the printf family of functions now work for
+    64-bit integers and are more compatible with Matlab when printing
+    non-integer values.  Now instead of truncating, Octave will switch
+    the effective format to '%g' in the following circumstances:
+
+      * the value of an integer type (int8, uint32, etc.) value exceeds
+        the maximum for the format specifier.  For '%d', the limit is
+        intmax ('int64') and for '%u' it is intmax ('uint64').
+
+      * round(x) != x or the value is outside the range allowed by the
+        integer format specifier.
+
+    There is still one difference: Matlab switches to '%e' and Octave
+    switches to '%g'.
+
+ ** The functions intersect, setdiff, setxor, and union now return a
+    column vector as output unless the input was a row vector.  This
+    change was made for Matlab compatibility.
+
+ ** The inpolygon function now returns true for points that are within
+    the polygon OR on it's edge.  This change was made for Matlab
+    compatibility.
+
+ ** The archive family of functions (bzip2, gzip, zip, tar) and their
+    unpacking routines (bunzip2, gunzip, unzip, untar, unpack) have been
+    recoded.  Excepting unpack, the default is now to place files in the
+    same directory as the archive (on unpack) or as the original files
+    (on archiving).
+
+ ** Qt and FLTK graphics toolkits now support offscreen rendering on
+    Linux.  In other words, print will work even when the figure
+    visibility is "off".
+
+ ** Z-order stacking issues with patches, grid lines, and line object
+    plot markers for on screen display and printing have all been
+    resolved.  For 2-D plots the axis grid lines can be placed on top of
+    the plot with set (gca, "layer", "top").
+
+ ** The patch graphic object has been overhauled.  It now produces
+    visual results equivalent to Matlab even for esoteric combinations
+    of faces/vertices/cdata.
+
+ ** The polar() plot function now draws a circular theta axis and radial
+    rho axis rather than using a rectangular x/y axis.
+
+ ** linkprop has been completely re-coded for performance and Matlab
+    compatibility.  It now returns a linkprop object which must be
+    stored in a variable for as long as the graphic objects should
+    remain linked.  To unlink properties use 'clear hlink' where hlink
+    is the variable containing the linkprop object.
+
+ ** isprime has been extended to operate on negative and complex inputs.
+
+ ** xor has been extended to accept more than two arguments in which
+    case it performs cumulative XOR reduction.
+
+ ** The following functions now support N-dimensional arrays:
+
+      fliplr   flipud   rot90   rectint
+
+ ** The new warning ID "Octave:data-file-in-path" replaces the three
+    previous separate warning IDs "Octave:fopen-file-in-path",
+    "Octave:load-file-in-path", and "Octave:md5sum-file-in-path".
+
+ ** The warning ID Octave:singular-matrix-div has been replaced by
+    Octave:nearly-singular-matrix and Octave:singular-matrix.
+
+ ** The warning ID Octave:matlab-incompatible has been replaced by
+    Octave:language-extension to better reflect its meaning.
+
+ ** The warning ID Octave:broadcast has been removed.  Instead automatic
+    broadcasting will throw an Octave:language-extension warning.  This
+    warning ID is used for broadcasting as well as other features not
+    available in Matlab.
+
+ ** Other new functions added in 4.0:
+
+      annotation
+      bandwidth
+      cubehelix
+      dir_in_loadpath
+      flip
+      frame2im
+      get_home_directory
+      hgload
+      hgsave
+      ichol
+      ilu
+      im2frame
+      isbanded
+      isdiag
+      isstudent
+      istril
+      istriu
+      javachk
+      jit_failcnt
+      linkaxes
+      lscov
+      metaclass
+      numfields
+      open
+      ordschur
+      pan
+      qmr
+      rotate
+      rotate3d
+      sylvester
+      unsetenv
+      validateattributes
+      zoom
+
+ ** inline() scheduled for eventual deprecation by Matlab
+
+    Functions created through the use of inline are scheduled for
+    deprecation by Matlab.  When this occurs Octave will continue to
+    support inline functions for an indeterminate amount of time before
+    also removing support.  All new code should use anonymous functions
+    in place of inline functions.
+
+ ** Deprecated functions.
+
+    The following functions have been deprecated in Octave 4.0 and will
+    be removed from Octave 4.4 (or whatever version is the second major
+    release after 4.0):
+
+      Function             | Replacement
+      ---------------------|------------------
+      bicubic              | interp2
+      delaunay3            | delaunay
+      dump_prefs           | individual preference get/set routines
+      find_dir_in_path     | dir_in_loadpath
+      finite               | isfinite
+      fmod                 | rem
+      fnmatch              | glob or regexp
+      gmap40               | ----
+      loadaudio            | audioread
+      luinc                | ilu or ichol
+      mouse_wheel_zoom     | mousewheelzoom axes property
+      nfields              | numfields
+      octave_tmp_file_name | tempname
+      playaudio            | audioplayer
+      saveaudio            | audiowrite
+      syl                  | sylvester
+      usage                | print_usage
+
+      allow_noninteger_range_as_index
+      do_braindead_shortcircuit_evaluation
+      setaudio
+
+ ** The following functions were deprecated in Octave 3.8 and will be
+    removed from Octave 4.2 (or whatever version is the second major
+    release after 3.8):
+
+      default_save_options    java_new
+      gen_doc_cache           java_unsigned_conversion
+      interp1q                javafields
+      isequalwithequalnans    javamethods
+      java_convert_matrix     re_read_readline_init_file
+      java_debug              read_readline_init_file
+      java_invoke             saving_history
+
+ ** The following functions were deprecated in Octave 3.6 and have been
+    removed from Octave 4.0.
+
+      cut                polyderiv
+      cor                shell_cmd
+      corrcoef           studentize
+      __error_text__     sylvester_matrix
+      error_text
+
+ ** The following keywords were deprecated in Octave 3.8 and have been
+    removed from Octave 4.0
+
+      static
+
+ ** The following configuration variables were deprecated in Octave 3.8
+    and have been removed from Octave 4.0
+
+      CC_VERSION  (now GCC_VERSION)
+      CXX_VERSION (now GXX_VERSION)
+
+ ** The internal function atan2 of the sparse matrix class has been
+    deprecated in Octave 4.0 and will be removed from Octave 4.4 (or
+    whatever version is the second major release after 4.0).  Use the
+    Fatan2 function with sparse inputs as a replacement.
+
+ ** The internal class Octave_map was deprecated in Octave 3.8 and has
+    been removed from Octave 4.0.  Replacement classes are octave_map
+    (struct array) or octave_scalar_map for a single structure.
+
+ ** Octave now has OpenMP enabled by default if the system provides a
+    working OpenMP implementation.  This allows oct-file modules to take
+    advantage of OpenMP if desired.  This can be disabled when building
+    Octave with the configure option --disable-openmp.
+
+ ** Octave now automatically truncates intermediate calculations done
+    with floating point values to 64 bits.  Some hardware math
+    co-processors, such as the x87, maintain extra precision, but this
+    leads to disagreements in calculations when compared to reference
+    implementations in software using the IEEE standard for double
+    precision.  There was no measurable performance impact to this
+    change, but it may be disabled with the configure option
+    --disable-float-truncate.  MinGW and Cygwin platforms, as well as
+    GCC compilers >= 5.0 require this feature.  Non-x87 hardware, or
+    hardware using SSE options exclusively, can disable float truncation
+    if desired.
+
+---------------------------------------------------------
+
+See NEWS.3 for old news.
--- a/etc/RELEASE.PROCESS	Fri Aug 10 09:08:33 2018 +0200
+++ b/etc/RELEASE.PROCESS	Fri Aug 10 09:09:51 2018 +0200
@@ -3,9 +3,7 @@
    The format of the file is wiki markup and can be directly used as a page
    on wiki.octave.org.
 <!----------------------------------------------------------------------------->
-==4.4.0 Release Tasks==
-
-This page shows the tasks to be completed before the GUI release is finalized.
+==5.0.0 Release Tasks==
 
 <!----------------------------------------------------------------------------->
 # Update gnulib to latest version
@@ -25,23 +23,23 @@
 #: Completion Date:
 <!----------------------------------------------------------------------------->
 # Clear all bugs identified as must-fix
-#* See [[Bug Fix List - 4.2 Release]]
+#* See [[Bug Fix List - 5.0 Release]]
 #: Completion Date:
 <!----------------------------------------------------------------------------->
 # GPL License activities
 #* Update Copyright statements for all source controlled files
-#* Update dates in any other locations (launch message, citation, etc.)
+#* Update dates in any other locations (launch message, citation, MXE files, etc.)
 #* Add any new contributors to contributors.in
 #: Completion Date:
 <!----------------------------------------------------------------------------->
 # Style-check code base
 #* This will produce lots of whitespace changes, but no behavior changes
-#* Must occur after patches have been added since whitespace changes will often prevent patches from applying
+#* Must occur after patches have been added since whitespace changes can prevent patches from applying
 #* m-file style check. Completion Date:
 #* C++ style check.  Completion Date:
 <!----------------------------------------------------------------------------->
 # Run lint checker on code base
-#* cppcheck, -fsanitize, etc.
+#* Possibilities include compiling with -fsanitize=undefined and running 'make check', cppcheck, etc.
 #: Completion Date:
 <!----------------------------------------------------------------------------->
 # Verify 'make check' is passing on all buildbot combinations of OS and compilers
@@ -60,35 +58,49 @@
 #* Verify deprecated functions removed from "see also" links
 #* Verify all formats (Info, HTML, pdf) build correctly
 #* Review NEWS for any features which should be announced
+#* Update major version number in "@subtitle Edition XXX" in octave.texi
 #: Completion Date:
 <!----------------------------------------------------------------------------->
 # Localization and Internationalization
 #* Update language translation files (*.ts)
-#* Submit call for translations for GUI strings.
+#* Create issue report on Savannah as a centralized location for uploading files
+#* Submit call for translations for GUI strings
 #: Completion Date:
 <!----------------------------------------------------------------------------->
 # Verify build process and create release candidates
-#* Update version information in configure.ac/Makefile.am
+#* Update configure.ac with new version information
+#** Update AC_INIT, OCTAVE_MAJOR_VERSION, OCTAVE_MINOR_VERSION, OCTAVE_PATCH_VERSION, OCTAVE_RELEASE_DATE
 #* Verify 'make distcheck' passes
 #* Create release candidate
 #** 'make dist'
 #** hg tag repository with release candidate ID
 #** For Windows, create installer [[Windows Installer]]
 #** Upload release candidate
+#** Add release candidate version to Savannah bug tracker
 #** Announce release candidate to Octave-Maintainers, Octave-Help, on web page
 #** Repeat release candidate cycle until clean
 #: Completion Date:
 <!----------------------------------------------------------------------------->
 # Final Release
-#* hg tag repository with release
+#* Update version information
+#** Update configure.ac (AC_INIT, OCTAVE_MAJOR_VERSION, OCTAVE_MINOR_VERSION, OCTAVE_PATCH_VERSION, OCTAVE_RELEASE_DATE)
+#** Update libtool versioning (configure.ac:OCTAVE_API_VERSION, liboctave/module.mk:%canon_reldir%_%canon_reldir%_current, libinterp/module.mk:%canon_reldir%_liboctinterp_current, libgui/module.mk:%canon_reldir%_liboctgui_current)
+#** Update NEWS (final release date)
+#** Update CITATION (version, year, URL)
+#** Update org.octave.Octave.appdata.xml (version number and release date)
+#* hg tag repository with release version number
 #* merge default onto stable to become the current stable release
-#* add new release version to Savannah bug tracker
+#* Savannah bug tracker version info
+#** add new release version to bug tracker
+#** remove release candidate versions from bug tracker
 #* Announce final release on Octave mailing lists and web site
 #: Completion Date:
 <!----------------------------------------------------------------------------->
 # Post-Release
-#* Update configure.ac/Makefile.am versioning to next release cycle
-#* Remove all deprecated functions scheduled for deletion in default branch
+#* Update configure.ac (AC_INIT, OCTAVE_MAJOR_VERSION, OCTAVE_MINOR_VERSION, OCTAVE_PATCH_VERSION) to next release cycle
+#* Remove all deprecated functions (either OCTAVE_DEPRECATED in C++ or scripts/deprecated for m-files) scheduled for deletion in default branch
+#* Move NEWS file to backup in etc/NEWS.X
+#* Create new NEWS file
 #: Completion Date:
 
 [[Category:Releases]]
--- a/etc/module.mk	Fri Aug 10 09:08:33 2018 +0200
+++ b/etc/module.mk	Fri Aug 10 09:09:51 2018 +0200
@@ -8,6 +8,7 @@
   %reldir%/NEWS.1 \
   %reldir%/NEWS.2 \
   %reldir%/NEWS.3 \
+  %reldir%/NEWS.4 \
   %reldir%/PROJECTS \
   %reldir%/gdbinit
 
@@ -37,9 +38,11 @@
 
 appdatadir = $(datadir)/metainfo
 
-appdata_DATA = \
+APPDATA_XML_FILE := \
   %reldir%/icons/org.octave.Octave.appdata.xml
 
+appdata_DATA = $(APPDATA_XML_FILE)
+
 desktopdir = $(datadir)/applications
 
 desktop_DATA = \
@@ -102,6 +105,23 @@
 	$(ICOTOOL) --create --raw  $(WINDOWS_PNG_ICONS) > $@-t && \
 	mv $@-t $@
 
+## Check that the release date and version number are in
+## $(APPDATA_XML_FILE), but only for actual releases, which means
+## we skip the test if the minor version number is 0 or the patch
+## version number is not 0.
+
+appdata-dist-hook:
+	@test x"$(DIST_IGNORE_APPDATA_VERSION)" != x || \
+	 test $(OCTAVE_MINOR_VERSION) -eq 0 || \
+	 test $(OCTAVE_PATCH_VERSION) -ne 0 || \
+	 grep "<release *date=\"$(OCTAVE_RELEASE_DATE)\" *version=\"$(OCTAVE_VERSION)\"/>" $(srcdir)/$(APPDATA_XML_FILE) > /dev/null || \
+	{ echo; \
+	  echo "Packaging distribution requires the version number in the $(APPDATA_XML_FILE)."; \
+	  echo "Please update first or pass DIST_IGNORE_APPDATA_VERSION=1."; \
+	  echo "Cannot package distribution!"; \
+	  echo; exit 1; }
+.PHONY: appdata-dist-hook
+
 install-data-local: install-icons
 
 uninstall-local: uninstall-icons
--- a/libgui/graphics/ObjectProxy.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/graphics/ObjectProxy.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -135,11 +135,11 @@
     if (! QMetaObject::invokeMethod (m_object, "slotGetPixels", t,
                                      Q_RETURN_ARG (uint8NDArray, retval)))
       {
-        octave_sleep (0.1);
+        octave::sleep (0.1);
         if (! QMetaObject::invokeMethod (m_object, "slotGetPixels", t,
                                          Q_RETURN_ARG (uint8NDArray, retval)))
           {
-            octave_sleep (0.2);
+            octave::sleep (0.2);
             if (! QMetaObject::invokeMethod (m_object, "slotGetPixels", t,
                                              Q_RETURN_ARG (uint8NDArray, retval)))
               error ("getframe: unable to retrieve figure pixels");
--- a/libgui/graphics/PopupMenuControl.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/graphics/PopupMenuControl.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -104,7 +104,7 @@
 
           if (value.numel () > 0)
             {
-              if (value(0) != static_cast<int>(value(0)))
+              if (value(0) != static_cast<int> (value(0)))
                 warning ("popupmenu value should be integer");
               else
                 {
--- a/libgui/graphics/QtHandlesUtils.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/graphics/QtHandlesUtils.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -50,13 +50,13 @@
     QString
     fromStdString (const std::string& s)
     {
-      return QString::fromLocal8Bit (s.c_str ());
+      return QString::fromUtf8 (s.c_str ());
     }
 
     std::string
     toStdString (const QString& s)
     {
-      return std::string (s.toLocal8Bit ().data ());
+      return std::string (s.toUtf8 ().data ());
     }
 
     QStringList
--- a/libgui/graphics/module.mk	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/graphics/module.mk	Fri Aug 10 09:09:51 2018 +0200
@@ -135,6 +135,7 @@
   @QT_CPPFLAGS@ \
   -Ilibgui/graphics -I$(srcdir)/libgui/graphics \
   -Isrc -I$(srcdir)/libgui/src \
+  -Iliboctave \
   -I$(srcdir)/liboctave/array \
   -Iliboctave/numeric -I$(srcdir)/liboctave/numeric \
   -Iliboctave/operators -I$(srcdir)/liboctave/operators \
@@ -145,10 +146,6 @@
   -Ilibinterp/corefcn -I$(srcdir)/libinterp/corefcn \
   -I$(srcdir)/libinterp/octave-value
 
-%canon_reldir%_%canon_reldir%_la_CFLAGS = $(AM_CFLAGS) $(WARN_CFLAGS)
-
-%canon_reldir%_%canon_reldir%_la_CXXFLAGS = $(AM_CXXFLAGS) $(WARN_CXXFLAGS)
-
 noinst_LTLIBRARIES += %reldir%/libgui-graphics.la
 
 libgui_EXTRA_DIST += \
--- a/libgui/module.mk	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/module.mk	Fri Aug 10 09:09:51 2018 +0200
@@ -39,7 +39,7 @@
 
 include %reldir%/src/module.mk
 include %reldir%/graphics/module.mk
-include %reldir%/qterminal-module.mk
+include %reldir%/qterminal/module.mk
 
 nodist_%canon_reldir%_liboctgui_la_SOURCES = \
   %reldir%/liboctgui-build-info.cc
@@ -50,10 +50,6 @@
   -Ilibgui \
   -I$(srcdir)/libgui
 
-%canon_reldir%_liboctgui_la_CFLAGS = $(AM_CFLAGS) $(WARN_CFLAGS)
-
-%canon_reldir%_liboctgui_la_CXXFLAGS = $(AM_CXXFLAGS) $(WARN_CXXFLAGS)
-
 %canon_reldir%_liboctgui_la_LIBADD = \
   %reldir%/qterminal/libqterminal.la \
   %reldir%/src/libgui-src.la \
@@ -62,7 +58,9 @@
   liboctave/liboctave.la \
   $(LIBOCTGUI_LINK_DEPS)
 
-# Increment these as needed and according to the rules in the libtool manual:
+## Increment the following version numbers as needed and according
+## to the rules in the etc/HACKING.md file:
+
 %canon_reldir%_liboctgui_current = 3
 %canon_reldir%_liboctgui_revision = 0
 %canon_reldir%_liboctgui_age = 0
--- a/libgui/qterminal-module.mk	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-noinst_HEADERS += \
-  libgui/qterminal/libqterminal/QTerminal.h \
-  libgui/qterminal/libqterminal/win32/QTerminalColors.h \
-  libgui/qterminal/libqterminal/win32/QWinTerminalImpl.h \
-  libgui/qterminal/libqterminal/unix/BlockArray.h \
-  libgui/qterminal/libqterminal/unix/Character.h \
-  libgui/qterminal/libqterminal/unix/CharacterColor.h \
-  libgui/qterminal/libqterminal/unix/Emulation.h \
-  libgui/qterminal/libqterminal/unix/ExtendedDefaultTranslator.h \
-  libgui/qterminal/libqterminal/unix/ExtendedDefaultTranslatorMac.h \
-  libgui/qterminal/libqterminal/unix/Filter.h \
-  libgui/qterminal/libqterminal/unix/History.h \
-  libgui/qterminal/libqterminal/unix/KeyboardTranslator.h \
-  libgui/qterminal/libqterminal/unix/konsole_wcwidth.h \
-  libgui/qterminal/libqterminal/unix/kpty.h \
-  libgui/qterminal/libqterminal/unix/kpty_p.h \
-  libgui/qterminal/libqterminal/unix/LineFont.h \
-  libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.h \
-  libgui/qterminal/libqterminal/unix/Screen.h \
-  libgui/qterminal/libqterminal/unix/ScreenWindow.h \
-  libgui/qterminal/libqterminal/unix/TerminalCharacterDecoder.h \
-  libgui/qterminal/libqterminal/unix/Vt102Emulation.h \
-  libgui/qterminal/libqterminal/unix/SelfListener.h \
-  libgui/qterminal/libqterminal/unix/TerminalModel.h \
-  libgui/qterminal/libqterminal/unix/TerminalView.h
-
-libgui_qterminal_libqterminal_la_MOC =
-
-OCTAVE_GUI_QTERMINAL_LIBQTERMINAL_MOC = \
-  libgui/qterminal/libqterminal/moc-QTerminal.cc
-
-$(OCTAVE_GUI_QTERMINAL_LIBQTERMINAL_MOC): | libgui/qterminal/libqterminal/$(octave_dirstamp)
-
-DIRSTAMP_FILES += \
-  libgui/qterminal/libqterminal/$(octave_dirstamp)
-
-libgui_qterminal_libqterminal_la_MOC += \
-  $(OCTAVE_GUI_QTERMINAL_LIBQTERMINAL_MOC)
-
-nodist_libgui_qterminal_libqterminal_la_SOURCES = $(libgui_qterminal_libqterminal_la_MOC)
-
-libgui_qterminal_libqterminal_la_CPPFLAGS = \
-  $(AM_CPPFLAGS) \
-  @QT_CPPFLAGS@ \
-  -I$(srcdir)/libgui/qterminal/libqterminal \
-  -I$(srcdir)/libgui/src
-
-libgui_qterminal_libqterminal_la_CFLAGS = $(AM_CFLAGS)
-
-libgui_qterminal_libqterminal_la_CXXFLAGS = $(AM_CXXFLAGS)
-
-if WIN32_TERMINAL
-
-libgui_qterminal_libqterminal_la_SOURCES = \
-  libgui/qterminal/libqterminal/win32/QTerminalColors.cpp \
-  libgui/qterminal/libqterminal/win32/QWinTerminalImpl.cpp \
-  libgui/qterminal/libqterminal/QTerminal.cc
-
-OCTAVE_GUI_QTERMINAL_LIBQTERMINAL_WIN32_MOC = \
-  libgui/qterminal/libqterminal/win32/moc-QWinTerminalImpl.cc
-
-libgui_qterminal_libqterminal_la_MOC += \
-  $(OCTAVE_GUI_QTERMINAL_LIBQTERMINAL_WIN32_MOC)
-
-$(OCTAVE_GUI_QTERMINAL_LIBQTERMINAL_WIN32_MOC): | libgui/qterminal/libqterminal/win32/$(octave_dirstamp)
-
-DIRSTAMP_FILES += \
-  libgui/qterminal/libqterminal/win32/$(octave_dirstamp)
-
-libgui_qterminal_libqterminal_la_CPPFLAGS += -DUNICODE
-
-# This flag is required to let MOC know about Q_OS_WIN32.
-MOC_CPPFLAGS += -DQ_OS_WIN32
-
-else
-
-libgui_qterminal_libqterminal_la_SOURCES = \
-  libgui/qterminal/libqterminal/unix/BlockArray.cpp \
-  libgui/qterminal/libqterminal/unix/Emulation.cpp \
-  libgui/qterminal/libqterminal/unix/Filter.cpp \
-  libgui/qterminal/libqterminal/unix/History.cpp \
-  libgui/qterminal/libqterminal/unix/KeyboardTranslator.cpp \
-  libgui/qterminal/libqterminal/unix/konsole_wcwidth.cpp \
-  libgui/qterminal/libqterminal/unix/kpty.cpp \
-  libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.cpp \
-  libgui/qterminal/libqterminal/unix/Screen.cpp \
-  libgui/qterminal/libqterminal/unix/ScreenWindow.cpp \
-  libgui/qterminal/libqterminal/unix/TerminalCharacterDecoder.cpp \
-  libgui/qterminal/libqterminal/unix/Vt102Emulation.cpp \
-  libgui/qterminal/libqterminal/unix/SelfListener.cpp \
-  libgui/qterminal/libqterminal/unix/TerminalModel.cpp \
-  libgui/qterminal/libqterminal/unix/TerminalView.cpp \
-  libgui/qterminal/libqterminal/QTerminal.cc
-
-OCTAVE_GUI_QTERMINAL_LIBQTERMINAL_UNIX_MOC = \
-  libgui/qterminal/libqterminal/unix/moc-Emulation.cc \
-  libgui/qterminal/libqterminal/unix/moc-Filter.cc \
-  libgui/qterminal/libqterminal/unix/moc-QUnixTerminalImpl.cc \
-  libgui/qterminal/libqterminal/unix/moc-ScreenWindow.cc \
-  libgui/qterminal/libqterminal/unix/moc-SelfListener.cc \
-  libgui/qterminal/libqterminal/unix/moc-TerminalModel.cc \
-  libgui/qterminal/libqterminal/unix/moc-TerminalView.cc \
-  libgui/qterminal/libqterminal/unix/moc-Vt102Emulation.cc
-
-libgui_qterminal_libqterminal_la_MOC += \
-  $(OCTAVE_GUI_QTERMINAL_LIBQTERMINAL_UNIX_MOC)
-
-$(OCTAVE_GUI_QTERMINAL_LIBQTERMINAL_UNIX_MOC): | libgui/qterminal/libqterminal/unix/$(octave_dirstamp)
-
-DIRSTAMP_FILES += \
-  libgui/qterminal/libqterminal/unix/$(octave_dirstamp)
-
-endif
-
-noinst_LTLIBRARIES += libgui/qterminal/libqterminal.la
-
-libgui_CLEANFILES += $(libgui_qterminal_libqterminal_la_MOC)
--- a/libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.cpp	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.cpp	Fri Aug 10 09:09:51 2018 +0200
@@ -188,6 +188,11 @@
 
     m_terminalView->setColorTable(cols);
 
+    QString css = QString ("TerminalView {\n"
+                           "  background: %1;\n"
+                           "}\n").arg (color.name ());
+    setStyleSheet (css);
+
   }
 void QUnixTerminalImpl::setForegroundColor (const QColor& color)
 {
--- a/libgui/qterminal/libqterminal/win32/QWinTerminalImpl.cpp	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/qterminal/libqterminal/win32/QWinTerminalImpl.cpp	Fri Aug 10 09:09:51 2018 +0200
@@ -52,7 +52,6 @@
 #include <versionhelpers.h>
 #include <cstring>
 #include <csignal>
-#include <limits>
 
 #include "QWinTerminalImpl.h"
 #include "QTerminalColors.h"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/qterminal/module.mk	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,117 @@
+noinst_HEADERS += \
+  %reldir%/libqterminal/QTerminal.h \
+  %reldir%/libqterminal/win32/QTerminalColors.h \
+  %reldir%/libqterminal/win32/QWinTerminalImpl.h \
+  %reldir%/libqterminal/unix/BlockArray.h \
+  %reldir%/libqterminal/unix/Character.h \
+  %reldir%/libqterminal/unix/CharacterColor.h \
+  %reldir%/libqterminal/unix/Emulation.h \
+  %reldir%/libqterminal/unix/ExtendedDefaultTranslator.h \
+  %reldir%/libqterminal/unix/ExtendedDefaultTranslatorMac.h \
+  %reldir%/libqterminal/unix/Filter.h \
+  %reldir%/libqterminal/unix/History.h \
+  %reldir%/libqterminal/unix/KeyboardTranslator.h \
+  %reldir%/libqterminal/unix/konsole_wcwidth.h \
+  %reldir%/libqterminal/unix/kpty.h \
+  %reldir%/libqterminal/unix/kpty_p.h \
+  %reldir%/libqterminal/unix/LineFont.h \
+  %reldir%/libqterminal/unix/QUnixTerminalImpl.h \
+  %reldir%/libqterminal/unix/Screen.h \
+  %reldir%/libqterminal/unix/ScreenWindow.h \
+  %reldir%/libqterminal/unix/TerminalCharacterDecoder.h \
+  %reldir%/libqterminal/unix/Vt102Emulation.h \
+  %reldir%/libqterminal/unix/SelfListener.h \
+  %reldir%/libqterminal/unix/TerminalModel.h \
+  %reldir%/libqterminal/unix/TerminalView.h
+
+libgui_qterminal_libqterminal_la_MOC =
+
+OCTAVE_GUI_QTERMINAL_LIBQTERMINAL_MOC = \
+  %reldir%/libqterminal/moc-QTerminal.cc
+
+$(OCTAVE_GUI_QTERMINAL_LIBQTERMINAL_MOC): | %reldir%/libqterminal/$(octave_dirstamp)
+
+DIRSTAMP_FILES += \
+  %reldir%/libqterminal/$(octave_dirstamp)
+
+%canon_reldir%_libqterminal_la_MOC += \
+  $(OCTAVE_GUI_QTERMINAL_LIBQTERMINAL_MOC)
+
+nodist_%canon_reldir%_libqterminal_la_SOURCES = $(%canon_reldir%_libqterminal_la_MOC)
+
+%canon_reldir%_libqterminal_la_CPPFLAGS = \
+  $(AM_CPPFLAGS) \
+  @QT_CPPFLAGS@ \
+  -I$(srcdir)/libgui/qterminal/libqterminal \
+  -I$(srcdir)/libgui/src
+
+%canon_reldir%_libqterminal_la_CFLAGS = ${CPICFLAG} ${XTRA_CFLAGS}
+
+%canon_reldir%_libqterminal_la_CXXFLAGS = ${CXXPICFLAG} ${XTRA_CXXFLAGS}
+
+if WIN32_TERMINAL
+
+%canon_reldir%_libqterminal_la_SOURCES = \
+  %reldir%/libqterminal/win32/QTerminalColors.cpp \
+  %reldir%/libqterminal/win32/QWinTerminalImpl.cpp \
+  %reldir%/libqterminal/QTerminal.cc
+
+OCTAVE_GUI_QTERMINAL_LIBQTERMINAL_WIN32_MOC = \
+  %reldir%/libqterminal/win32/moc-QWinTerminalImpl.cc
+
+%canon_reldir%_libqterminal_la_MOC += \
+  $(OCTAVE_GUI_QTERMINAL_LIBQTERMINAL_WIN32_MOC)
+
+$(OCTAVE_GUI_QTERMINAL_LIBQTERMINAL_WIN32_MOC): | %reldir%/libqterminal/win32/$(octave_dirstamp)
+
+DIRSTAMP_FILES += \
+  %reldir%/libqterminal/win32/$(octave_dirstamp)
+
+%canon_reldir%_libqterminal_la_CPPFLAGS += -DUNICODE
+
+# This flag is required to let MOC know about Q_OS_WIN32.
+MOC_CPPFLAGS += -DQ_OS_WIN32
+
+else
+
+%canon_reldir%_libqterminal_la_SOURCES = \
+  %reldir%/libqterminal/unix/BlockArray.cpp \
+  %reldir%/libqterminal/unix/Emulation.cpp \
+  %reldir%/libqterminal/unix/Filter.cpp \
+  %reldir%/libqterminal/unix/History.cpp \
+  %reldir%/libqterminal/unix/KeyboardTranslator.cpp \
+  %reldir%/libqterminal/unix/konsole_wcwidth.cpp \
+  %reldir%/libqterminal/unix/kpty.cpp \
+  %reldir%/libqterminal/unix/QUnixTerminalImpl.cpp \
+  %reldir%/libqterminal/unix/Screen.cpp \
+  %reldir%/libqterminal/unix/ScreenWindow.cpp \
+  %reldir%/libqterminal/unix/TerminalCharacterDecoder.cpp \
+  %reldir%/libqterminal/unix/Vt102Emulation.cpp \
+  %reldir%/libqterminal/unix/SelfListener.cpp \
+  %reldir%/libqterminal/unix/TerminalModel.cpp \
+  %reldir%/libqterminal/unix/TerminalView.cpp \
+  %reldir%/libqterminal/QTerminal.cc
+
+OCTAVE_GUI_QTERMINAL_LIBQTERMINAL_UNIX_MOC = \
+  %reldir%/libqterminal/unix/moc-Emulation.cc \
+  %reldir%/libqterminal/unix/moc-Filter.cc \
+  %reldir%/libqterminal/unix/moc-QUnixTerminalImpl.cc \
+  %reldir%/libqterminal/unix/moc-ScreenWindow.cc \
+  %reldir%/libqterminal/unix/moc-SelfListener.cc \
+  %reldir%/libqterminal/unix/moc-TerminalModel.cc \
+  %reldir%/libqterminal/unix/moc-TerminalView.cc \
+  %reldir%/libqterminal/unix/moc-Vt102Emulation.cc
+
+%canon_reldir%_libqterminal_la_MOC += \
+  $(OCTAVE_GUI_QTERMINAL_LIBQTERMINAL_UNIX_MOC)
+
+$(OCTAVE_GUI_QTERMINAL_LIBQTERMINAL_UNIX_MOC): | %reldir%/libqterminal/unix/$(octave_dirstamp)
+
+DIRSTAMP_FILES += \
+  %reldir%/libqterminal/unix/$(octave_dirstamp)
+
+endif
+
+noinst_LTLIBRARIES += %reldir%/libqterminal.la
+
+libgui_CLEANFILES += $(%canon_reldir%_libqterminal_la_MOC)
--- a/libgui/src/dialog.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/src/dialog.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -70,15 +70,18 @@
     // Wait for link thread to go to sleep state.
     lock ();
 
-    // Check for a matching button text while ignoring accelerators because
-    // the window manager may have added one in the passed button
-    QString text_clean = rm_amp (button->text ());
-    for (int i = 0; i < m_button_list.count (); i++)
+    if (button)   // button is NULL when dialog is closed
       {
-        if (rm_amp (m_button_list.at (i)) == text_clean)
+        // Check for a matching button text while ignoring accelerators because
+        // the window manager may have added one in the passed button
+        QString text_clean = rm_amp (button->text ());
+        for (int i = 0; i < m_button_list.count (); i++)
           {
-            m_dialog_button = m_button_list.at (i); // text w/o extra accelerator
-            break;
+            if (rm_amp (m_button_list.at (i)) == text_clean)
+              {
+                m_dialog_button = m_button_list.at (i); // text w/o extra accelerator
+                break;
+              }
           }
       }
 
@@ -230,8 +233,7 @@
 
     selector = view->selectionModel ();
     int i = 0;
-    for (QList<int>::const_iterator it = initial.begin ();
-         it != initial.end (); it++)
+    for (auto it = initial.begin (); it != initial.end (); it++)
       {
         QModelIndex idx = m_model->index (initial.value (i++) - 1, 0,
                                           QModelIndex ());
--- a/libgui/src/documentation-dock-widget.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/src/documentation-dock-widget.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -32,14 +32,13 @@
 namespace octave
 {
   documentation_dock_widget::documentation_dock_widget (QWidget *p)
-    : octave_dock_widget (p)
+    : octave_dock_widget ("DocumentationDockWidget", p)
   {
-    setObjectName ("DocumentationDockWidget");
     setWindowIcon (QIcon (":/actions/icons/logo.png"));
     set_title (tr ("Documentation"));
     setStatusTip (tr ("See the documentation for help."));
 
-    m_docs = new octave::documentation (this);
+    m_docs = new documentation (this);
     setWidget (m_docs);
 
     connect (p, SIGNAL (show_doc_signal (const QString&)),
--- a/libgui/src/documentation-dock-widget.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/src/documentation-dock-widget.h	Fri Aug 10 09:09:51 2018 +0200
@@ -53,7 +53,7 @@
 
   private:
 
-    octave::documentation *m_docs;
+    documentation *m_docs;
   };
 }
 
--- a/libgui/src/documentation.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/src/documentation.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -41,26 +41,29 @@
 #include <QLabel>
 #include <QLineEdit>
 #include <QMessageBox>
-#include <QShortcut>
 #include <QTabWidget>
 #include <QToolButton>
 #include <QVBoxLayout>
 
 #include "documentation.h"
 #include "resource-manager.h"
+#include "shortcut-manager.h"
 
 namespace octave
 {
   // The documentation splitter, which is the main widget
   // of the doc dock widget
   documentation::documentation (QWidget *p)
-    : QSplitter (Qt::Horizontal, p)
+    : QSplitter (Qt::Horizontal, p),
+      m_show_shortcut (new QShortcut (p)),
+      m_findnext_shortcut (new QShortcut (p)),
+      m_findprev_shortcut (new QShortcut (p))
   {
     // Get original collection
     QString collection = getenv ("OCTAVE_QTHELP_COLLECTION");
     if (collection.isEmpty ())
-      collection = QString::fromStdString (octave::config::oct_doc_dir ()
-                                           + octave::sys::file_ops::dir_sep_str ()
+      collection = QString::fromStdString (config::oct_doc_dir ()
+                                           + sys::file_ops::dir_sep_str ()
                                            + "octave_interpreter.qhc");
 
     // Setup the help engine with the original collection, use a writable copy
@@ -69,8 +72,8 @@
 
     QString tmpdir = QDir::tempPath();
     m_collection
-      = QString::fromStdString (octave::sys::tempnam (tmpdir.toStdString (),
-                                                      "oct-qhelp-"));
+      = QString::fromStdString (sys::tempnam (tmpdir.toStdString (),
+                                              "oct-qhelp-"));
 
     if (m_help_engine->copyCollectionFile (m_collection))
       m_help_engine->setCollectionFile (m_collection);
@@ -88,7 +91,7 @@
         QMessageBox::warning (this, tr ("Octave Documentation"),
                               tr ("Could not setup the data required for the\n"
                                   "documentation viewer. Only help texts in\n"
-                                  "the Console Widget will be available."));
+                                  "the Command Window will be available."));
         if (m_help_engine)
           delete m_help_engine;
         m_help_engine = 0;
@@ -133,28 +136,30 @@
     v_box_browser_find->addWidget (find_footer);
     browser_find->setLayout (v_box_browser_find);
 
-    QShortcut *show_shortcut = new QShortcut (QKeySequence (QKeySequence::Find), p);
-    show_shortcut->setContext (Qt::WidgetWithChildrenShortcut);
-    connect (show_shortcut, SIGNAL (activated (void)),
+    notice_settings (resource_manager::get_settings ());
+
+    m_show_shortcut->setContext (Qt::WidgetWithChildrenShortcut);
+    connect (m_show_shortcut, SIGNAL (activated (void)),
              m_find_line_edit->parentWidget (), SLOT (show (void)));
-    connect (show_shortcut, SIGNAL (activated (void)),
+    connect (m_show_shortcut, SIGNAL (activated (void)),
              m_find_line_edit, SLOT (selectAll (void)));
-    connect (show_shortcut, SIGNAL (activated (void)),
+    connect (m_show_shortcut, SIGNAL (activated (void)),
              m_find_line_edit, SLOT (setFocus (void)));
     QShortcut *hide_shortcut = new QShortcut (Qt::Key_Escape, p);
+
     hide_shortcut->setContext (Qt::WidgetWithChildrenShortcut);
     connect (hide_shortcut, SIGNAL (activated (void)),
              m_find_line_edit->parentWidget (), SLOT(hide (void)));
     connect (hide_shortcut, SIGNAL (activated (void)),
              m_doc_browser, SLOT (setFocus (void)));
-    QShortcut *findnext_shortcut = new QShortcut (QKeySequence (QKeySequence::FindNext), p);
-    findnext_shortcut->setContext (Qt::WidgetWithChildrenShortcut);
-    connect (findnext_shortcut, SIGNAL (activated (void)),
+
+    m_findnext_shortcut->setContext (Qt::WidgetWithChildrenShortcut);
+    connect (m_findnext_shortcut, SIGNAL (activated (void)),
              this, SLOT(find_forward (void)));
-    QShortcut *findprev_shortcut = new QShortcut (QKeySequence (QKeySequence::FindPrevious), p);
-    findprev_shortcut->setContext (Qt::WidgetWithChildrenShortcut);
-    connect (findprev_shortcut, SIGNAL (activated (void)),
+    m_findprev_shortcut->setContext (Qt::WidgetWithChildrenShortcut);
+    connect (m_findprev_shortcut, SIGNAL (activated (void)),
              this, SLOT(find_backward (void)));
+
     find_footer->hide ();
     m_search_anchor_position = 0;
 
@@ -165,6 +170,7 @@
 
     // Contents
     QHelpContentWidget *content = m_help_engine->contentWidget ();
+    content->setObjectName ("documentation_tab_contents");
     navi->addTab (content, tr ("Contents"));
 
     connect(m_help_engine->contentWidget (),
@@ -195,12 +201,13 @@
     filter_all->setLayout (h_box_index);
 
     QWidget *index_all = new QWidget (navi);
+    index_all->setObjectName ("documentation_tab_index");
     QVBoxLayout *v_box_index = new QVBoxLayout (index_all);
     v_box_index->addWidget (filter_all);
     v_box_index->addWidget (index);
     index_all->setLayout (v_box_index);
 
-    navi->addTab (index_all, tr ("Index"));
+    navi->addTab (index_all, tr ("Function Index"));
 
     connect(m_help_engine->indexWidget (),
             SIGNAL (linkActivated (const QUrl&, const QString&)),
@@ -222,6 +229,7 @@
     v_box_search->addWidget (search);
     v_box_search->addWidget (result);
     search_all->setLayout (v_box_search);
+    search_all->setObjectName ("documentation_tab_search");
     navi->addTab (search_all, tr ("Search"));
 
     connect (search, SIGNAL (search (void)),
@@ -292,10 +300,79 @@
 
   void documentation::global_search_finished (int)
   {
+    if (! m_internal_search.isEmpty ())
+      {
+        QHelpSearchEngine *search_engine = m_help_engine->searchEngine ();
+        if (search_engine)
+          {
+#if defined (HAVE_QHELPSEARCHQUERYWIDGET_SEARCHINPUT)
+            QVector<QHelpSearchResult> res
+              = search_engine->searchResults (0, search_engine->searchResultCount ());
+#else
+            QList< QPair<QString, QString> > res
+              = search_engine->hits (0, search_engine->hitCount ());
+#endif
+
+            if (res.count ())
+              {
+                QUrl url;
+
+                if (res.count () == 1)
+#if defined (HAVE_QHELPSEARCHQUERYWIDGET_SEARCHINPUT)
+                  url = res.front ().url ();
+#else
+                  url = res.front ().first;
+#endif
+                else
+                  {
+                    // Remove the quotes we added
+                    QString search_string = m_internal_search;
+
+                    for (auto r = res.begin (); r != res.end (); r++)
+                      {
+#if defined (HAVE_QHELPSEARCHQUERYWIDGET_SEARCHINPUT)
+                        QString title = r->title ().toLower ();
+                        QUrl tmpurl = r->url ();
+#else
+                        QString title = r->second.toLower ();
+                        QUrl tmpurl = r->first;
+#endif
+                        if (title.contains (search_string.toLower ()))
+                          {
+                            if (title.indexOf (search_string.toLower ()) == 0)
+                              {
+                                url = tmpurl;
+                                break;
+                              }
+                            else if (url.isEmpty ())
+                              url = tmpurl;
+                          }
+                      }
+                  }
+
+                if (! url.isEmpty ())
+                  {
+                    connect (this, SIGNAL (show_single_result (const QUrl)),
+                             m_doc_browser,
+                             SLOT (handle_index_clicked (const QUrl)));
+
+                    emit show_single_result (url);
+                  }
+              }
+           }
+
+        m_internal_search = QString ();
+      }
+
     qApp->restoreOverrideCursor();
   }
 
-  void documentation::notice_settings (const QSettings *) { }
+  void documentation::notice_settings (const QSettings *)
+  {
+    shortcut_manager::shortcut (m_show_shortcut, "editor_edit:find_replace");
+    shortcut_manager::shortcut (m_findnext_shortcut, "editor_edit:find_next");
+    shortcut_manager::shortcut (m_findprev_shortcut, "editor_edit:find_previous");
+  }
 
   void documentation::copyClipboard (void) { }
 
@@ -305,12 +382,51 @@
 
   void documentation::load_ref (const QString& ref_name)
   {
-    if (m_help_engine)
+    if (! m_help_engine)
+      return;
+
+    // First search in the function index
+    QMap<QString, QUrl> found_links
+      = m_help_engine->linksForIdentifier (ref_name);
+
+    QTabWidget *navi = static_cast<QTabWidget*> (widget (0));
+
+    if (found_links.count() > 0)
+      {
+        m_doc_browser->setSource (found_links.constBegin().value());
+
+        // Switch to function index tab
+        m_help_engine->indexWidget()->filterIndices (ref_name);
+        QWidget *index_tab
+          = navi->findChild<QWidget*> ("documentation_tab_index");
+        navi->setCurrentWidget (index_tab);
+      }
+    else
       {
-        QMap<QString, QUrl> found_links
-          = m_help_engine->linksForIdentifier (ref_name);
-        if (found_links.count() > 0)
-          m_doc_browser->setSource (found_links.constBegin().value());
+        // Use full text search to provide the best match
+        QHelpSearchEngine *search_engine = m_help_engine->searchEngine ();
+        QHelpSearchQueryWidget *search_query = search_engine->queryWidget ();
+
+#if defined (HAVE_QHELPSEARCHQUERYWIDGET_SEARCHINPUT)
+        QString query = ref_name;
+        query.prepend ("\"").append ("\"");
+#else
+        QList<QHelpSearchQuery> query;
+        query << QHelpSearchQuery (QHelpSearchQuery::DEFAULT,
+                                   QStringList (QString("\"") + ref_name + QString("\"")));
+#endif
+        m_internal_search = ref_name;
+        search_engine->search (query);
+
+        // Switch to search tab
+#if defined (HAVE_QHELPSEARCHQUERYWIDGET_SEARCHINPUT)
+        search_query->setSearchInput (query);
+#else
+        search_query->setQuery (query);
+#endif
+        QWidget *search_tab
+          = navi->findChild<QWidget*> ("documentation_tab_search");
+        navi->setCurrentWidget (search_tab);
       }
   }
 
@@ -451,5 +567,4 @@
     else
       return QTextBrowser::loadResource(type, url);
   }
-
 }
--- a/libgui/src/documentation.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/src/documentation.h	Fri Aug 10 09:09:51 2018 +0200
@@ -26,6 +26,7 @@
 #include <QComboBox>
 #include <QWidget>
 #include <QSettings>
+#include <QShortcut>
 #include <QSplitter>
 #include <QTextBrowser>
 #include <QtHelp/QHelpEngine>
@@ -53,7 +54,6 @@
   private:
 
     QHelpEngine *m_help_engine;
-
   };
 
 
@@ -92,17 +92,23 @@
     void record_anchor_position (void);
     void handle_cursor_position_change (void);
 
+  signals:
+
+    void show_single_result (const QUrl);
+
   private:
 
     QHelpEngine *m_help_engine;
+    QString m_internal_search;
     documentation_browser *m_doc_browser;
     QLineEdit *m_find_line_edit;
     int m_search_anchor_position;
     QComboBox *m_filter;
     QString m_collection;
-
+    QShortcut *m_show_shortcut;
+    QShortcut *m_findnext_shortcut;
+    QShortcut *m_findprev_shortcut;
   };
-
 }
 
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/dw-main-window.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,252 @@
+/*
+
+Copyright (C) 2013-2018 Torsten <mttl@mailbox.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
+<https://www.gnu.org/licenses/>.
+
+*/
+
+/* This is the main window derived from QMainWindow for being used
+   as the main window in dock widgets like the variable editor or
+   the file editor
+*/
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include <QMenu>
+#include <QDockWidget>
+
+#include "resource-manager.h"
+#include "shortcut-manager.h"
+#include "dw-main-window.h"
+
+namespace octave
+{
+
+  dw_main_window::dw_main_window (QWidget *p)
+    : QMainWindow (p)
+  {
+    // Adding the actions for closing the dock widgets
+    m_close_action
+      = add_action (nullptr,
+                    resource_manager::icon ("window-close",false),
+                    tr ("&Close"),
+                    SLOT (request_close ()), this);
+
+    m_close_all_action
+      = add_action (nullptr,
+                    resource_manager::icon ("window-close",false),
+                    tr ("Close &All"),
+                    SLOT (request_close_all ()), this);
+
+    m_close_others_action
+      = add_action (nullptr,
+                    resource_manager::icon ("window-close",false),
+                    tr ("Close &Other"),
+                    SLOT (request_close_other ()), this);
+
+    m_switch_left_action
+      = add_action (nullptr, QIcon (), tr ("Switch to &Left Widget"),
+                    SLOT (request_switch_left ()), this);
+
+    m_switch_right_action
+      = add_action (nullptr, QIcon (), tr ("Switch to &Right Widget"),
+                    SLOT (request_switch_right ()), this);
+
+    // The list of actions for floating widgets
+    m_actions_list << m_close_action;
+    m_actions_list << m_close_others_action;
+    m_actions_list << m_close_all_action;
+    m_actions_list << m_switch_left_action;
+    m_actions_list << m_switch_right_action;
+
+    notice_settings (resource_manager::get_settings ());
+  }
+
+
+  // Re-implementing the popup menu of the main window
+  QMenu *dw_main_window::createPopupMenu ()
+  {
+    QList<QAction *> new_actions = QList<QAction *> ();
+    new_actions.append (m_close_action);
+    new_actions.append (m_close_others_action);
+    new_actions.append (m_close_all_action);
+
+    QMenu *menu = QMainWindow::createPopupMenu ();
+    QList<QAction *> actions = menu->actions();
+
+    if (actions.length () > 0)
+      {
+        QAction *sep = menu->insertSeparator (actions.at (0));
+        menu->insertActions (sep, new_actions);
+      }
+    else
+      menu->addActions (new_actions);
+
+    return menu;
+  }
+
+
+  // Adding an action to the main window
+  QAction * dw_main_window::add_action (QMenu *menu, const QIcon& icon,
+                                        const QString& text, const char *member,
+                                        QWidget *receiver)
+  {
+    QAction *a;
+    QWidget *r = this;
+
+    if (receiver != nullptr)
+      r = receiver;
+
+    if (menu)
+      a = menu->addAction (icon, text, r, member);
+    else
+      {
+        a = new QAction (icon, text, this);
+        a->setEnabled (true);
+        connect (a, SIGNAL (triggered ()), r, member);
+      }
+
+    addAction (a);  // important for shortcut context
+    a->setShortcutContext (Qt::WidgetWithChildrenShortcut);
+
+    return a;
+  }
+
+  // Update the settings
+  void dw_main_window::notice_settings (const QSettings*)
+  {
+    shortcut_manager::set_shortcut (m_close_action, "editor_file:close");
+    shortcut_manager::set_shortcut (m_close_all_action, "editor_file:close_all");
+    shortcut_manager::set_shortcut (m_close_others_action, "editor_file:close_other");
+
+    shortcut_manager::set_shortcut (m_switch_left_action, "editor_tabs:switch_left_tab");
+    shortcut_manager::set_shortcut (m_switch_right_action, "editor_tabs:switch_right_tab");
+  }
+
+
+  // Slots for handling actions
+
+  // Close current widget
+  void dw_main_window::request_close ()
+  {
+    for (int i = 0; i < m_dw_list.length (); i++)
+      {
+        if (m_dw_list.at (i)->hasFocus ())
+          {
+            m_dw_list.at (i)->close ();
+            if (i > 0)
+              m_dw_list.at (i-1)->setFocus ();
+            break;
+          }
+      }
+  }
+
+  // Close other widgets
+  void dw_main_window::request_close_other ()
+  {
+    for (int i = m_dw_list.length () - 1; i >= 0; i--)
+      {
+        if (! m_dw_list.at (i)->hasFocus ())
+          m_dw_list.at (i)->close ();
+      }
+  }
+
+  // Close all widgets
+  void dw_main_window::request_close_all ()
+  {
+    for (int i = m_dw_list.length () - 1; i >= 0; i--)
+      m_dw_list.at (i)->close ();
+  }
+
+  // Switch to left widget
+  void dw_main_window::request_switch_left ()
+  {
+    request_switch (-1);
+  }
+
+  // Switch to right widget
+  void dw_main_window::request_switch_right ()
+  {
+    request_switch (1);
+  }
+
+  // Switch to left/right widget
+  void dw_main_window::request_switch (int direction)
+  {
+    int active = -1, next;
+
+    for (int i = m_dw_list.length () - 1; i >= 0; i--)
+      {
+        if (m_dw_list.at (i)->hasFocus ())
+          {
+            active = i;
+            break;
+          }
+      }
+
+    if (active == -1)
+      return;
+
+    if (direction == -1 && active == 0)
+      next = m_dw_list.length () - 1;
+    else if (direction == 1 && active == m_dw_list.length () - 1)
+      next = 0;
+    else
+      next = active + direction;
+
+    m_dw_list.at (next)->raise ();
+    m_dw_list.at (next)->activateWindow ();
+    m_dw_list.at (next)->setFocus ();
+  }
+
+
+  // Reimplemented Event
+  bool dw_main_window::event (QEvent *ev)
+  {
+    if (ev->type () == QEvent::ChildAdded ||
+        ev->type () == QEvent::ChildRemoved)
+      {
+        // Adding or Removing a child indicates that a dock widget was
+        // created or removed.
+        // In all cases, the list of dock widgets has to be updated.
+        m_dw_list = findChildren<QDockWidget *>();
+      }
+
+    if (ev->type () == QEvent::StyleChange)
+      {
+        // This might indicate un- or re-docking a widget: Make sure
+        // floating widget get a copy of our actions
+        for (int i = m_dw_list.length () - 1; i >= 0; i--)
+          {
+            // First remove possibly existing actions
+            for (int j = m_actions_list.length () - 1; j >0; j--)
+              m_dw_list.at (i)->removeAction (m_actions_list.at (j));
+
+            // Then add our actions for floating widgets
+            if (m_dw_list.at (i)->isFloating ())
+              m_dw_list.at (i)->addActions (m_actions_list);
+          }
+      }
+
+    return QMainWindow::event (ev);
+  }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/dw-main-window.h	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,89 @@
+/*
+
+Copyright (C) 2013-2018 Torsten <mttl@mailbox.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
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if ! defined (dw_main_window_h)
+#define dw_main_window_h 1
+
+#include <QMainWindow>
+#include <QSettings>
+
+
+namespace octave
+{
+
+  class dw_main_window : public QMainWindow
+  {
+    Q_OBJECT
+
+  public:
+
+    dw_main_window (QWidget *parent = nullptr);
+
+    ~dw_main_window (void) = default;
+
+    // No copying!
+
+    dw_main_window (const dw_main_window&) = delete;
+
+    dw_main_window& operator = (const dw_main_window&) = delete;
+
+  public slots:
+
+    void notice_settings (const QSettings*);
+
+  protected slots:
+
+    virtual QMenu* createPopupMenu ();
+
+    virtual bool event (QEvent *ev);
+
+  private slots:
+
+    void request_close ();
+    void request_close_all ();
+    void request_close_other ();
+
+    void request_switch_left ();
+    void request_switch_right ();
+
+  private:
+
+    void request_switch (int direction);
+
+    QList<QDockWidget *> m_dw_list;
+
+    QAction *add_action (QMenu *menu, const QIcon& icon, const QString& text,
+                         const char *member, QWidget *receiver);
+
+    QAction *m_close_action;
+    QAction *m_close_all_action;
+    QAction *m_close_others_action;
+
+    QAction *m_switch_left_action;
+    QAction *m_switch_right_action;
+
+    QList<QAction *> m_actions_list;
+  };
+
+}
+
+#endif
--- a/libgui/src/files-dock-widget.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/src/files-dock-widget.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -66,9 +66,8 @@
   };
 
   files_dock_widget::files_dock_widget (QWidget *p)
-    : octave_dock_widget (p)
+    : octave_dock_widget ("FilesDockWidget", p)
   {
-    setObjectName ("FilesDockWidget");
     setWindowIcon (QIcon (":/actions/icons/logo.png"));
     set_title (tr ("File Browser"));
     setToolTip (tr ("Browse your files"));
@@ -213,8 +212,7 @@
     m_file_tree_view->setSortingEnabled (true);
     m_file_tree_view->setAlternatingRowColors (true);
     m_file_tree_view->setAnimated (true);
-    m_file_tree_view->setToolTip (
-                                  tr ("Activate to open in editor, right click for alternatives"));
+    m_file_tree_view->setToolTip (tr ("Double click to open file/folder, right click for alternatives"));
 
     // get sort column and order as well as cloumn state (order and width)
 
@@ -389,13 +387,10 @@
 
             if (QFile::exists (abs_fname))
               {
-                if (is_octave_data_file (abs_fname.toStdString ()))
-                  emit load_file_signal (abs_fname);
-                else if (extensions.contains (suffix))
+                if (extensions.contains (suffix))
                   emit open_file (fileInfo.absoluteFilePath ());
                 else
-                  open_item_in_app (m_file_tree_view->selectionModel ()
-                                    ->currentIndex ());
+                  emit open_any_signal (abs_fname);
               }
           }
       }
@@ -550,7 +545,7 @@
     QItemSelectionModel *m = m_file_tree_view->selectionModel ();
     QModelIndexList rows = m->selectedRows ();
 
-    for (QModelIndexList::iterator it = rows.begin (); it != rows.end (); it++)
+    for (auto it = rows.begin (); it != rows.end (); it++)
       {
         QFileInfo file = m_file_system_model->fileInfo (*it);
         if (file.exists ())
@@ -564,7 +559,7 @@
     QItemSelectionModel *m = m_file_tree_view->selectionModel ();
     QModelIndexList rows = m->selectedRows ();
 
-    for (QModelIndexList::iterator it = rows.begin (); it != rows.end (); it++)
+    for (auto it = rows.begin (); it != rows.end (); it++)
       {
         QFileInfo file = m_file_system_model->fileInfo (*it);
         if (file.exists ())
@@ -577,7 +572,7 @@
     QItemSelectionModel *m = m_file_tree_view->selectionModel ();
     QModelIndexList rows = m->selectedRows ();
 
-    for (QModelIndexList::iterator it = rows.begin (); it != rows.end (); it++)
+    for (auto it = rows.begin (); it != rows.end (); it++)
       open_item_in_app (*it);
   }
 
@@ -588,7 +583,7 @@
 
     QStringList selection;
 
-    for (QModelIndexList::iterator it = rows.begin (); it != rows.end (); it++)
+    for (auto it = rows.begin (); it != rows.end (); it++)
       {
         QFileInfo info = m_file_system_model->fileInfo (*it);
 
@@ -669,7 +664,7 @@
     QItemSelectionModel *m = m_file_tree_view->selectionModel ();
     QModelIndexList rows = m->selectedRows ();
 
-    for (QModelIndexList::iterator it = rows.begin (); it != rows.end (); it++)
+    for (auto it = rows.begin (); it != rows.end (); it++)
       {
         QModelIndex index = *it;
 
@@ -823,8 +818,7 @@
 
   void files_dock_widget::popdownmenu_home (bool)
   {
-    QString dir
-      = QString::fromStdString (octave::sys::env::get_home_directory ());
+    QString dir = QString::fromStdString (sys::env::get_home_directory ());
 
     if (dir.isEmpty ())
       dir = QDir::homePath ();
--- a/libgui/src/files-dock-widget.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/src/files-dock-widget.h	Fri Aug 10 09:09:51 2018 +0200
@@ -141,10 +141,14 @@
 
     void displayed_directory_changed (const QString& dir);
 
-    //! Emitted, whenever the user requested to load a file.
+    //! Emitted, whenever the user requested to load a file in the text editor.
 
     void load_file_signal (const QString& fileName);
 
+    //! Emitted, whenever the user requested to open an unknown type file.
+
+    void open_any_signal (const QString& fileName);
+
     //! Emitted, whenever the user requested to run a file.
 
     void run_file_signal (const QFileInfo& info);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/gui-preferences.h	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,74 @@
+/*
+
+Copyright (C) 2017-2018 Torsten <mttl@mailbox.de>
+
+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
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if ! defined (octave_editor_settings_h)
+#define octave_editor_settings_h 1
+
+//#if defined (HAVE_CONFIG_H)
+//#  include "config.h"
+//#endif
+
+#include <QStringList>
+#include <QVariant>
+
+// Structure for the definition of pairs: key and default value
+
+struct gui_pref
+{
+  gui_pref (const QString& key_, QVariant def_): key (key_), def (def_) {}
+  QString   key;  // the key name
+  QVariant  def;  // the default value
+};
+
+// Editor preferences
+
+// Octave comment strings
+const gui_pref ed_comment_str_old ("editor/octave_comment_string", QVariant (0));
+const gui_pref ed_comment_str ("editor/oct_comment_str", QVariant (0));
+const gui_pref ed_uncomment_str ("editor/oct_uncomment_str", QVariant (1 + 2 + 4 + 8));
+
+const QString ed_last_comment_str ("editor/oct_last_comment_str");
+const QStringList ed_comment_strings (QStringList () << "##" << "#" << "%"<< "%%" << "%!");
+const int ed_comment_strings_count = 5;
+
+// Session data
+const gui_pref ed_session_names ("editor/savedSessionTabs",
+                                  QVariant (QStringList ()));
+const gui_pref ed_session_enc ("editor/saved_session_encodings",
+                                  QVariant (QStringList ()));
+const gui_pref ed_session_ind ("editor/saved_session_tab_index",
+                                  QVariant (QStringList ()));
+const gui_pref ed_session_lines ("editor/saved_session_lines",
+                                  QVariant (QStringList ()));
+
+
+// File handling
+const gui_pref ed_show_dbg_file ("editor/show_dbg_file", QVariant (true));
+#if defined (Q_OS_WIN32)
+const gui_pref ed_default_enc ("editor/default_encoding", QVariant ("SYSTEM"));
+#else
+const gui_pref ed_default_enc ("editor/default_encoding", QVariant ("UTF-8"));
+#endif
+
+
+
+#endif
--- a/libgui/src/history-dock-widget.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/src/history-dock-widget.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -42,9 +42,8 @@
 namespace octave
 {
   history_dock_widget::history_dock_widget (QWidget *p)
-    : octave_dock_widget (p)
+    : octave_dock_widget ("HistoryDockWidget", p)
   {
-    setObjectName ("HistoryDockWidget");
     setStatusTip (tr ("Browse and search the command history."));
 
     connect (this, SIGNAL (command_create_script (const QString&)),
@@ -166,9 +165,8 @@
     QString text;
     QItemSelectionModel *selectionModel = m_history_list_view->selectionModel ();
     QModelIndexList rows = selectionModel->selectedRows ();
-    QModelIndexList::iterator it;
     bool prev_valid_row = false;
-    for (it = rows.begin (); it != rows.end (); it++)
+    for (auto it = rows.begin (); it != rows.end (); it++)
       {
         if ((*it).isValid ())
           {
@@ -185,8 +183,7 @@
   {
     QItemSelectionModel *selectionModel = m_history_list_view->selectionModel ();
     QModelIndexList rows = selectionModel->selectedRows ();
-    QModelIndexList::iterator it;
-    for (it = rows.begin () ; it != rows.end (); it++)
+    for (auto it = rows.begin () ; it != rows.end (); it++)
       {
         if ((*it).isValid ())
           emit command_double_clicked ((*it).data ().toString ());
@@ -200,7 +197,7 @@
     QModelIndexList rows = selectionModel->selectedRows ();
 
     bool prev_valid_row = false;
-    for (QModelIndexList::iterator it = rows.begin (); it != rows.end (); it++)
+    for (auto it = rows.begin (); it != rows.end (); it++)
       {
         if ((*it).isValid ())
           {
@@ -273,7 +270,7 @@
     m_history_list_view->setAlternatingRowColors (true);
     m_history_list_view->setEditTriggers (QAbstractItemView::NoEditTriggers);
     m_history_list_view->setStatusTip (
-      tr ("Double-click a command to transfer it to the terminal."));
+      tr ("Double-click a command to transfer it to the Command Window."));
     m_history_list_view->setSelectionMode (QAbstractItemView::ExtendedSelection);
     m_history_list_view->setContextMenuPolicy (Qt::CustomContextMenu);
     connect (m_history_list_view,
--- a/libgui/src/m-editor/file-editor-interface.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/src/m-editor/file-editor-interface.h	Fri Aug 10 09:09:51 2018 +0200
@@ -37,9 +37,8 @@
   public:
 
     file_editor_interface (QWidget *p)
-      : octave_dock_widget (p)
+      : octave_dock_widget ("FileEditor", p)
     {
-      setObjectName ("FileEditor");
     }
 
     virtual ~file_editor_interface (void) = default;
@@ -74,6 +73,8 @@
 
   public slots:
 
+    virtual void handle_file_remove (const QString& o, const QString& n) = 0;
+
     virtual void request_new_file (const QString& command = QString ()) = 0;
 
     virtual void request_open_file (const QString& openFileName,
@@ -82,7 +83,8 @@
                                     bool debug_pointer = false,
                                     bool breakpoint_marker = false,
                                     bool insert = true,
-                                    const QString& cond = "") = 0;
+                                    const QString& cond = "",
+                                    int index = -1) = 0;
   };
 }
 
--- a/libgui/src/m-editor/file-editor-tab.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/src/m-editor/file-editor-tab.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -60,7 +60,9 @@
 #include <QDialogButtonBox>
 #include <QPushButton>
 
+#include "gui-preferences.h"
 #include "resource-manager.h"
+
 #include "file-editor-tab.h"
 #include "file-editor.h"
 #include "octave-txt-lexer.h"
@@ -70,7 +72,6 @@
 
 #include "bp-table.h"
 #include "call-stack.h"
-#include "defaults.h"
 #include "interpreter-private.h"
 #include "interpreter.h"
 #include "oct-map.h"
@@ -80,7 +81,6 @@
 #include "unwind-prot.h"
 #include "utils.h"
 #include "version.h"
-#include "octave-settings.h"
 
 namespace octave
 {
@@ -112,6 +112,9 @@
     _bp_conditions.clear ();
     m_bp_restore_count = 0;
 
+    // Initialize last modification date to now
+    m_last_modified = QDateTime::currentDateTimeUtc();
+
     // disable editor drag & drop so parent can handle
     _edit_area->setAcceptDrops (false);
 
@@ -397,8 +400,8 @@
                 frame.protect_var (buffer_error_messages);
                 buffer_error_messages++;
 
-                octave::bp_table& bptab
-                  = octave::__get_bp_table__ ("handle_context_menu_break_condition");
+                bp_table& bptab
+                  = __get_bp_table__ ("handle_context_menu_break_condition");
 
                 bptab.condition_valid (new_condition.toStdString ());
                 valid = true;
@@ -434,8 +437,11 @@
     QStringList trackedFiles = _file_system_watcher.files ();
     if (! trackedFiles.isEmpty ())
       _file_system_watcher.removePath (_file_name);
-    if (! fileName.isEmpty ())
+    if (! fileName.isEmpty () && QFile::exists (fileName))
+    {
       _file_system_watcher.addPath (fileName);
+      m_last_modified =  QFileInfo (fileName).lastModified ().toUTC ();
+    }
 
     // update lexer and file name variable if file name changes
     if (_file_name != fileName)
@@ -474,10 +480,10 @@
   bool file_editor_tab::unchanged_or_saved (void)
   {
     bool retval = true;
-    if (_edit_area->isModified ())
+    if (_edit_area->isModified () || ! valid_file_name ())
       {
         int ans = QMessageBox::question (nullptr, tr ("Octave Editor"),
-                                         tr ("Cannot add breakpoint to modified file.\n"
+                                         tr ("Cannot add breakpoint to modified or unnamed file.\n"
                                              "Save and add breakpoint, or cancel?"),
                                          QMessageBox::Save | QMessageBox::Cancel, QMessageBox::Save);
 
@@ -713,8 +719,7 @@
                 add_octave_apis (Fiskeyword ());            // add new entries
 
                 interpreter& interp
-                  = __get_interpreter__ (
-                      "file_editor_tab::update_lexer_settings");
+                  = __get_interpreter__ ("file_editor_tab::update_lexer_settings");
 
                 if (octave_builtins)
                   add_octave_apis (F__builtins__ (interp));       // add new entries
@@ -995,8 +1000,7 @@
 
     if (octave_qt_link::file_in_path (info.file, info.dir))
       {
-        octave::bp_table& bptab
-          = octave::__get_bp_table__ ("octave_qt_link::file_in_path");
+        bp_table& bptab = __get_bp_table__ ("octave_qt_link::file_in_path");
 
         bptab.add_breakpoint (info.function_name, line_info, info.condition);
       }
@@ -1009,8 +1013,7 @@
 
     if (octave_qt_link::file_in_path (info.file, info.dir))
       {
-        octave::bp_table& bptab
-          = octave::__get_bp_table__ ("remove_breakpoint_callback");
+        bp_table& bptab = __get_bp_table__ ("remove_breakpoint_callback");
 
         bptab.remove_breakpoint (info.function_name, line_info);
       }
@@ -1020,8 +1023,7 @@
   {
     if (octave_qt_link::file_in_path (info.file, info.dir))
       {
-        octave::bp_table& bptab
-          = octave::__get_bp_table__ ("remove_all_breakpoints_callback");
+        bp_table& bptab = __get_bp_table__ ("remove_all_breakpoints_callback");
 
         bptab.remove_all_breakpoints_in_file (info.function_name, true);
       }
@@ -1443,13 +1445,13 @@
             used_comment_str = QInputDialog::getText (
                                  this, tr ("Comment selected text"),
                                  tr ("Comment string to use:\n"), QLineEdit::Normal,
-                                 settings->value (oct_last_comment_str, comment_str.at (0)).toString (),
+                                 settings->value (ed_last_comment_str, comment_str.at (0)).toString (),
                                  &ok);
 
             if ((! ok) || used_comment_str.isEmpty ())
               return;  // No input, do nothing
             else
-              settings->setValue (oct_last_comment_str, used_comment_str);  // Store last
+              settings->setValue (ed_last_comment_str, used_comment_str);  // Store last
           }
       }
     else
@@ -1947,7 +1949,7 @@
                 // Wait until dbquit has actually occurred
                 while (names.numel () > i)
                   {
-                    octave_sleep (0.01);
+                    octave::sleep (0.01);
                     stk = cs.backtrace (nskip, curr_frame, false);
                     names = stk.contents ("name");
                   }
@@ -2313,6 +2315,20 @@
 
   void file_editor_tab::file_has_changed (const QString&, bool do_close)
   {
+    bool file_exists = QFile::exists (_file_name);
+
+    if (file_exists && ! do_close)
+      {
+        // Test if file is really modified or if just the timezone has
+        // changed. In the latter, just return without doing anything
+        QDateTime modified = QFileInfo (_file_name).lastModified ().toUTC ();
+
+        if (modified <= m_last_modified)
+          return;
+
+        m_last_modified = modified;
+      }
+
     // Prevent popping up multiple message boxes when the file has
     // been changed multiple times by temporarily removing from the
     // file watcher.
@@ -2320,11 +2336,11 @@
     if (! trackedFiles.isEmpty ())
       _file_system_watcher.removePath (_file_name);
 
-    if (QFile::exists (_file_name) && ! do_close)
+    if (file_exists && ! do_close)
       {
+
         // The file is modified
         if (_always_reload_changed_files)
-
           load_file (_file_name);
 
         else
--- a/libgui/src/m-editor/file-editor-tab.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/src/m-editor/file-editor-tab.h	Fri Aug 10 09:09:51 2018 +0200
@@ -25,6 +25,7 @@
 
 #include <QWidget>
 #include <QCloseEvent>
+#include <QDateTime>
 #include <QFileSystemWatcher>
 #include <QSettings>
 #include <QFileInfo>
@@ -284,6 +285,7 @@
     QString _ced;
     QString _encoding;
     QString _new_encoding;
+    QDateTime m_last_modified;
 
     bool _long_title;
     bool _copy_available;
--- a/libgui/src/m-editor/file-editor.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/src/m-editor/file-editor.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -45,6 +45,7 @@
 #include <Qsci/qscicommandset.h>
 
 #include "main-window.h"
+#include "gui-preferences.h"
 #include "oct-map.h"
 #include "octave-link.h"
 #include "utils.h"
@@ -256,22 +257,27 @@
 
     // get the data from the settings file
     QStringList sessionFileNames
-      = settings->value ("editor/savedSessionTabs",
-                         QStringList ()).toStringList ();
+      = settings->value (ed_session_names.key, ed_session_names.def)
+                         .toStringList ();
 
     QStringList session_encodings
-      = settings->value ("editor/saved_session_encodings",
-                         QStringList ()).toStringList ();
+      = settings->value (ed_session_enc.key, ed_session_enc.def)
+                        .toStringList ();
 
     QStringList session_index
-      = settings->value ("editor/saved_session_tab_index",
-                         QStringList ()).toStringList ();
+      = settings->value (ed_session_ind.key, ed_session_ind.def)
+                         .toStringList ();
+
+    QStringList session_lines
+      = settings->value (ed_session_lines.key, ed_session_lines.def)
+                         .toStringList ();
 
     // fill a list of the struct and sort it (depending on index)
     QList<session_data> s_data;
 
     bool do_encoding = (session_encodings.count () == sessionFileNames.count ());
     bool do_index = (session_index.count () == sessionFileNames.count ());
+    bool do_lines = (session_lines.count () == sessionFileNames.count ());
 
     for (int n = 0; n < sessionFileNames.count (); ++n)
       {
@@ -279,7 +285,10 @@
         if (! file.exists ())
           continue;
 
-        session_data item = { 0, sessionFileNames.at (n), QString ()};
+        session_data item = { 0, -1, sessionFileNames.at (n),
+                              QString (), QString ()};
+        if (do_lines)
+          item.line = session_lines.at (n).toInt ();
         if (do_index)
           item.index = session_index.at (n).toInt ();
         if (do_encoding)
@@ -292,7 +301,8 @@
 
     // finally open the file with the desired encoding in the desired order
     for (int n = 0; n < s_data.count (); ++n)
-      request_open_file (s_data.at (n).file_name, s_data.at (n).encoding);
+      request_open_file (s_data.at (n).file_name, s_data.at (n).encoding,
+                         s_data.at (n).line);
   }
 
   void file_editor::focus (void)
@@ -375,29 +385,42 @@
     QStringList fetFileNames;
     QStringList fet_encodings;
     QStringList fet_index;
+    QStringList fet_lines;
 
     // save all open tabs before they are definitely closed
-    for (editor_tab_map_const_iterator p = m_editor_tab_map.begin ();
-         p != m_editor_tab_map.end (); p++)
+    for (auto p = m_editor_tab_map.cbegin ();
+         p != m_editor_tab_map.cend (); p++)
       {
         QString file_name = p->first;   // get file name of tab
         if (! file_name.isEmpty ())      // do not append unnamed files
           {
             fetFileNames.append (file_name);
             fet_encodings.append (m_editor_tab_map[file_name].encoding);
+
             QString index;
+            file_editor_tab *editor_tab
+              = static_cast<file_editor_tab *> (m_editor_tab_map[file_name].fet_ID);
             fet_index.append (index.setNum
-                              (m_tab_widget->indexOf (m_editor_tab_map[file_name].fet_ID)));
+                              (m_tab_widget->indexOf (editor_tab)));
+
+            int l, c;
+            editor_tab->qsci_edit_area ()->getCursorPosition (&l, &c);
+            fet_lines.append (index.setNum (l + 1));
           }
       }
 
-    settings->setValue ("editor/savedSessionTabs", fetFileNames);
-    settings->setValue ("editor/saved_session_encodings", fet_encodings);
-    settings->setValue ("editor/saved_session_tab_index", fet_index);
+    settings->setValue (ed_session_names.key, fetFileNames);
+    settings->setValue (ed_session_enc.key, fet_encodings);
+    settings->setValue (ed_session_ind.key, fet_index);
+    settings->setValue (ed_session_lines.key, fet_lines);
     settings->sync ();
 
     // Finally close all the tabs and return indication that we can exit
-    // the application or close the editor
+    // the application or close the editor.
+    // Closing and deleting the tabs makes the editor visible. In case it was
+    // hidden before, this state has to be restored afterwards
+    bool vis = isVisible ();
+
     for (int i = m_tab_widget->count () - 1; i >= 0; i--)
       {
         // backwards loop since m_tab_widget->count () changes during the loop
@@ -405,6 +428,8 @@
         m_tab_widget->removeTab (i);
       }
 
+    setVisible (vis);
+
     return true;
   }
 
@@ -918,8 +943,9 @@
   void file_editor::handle_file_remove (const QString& old_name,
                                         const QString& new_name)
   {
-    // Clear old lsit of files to reload
+    // Clear old list of file data and declare a structure for file data
     m_tmp_closed_files.clear ();
+    session_data f_data;
 
     // Check if old name is a file or directory
     QFileInfo old (old_name);
@@ -927,36 +953,43 @@
       {
         // Call the function which handles directories and return
         handle_dir_remove (old_name, new_name);
-        return;
       }
-
-    // Is old file open?
-    file_editor_tab *editor_tab
-      = static_cast<file_editor_tab *> (find_tab_widget (old_name));
-
-    if (editor_tab)
+    else
       {
-        // Yes, close it silently
-        m_no_focus = true;  // Remember for not focussing editor
-        editor_tab->file_has_changed (QString (), true);  // Close the tab
-        m_no_focus = false;  // Back to normal
-
-        m_tmp_closed_files << old_name;  // for reloading if error removing
-
-        if (! new_name.isEmpty ())
-          m_tmp_closed_files << new_name;  // store new name
-        else
-          m_tmp_closed_files << ""; // no new name, just removing this file
-
-        // Get and store the related encoding
-        for (editor_tab_map_const_iterator p = m_editor_tab_map.begin ();
-             p != m_editor_tab_map.end (); p++)
+        // It is a single file. Is it open?
+        file_editor_tab *editor_tab
+          = static_cast<file_editor_tab *> (find_tab_widget (old_name));
+
+        if (editor_tab)
           {
-            if (editor_tab == p->second.fet_ID)
+            // YES: Get and store the related encoding
+            for (editor_tab_map_const_iterator p = m_editor_tab_map.begin ();
+                  p != m_editor_tab_map.end (); p++)
               {
-                m_tmp_closed_files << p->second.encoding;
-                break;
+                if (editor_tab == p->second.fet_ID)
+                  {
+                    // Get index and line
+                    f_data.encoding = p->second.encoding;
+                    f_data.index = m_tab_widget->indexOf (editor_tab);
+                    int l, c;
+                    editor_tab->qsci_edit_area ()->getCursorPosition (&l, &c);
+                    f_data.line = l + 1;
+                    break;
+                  }
               }
+
+            // Close it silently
+            m_no_focus = true;  // Remember for not focussing editor
+            editor_tab->file_has_changed (QString (), true);  // Close the tab
+            m_no_focus = false;  // Back to normal
+
+            // For reloading old file if error while removing
+            f_data.file_name = old_name;
+            // For reloading new file (if new_fiel is not empty)
+            f_data.new_file_name = new_name;
+
+            // Add file data to list
+            m_tmp_closed_files << f_data;
           }
       }
   }
@@ -965,13 +998,36 @@
   void file_editor::handle_file_renamed (bool load_new)
   {
     m_no_focus = true;  // Remember for not focussing editor
-    for (int i = 0; i < m_tmp_closed_files.count (); i = i + 3)
+
+    // Loop over all file that have to be reloaded. Start at the end of the
+    // list, otherwise the stored indexes are not correct
+    for (int i = m_tmp_closed_files.count () - 1; i >= 0; i--)
       {
-        if (! m_tmp_closed_files.at (i + load_new).isEmpty ())
-          request_open_file (m_tmp_closed_files.at (i + load_new),
-                             m_tmp_closed_files.at (i+2));
+        // Load old or new file
+        if (load_new)
+          {
+            if (! m_tmp_closed_files.at (i).new_file_name.isEmpty ())
+              request_open_file (m_tmp_closed_files.at (i).new_file_name,
+                                 m_tmp_closed_files.at (i).encoding,
+                                 m_tmp_closed_files.at (i).line,
+                                 false, false, true, "",
+                                 m_tmp_closed_files.at (i).index);
+          }
+        else
+          {
+            request_open_file (m_tmp_closed_files.at (i).file_name,
+                                 m_tmp_closed_files.at (i).encoding,
+                                 m_tmp_closed_files.at (i).line,
+                                 false, false, true, "",
+                                 m_tmp_closed_files.at (i).index);
+          }
+
       }
+
     m_no_focus = false;  // Back to normal focus
+
+    // Clear the list of file data
+    m_tmp_closed_files.clear ();
   }
 
   void file_editor::notice_settings (const QSettings *settings)
@@ -1179,11 +1235,15 @@
                                        const QString& encoding,
                                        int line, bool debug_pointer,
                                        bool breakpoint_marker, bool insert,
-                                       const QString& cond)
+                                       const QString& cond, int index)
   {
     if (call_custom_editor (openFileName, line))
       return;   // custom editor called
 
+    QSettings *settings = resource_manager::get_settings ();
+    bool show_dbg_file
+      = settings->value (ed_show_dbg_file.key, ed_show_dbg_file.def).toBool ();
+
     if (openFileName.isEmpty ())
       {
         // This happens if edit is calles without an argument
@@ -1211,7 +1271,7 @@
                   emit fetab_do_breakpoint_marker (insert, tab, line, cond);
               }
 
-            if (! ((breakpoint_marker || debug_pointer) && is_editor_console_tabbed ()))
+            if (show_dbg_file && ! ((breakpoint_marker || debug_pointer) && is_editor_console_tabbed ()))
               {
                 emit fetab_set_focus (tab);
                 focus ();
@@ -1219,6 +1279,12 @@
           }
         else
           {
+            if (! show_dbg_file && (breakpoint_marker  || debug_pointer))
+              return;   // Do not open a file for showing dbg markers
+
+            if (breakpoint_marker && ! insert)
+              return;   // Never open a file when removing breakpoints
+
             file_editor_tab *fileEditorTab = nullptr;
             // Reuse <unnamed> tab if it hasn't yet been modified.
             bool reusing = false;
@@ -1245,7 +1311,7 @@
                     // Supply empty title then have the file_editor_tab update
                     // with full or short name.
                     if (! reusing)
-                      add_file_editor_tab (fileEditorTab, "");
+                      add_file_editor_tab (fileEditorTab, "", index);
                     fileEditorTab->update_window_title (false);
                     // file already loaded, add file to mru list here
                     QFileInfo file_info = QFileInfo (openFileName);
@@ -1289,7 +1355,6 @@
                         // File does not exist, should it be created?
                         bool create_file = true;
                         QMessageBox *msgBox;
-                        QSettings *settings = resource_manager::get_settings ();
 
                         if (! settings->value ("editor/create_new_file", false).toBool ())
                           {
@@ -1465,10 +1530,15 @@
             e->accept ();
           }
         else
-          e->ignore ();
+          {
+            e->ignore ();
+            return;
+          }
       }
     else
       e->accept ();
+
+    octave_dock_widget::closeEvent (e);
   }
 
   void file_editor::dragEnterEvent (QDragEnterEvent *e)
@@ -1490,7 +1560,7 @@
 
   bool file_editor::is_editor_console_tabbed (void)
   {
-    octave::main_window *w = static_cast<octave::main_window *>(main_win ());
+    main_window *w = static_cast<main_window *>(main_win ());
     QList<QDockWidget *> w_list = w->tabifiedDockWidgets (this);
     QDockWidget *console =
       static_cast<QDockWidget *> (w->get_dock_widget_list ().at (0));
@@ -2045,9 +2115,13 @@
     check_actions ();
   }
 
-  void file_editor::add_file_editor_tab (file_editor_tab *f, const QString& fn)
+  void file_editor::add_file_editor_tab (file_editor_tab *f, const QString& fn,
+                                         int index)
   {
-    m_tab_widget->addTab (f, fn);
+    if (index == -1)
+      m_tab_widget->addTab (f, fn);
+    else
+      m_tab_widget->insertTab (index, f, fn);
 
     // signals from the qscintilla edit area
     connect (f->qsci_edit_area (), SIGNAL (status_update (bool, bool)),
@@ -2310,14 +2384,15 @@
                                        const QString& new_name)
   {
     QDir old_dir (old_name);
+    session_data f_data;
 
     // Have all file editor tabs signal what their filenames are.
     m_editor_tab_map.clear ();
     emit fetab_file_name_query (nullptr);
 
     // Loop over all open files and pick those within old_dir
-    for (editor_tab_map_const_iterator p = m_editor_tab_map.begin ();
-         p != m_editor_tab_map.end (); p++)
+    for (auto p = m_editor_tab_map.cbegin ();
+         p != m_editor_tab_map.cend (); p++)
       {
         QString rel_path_to_file = old_dir.relativeFilePath (p->first);
         if (rel_path_to_file.left (3) != QString ("../"))
@@ -2328,23 +2403,35 @@
             m_no_focus = true;  // Remember for not focussing editor
             file_editor_tab *editor_tab
               = static_cast<file_editor_tab *> (p->second.fet_ID);
-            editor_tab->file_has_changed (QString (), true);  // Close
+            if (editor_tab)
+              {
+                // Get index and line
+                int l, c;
+                editor_tab->qsci_edit_area ()->getCursorPosition (&l, &c);
+                f_data.line = l + 1;
+                f_data.index = m_tab_widget->indexOf (p->second.fet_ID);
+                // Close
+                editor_tab->file_has_changed (QString (), true);
+              }
             m_no_focus = false;  // Back to normal
 
             // Store file for possible later reload
-            m_tmp_closed_files << p->first;
+            f_data.file_name = p->first;
 
             // Add the new file path and the encoding for later reloading
             // if new_name is given
             if (! new_name.isEmpty ())
               {
                 QDir new_dir (new_name);
-                m_tmp_closed_files << new_dir.absoluteFilePath (rel_path_to_file);
+                f_data.new_file_name = new_dir.absoluteFilePath (rel_path_to_file);
               }
             else
-              m_tmp_closed_files << ""; // no new name, just removing this file
-
-            m_tmp_closed_files << p->second.encoding; // store the encoding
+              f_data.new_file_name = ""; // no new name, just removing this file
+
+            f_data.encoding = p->second.encoding; // store the encoding
+
+            // Store data in list for later reloading
+            m_tmp_closed_files << f_data;
           }
       }
   }
@@ -2367,8 +2454,8 @@
     // Check all tabs for the given file name
     QWidget *retval = nullptr;
 
-    for (editor_tab_map_const_iterator p = m_editor_tab_map.begin ();
-         p != m_editor_tab_map.end (); p++)
+    for (auto p = m_editor_tab_map.cbegin ();
+         p != m_editor_tab_map.cend (); p++)
       {
         QString tab_file = p->first;
         if (same_file (file.toStdString (), tab_file.toStdString ())
--- a/libgui/src/m-editor/file-editor.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/src/m-editor/file-editor.h	Fri Aug 10 09:09:51 2018 +0200
@@ -78,7 +78,9 @@
     struct session_data
     {
       int index;
+      int line;
       QString file_name;
+      QString new_file_name;
       QString encoding;
 
       bool operator < (const session_data& other) const
@@ -284,7 +286,7 @@
                             const QString& encoding = QString (),
                             int line = -1, bool debug_pointer = false,
                             bool breakpoint_marker = false, bool insert = true,
-                            const QString& cond = "");
+                            const QString& cond = "", int index = -1);
     void request_preferences (bool);
     void request_styles_preferences (bool);
 
@@ -313,7 +315,8 @@
 
     bool is_editor_console_tabbed (void);
     void construct (void);
-    void add_file_editor_tab (file_editor_tab *f, const QString& fn);
+    void add_file_editor_tab (file_editor_tab *f, const QString& fn,
+                              int index = -1);
     void mru_menu_update (void);
     bool call_custom_editor (const QString& file_name = QString (), int line = -1);
 
@@ -449,11 +452,8 @@
     QStringList m_mru_files;
     QStringList m_mru_files_encodings;
 
-    // List of temporarily closed files for later reloading.
-    // Order: first closed old file
-    //        first new location of closed file
-    //        encoding to use for reload
-    QStringList m_tmp_closed_files;
+    // List of data on temporarily closed files for later reloading.
+    QList<session_data> m_tmp_closed_files;
   };
 }
 
--- a/libgui/src/m-editor/octave-qscintilla.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/src/m-editor/octave-qscintilla.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -50,14 +50,14 @@
 #include <QToolTip>
 #include <QVBoxLayout>
 
-// FIXME: hardwired marker numbers?
-#include "marker.h"
+#include "gui-preferences.h"
+#include "resource-manager.h"
+#include "shortcut-manager.h"
 
 #include "octave-qscintilla.h"
 #include "file-editor-tab.h"
-#include "shortcut-manager.h"
-#include "resource-manager.h"
-#include "octave-settings.h"
+// FIXME: hardwired marker numbers?
+#include "marker.h"
 
 // Return true if CANDIDATE is a "closing" that matches OPENING,
 // such as "end" or "endif" for "if", or "catch" for "try".
@@ -392,29 +392,29 @@
           if (comment)
             {
               // The commenting string is requested
-              if (settings->contains (oct_comment_str))
+              if (settings->contains (ed_comment_str.key))
                 // new version (radio buttons)
-                comment_string = settings->value (oct_comment_str,
-                                                  oct_comment_str_d).toInt ();
+                comment_string = settings->value (ed_comment_str.key,
+                                                  ed_comment_str.def).toInt ();
               else
                 // old version (combo box)
-                comment_string = settings->value (oct_comment_str_old,
-                                                  oct_comment_str_d).toInt ();
+                comment_string = settings->value (ed_comment_str_old.key,
+                                                  ed_comment_str.def).toInt ();
 
-              return (QStringList (oct_comment_strings.at (comment_string)));
+              return (QStringList (ed_comment_strings.at (comment_string)));
             }
           else
             {
               QStringList c_str;
 
               // The possible uncommenting string(s) are requested
-              comment_string = settings->value (oct_uncomment_str,
-                                                oct_uncomment_str_d).toInt ();
+              comment_string = settings->value (ed_uncomment_str.key,
+                                                ed_uncomment_str.def).toInt ();
 
-              for (int i = 0; i < oct_comment_strings_count; i++)
+              for (int i = 0; i < ed_comment_strings_count; i++)
                 {
                   if (1 << i & comment_string)
-                    c_str.append (oct_comment_strings.at (i));
+                    c_str.append (ed_comment_strings.at (i));
                 }
 
               return c_str;
--- a/libgui/src/main-window.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/src/main-window.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -69,6 +69,7 @@
 #include "interpreter.h"
 #include "oct-map.h"
 #include "octave.h"
+#include "parse.h"
 #include "symscope.h"
 #include "utils.h"
 #include "version.h"
@@ -87,7 +88,7 @@
 
 namespace octave
 {
-  octave_interpreter::octave_interpreter (application *app_context)
+  octave_interpreter::octave_interpreter (gui_application *app_context)
     : QObject (), m_app_context (app_context)
   { }
 
@@ -105,6 +106,18 @@
 
         interp.initialize ();
 
+        if (m_app_context->start_gui_p ())
+          {
+            input_system& input_sys = interp.get_input_system ();
+
+            input_sys.PS1 (">> ");
+            input_sys.PS2 ("");
+
+            tree_evaluator& tw = interp.get_evaluator ();
+
+            tw.PS4 ("");
+          }
+
         if (interp.initialized ())
           {
             // The interpreter should be completely ready at this point so let
@@ -198,6 +211,8 @@
           = settings->value ("news/last_time_checked", QDateTime ()).toDateTime ();
 
         serial = settings->value ("news/last_news_item", 0).toInt ();
+        m_default_encoding = settings->value (ed_default_enc.key,
+                                              ed_default_enc.def).toString ();
       }
 
     QDateTime current = QDateTime::currentDateTime ();
@@ -362,8 +377,11 @@
                                       QFileDialog::DontUseNativeDialog);
 
     if (! file.isEmpty ())
-      octave_link::post_event (this, &main_window::save_workspace_callback,
-                               file.toStdString ());
+      {
+        octave_cmd_builtin *cmd
+                = new octave_cmd_builtin (&Fsave, ovl (file.toStdString ()));
+        m_cmd_queue.add_cmd (cmd);
+      }
   }
 
   void main_window::handle_load_workspace_request (const QString& file_arg)
@@ -376,13 +394,26 @@
                                            QFileDialog::DontUseNativeDialog);
 
     if (! file.isEmpty ())
-      octave_link::post_event (this, &main_window::load_workspace_callback,
-                               file.toStdString ());
+      {
+        octave_cmd_builtin *cmd
+            = new octave_cmd_builtin (&Fload, ovl (file.toStdString ()),
+                                      0, octave_cmd_builtin::CMD_UPD_WORKSPACE);
+        m_cmd_queue.add_cmd (cmd);
+      }
+  }
+
+  void main_window::handle_open_any_request (const QString& file_arg)
+  {
+    if (! file_arg.isEmpty ())
+      octave_link::post_event (this, &main_window::open_any_callback,
+                               file_arg.toStdString ());
   }
 
   void main_window::handle_clear_workspace_request (void)
   {
-    octave_link::post_event (this, &main_window::clear_workspace_callback);
+    octave_cmd_builtin *cmd
+          = new octave_cmd_builtin (&Fclear, ovl ());
+    m_cmd_queue.add_cmd (cmd);
   }
 
   void main_window::handle_clear_command_window_request (void)
@@ -431,6 +462,19 @@
     handle_edit_mfile_request (name, QString (), QString (), line);
   }
 
+  void main_window::file_remove_proxy (const QString& o, const QString& n)
+  {
+    // Wait for worker to suspend
+    m_octave_qt_link->lock ();
+
+    // Close the file if opened
+    m_editor_window->handle_file_remove (o, n);
+
+    // We are done: Unlock and wake the worker thread
+    m_octave_qt_link->unlock ();
+    m_octave_qt_link->wake_all ();
+  }
+
   void main_window::open_online_documentation_page (void)
   {
     QDesktopServices::openUrl (
@@ -738,6 +782,17 @@
     set_global_shortcuts (m_active_dock == m_command_window);
     disable_menu_shortcuts (m_active_dock == m_editor_window);
 
+    // Ckeck whether some octave internal preferences have to be updated
+    QString new_default_encoding
+      = settings->value (ed_default_enc.key, ed_default_enc.def).toString ();
+    if (new_default_encoding != m_default_encoding)
+      {
+        m_default_encoding = new_default_encoding;
+        octave_cmd_builtin *cmd = new octave_cmd_builtin (
+                                    &F__mfile_encoding__,
+                                    ovl (m_default_encoding.toStdString ()));
+        m_cmd_queue.add_cmd (cmd);
+      }
 
     // Set cursor blinking depending on the settings
     // Cursor blinking: consider old terminal related setting if not yet set
@@ -853,8 +908,11 @@
     QFileInfo fileInfo (xdir);
 
     if (fileInfo.exists () && fileInfo.isDir ())
-      octave_link::post_event (this, &main_window::change_directory_callback,
-                               xdir.toStdString ());
+      {
+        octave_cmd_builtin *cmd
+                = new octave_cmd_builtin (&Fcd, ovl (xdir.toStdString ()));
+        m_cmd_queue.add_cmd (cmd);
+      }
   }
 
   void main_window::change_directory_up (void)
@@ -1090,20 +1148,18 @@
     octave_value_list fct = F__which__ (interp, ovl (fname.toStdString ()),0);
     octave_map map = fct(0).map_value ();
 
-    QString type = QString::fromStdString (
-                                           map.contents ("type").data ()[0].string_value ());
-    QString name = QString::fromStdString (
-                                           map.contents ("name").data ()[0].string_value ());
+    std::string type = map.contents ("type").data ()[0].string_value ();
+    std::string name = map.contents ("name").data ()[0].string_value ();
 
     QString message = QString ();
     QString filename = QString ();
 
-    if (type == QString ("built-in function"))
+    if (type == "built-in function")
       {
         // built in function: can't edit
         message = tr ("%1 is a built-in function");
       }
-    else if (type.isEmpty ())
+    else if (type == "")
       {
         // function not known to octave -> try directory of edited file
         // get directory
@@ -1148,7 +1204,7 @@
         QMessageBox *msgBox
           = new QMessageBox (QMessageBox::Critical,
                              tr ("Octave Editor"),
-                             message.arg (name),
+                             message.arg (QString::fromStdString (name)),
                              QMessageBox::Ok, this);
 
         msgBox->setWindowModality (Qt::NonModal);
@@ -1253,7 +1309,7 @@
 
                 if (visible)
                   {
-                    if (settings->value ("DockWidgets/" + widget->objectName ()
+                    if (settings->value ("DockWidgets/" + name
                                          + "_minimized").toBool ())
                       widget->showMinimized ();
                     else
@@ -1822,6 +1878,9 @@
         connect (m_file_browser_window, SIGNAL (load_file_signal (const QString&)),
                  this, SLOT (handle_load_workspace_request (const QString&)));
 
+        connect (m_file_browser_window, SIGNAL (open_any_signal (const QString&)),
+                 this, SLOT (handle_open_any_request (const QString&)));
+
         connect (m_file_browser_window, SIGNAL (find_files_signal (const QString&)),
                  this, SLOT (find_files (const QString&)));
 
@@ -1886,6 +1945,7 @@
                                                                 int,
                                                                 const QString&)));
 
+        // Signals for removing/renaming files/dirs in the file browser
         connect (m_file_browser_window,
                  SIGNAL (file_remove_signal (const QString&, const QString&)),
                  m_editor_window,
@@ -1893,6 +1953,13 @@
 
         connect (m_file_browser_window, SIGNAL (file_renamed_signal (bool)),
                  m_editor_window, SLOT (handle_file_renamed (bool)));
+
+        // Signals for removing/renaming files/dirs in the temrinal window
+        connect (m_octave_qt_link,
+                 SIGNAL (file_remove_signal (const QString&, const QString&)),
+                 this, SLOT (file_remove_proxy (const QString&, const QString&)));
+        connect (m_octave_qt_link, SIGNAL (file_renamed_signal (bool)),
+                 m_editor_window, SLOT (handle_file_renamed (bool)));
 #endif
 
         octave_link::post_event (this,
@@ -1962,6 +2029,12 @@
                  this, SLOT (process_settings_dialog_request (void)));
 
         connect (m_octave_qt_link,
+                 SIGNAL (gui_preference_signal (const QString&, const QString&,
+                                                QString*)),
+                 this, SLOT (gui_preference (const QString&, const QString&,
+                                             QString*)));
+
+        connect (m_octave_qt_link,
                  SIGNAL (edit_file_signal (const QString&)),
                  m_active_editor,
                  SLOT (handle_edit_file_request (const QString&)));
@@ -2465,24 +2538,63 @@
              this, SLOT (handle_undo_request (void)));
   }
 
-  void main_window::save_workspace_callback (const std::string& file)
-  {
-    // INTERPRETER THREAD
-
-    Fsave (ovl (file));
-  }
-
-  void main_window::load_workspace_callback (const std::string& file)
+  QString main_window::gui_preference_adjust (const QString& key,
+                                              const QString& value)
   {
-    // INTERPRETER THREAD
-
-    Fload (ovl (file));
-
-    symbol_scope scope
-      = __get_current_scope__ ("main_window::load_workspace_callback");
-
-    if (scope)
-      octave_link::set_workspace (true, scope);
+    QString adjusted_value = value;
+
+    // Immediately return if no new value is given
+    if (adjusted_value.isEmpty ())
+      return adjusted_value;
+
+    // Not all encodings are available. Encodings are uppercase and do not
+    // use CPxxx but IBMxxx or WINDOWS-xxx.
+    if (key == ed_default_enc.key)
+      {
+        adjusted_value = adjusted_value.toUpper ();
+
+        QStringList codecs;
+        resource_manager::get_codecs (&codecs);
+
+        QRegExp re ("^CP(\\d+)$");
+        if (re.indexIn (adjusted_value) > -1)
+          {
+            if (codecs.contains ("IBM" + re.cap (1)))
+              adjusted_value = "IBM" + re.cap (1);
+            else if (codecs.contains ("WINDOWS-" + re.cap (1)))
+              adjusted_value = "WINDOWS-" + re.cap (1);
+            else
+              adjusted_value.clear ();
+          }
+        else if (! codecs.contains (adjusted_value))
+          adjusted_value.clear ();
+      }
+
+    return adjusted_value;
+  }
+
+  void main_window::gui_preference (const QString& key, const QString& value,
+                                    QString* read_value)
+  {
+    QSettings *settings = resource_manager::get_settings ();
+    *read_value = settings->value (key).toString ();
+
+    // Wait for worker to suspend
+    m_octave_qt_link->lock ();
+
+    // Some preferences need extra handling
+    QString adjusted_value = gui_preference_adjust (key, value);
+
+    if (! adjusted_value.isEmpty () && (*read_value != adjusted_value))
+      {
+        // Change settings only for new, non-empty values
+        settings->setValue (key, QVariant (adjusted_value));
+        emit settings_changed (settings);
+      }
+
+    // We are done: Unlock and wake the worker thread
+    m_octave_qt_link->unlock ();
+    m_octave_qt_link->wake_all ();
   }
 
   void main_window::rename_variable_callback (const main_window::name_pair& names)
@@ -2533,14 +2645,18 @@
     command_editor::set_screen_size (sz.first, sz.second);
   }
 
-  void main_window::clear_workspace_callback (void)
+  void main_window::open_any_callback (const std::string& file)
   {
     // INTERPRETER THREAD
 
-    interpreter& interp
-      = __get_interpreter__ ("main_window::clear_workspace_callback");
-
-    Fclear (interp);
+    octave::feval ("open", ovl (file));
+
+    // Update the workspace since open.m may have loaded new variables.
+    symbol_scope scope
+      = __get_current_scope__ ("main_window::open_any_callback");
+
+    if (scope)
+          octave_link::set_workspace (true, scope);
   }
 
   void main_window::clear_history_callback (void)
@@ -2578,13 +2694,6 @@
     Fdrawnow ();
   }
 
-  void main_window::change_directory_callback (const std::string& directory)
-  {
-    // INTERPRETER THREAD
-
-    Fcd (ovl (directory));
-  }
-
   void main_window::configure_shortcuts (void)
   {
     // file menu
--- a/libgui/src/main-window.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/src/main-window.h	Fri Aug 10 09:09:51 2018 +0200
@@ -71,7 +71,7 @@
 
   public:
 
-    octave_interpreter (application *app_context);
+    octave_interpreter (gui_application *app_context);
 
     ~octave_interpreter (void) = default;
 
@@ -88,7 +88,7 @@
 
   private:
 
-    application *m_app_context;
+    gui_application *m_app_context;
   };
 
   //! Represents the main window.
@@ -145,6 +145,7 @@
     void report_status_message (const QString& statusMessage);
     void handle_save_workspace_request (void);
     void handle_load_workspace_request (const QString& file = QString ());
+    void handle_open_any_request (const QString& file = QString ());
     void handle_clear_workspace_request (void);
     void handle_clear_command_window_request (void);
     void handle_clear_history_request (void);
@@ -154,6 +155,7 @@
     void new_file (const QString& commands = QString ());
     void open_file (const QString& file_name = QString (), int line = -1);
     void edit_mfile (const QString&, int);
+    void file_remove_proxy (const QString& o, const QString& n);
     void open_online_documentation_page (void);
     void display_release_notes (void);
     void load_and_display_community_news (int serial = -1);
@@ -239,6 +241,8 @@
                                    const QString& dirname,
                                    const QString& multimode);
 
+    void gui_preference (const QString& key, const QString& value,
+                         QString* read_value);
     void handle_show_doc (const QString& file);
     void handle_register_doc (const QString& file);
     void handle_unregister_doc (const QString& file);
@@ -318,9 +322,9 @@
 
     void construct_tool_bar (void);
 
-    void save_workspace_callback (const std::string& file);
+    QString gui_preference_adjust (const QString& key, const QString& value);
 
-    void load_workspace_callback (const std::string& file);
+    void open_any_callback (const std::string& file);
 
     void rename_variable_callback (const name_pair& names);
 
@@ -332,8 +336,6 @@
 
     void set_screen_size_callback (const int_pair&);
 
-    void clear_workspace_callback (void);
-
     void clear_history_callback (void);
 
     void refresh_workspace_callback (void);
@@ -342,8 +344,6 @@
 
     void new_figure_callback (void);
 
-    void change_directory_callback (const std::string& directory);
-
     void configure_shortcuts (void);
 
     QList<octave_dock_widget *> dock_widget_list (void);
@@ -358,6 +358,8 @@
 
     QHash<QMenu*, QStringList> m_hash_menu_text;
 
+    QString m_default_encoding;
+
     //! Toolbar.
 
     QStatusBar *m_status_bar;
--- a/libgui/src/module.mk	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/src/module.mk	Fri Aug 10 09:09:51 2018 +0200
@@ -108,6 +108,7 @@
   %reldir%/moc-dialog.cc \
   %reldir%/moc-documentation-dock-widget.cc \
   %reldir%/moc-documentation.cc \
+  %reldir%/moc-dw-main-window.cc \
   %reldir%/moc-files-dock-widget.cc \
   %reldir%/moc-history-dock-widget.cc \
   %reldir%/moc-main-window.cc \
@@ -153,6 +154,8 @@
   %reldir%/octave-dock-widget.h \
   %reldir%/documentation-dock-widget.h \
   %reldir%/documentation.h \
+  %reldir%/dw-main-window.h \
+  %reldir%/gui-preferences.h \
   %reldir%/external-editor-interface.h \
   %reldir%/files-dock-widget.h \
   %reldir%/history-dock-widget.h \
@@ -167,7 +170,6 @@
   %reldir%/octave-gui.h \
   %reldir%/octave-cmd.h \
   %reldir%/octave-qt-link.h \
-  %reldir%/octave-settings.h \
   %reldir%/resource-manager.h \
   %reldir%/settings-dialog.h \
   %reldir%/shortcut-manager.h \
@@ -186,6 +188,7 @@
   %reldir%/dialog.cc \
   %reldir%/documentation-dock-widget.cc \
   %reldir%/documentation.cc \
+  %reldir%/dw-main-window.cc \
   %reldir%/external-editor-interface.cc \
   %reldir%/files-dock-widget.cc \
   %reldir%/history-dock-widget.cc \
@@ -228,6 +231,7 @@
   -Ilibgui/src -I$(srcdir)/libgui/src \
   -I$(srcdir)/%reldir%/m-editor \
   -I$(srcdir)/libgui/graphics \
+  -Iliboctave \
   -I$(srcdir)/liboctave/array \
   -Iliboctave/numeric -I$(srcdir)/liboctave/numeric \
   -Iliboctave/operators -I$(srcdir)/liboctave/operators \
@@ -239,10 +243,6 @@
   -I$(srcdir)/libinterp/octave-value \
   -I$(srcdir)/liboctave/wrappers
 
-%canon_reldir%_%canon_reldir%_la_CFLAGS = $(AM_CFLAGS) $(WARN_CFLAGS)
-
-%canon_reldir%_%canon_reldir%_la_CXXFLAGS = $(AM_CXXFLAGS) $(WARN_CXXFLAGS)
-
 noinst_LTLIBRARIES += %reldir%/libgui-src.la
 
 libgui_EXTRA_DIST += \
--- a/libgui/src/octave-cmd.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/src/octave-cmd.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -28,72 +28,98 @@
 
 #include "octave-cmd.h"
 
-#include "octave-qt-link.h"
+#include "builtin-defun-decls.h"
 #include "cmd-edit.h"
-#include "builtin-defun-decls.h"
+#include "interpreter-private.h"
+#include "interpreter.h"
+#include "octave-qt-link.h"
 #include "utils.h"
 
 namespace octave
 {
-  void octave_cmd_exec::execute (void)
+  void octave_cmd_exec::execute (interpreter&)
   {
-    std::string pending_input = octave::command_editor::get_current_line ();
+    std::string pending_input = command_editor::get_current_line ();
 
-    octave::command_editor::set_initial_input (pending_input);
-    octave::command_editor::replace_line (m_cmd.toStdString ());
-    octave::command_editor::redisplay ();
-    octave::command_editor::accept_line ();
+    command_editor::set_initial_input (pending_input);
+    command_editor::replace_line (m_cmd.toStdString ());
+    command_editor::redisplay ();
+    command_editor::accept_line ();
   }
 
-  void octave_cmd_eval::execute (void)
+  void octave_cmd_eval::execute (interpreter&)
   {
     QString function_name = m_info.fileName ();
     function_name.chop (m_info.suffix ().length () + 1);
     std::string file_path = m_info.absoluteFilePath ().toStdString ();
 
-    std::string pending_input = octave::command_editor::get_current_line ();
+    std::string pending_input = command_editor::get_current_line ();
 
     if (valid_identifier (function_name.toStdString ()))
       {
         // valid identifier: call as function with possibility to debug
         std::string path = m_info.absolutePath ().toStdString ();
         if (octave_qt_link::file_in_path (file_path, path))
-          octave::command_editor::replace_line (function_name.toStdString ());
+          command_editor::replace_line (function_name.toStdString ());
       }
     else
       {
         // no valid identifier: use Fsource (), no debug possible
         Fsource (ovl (file_path));
-        octave::command_editor::replace_line ("");
+        command_editor::replace_line ("");
       }
 
-    octave::command_editor::set_initial_input (pending_input);
-    octave::command_editor::redisplay ();
+    command_editor::set_initial_input (pending_input);
+    command_editor::redisplay ();
 
-    octave::command_editor::accept_line ();
+    command_editor::accept_line ();
   }
 
-  void octave_cmd_debug::execute (void)
+  void octave_cmd_builtin::execute (interpreter& interp)
+  {
+    if (m_callback_fi)
+      m_callback_fi (interp, m_argin, m_nargin);
+    else if (m_callback_f)
+      m_callback_f (m_argin, m_nargin);
+
+    switch (m_update)
+      {
+        case CMD_UPD_WORKSPACE:
+          {
+            symbol_scope scope
+                = __get_current_scope__ ("octave_cmd_builtin::execute");
+            if (scope)
+              octave_link::set_workspace (true, scope);
+            break;
+          }
+
+        default:
+          break;
+      }
+
+  }
+
+  void octave_cmd_debug::execute (interpreter& interp)
   {
     if (m_cmd == "step")
       {
-        F__db_next_breakpoint_quiet__ (ovl (m_suppress_dbg_location));
-        Fdbstep ();
+        F__db_next_breakpoint_quiet__ (interp, ovl (m_suppress_dbg_location));
+        Fdbstep (interp);
       }
     else if (m_cmd == "cont")
       {
-        F__db_next_breakpoint_quiet__ (ovl (m_suppress_dbg_location));
-        Fdbcont ();
+        F__db_next_breakpoint_quiet__ (interp, ovl (m_suppress_dbg_location));
+        Fdbcont (interp);
       }
     else if (m_cmd == "quit")
-      Fdbquit ();
+      Fdbquit (interp);
     else
       {
-        F__db_next_breakpoint_quiet__ (ovl (m_suppress_dbg_location));
-        Fdbstep (ovl (m_cmd.toStdString ()));
+        F__db_next_breakpoint_quiet__ (interp, ovl (m_suppress_dbg_location));
+        Fdbstep (interp, ovl (m_cmd.toStdString ()));
       }
 
-    octave::command_editor::interrupt (true);
+    command_editor::interrupt (true);
   }
 
   // add a command to the queue
@@ -126,7 +152,13 @@
           repost = true;          // not empty, repost at end
         m_queue_mutex.unlock ();
 
-        cmd->execute ();
+        // FIXME: Could we store a reference to the interpreter in the
+        // octave_command_queue object?  If so, where is the proper
+        // place to initialize that?
+
+        interpreter& interp = __get_interpreter__ ("octave_command_queue::execute_command_callback");
+
+        cmd->execute (interp);
 
         delete cmd;
       }
--- a/libgui/src/octave-cmd.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/src/octave-cmd.h	Fri Aug 10 09:09:51 2018 +0200
@@ -31,9 +31,13 @@
 #include <QFileInfo>
 
 #include "octave-qt-link.h"
+#include "ovl.h"
+
 
 namespace octave
 {
+  class interpreter;
+
   class octave_cmd
   {
   public:
@@ -42,7 +46,7 @@
 
     virtual ~octave_cmd (void) = default;
 
-    virtual void execute (void) { }
+    virtual void execute (interpreter&) { }
   };
 
   class octave_cmd_exec : public octave_cmd
@@ -51,7 +55,7 @@
 
     octave_cmd_exec (const QString& cmd) : octave_cmd () { m_cmd = cmd; }
 
-    void execute (void);
+    void execute (interpreter& interp);
 
   protected:
 
@@ -64,13 +68,56 @@
 
     octave_cmd_eval (const QFileInfo& info) : octave_cmd () { m_info = info; }
 
-    void execute (void);
+    void execute (interpreter& interp);
 
   protected:
 
     QFileInfo m_info;
   };
 
+  class octave_cmd_builtin : public octave_cmd
+  {
+    public:
+
+    enum cmd_upd {
+      CMD_UPD_NO        = 0,
+      CMD_UPD_WORKSPACE = 1
+    };
+
+    // C'tor for Fxxx requiring the interpreter
+    octave_cmd_builtin (
+          octave_value_list (*Ff) (octave::interpreter&,
+                                   const octave_value_list&, int),
+          octave_value_list argin = ovl (), int nargin = 0,
+          cmd_upd update = CMD_UPD_NO, octave_qt_link *oct_qt_link = nullptr)
+      : octave_cmd (), m_callback_fi (Ff), m_callback_f (nullptr),
+        m_argin (argin), m_nargin (nargin), m_update (update),
+        m_octave_qt_link (oct_qt_link)
+    { };
+
+    // C'tor for Fxxx not requiring the interpreter
+    octave_cmd_builtin (
+          octave_value_list (*Ff) (const octave_value_list&, int),
+          octave_value_list argin = ovl (), int nargin = 0,
+          cmd_upd update = CMD_UPD_NO, octave_qt_link *oct_qt_link = nullptr)
+      : octave_cmd (), m_callback_fi (nullptr), m_callback_f (Ff),
+        m_argin (argin), m_nargin (nargin), m_update (update),
+        m_octave_qt_link (oct_qt_link)
+    { };
+
+    void execute (interpreter& interp);
+
+  protected:
+
+    octave_value_list (*m_callback_fi) (octave::interpreter&,
+                                        const octave_value_list&, int);
+    octave_value_list (*m_callback_f) (const octave_value_list&, int);
+    octave_value_list m_argin;
+    int m_nargin;
+    cmd_upd m_update;
+    octave_qt_link *m_octave_qt_link;
+  };
+
   class octave_cmd_debug : public octave_cmd_exec
   {
   public:
@@ -78,7 +125,7 @@
     octave_cmd_debug (const QString& cmd, bool suppress_location)
       : octave_cmd_exec (cmd), m_suppress_dbg_location (suppress_location) { }
 
-    void execute (void);
+    void execute (interpreter& interp);
 
   protected:
 
--- a/libgui/src/octave-dock-widget.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/src/octave-dock-widget.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -39,11 +39,29 @@
 namespace octave
 {
   label_dock_widget::label_dock_widget (QWidget *p)
-    : QDockWidget (p)
+    : QDockWidget (p), m_default_float_button (nullptr),
+      m_default_close_button (nullptr)
   {
     QStyle *st = style ();
     m_icon_size = 0.75*st->pixelMetric (QStyle::PM_SmallIconSize);
 
+    // keep track of the original buttons on the default title bar,
+    // the button further left is considered "float"
+    QList<QAbstractButton *> buttonlist = findChildren<QAbstractButton *> ();
+    if (buttonlist.size () == 2)
+      {
+        if (buttonlist.at (0)->x () < buttonlist.at (1)->x ())
+          {
+            m_default_float_button = buttonlist.at (0);
+            m_default_close_button = buttonlist.at (1);
+          }
+        else
+          {
+            m_default_float_button = buttonlist.at (0);
+            m_default_close_button = buttonlist.at (1);
+          }
+      }
+
     // the custom (extra) title bar of the widget
     m_title_widget = new QWidget ();
 
@@ -71,11 +89,10 @@
     h_layout->addStretch (100);
     h_layout->addWidget (m_dock_button);
     h_layout->addWidget (m_close_button);
-    h_layout->setSpacing (0);
+    h_layout->setSpacing (10);
     h_layout->setContentsMargins (5,2,2,2);
 
     m_title_widget->setLayout (h_layout);
-    setTitleBarWidget (m_title_widget);
 
     // copy & paste handling
     connect (p, SIGNAL (copyClipboard_signal ()),
@@ -93,21 +110,79 @@
   label_dock_widget::set_title (const QString& title)
   {
     QHBoxLayout *h_layout
-      = static_cast<QHBoxLayout *> (titleBarWidget ()->layout ());
-    QLabel *label = new QLabel (title, titleBarWidget ());
-    label->setStyleSheet ("background: transparent;");
+      = static_cast<QHBoxLayout *> (m_title_widget->layout ());
+    QLabel *label = new QLabel (title, m_title_widget);
+    label->setStyleSheet ("background-color: transparent;");
     h_layout->insertWidget (0,label);
+    setTitleBarWidget (m_title_widget);
     setWindowTitle (title);
   }
 
 
-  octave_dock_widget::octave_dock_widget (QWidget *p)
-    : label_dock_widget (p)
+  static QString
+  qdockwidget_css (const QString& close_icon, const QString& close_tooltip,
+                   const QString& float_icon, const QString& float_tooltip,
+                   int icon_size, const QString& titlebar_foreground,
+                   const QString& titlebar_background)
   {
+    return QString ("QDockWidget\n"
+                    "{\n"
+                    "%6"
+                    "  border: none;\n"
+                    "  titlebar-close-icon: url(%1);\n"
+                    "  titlebar-normal-icon: url(%2);\n"
+                    "}\n"
+                    "\n"
+                    "QDockWidget::close-button, QDockWidget::float-button\n"
+                    "{\n"
+                    "  border: none;\n"
+                    "  icon-size: %3px;\n"
+                    "}\n"
+                    "\n"
+                    "QAbstractButton#qt_dockwidget_closebutton\n"
+                    "{\n"
+                    "  qproperty-toolTip: \"%4\";\n"
+                    "}\n"
+                    "\n"
+                    "QAbstractButton#qt_dockwidget_floatbutton\n"
+                    "{\n"
+                    "  qproperty-toolTip: \"%5\";\n"
+                    "}\n"
+                    "\n"
+                    "QDockWidget::title {\n"
+                    "  text-align: left;\n"
+                    "%7"
+                    "  padding-left: 1px;\n"
+                    "}\n"
+                    "\n"
+                    "QDockWidget::close-button\n"
+                    "{\n"
+                    "  right: %8px;\n"
+                    "  top: 3px;\n"
+                    "}\n"
+                    "\n"
+                    "QDockWidget::float-button\n"
+                    "{\n"
+                    "  right: %9px;\n"
+                    "  top: 3px;\n"
+                    "}\n"
+                    ).arg (close_icon).arg (float_icon).arg (icon_size)
+                     .arg (close_tooltip).arg (float_tooltip)
+                     .arg (titlebar_foreground). arg (titlebar_background)
+                     .arg ((icon_size*2)/3). arg((icon_size*7)/3);
+  }
+
+  octave_dock_widget::octave_dock_widget (const QString& obj_name, QWidget *p)
+    : label_dock_widget (p), m_recent_float_geom (), m_recent_dock_geom (),
+      m_waiting_for_mouse_button_release (false)
+  {
+    setObjectName (obj_name);
+
     m_parent = static_cast<QMainWindow *> (p);     // store main window
-    m_floating = false;
     m_predecessor_widget = nullptr;
 
+    connect (this, SIGNAL (topLevelChanged (bool)),
+             this, SLOT (toplevel_change (bool)));
     connect (this, SIGNAL (visibilityChanged (bool)),
              this, SLOT (handle_visibility_changed (bool)));
 
@@ -119,21 +194,44 @@
              this, SLOT (handle_active_dock_changed (octave_dock_widget*,
                                                      octave_dock_widget*)));
 
-    setFeatures (QDockWidget::DockWidgetMovable); // not floatable or closeable
+    if (m_default_float_button != nullptr)
+      {
+        disconnect (m_default_float_button, 0, 0, 0);
+        connect (m_default_float_button, SIGNAL (clicked (bool)),
+                 this, SLOT (make_window (bool)));
+      }
+    connect (this, SIGNAL (queue_make_window ()),
+             this, SLOT (make_window ()), Qt::QueuedConnection);
+    connect (this, SIGNAL (queue_make_widget ()),
+             this, SLOT (make_widget ()), Qt::QueuedConnection);
 
     connect (m_dock_action, SIGNAL (triggered (bool)),
-             this, SLOT (change_floating (bool)));
+             this, SLOT (make_window (bool)));
     connect (m_close_action, SIGNAL (triggered (bool)),
              this, SLOT (change_visibility (bool)));
 
     m_close_action->setToolTip (tr ("Hide widget"));
 
+    setStyleSheet (qdockwidget_css (QString (":/actions/icons/widget-close.png"),
+                                    QString ("Close widget"),
+                                    QString (":/actions/icons/widget-undock.png"),
+                                    QString ("Undock widget"),
+                                    m_icon_size,
+                                    QString (""),
+                                    QString ("")));
+    if (widget ())
+      widget ()->setToolTip (QString (""));
+
     m_icon_color = "";
     m_title_3d = 50;
 
     installEventFilter (this);
 
     setFocusPolicy (Qt::StrongFocus);
+
+    setFeatures (QDockWidget::AllDockWidgetFeatures);
+
+    handle_settings (resource_manager::get_settings ());
   }
 
   // connect signal visibility changed to related slot (called from main-window)
@@ -147,82 +245,108 @@
 
   // make the widget floating
   void
-  octave_dock_widget::make_window (void)
+  octave_dock_widget::make_window (bool)
   {
-    // the widget has to be reparented (parent = 0)
+    bool vis = isVisible ();
 
-    QSettings *settings = resource_manager::get_settings ();
+    // prevent follow-up calls by clearing state variable
+    m_waiting_for_mouse_button_release = false;
 
-    // save the docking area and geometry for later redocking
-    settings->setValue ("DockWidgets/" + objectName () + "_dock_area",
-                        m_parent->dockWidgetArea (this));
-    settings->setValue ("DockWidgets/" + objectName (), saveGeometry ());
-    settings->sync ();
+    set_focus_predecessor ();  // set focus previously active widget if tabbed
 
-    // remove parent and adjust the (un)dock icon
-    setTitleBarWidget (0);
-    setParent (0, Qt::Window | Qt::CustomizeWindowHint | Qt::WindowTitleHint |
-               Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint);
-    setTitleBarWidget (m_title_widget);
-    setParent (0, Qt::Window | Qt::CustomizeWindowHint | Qt::WindowTitleHint |
+    // the widget has to be reparented (parent = 0), preferably
+    // from a non-toplevel widget otherwise may not have full
+    // decorations, e.g., no taskbar icon and always in front
+    if (isFloating ())
+      setFloating (false);
+// Remove after thorough testing 3/20/18    m_parent->removeDockWidget (this);
+    setParent (0, Qt::CustomizeWindowHint | Qt::WindowTitleHint |
                Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint);
 
-#if defined (Q_OS_UNIX)
-    m_title_widget->setToolTip (
-      tr ("Use <Alt> + <Left Mouse Button> for moving the window"));
-#endif
-
-    m_dock_action->setIcon (QIcon (":/actions/icons/widget-dock"
-                                   + m_icon_color + ".png"));
-    m_dock_action->setToolTip (tr ("Dock widget"));
+    // restore the last geometry when floating
+    QRect geom = m_recent_float_geom.isNull () ? QRect (50,100,480,480)
+                                               : m_recent_float_geom;
+    setGeometry (geom);
 
-    // restore the last geometry when floating
-    setGeometry (settings->value ("DockWidgets/" + objectName ()
-                                  + "_floating_geometry",
-                                  QRect (50,100,480,480)).toRect ());
+    // adjust the (un)dock icon
+    if (titleBarWidget ())
+      {
+        m_dock_action->setIcon (QIcon (":/actions/icons/widget-dock"
+                                       + m_icon_color + ".png"));
+        m_dock_action->setToolTip (tr ("Dock widget"));
+        disconnect (m_dock_action, 0, this, 0);
+        connect (m_dock_action, SIGNAL (triggered (bool)),
+                 this, SLOT (make_widget (bool)));
+      }
+    else
+      {
+        disconnect (m_default_float_button, 0, this, 0);
+        connect (m_default_float_button, SIGNAL (clicked (bool)),
+                 this, SLOT (make_widget (bool)));
+      }
 
-    m_floating = true;
+    raise ();
+    activateWindow ();
 
-    set_focus_predecessor ();  // set focus previously active widget if tabbed
+    if (vis)
+    {
+      show ();
+      focus ();
+      set_style (true);
+    }
   }
 
   // dock the widget
   void
-  octave_dock_widget::make_widget (bool dock)
+  octave_dock_widget::make_widget (bool)
   {
+    bool vis = isVisible ();
+
     // Since floating widget has no parent, we have to read it
-
     QSettings *settings = resource_manager::get_settings ();
 
-    // save last floating geometry if widget really was floating
-    if (m_floating)
-      settings->setValue ("DockWidgets/" + objectName () + "_floating_geometry",
-                          geometry ());
-    settings->sync ();
-
-    if (dock)
-      {
-        settings->setValue ("MainWindow/windowState", m_parent->saveState ());
-        // Stay window, otherwise will bounce back to window by default because
-        // there is no layout information for this widget in the saved settings.
-        setParent (m_parent, Qt::Window);
-        m_parent->addDockWidget (Qt::TopDockWidgetArea, this);
-        // recover old window states, hide and re-show new added widget
-        m_parent->restoreState (settings->value ("MainWindow/windowState").toByteArray ());
-        setFloating (false);
-        focus ();
-        QApplication::setActiveWindow (this);
-        m_title_widget->setToolTip ("");
-      }
-    else  // only reparent, no docking
-      setParent (m_parent);
+    settings->setValue ("MainWindow/windowState", m_parent->saveState ());
+    // Stay window, otherwise will bounce back to window by default because
+    // there is no layout information for this widget in the saved settings.
+    setParent (m_parent, Qt::Window);
+    m_parent->addDockWidget (Qt::BottomDockWidgetArea, this);
+    // recover old window states, hide and re-show new added widget
+    m_parent->restoreState (settings->value ("MainWindow/windowState").toByteArray ());
+    setFloating (false);
 
     // adjust the (un)dock icon
-    m_dock_action->setIcon (QIcon (":/actions/icons/widget-undock"
-                                   + m_icon_color + ".png"));
-    m_dock_action->setToolTip (tr ("Undock widget"));
+    if (titleBarWidget ())
+      {
+        m_dock_action->setIcon (QIcon (":/actions/icons/widget-undock"
+                                       + m_icon_color + ".png"));
+        m_dock_action->setToolTip (tr ("Undock widget"));
+        disconnect (m_dock_action, 0, this, 0);
+        connect (m_dock_action, SIGNAL (triggered (bool)),
+                 this, SLOT (make_window (bool)));
+      }
+    else
+      {
+        disconnect (m_default_float_button, 0, this, 0);
+        connect (m_default_float_button, SIGNAL (clicked (bool)),
+                 this, SLOT (make_window (bool)));
+      }
 
-    m_floating = false;
+    raise ();
+    QApplication::setActiveWindow (this);
+
+    if (vis)
+      {
+        show ();
+        focus ();
+        set_style (true);
+      }
+  }
+
+  // dock the widget
+  void
+  octave_dock_widget::default_dock (bool)
+  {
+    setFloating (false);
   }
 
   // set the widget which previously had focus when tabified
@@ -250,6 +374,26 @@
     return w;
   }
 
+  bool
+  octave_dock_widget::event (QEvent *event)
+  {
+    // low-level check of whether docked-widget became a window via
+    // double-click or via drag-and-drop
+    if ((event->type () == QEvent::MouseButtonDblClick && ! isFloating ())
+        || (event->type () == QEvent::ActivationChange && m_waiting_for_mouse_button_release))
+      {
+        bool retval = QDockWidget::event (event);
+        if (isFloating () && parent () != 0)
+          {
+            m_waiting_for_mouse_button_release = false;
+            emit queue_make_window ();
+          }
+        return retval;
+      }
+
+    return QDockWidget::event (event);
+  }
+
   void
   octave_dock_widget::handle_settings (const QSettings *settings)
   {
@@ -278,7 +422,7 @@
 
     if (! m_custom_style)
       {
-        bcol = QWidget::palette ().color (m_title_widget->backgroundRole());
+        bcol = QWidget::palette ().color (m_title_widget->backgroundRole ());
         bcola = bcol;
       }
 
@@ -295,6 +439,13 @@
     else
       m_icon_color_active = "";
 
+    m_recent_float_geom = settings->value ("DockWidgets/" + objectName ()
+                                           + "_floating_geometry",
+                                           QRect (50,100,480,480)).toRect ();
+
+    m_recent_dock_geom = settings->value ("DockWidgets/" + objectName (),
+                                          QByteArray ()).toByteArray ();
+
     notice_settings (settings);  // call individual handler
 
     set_style (false);
@@ -327,15 +478,18 @@
     if (! settings)
       return;
 
+    store_geometry ();
+
     settings->beginGroup ("DockWidgets");
 
-    if (m_floating) // widget is floating (windows), save actual floating geometry
-      settings->setValue (name+"_floating_geometry", geometry ());
-    else           // not floating save docked (normal) geometry
-      settings->setValue (name, saveGeometry ());
+    // conditional needed?
+    if (! m_recent_float_geom.isNull ())
+      settings->setValue (name + "_floating_geometry", m_recent_float_geom);
 
+    if (! m_recent_dock_geom.isEmpty ())
+      settings->setValue (name, m_recent_dock_geom);
     settings->setValue (name+"Visible", isVisible ()); // store visibility
-    settings->setValue (name+"Floating", m_floating);    // store visibility
+    settings->setValue (name+"Floating", isFloating ()); // store floating
     settings->setValue (name+"_minimized", isMinimized ()); // store minimized
 
     settings->endGroup ();
@@ -353,19 +507,36 @@
     return QDockWidget::eventFilter (obj,e);
   }
 
-  // slot for (un)dock action
   void
-  octave_dock_widget::change_floating (bool)
+  octave_dock_widget::store_geometry (void)
   {
-    if (m_floating)
-      make_widget ();
+    if (isFloating ())
+      {
+        if (! parent ())
+          m_recent_float_geom = geometry ();
+      }
     else
       {
-        make_window ();
-        focus ();
+        m_recent_dock_geom = saveGeometry ();
       }
   }
 
+  void
+  octave_dock_widget::moveEvent (QMoveEvent *event)
+  {
+    store_geometry ();
+
+    QDockWidget::moveEvent (event);
+  }
+
+  void
+  octave_dock_widget::resizeEvent (QResizeEvent *event)
+  {
+    store_geometry ();
+
+    QDockWidget::resizeEvent (event);
+  }
+
   // slot for hiding the widget
   void
   octave_dock_widget::change_visibility (bool)
@@ -375,18 +546,69 @@
   }
 
   void
+  octave_dock_widget::toplevel_change (bool toplevel)
+  {
+    QObject *dockobj;
+    const char *docksig;
+
+    if (titleBarWidget ())
+      {
+        dockobj = m_dock_action;
+        docksig = SIGNAL (triggered (bool));
+      }
+    else
+      {
+        dockobj = m_default_float_button;
+        docksig = SIGNAL (clicked (bool));
+      }
+
+    if (toplevel)
+      {
+        // This is a fallback in case the attempt to create a floated
+        // top-level window fails and the QDockWidget remains a child
+        // of the QMainWindow.
+        connect (dockobj, docksig, this, SLOT (default_dock (bool)));
+
+        // Could be dragging window, so must wait until there is a
+        // change in focus.
+        if (parent () != 0)
+          m_waiting_for_mouse_button_release = true;
+      }
+    else
+      {
+        // If a drag-and-drop within the QMainWindow occurred, want to remain a widget.
+        m_waiting_for_mouse_button_release = false;
+
+        // Making into a widget immediately will mangle the double-click
+        // status and cause problems on followup button clicks.
+        if (parent () == 0)
+          emit queue_make_widget ();
+      }
+  }
+
+  void
   octave_dock_widget::set_style (bool active)
   {
-    QString css;
+    QString css_foreground;
+    QString css_background;
     QString css_button;
     QString dock_icon;
 
     QString icon_col = m_icon_color;
 
-    if (m_floating)
-      dock_icon = "widget-dock";
+    QString close_tooltip = "Close widget";
+    QString dock_tooltip;
+
+    if (isFloating ())
+      {
+        dock_icon = "widget-dock";
+        dock_tooltip = "Dock widget";
+      }
     else
-      dock_icon = "widget-undock";
+      {
+        dock_icon = "widget-undock";
+        dock_tooltip = "Undock widget";
+      }
 
 #if defined (Q_OS_MAC)
     QString alignment = "center";
@@ -423,35 +645,50 @@
             bg_col_bottom = bg_col.lighter (100 - m_title_3d);
           }
 
-        QString background =
-          QString ("background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,"
-                   "            stop: 0 %1, stop: 0.60 %2, stop: 0.95 %2 stop: 1.0 %3);").
+        css_foreground = QString ("  color: %1;\n").arg (fg_col.name ());
+
+        css_background =
+          QString ("  background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,"
+                   " stop: 0 %1, stop: 0.60 %2, stop: 0.95 %2 stop: 1.0 %3);\n").
           arg (bg_col_top.name ()).
           arg (bg_col.name ()).
           arg (bg_col_bottom.name ());
-
-        css = background + QString (" color: %1 ;").arg (fg_col.name ());
       }
     else
       {
-        css = QString ("");
+        css_foreground = QString ("");
+        css_background = QString ("");
       }
 
-    m_title_widget->setStyleSheet (css);
-    css_button = QString ("QToolButton {background: transparent; border: 0px;}");
-    m_dock_button->setStyleSheet (css_button);
-    m_close_button->setStyleSheet (css_button);
-    m_dock_action->setIcon (QIcon (":/actions/icons/" + dock_icon + icon_col +
-                                   ".png"));
-    m_close_action->setIcon (QIcon (":/actions/icons/widget-close" + icon_col +
-                                    ".png"));
+    QString full_dock_icon = ":/actions/icons/" + dock_icon + icon_col + ".png";
+    QString full_close_icon = ":/actions/icons/widget-close" + icon_col + ".png";
+    if (titleBarWidget ())
+      {
+        titleBarWidget ()->setStyleSheet (css_foreground + css_background);
+        css_button = QString ("QToolButton {background: transparent; border: 0px;}");
+        m_dock_button->setStyleSheet (css_button);
+        m_close_button->setStyleSheet (css_button);
+        m_dock_action->setIcon (QIcon (full_dock_icon));
+        m_close_action->setIcon (QIcon (full_close_icon));
+      }
+    else
+      {
+        setStyleSheet (qdockwidget_css (full_close_icon,
+                                        close_tooltip,
+                                        full_dock_icon,
+                                        dock_tooltip,
+                                        m_icon_size,
+                                        css_foreground,
+                                        css_background));
+      }
   }
 
   // set focus to previously active widget in tabbed widget stack
   void
   octave_dock_widget::set_focus_predecessor (void)
   {
-    if (m_predecessor_widget)    // only != 0 if widget was tabbed
+    // only != 0 if widget was tabbed
+    if (m_predecessor_widget && m_predecessor_widget->isVisible ())
       m_predecessor_widget->focus ();
 
     m_predecessor_widget = nullptr;
--- a/libgui/src/octave-dock-widget.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/src/octave-dock-widget.h	Fri Aug 10 09:09:51 2018 +0200
@@ -43,6 +43,8 @@
 
     label_dock_widget (QWidget *p = nullptr);
 
+    // set_title() uses the custom title bar while setWindowTitle() uses
+    // the default title bar (with style sheets)
     void set_title (const QString&);
 
   protected slots:
@@ -66,6 +68,9 @@
     QToolButton *m_close_button;
     QAction *m_dock_action;
     QAction *m_close_action;
+
+    QAbstractButton *m_default_float_button;
+    QAbstractButton *m_default_close_button;
   };
 
   class octave_dock_widget : public label_dock_widget
@@ -74,14 +79,12 @@
 
   public:
 
-    octave_dock_widget (QWidget *p = nullptr);
+    octave_dock_widget (const QString& obj_name, QWidget *p = nullptr);
 
     virtual ~octave_dock_widget (void) = default;
 
     virtual void connect_visibility_changed (void);
 
-    void make_window (void);
-    void make_widget (bool dock=true);
     void set_predecessor_widget (octave_dock_widget *prev_widget);
 
   signals:
@@ -91,12 +94,18 @@
 
     void active_changed (bool active);
 
+    void queue_make_window (void);
+
+    void queue_make_widget (void);
+
   protected:
 
     virtual void closeEvent (QCloseEvent *e);
 
     QWidget * focusWidget (void);
 
+    bool event (QEvent *event);
+
   public slots:
 
     virtual void focus (void)
@@ -125,6 +134,16 @@
 
     void save_settings (void);
 
+    void moveEvent (QMoveEvent *event);
+
+    void resizeEvent (QResizeEvent *event);
+
+    void make_window (bool not_used = false);
+
+    void make_widget (bool not_used = false);
+
+    void default_dock (bool not_used = false);
+
   protected slots:
 
     //! Slot to steer changing visibility from outside.
@@ -141,19 +160,19 @@
 
   private slots:
 
-    void change_floating (bool);
     void change_visibility (bool);
+    void toplevel_change (bool);
 
   private:
 
     void set_style (bool active);
     void set_focus_predecessor (void);
+    void store_geometry (void);
 
     //! Stores the parent, since we are reparenting to 0.
 
     QMainWindow *m_parent;
 
-    bool m_floating;
     bool m_custom_style;
     int m_title_3d;
     QColor m_bg_color;
@@ -163,6 +182,9 @@
     QString m_icon_color;
     QString m_icon_color_active;
     octave_dock_widget *m_predecessor_widget;
+    QRect m_recent_float_geom;
+    QByteArray m_recent_dock_geom;
+    bool m_waiting_for_mouse_button_release;
 
   };
 }
--- a/libgui/src/octave-gui.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/src/octave-gui.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -45,7 +45,6 @@
 #include "signal-wrappers.h"
 
 #include "builtin-defun-decls.h"
-#include "defaults.h"
 #include "display.h"
 #include "octave.h"
 #include "sysdep.h"
--- a/libgui/src/octave-qt-link.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/src/octave-qt-link.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -41,6 +41,8 @@
 #include "interpreter-private.h"
 #include "load-path.h"
 #include "ov.h"
+#include "octave.h"
+#include "oct-map.h"
 #include "symscope.h"
 #include "utils.h"
 
@@ -195,11 +197,8 @@
   {
     QStringList retval;
 
-    for (std::list<std::string>::const_iterator it = lst.begin ();
-         it != lst.end (); it++)
-      {
-        retval.append (QString::fromStdString (*it));
-      }
+    for (auto it = lst.begin (); it != lst.end (); it++)
+      retval.append (QString::fromStdString (*it));
 
     return retval;
   }
@@ -214,8 +213,7 @@
     // (optional).  Qt wants a list of filters in the format of
     // 'FilterName (space separated exts)'.
 
-    for (octave_link::filter_list::const_iterator it = lst.begin ();
-         it != lst.end (); it++)
+    for (auto it = lst.begin (); it != lst.end (); it++)
       {
         QString ext = QString::fromStdString (it->first);
         QString name = QString::fromStdString (it->second);
@@ -300,11 +298,8 @@
 
     uiwidget_creator.unlock ();
 
-    for (QStringList::const_iterator it = inputLine->begin ();
-         it != inputLine->end (); it++)
-      {
-        retval.push_back (it->toStdString ());
-      }
+    for (auto it = inputLine->begin (); it != inputLine->end (); it++)
+      retval.push_back (it->toStdString ());
 
     return retval;
   }
@@ -335,8 +330,7 @@
     // Add all the file dialog results to a string list.
     const QStringList *inputLine = uiwidget_creator.get_string_list ();
 
-    for (QStringList::const_iterator it = inputLine->begin ();
-         it != inputLine->end (); it++)
+    for (auto it = inputLine->begin (); it != inputLine->end (); it++)
       retval.push_back (it->toStdString ());
 
     retval.push_back (uiwidget_creator.get_dialog_path ()->toStdString ());
@@ -411,6 +405,26 @@
     emit change_directory_signal (QString::fromStdString (dir));
   }
 
+  void octave_qt_link::do_file_remove (const std::string& old_name,
+                                       const std::string& new_name)
+  {
+    // Lock the mutex before signaling
+    lock ();
+
+    // Emit the signal for the editor for closing the file if it is open
+    emit file_remove_signal (QString::fromStdString (old_name),
+                             QString::fromStdString (new_name));
+
+    // Wait for the GUI and unlock when resumed
+    wait ();
+    unlock ();
+  }
+
+  void octave_qt_link::do_file_renamed (bool load_new)
+  {
+    emit file_renamed_signal (load_new);
+  }
+
   void octave_qt_link::do_execute_command_in_terminal
     (const std::string& command)
   {
@@ -464,6 +478,15 @@
   void octave_qt_link::do_enter_debugger_event (const std::string& file,
                                                 int line)
   {
+    interpreter& interp = __get_interpreter__ (
+                                  "octave_qt_link::do_enter_debugger_event");
+    octave_value_list fct = F__which__ (interp, ovl (file),0);
+    octave_map map = fct(0).map_value ();
+
+    std::string type = map.contents ("type").data ()[0].string_value ();
+    if (type == "command-line function")
+      return;
+
     do_insert_debugger_pointer (file, line);
 
     emit enter_debugger_signal ();
@@ -491,18 +514,6 @@
                                           line, QString::fromStdString (cond));
   }
 
-  void octave_qt_link::do_set_default_prompts (std::string& ps1,
-                                               std::string& ps2,
-                                               std::string& ps4)
-  {
-    if (m_app_context->start_gui_p ())
-      {
-        ps1 = ">> ";
-        ps2 = "";
-        ps4 = "";
-      }
-  }
-
   bool octave_qt_link::file_in_path (const std::string& file,
                                      const std::string& dir)
   {
@@ -582,6 +593,25 @@
     emit show_preferences_signal ();
   }
 
+  std::string octave_qt_link::do_gui_preference (const std::string& key,
+                                                 const std::string& value)
+  {
+    QString pref_value;
+
+    // Lock the mutex before signaling
+    lock ();
+
+    // Emit the signal for changing or getting a preference
+    emit gui_preference_signal (QString::fromStdString (key),
+                                QString::fromStdString (value), &pref_value);
+
+    // Wait for the GUI and unlock when resumed
+    wait ();
+    unlock ();
+
+    return pref_value.toStdString ();
+  }
+
   void octave_qt_link::do_show_doc (const std::string& file)
   {
     emit show_doc_signal (QString::fromStdString (file));
--- a/libgui/src/octave-qt-link.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/src/octave-qt-link.h	Fri Aug 10 09:09:51 2018 +0200
@@ -112,6 +112,10 @@
 
     void do_change_directory (const std::string& dir);
 
+    void do_file_remove (const std::string& old_name,
+                         const std::string& new_name);
+    void do_file_renamed (bool load_new = true);
+
     void do_execute_command_in_terminal (const std::string& command);
 
     void do_set_workspace (bool top_level, bool debug,
@@ -134,13 +138,12 @@
     void do_update_breakpoint (bool insert, const std::string& file, int line,
                                const std::string& cond);
 
-    void do_set_default_prompts (std::string& ps1, std::string& ps2,
-                                 std::string& ps4);
-
     static bool file_in_path (const std::string& file, const std::string& dir);
 
     void do_show_preferences (void);
 
+    std::string do_gui_preference (const std::string& key,
+                                   const std::string& value);
     void do_show_doc (const std::string& file);
     void do_register_doc (const std::string& file);
     void do_unregister_doc (const std::string& file);
@@ -174,6 +177,9 @@
 
     void change_directory_signal (const QString& dir);
 
+    void file_remove_signal (const QString& old_name, const QString& new_name);
+    void file_renamed_signal (bool load_new);
+
     void execute_command_in_terminal_signal (const QString& command);
 
     void set_workspace_signal (bool top_level, bool debug,
@@ -196,6 +202,8 @@
 
     void show_preferences_signal (void);
 
+    void gui_preference_signal (const QString&, const QString&, QString*);
+
     void show_doc_signal (const QString& file);
 
     void register_doc_signal (const QString& file);
--- a/libgui/src/octave-settings.h	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/*
-
-Copyright (C) 2017-2018 Torsten <mttl@mailbox.de>
-
-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
-<https://www.gnu.org/licenses/>.
-
-*/
-
-#if ! defined (octave_settings_h)
-#define octave_settings_h 1
-
-//#if defined (HAVE_CONFIG_H)
-//#  include "config.h"
-//#endif
-
-#include <QStringList>
-
-// Octave comment strings
-const QString oct_comment_str_old ("editor/octave_comment_string");
-const int oct_comment_str_old_d = 0;
-
-const QString oct_comment_str ("editor/oct_comment_str");
-const QString oct_uncomment_str ("editor/oct_uncomment_str");
-const QString oct_last_comment_str ("editor/oct_last_comment_str");
-const QStringList oct_comment_strings (QStringList () << "##" << "#" << "%"<< "%%" << "%!");
-const int oct_comment_strings_count = 5;
-const int oct_comment_str_d = 0;
-const int oct_uncomment_str_d = 1 + 2 + 4 + 8;
-
-#endif
--- a/libgui/src/resource-manager.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/src/resource-manager.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -47,6 +47,7 @@
 #include "workspace-model.h"
 #include "variable-editor.h"
 #include "resource-manager.h"
+#include "gui-preferences.h"
 
 namespace octave
 {
@@ -55,11 +56,11 @@
   static QString
   default_qt_settings_file (void)
   {
-    std::string dsf = octave::sys::env::getenv ("OCTAVE_DEFAULT_QT_SETTINGS");
+    std::string dsf = sys::env::getenv ("OCTAVE_DEFAULT_QT_SETTINGS");
 
     if (dsf.empty ())
-      dsf = (octave::config::oct_etc_dir ()
-             + octave::sys::file_ops::dir_sep_str ()
+      dsf = (config::oct_etc_dir ()
+             + sys::file_ops::dir_sep_str ()
              + "default-qt-settings");
 
     return QString::fromStdString (dsf);
@@ -94,9 +95,9 @@
   QString resource_manager::get_gui_translation_dir (void)
   {
     // get environment variable for the locale dir (e.g. from run-octave)
-    std::string dldir = octave::sys::env::getenv ("OCTAVE_LOCALE_DIR");
+    std::string dldir = sys::env::getenv ("OCTAVE_LOCALE_DIR");
     if (dldir.empty ())
-      dldir = octave::config::oct_locale_dir (); // env-var empty, load the default location
+      dldir = config::oct_locale_dir (); // env-var empty, load the default location
     return QString::fromStdString (dldir);
   }
 
@@ -340,34 +341,33 @@
       return QIcon::fromTheme (icon_name);
   }
 
-  // initialize a given combo box with available text encodings
-  void resource_manager::do_combo_encoding (QComboBox *combo, QString current)
+  // get a list of all available encodings
+  void resource_manager::do_get_codecs (QStringList *codecs)
   {
     // get the codec name for each mib
     QList<int> all_mibs = QTextCodec::availableMibs ();
-    QStringList all_codecs;
     foreach (int mib, all_mibs)
       {
         QTextCodec *c = QTextCodec::codecForMib (mib);
-        all_codecs << c->name ().toUpper ();
+        codecs->append (c->name ().toUpper ());
       }
-    all_codecs.removeDuplicates ();
-    qSort (all_codecs);
+    codecs->removeDuplicates ();
+    qSort (*codecs);
+  }
 
-    // the default encoding
-#if defined (Q_OS_WIN32)
-    QString def_enc = "SYSTEM";
-#else
-    QString def_enc = "UTF-8";
-#endif
+  // initialize a given combo box with available text encodings
+  void resource_manager::do_combo_encoding (QComboBox *combo, QString current)
+  {
+    QStringList all_codecs;
+    do_get_codecs (&all_codecs);
 
     // get the value from the settings file if no current encoding is given
     QString enc = current;
     if (enc.isEmpty ())
       {
-        enc = m_settings->value ("editor/default_encoding",def_enc).toString ();
+        enc = m_settings->value (ed_default_enc.key, ed_default_enc.def).toString ();
         if (enc.isEmpty ())  // still empty?
-          enc = def_enc;     // take default
+          enc = ed_default_enc.def.toString ();     // take default
       }
 
     // fill the combo box
@@ -376,7 +376,7 @@
 
     // prepend the default item
     combo->insertSeparator (0);
-    combo->insertItem (0, def_enc);
+    combo->insertItem (0, ed_default_enc.def.toString ());
 
     // select the current/default item
     int idx = combo->findText (enc);
--- a/libgui/src/resource-manager.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/src/resource-manager.h	Fri Aug 10 09:09:51 2018 +0200
@@ -93,6 +93,12 @@
               : false);
     }
 
+    static void get_codecs (QStringList *codecs)
+    {
+      if (instance_ok ())
+        instance->do_get_codecs (codecs);
+    }
+
     static void combo_encoding (QComboBox *combo, QString current = QString ())
     {
       if (instance_ok ())
@@ -156,6 +162,7 @@
 
     QIcon do_icon (const QString& icon, bool fallback);
 
+    void do_get_codecs (QStringList *codecs);
     void do_combo_encoding (QComboBox *combo, QString current);
 
     QString m_settings_directory;
--- a/libgui/src/settings-dialog.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/src/settings-dialog.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -42,6 +42,7 @@
 #include <QVector>
 #include <QHash>
 #include <QMessageBox>
+#include <QScrollBar>
 #include <QTextCodec>
 
 #if defined (HAVE_QSCINTILLA)
@@ -273,8 +274,8 @@
   if (! settings)
     {
       QMessageBox msgBox
-        (QMessageBox::Warning, tr ("Octave Settings"),
-         tr ("Unable to save settings.  Missing settings file or unknown directory."));
+        (QMessageBox::Warning, tr ("Octave Preferences"),
+         tr ("Unable to save preferences.  Missing preferences file or unknown directory."));
 
       msgBox.exec ();
 
@@ -450,17 +451,17 @@
 
   int selected_comment_string, selected_uncomment_string;
 
-  if (settings->contains (oct_comment_str))   // new version (radio buttons)
-    selected_comment_string = settings->value (oct_comment_str,
-                                               oct_comment_str_d).toInt ();
+  if (settings->contains (ed_comment_str.key))   // new version (radio buttons)
+    selected_comment_string = settings->value (ed_comment_str.key,
+                                               ed_comment_str.def).toInt ();
   else                                         // old version (combo box)
-    selected_comment_string = settings->value (oct_comment_str_old,
-                                               oct_comment_str_d).toInt ();
+    selected_comment_string = settings->value (ed_comment_str_old.key,
+                                               ed_comment_str.def).toInt ();
 
-  selected_uncomment_string = settings->value (oct_uncomment_str,
-                                               oct_uncomment_str_d).toInt ();
+  selected_uncomment_string = settings->value (ed_uncomment_str.key,
+                                               ed_uncomment_str.def).toInt ();
 
-  for (int i = 0; i < oct_comment_strings_count; i++)
+  for (int i = 0; i < ed_comment_strings_count; i++)
     {
       m_rb_comment_strings[i] = new QRadioButton ();
       m_rb_uncomment_strings[i] = new QRadioButton ();
@@ -470,11 +471,11 @@
       connect (m_rb_comment_strings[i], SIGNAL (toggled (bool)),
                m_rb_uncomment_strings[i], SLOT (setDisabled (bool)));
 
-      m_rb_comment_strings[i]->setText (oct_comment_strings.at(i));
+      m_rb_comment_strings[i]->setText (ed_comment_strings.at(i));
       m_rb_comment_strings[i]->setChecked (i == selected_comment_string);
       ui->layout_comment_strings->addWidget (m_rb_comment_strings[i]);
 
-      m_rb_uncomment_strings[i]->setText (oct_comment_strings.at(i));
+      m_rb_uncomment_strings[i]->setText (ed_comment_strings.at(i));
       m_rb_uncomment_strings[i]->setAutoExclusive (false);
       m_rb_uncomment_strings[i]->setChecked ( 1 << i & selected_uncomment_string);
       ui->layout_uncomment_strings->addWidget (m_rb_uncomment_strings[i]);
@@ -507,6 +508,7 @@
   ui->editor_create_new_file->setChecked (settings->value ("editor/create_new_file", false).toBool ());
   ui->editor_reload_changed_files->setChecked (settings->value ("editor/always_reload_changed_files", false).toBool ());
   ui->editor_hiding_closes_files->setChecked (settings->value ("editor/hiding_closes_files", false).toBool ());
+  ui->editor_show_dbg_file->setChecked (settings->value (ed_show_dbg_file.key, ed_show_dbg_file.def).toBool ());
 
   // terminal
   ui->terminal_fontName->setCurrentFont (QFont (settings->value ("terminal/fontName", "Courier New").toString ()));
@@ -688,8 +690,10 @@
     {
       QHash <QString, QWidget*> tab_hash;
       tab_hash["editor"] = ui->tab_editor;
-      tab_hash["editor_styles"] = ui->tab_editor_styles;
+      tab_hash["editor_styles"] = ui->tab_editor;
       ui->tabWidget->setCurrentIndex (ui->tabWidget->indexOf (tab_hash.value (tab)));
+      if (tab == "editor_styles")
+        ui->tab_editor_scroll_area->ensureWidgetVisible (ui->group_box_editor_styles);
     }
 }
 
@@ -850,20 +854,20 @@
 
   // Comment strings
   int rb_uncomment = 0;
-  for (int i = 0; i < oct_comment_strings_count; i++)
+  for (int i = 0; i < ed_comment_strings_count; i++)
     {
       if (m_rb_comment_strings[i]->isChecked ())
         {
-          settings->setValue (oct_comment_str, i);
+          settings->setValue (ed_comment_str.key, i);
           if (i < 3)
-            settings->setValue (oct_comment_str_old, i);
+            settings->setValue (ed_comment_str_old.key, i);
           else
-            settings->setValue (oct_comment_str_old, oct_comment_str_d);
+            settings->setValue (ed_comment_str_old.key, ed_comment_str.def);
         }
       if (m_rb_uncomment_strings[i]->isChecked ())
         rb_uncomment = rb_uncomment + (1 << i);
     }
-  settings->setValue (oct_uncomment_str, rb_uncomment);
+  settings->setValue (ed_uncomment_str.key, rb_uncomment);
 
   settings->setValue ("editor/default_encoding", ui->editor_combo_encoding->currentText ());
   settings->setValue ("editor/auto_indent", ui->editor_auto_ind_checkbox->isChecked ());
@@ -880,6 +884,8 @@
   settings->setValue ("editor/create_new_file", ui->editor_create_new_file->isChecked ());
   settings->setValue ("editor/hiding_closes_files", ui->editor_hiding_closes_files->isChecked ());
   settings->setValue ("editor/always_reload_changed_files", ui->editor_reload_changed_files->isChecked ());
+  settings->setValue (ed_show_dbg_file.key, ui->editor_show_dbg_file->isChecked ());
+
   settings->setValue ("terminal/fontSize", ui->terminal_fontSize->value ());
   settings->setValue ("terminal/fontName", ui->terminal_fontName->currentFont ().family ());
 
--- a/libgui/src/settings-dialog.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/src/settings-dialog.h	Fri Aug 10 09:09:51 2018 +0200
@@ -29,7 +29,7 @@
 #include <QRadioButton>
 
 #include "color-picker.h"
-#include "octave-settings.h"
+#include "gui-preferences.h"
 
 namespace Ui
 {
@@ -86,8 +86,8 @@
   color_picker *m_widget_title_fg_color_active;
   color_picker *m_editor_current_line_color;
 
-  QRadioButton *m_rb_comment_strings[oct_comment_strings_count];
-  QRadioButton *m_rb_uncomment_strings[oct_comment_strings_count];
+  QRadioButton *m_rb_comment_strings[ed_comment_strings_count];
+  QRadioButton *m_rb_uncomment_strings[ed_comment_strings_count];
 };
 
 #endif
--- a/libgui/src/settings-dialog.ui	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/src/settings-dialog.ui	Fri Aug 10 09:09:51 2018 +0200
@@ -20,7 +20,7 @@
    </size>
   </property>
   <property name="windowTitle">
-   <string>Settings</string>
+   <string>Preferences</string>
   </property>
   <layout class="QVBoxLayout" name="verticalLayout_2">
    <item>
@@ -32,7 +32,7 @@
       </size>
      </property>
      <property name="currentIndex">
-      <number>8</number>
+      <number>2</number>
      </property>
      <widget class="QWidget" name="tab_general">
       <property name="enabled">
@@ -494,13 +494,294 @@
        </item>
       </layout>
      </widget>
+     <widget class="QWidget" name="tab_terminal">
+      <attribute name="title">
+       <string>Command</string>
+      </attribute>
+      <layout class="QVBoxLayout" name="verticalLayout_14">
+       <item>
+        <widget class="QScrollArea" name="scrollArea_3">
+         <property name="widgetResizable">
+          <bool>true</bool>
+         </property>
+         <widget class="QWidget" name="scrollAreaWidgetContents_4">
+          <property name="geometry">
+           <rect>
+            <x>0</x>
+            <y>0</y>
+            <width>658</width>
+            <height>573</height>
+           </rect>
+          </property>
+          <layout class="QVBoxLayout" name="verticalLayout_7">
+           <item>
+            <layout class="QVBoxLayout" name="verticalLayout_8">
+             <item>
+              <layout class="QGridLayout" name="gridLayout_7">
+               <property name="sizeHint" stdset="0">
+                <size>
+                 <width>40</width>
+                 <height>20</height>
+                </size>
+               </property>
+               <item row="1" column="2">
+                <layout class="QHBoxLayout" name="horizontalLayout_13">
+                 <item>
+                  <widget class="QCheckBox" name="terminal_cursorUseForegroundColor">
+                   <property name="text">
+                    <string>Use foreground color</string>
+                   </property>
+                  </widget>
+                 </item>
+                </layout>
+               </item>
+               <item row="1" column="0">
+                <layout class="QHBoxLayout" name="horizontalLayout_7">
+                 <item>
+                  <widget class="QLabel" name="label">
+                   <property name="text">
+                    <string>Cursor type:</string>
+                   </property>
+                  </widget>
+                 </item>
+                 <item>
+                  <widget class="QComboBox" name="terminal_cursorType"/>
+                 </item>
+                </layout>
+               </item>
+               <item row="0" column="0">
+                <layout class="QHBoxLayout" name="horizontalLayout_11">
+                 <item>
+                  <widget class="QLabel" name="label_11">
+                   <property name="text">
+                    <string>Font</string>
+                   </property>
+                  </widget>
+                 </item>
+                 <item>
+                  <widget class="QFontComboBox" name="terminal_fontName">
+                   <property name="sizePolicy">
+                    <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+                     <horstretch>0</horstretch>
+                     <verstretch>0</verstretch>
+                    </sizepolicy>
+                   </property>
+                   <property name="editable">
+                    <bool>false</bool>
+                   </property>
+                   <property name="fontFilters">
+                    <set>QFontComboBox::MonospacedFonts</set>
+                   </property>
+                  </widget>
+                 </item>
+                </layout>
+               </item>
+               <item row="0" column="2">
+                <layout class="QHBoxLayout" name="horizontalLayout_12">
+                 <item>
+                  <widget class="QLabel" name="label_12">
+                   <property name="text">
+                    <string>Font size</string>
+                   </property>
+                  </widget>
+                 </item>
+                 <item>
+                  <widget class="QSpinBox" name="terminal_fontSize">
+                   <property name="sizePolicy">
+                    <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+                     <horstretch>0</horstretch>
+                     <verstretch>0</verstretch>
+                    </sizepolicy>
+                   </property>
+                   <property name="minimum">
+                    <number>2</number>
+                   </property>
+                   <property name="maximum">
+                    <number>96</number>
+                   </property>
+                   <property name="value">
+                    <number>10</number>
+                   </property>
+                  </widget>
+                 </item>
+                 <item>
+                  <spacer name="horizontalSpacer_27">
+                   <property name="orientation">
+                    <enum>Qt::Horizontal</enum>
+                   </property>
+                   <property name="sizeHint" stdset="0">
+                    <size>
+                     <width>40</width>
+                     <height>20</height>
+                    </size>
+                   </property>
+                  </spacer>
+                 </item>
+                </layout>
+               </item>
+               <item row="2" column="2">
+                <layout class="QHBoxLayout" name="horizontalLayout_5">
+                 <property name="topMargin">
+                  <number>0</number>
+                 </property>
+                 <item>
+                  <widget class="QSpinBox" name="terminal_history_buffer">
+                   <property name="sizePolicy">
+                    <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+                     <horstretch>0</horstretch>
+                     <verstretch>0</verstretch>
+                    </sizepolicy>
+                   </property>
+                   <property name="minimum">
+                    <number>0</number>
+                   </property>
+                   <property name="maximum">
+                    <number>5000</number>
+                   </property>
+                   <property name="singleStep">
+                    <number>20</number>
+                   </property>
+                   <property name="value">
+                    <number>1000</number>
+                   </property>
+                  </widget>
+                 </item>
+                 <item>
+                  <widget class="QLabel" name="label_20">
+                   <property name="text">
+                    <string>(Changing buffer size clears history)</string>
+                   </property>
+                  </widget>
+                 </item>
+                 <item>
+                  <spacer name="horizontalSpacer_16">
+                   <property name="orientation">
+                    <enum>Qt::Horizontal</enum>
+                   </property>
+                   <property name="sizeHint" stdset="0">
+                    <size>
+                     <width>40</width>
+                     <height>20</height>
+                    </size>
+                   </property>
+                  </spacer>
+                 </item>
+                </layout>
+               </item>
+               <item row="2" column="0">
+                <widget class="QLabel" name="label_19">
+                 <property name="minimumSize">
+                  <size>
+                   <width>100</width>
+                   <height>20</height>
+                  </size>
+                 </property>
+                 <property name="text">
+                  <string>History buffer Size</string>
+                 </property>
+                </widget>
+               </item>
+               <item row="0" column="1">
+                <spacer name="horizontalSpacer_28">
+                 <property name="orientation">
+                  <enum>Qt::Horizontal</enum>
+                 </property>
+                 <property name="sizeType">
+                  <enum>QSizePolicy::Fixed</enum>
+                 </property>
+                 <property name="sizeHint" stdset="0">
+                  <size>
+                   <width>20</width>
+                   <height>20</height>
+                  </size>
+                 </property>
+                </spacer>
+               </item>
+              </layout>
+             </item>
+             <item>
+              <layout class="QGridLayout" name="gridLayout_15">
+               <item row="0" column="0">
+                <widget class="QCheckBox" name="terminal_focus_command">
+                 <property name="text">
+                  <string>Set focus to Command Window when running a command from within another widget</string>
+                 </property>
+                </widget>
+               </item>
+               <item row="1" column="0">
+                <widget class="QCheckBox" name="terminal_print_dbg_location">
+                 <property name="text">
+                  <string>Print debug location in Command Window in addition to the marker in the editor</string>
+                 </property>
+                </widget>
+               </item>
+              </layout>
+             </item>
+             <item>
+              <widget class="Line" name="line_7">
+               <property name="orientation">
+                <enum>Qt::Horizontal</enum>
+               </property>
+              </widget>
+             </item>
+             <item>
+              <widget class="QGroupBox" name="terminal_colors_box">
+               <property name="title">
+                <string>Command Window Colors</string>
+               </property>
+              </widget>
+             </item>
+             <item>
+              <widget class="Line" name="line_5">
+               <property name="minimumSize">
+                <size>
+                 <width>0</width>
+                 <height>0</height>
+                </size>
+               </property>
+               <property name="orientation">
+                <enum>Qt::Horizontal</enum>
+               </property>
+              </widget>
+             </item>
+             <item>
+              <widget class="Line" name="line_6">
+               <property name="orientation">
+                <enum>Qt::Horizontal</enum>
+               </property>
+              </widget>
+             </item>
+            </layout>
+           </item>
+           <item>
+            <spacer name="verticalSpacer_3">
+             <property name="orientation">
+              <enum>Qt::Vertical</enum>
+             </property>
+             <property name="sizeType">
+              <enum>QSizePolicy::Expanding</enum>
+             </property>
+             <property name="sizeHint" stdset="0">
+              <size>
+               <width>20</width>
+               <height>40</height>
+              </size>
+             </property>
+            </spacer>
+           </item>
+          </layout>
+         </widget>
+        </widget>
+       </item>
+      </layout>
+     </widget>
      <widget class="QWidget" name="tab_editor">
       <attribute name="title">
        <string>Editor</string>
       </attribute>
       <layout class="QVBoxLayout" name="verticalLayout_6">
        <item>
-        <widget class="QScrollArea" name="scrollArea">
+        <widget class="QScrollArea" name="tab_editor_scroll_area">
          <property name="widgetResizable">
           <bool>true</bool>
          </property>
@@ -508,9 +789,9 @@
           <property name="geometry">
            <rect>
             <x>0</x>
-            <y>0</y>
+            <y>-585</y>
             <width>645</width>
-            <height>1012</height>
+            <height>1196</height>
            </rect>
           </property>
           <layout class="QVBoxLayout" name="verticalLayout_16">
@@ -1584,6 +1865,32 @@
             </widget>
            </item>
            <item>
+            <widget class="QGroupBox" name="groupBox_10">
+             <property name="enabled">
+              <bool>true</bool>
+             </property>
+             <property name="title">
+              <string>Debugging</string>
+             </property>
+             <layout class="QVBoxLayout" name="verticalLayout_12">
+              <item>
+               <layout class="QGridLayout" name="gridLayout_19">
+                <item row="0" column="0">
+                 <widget class="QCheckBox" name="editor_show_dbg_file">
+                  <property name="text">
+                   <string>Always show debug breakpoints and pointers (opens related file if closed)</string>
+                  </property>
+                  <property name="checked">
+                   <bool>true</bool>
+                  </property>
+                 </widget>
+                </item>
+               </layout>
+              </item>
+             </layout>
+            </widget>
+           </item>
+           <item>
             <widget class="QGroupBox" name="groupBox_8">
              <property name="title">
               <string>File handling</string>
@@ -1635,7 +1942,7 @@
                     </property>
                    </widget>
                   </item>
-                  <item row="6" column="0">
+                  <item row="8" column="0">
                    <layout class="QHBoxLayout" name="horizontalLayout_2">
                     <property name="topMargin">
                      <number>0</number>
@@ -1693,7 +2000,7 @@
                     </item>
                    </layout>
                   </item>
-                  <item row="8" column="0">
+                  <item row="10" column="0">
                    <layout class="QHBoxLayout" name="horizontalLayout_16">
                     <item>
                      <widget class="QLabel" name="label_16">
@@ -1720,11 +2027,14 @@
                     </item>
                    </layout>
                   </item>
-                  <item row="5" column="0">
+                  <item row="7" column="0">
                    <widget class="QCheckBox" name="editor_hiding_closes_files">
                     <property name="text">
                      <string>Close all files when the editor widget is closed/hidden</string>
                     </property>
+                    <property name="checked">
+                     <bool>true</bool>
+                    </property>
                    </widget>
                   </item>
                  </layout>
@@ -1735,6 +2045,44 @@
             </widget>
            </item>
            <item>
+            <widget class="QGroupBox" name="group_box_editor_styles">
+             <property name="enabled">
+              <bool>true</bool>
+             </property>
+             <property name="autoFillBackground">
+              <bool>false</bool>
+             </property>
+             <property name="title">
+              <string>Editor Styles</string>
+             </property>
+             <property name="alignment">
+              <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+             </property>
+             <layout class="QVBoxLayout" name="verticalLayout_31">
+              <item>
+               <widget class="QLabel" name="label_23">
+                <property name="text">
+                 <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select font, font size (as a difference from the default size), font style (&lt;b&gt;b&lt;/b&gt;old, &lt;b&gt;i&lt;/b&gt;talic, &lt;b&gt;u&lt;/b&gt;nderline), text color, and background color (for the latter, the color magenta (255,0,255) is a placeholder for the default background color).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                </property>
+                <property name="wordWrap">
+                 <bool>true</bool>
+                </property>
+               </widget>
+              </item>
+              <item>
+               <widget class="QTabWidget" name="tabs_editor_lexers">
+                <property name="sizePolicy">
+                 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+                  <horstretch>0</horstretch>
+                  <verstretch>0</verstretch>
+                 </sizepolicy>
+                </property>
+               </widget>
+              </item>
+             </layout>
+            </widget>
+           </item>
+           <item>
             <spacer name="verticalSpacer_7">
              <property name="orientation">
               <enum>Qt::Vertical</enum>
@@ -1742,343 +2090,7 @@
              <property name="sizeHint" stdset="0">
               <size>
                <width>20</width>
-               <height>40</height>
-              </size>
-             </property>
-            </spacer>
-           </item>
-          </layout>
-         </widget>
-        </widget>
-       </item>
-      </layout>
-     </widget>
-     <widget class="QWidget" name="tab_editor_styles">
-      <property name="sizePolicy">
-       <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
-        <horstretch>0</horstretch>
-        <verstretch>0</verstretch>
-       </sizepolicy>
-      </property>
-      <attribute name="title">
-       <string>Editor Styles</string>
-      </attribute>
-      <layout class="QVBoxLayout" name="verticalLayout_12">
-       <item>
-        <layout class="QVBoxLayout" name="verticalLayout_5">
-         <item>
-          <widget class="QLabel" name="label_10">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="frameShape">
-            <enum>QFrame::NoFrame</enum>
-           </property>
-           <property name="text">
-            <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select font, font size (as a difference from the default size), font style (&lt;b&gt;b&lt;/b&gt;old, &lt;b&gt;i&lt;/b&gt;talic, &lt;b&gt;u&lt;/b&gt;nderline), text color, and background color (for the latter, the color magenta (255,0,255) is a placeholder for the default background color).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-           </property>
-           <property name="scaledContents">
-            <bool>false</bool>
-           </property>
-           <property name="alignment">
-            <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
-           </property>
-           <property name="wordWrap">
-            <bool>true</bool>
-           </property>
-           <property name="margin">
-            <number>4</number>
-           </property>
-          </widget>
-         </item>
-         <item>
-          <widget class="QTabWidget" name="tabs_editor_lexers">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-          </widget>
-         </item>
-        </layout>
-       </item>
-      </layout>
-     </widget>
-     <widget class="QWidget" name="tab_terminal">
-      <attribute name="title">
-       <string>Terminal</string>
-      </attribute>
-      <layout class="QVBoxLayout" name="verticalLayout_14">
-       <item>
-        <widget class="QScrollArea" name="scrollArea_3">
-         <property name="widgetResizable">
-          <bool>true</bool>
-         </property>
-         <widget class="QWidget" name="scrollAreaWidgetContents_4">
-          <property name="geometry">
-           <rect>
-            <x>0</x>
-            <y>0</y>
-            <width>658</width>
-            <height>573</height>
-           </rect>
-          </property>
-          <layout class="QVBoxLayout" name="verticalLayout_7">
-           <item>
-            <layout class="QVBoxLayout" name="verticalLayout_8">
-             <item>
-              <layout class="QGridLayout" name="gridLayout_7">
-               <property name="sizeHint" stdset="0">
-                <size>
-                 <width>40</width>
-                 <height>20</height>
-                </size>
-               </property>
-               <item row="1" column="2">
-                <layout class="QHBoxLayout" name="horizontalLayout_13">
-                 <item>
-                  <widget class="QCheckBox" name="terminal_cursorUseForegroundColor">
-                   <property name="text">
-                    <string>Use foreground color</string>
-                   </property>
-                  </widget>
-                 </item>
-                </layout>
-               </item>
-               <item row="1" column="0">
-                <layout class="QHBoxLayout" name="horizontalLayout_7">
-                 <item>
-                  <widget class="QLabel" name="label">
-                   <property name="text">
-                    <string>Cursor type:</string>
-                   </property>
-                  </widget>
-                 </item>
-                 <item>
-                  <widget class="QComboBox" name="terminal_cursorType"/>
-                 </item>
-                </layout>
-               </item>
-               <item row="0" column="0">
-                <layout class="QHBoxLayout" name="horizontalLayout_11">
-                 <item>
-                  <widget class="QLabel" name="label_11">
-                   <property name="text">
-                    <string>Font</string>
-                   </property>
-                  </widget>
-                 </item>
-                 <item>
-                  <widget class="QFontComboBox" name="terminal_fontName">
-                   <property name="sizePolicy">
-                    <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
-                     <horstretch>0</horstretch>
-                     <verstretch>0</verstretch>
-                    </sizepolicy>
-                   </property>
-                   <property name="editable">
-                    <bool>false</bool>
-                   </property>
-                   <property name="fontFilters">
-                    <set>QFontComboBox::MonospacedFonts</set>
-                   </property>
-                  </widget>
-                 </item>
-                </layout>
-               </item>
-               <item row="0" column="2">
-                <layout class="QHBoxLayout" name="horizontalLayout_12">
-                 <item>
-                  <widget class="QLabel" name="label_12">
-                   <property name="text">
-                    <string>Font size</string>
-                   </property>
-                  </widget>
-                 </item>
-                 <item>
-                  <widget class="QSpinBox" name="terminal_fontSize">
-                   <property name="sizePolicy">
-                    <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
-                     <horstretch>0</horstretch>
-                     <verstretch>0</verstretch>
-                    </sizepolicy>
-                   </property>
-                   <property name="minimum">
-                    <number>2</number>
-                   </property>
-                   <property name="maximum">
-                    <number>96</number>
-                   </property>
-                   <property name="value">
-                    <number>10</number>
-                   </property>
-                  </widget>
-                 </item>
-                 <item>
-                  <spacer name="horizontalSpacer_27">
-                   <property name="orientation">
-                    <enum>Qt::Horizontal</enum>
-                   </property>
-                   <property name="sizeHint" stdset="0">
-                    <size>
-                     <width>40</width>
-                     <height>20</height>
-                    </size>
-                   </property>
-                  </spacer>
-                 </item>
-                </layout>
-               </item>
-               <item row="2" column="2">
-                <layout class="QHBoxLayout" name="horizontalLayout_5">
-                 <property name="topMargin">
-                  <number>0</number>
-                 </property>
-                 <item>
-                  <widget class="QSpinBox" name="terminal_history_buffer">
-                   <property name="sizePolicy">
-                    <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
-                     <horstretch>0</horstretch>
-                     <verstretch>0</verstretch>
-                    </sizepolicy>
-                   </property>
-                   <property name="minimum">
-                    <number>0</number>
-                   </property>
-                   <property name="maximum">
-                    <number>5000</number>
-                   </property>
-                   <property name="singleStep">
-                    <number>20</number>
-                   </property>
-                   <property name="value">
-                    <number>1000</number>
-                   </property>
-                  </widget>
-                 </item>
-                 <item>
-                  <widget class="QLabel" name="label_20">
-                   <property name="text">
-                    <string>(Changing buffer size clears history)</string>
-                   </property>
-                  </widget>
-                 </item>
-                 <item>
-                  <spacer name="horizontalSpacer_16">
-                   <property name="orientation">
-                    <enum>Qt::Horizontal</enum>
-                   </property>
-                   <property name="sizeHint" stdset="0">
-                    <size>
-                     <width>40</width>
-                     <height>20</height>
-                    </size>
-                   </property>
-                  </spacer>
-                 </item>
-                </layout>
-               </item>
-               <item row="2" column="0">
-                <widget class="QLabel" name="label_19">
-                 <property name="minimumSize">
-                  <size>
-                   <width>100</width>
-                   <height>20</height>
-                  </size>
-                 </property>
-                 <property name="text">
-                  <string>History buffer Size</string>
-                 </property>
-                </widget>
-               </item>
-               <item row="0" column="1">
-                <spacer name="horizontalSpacer_28">
-                 <property name="orientation">
-                  <enum>Qt::Horizontal</enum>
-                 </property>
-                 <property name="sizeType">
-                  <enum>QSizePolicy::Fixed</enum>
-                 </property>
-                 <property name="sizeHint" stdset="0">
-                  <size>
-                   <width>20</width>
-                   <height>20</height>
-                  </size>
-                 </property>
-                </spacer>
-               </item>
-              </layout>
-             </item>
-             <item>
-              <layout class="QGridLayout" name="gridLayout_15">
-               <item row="0" column="0">
-                <widget class="QCheckBox" name="terminal_focus_command">
-                 <property name="text">
-                  <string>Set focus to terminal when running a command from within another widget</string>
-                 </property>
-                </widget>
-               </item>
-               <item row="1" column="0">
-                <widget class="QCheckBox" name="terminal_print_dbg_location">
-                 <property name="text">
-                  <string>Print debug location in terminal window in addition to the marker in the editor</string>
-                 </property>
-                </widget>
-               </item>
-              </layout>
-             </item>
-             <item>
-              <widget class="Line" name="line_7">
-               <property name="orientation">
-                <enum>Qt::Horizontal</enum>
-               </property>
-              </widget>
-             </item>
-             <item>
-              <widget class="QGroupBox" name="terminal_colors_box">
-               <property name="title">
-                <string>Terminal Colors</string>
-               </property>
-              </widget>
-             </item>
-             <item>
-              <widget class="Line" name="line_5">
-               <property name="minimumSize">
-                <size>
-                 <width>0</width>
-                 <height>0</height>
-                </size>
-               </property>
-               <property name="orientation">
-                <enum>Qt::Horizontal</enum>
-               </property>
-              </widget>
-             </item>
-             <item>
-              <widget class="Line" name="line_6">
-               <property name="orientation">
-                <enum>Qt::Horizontal</enum>
-               </property>
-              </widget>
-             </item>
-            </layout>
-           </item>
-           <item>
-            <spacer name="verticalSpacer_3">
-             <property name="orientation">
-              <enum>Qt::Vertical</enum>
-             </property>
-             <property name="sizeType">
-              <enum>QSizePolicy::Expanding</enum>
-             </property>
-             <property name="sizeHint" stdset="0">
-              <size>
-               <width>20</width>
-               <height>40</height>
+               <height>20</height>
               </size>
              </property>
             </spacer>
@@ -2302,6 +2314,208 @@
        </item>
       </layout>
      </widget>
+     <widget class="QWidget" name="tab_varedit">
+      <attribute name="title">
+       <string>Variable Editor</string>
+      </attribute>
+      <layout class="QVBoxLayout" name="verticalLayout_ve_manual">
+       <item>
+        <widget class="QScrollArea" name="scrollArea_8">
+         <property name="widgetResizable">
+          <bool>true</bool>
+         </property>
+         <widget class="QWidget" name="scrollAreaWidgetContents_3">
+          <property name="geometry">
+           <rect>
+            <x>0</x>
+            <y>0</y>
+            <width>671</width>
+            <height>560</height>
+           </rect>
+          </property>
+          <layout class="QVBoxLayout" name="verticalLayout_vesc_manual">
+           <property name="geometry" stdset="0">
+            <rect>
+             <x>0</x>
+             <y>0</y>
+             <width>678</width>
+             <height>384</height>
+            </rect>
+           </property>
+           <item>
+            <layout class="QVBoxLayout" name="verticalLayout_ve">
+             <item>
+              <layout class="QGridLayout" name="gridLayout_ve">
+               <item row="0" column="3">
+                <widget class="QLabel" name="label_26">
+                 <property name="text">
+                  <string>Font size</string>
+                 </property>
+                 <property name="alignment">
+                  <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+                 </property>
+                </widget>
+               </item>
+               <item row="2" column="2" colspan="2">
+                <widget class="QCheckBox" name="varedit_rowAutofit">
+                 <property name="text">
+                  <string>Plus font height</string>
+                 </property>
+                 <property name="checked">
+                  <bool>true</bool>
+                 </property>
+                </widget>
+               </item>
+               <item row="2" column="0">
+                <widget class="QLabel" name="label_27">
+                 <property name="text">
+                  <string>Default row height</string>
+                 </property>
+                </widget>
+               </item>
+               <item row="0" column="0">
+                <widget class="QLabel" name="label_25">
+                 <property name="text">
+                  <string>Font</string>
+                 </property>
+                 <property name="alignment">
+                  <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+                 </property>
+                </widget>
+               </item>
+               <item row="1" column="0">
+                <widget class="QLabel" name="label_ve_colwidth">
+                 <property name="text">
+                  <string>Default column width</string>
+                 </property>
+                 <property name="alignment">
+                  <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+                 </property>
+                </widget>
+               </item>
+               <item row="0" column="5">
+                <widget class="QCheckBox" name="varedit_useTerminalFont">
+                 <property name="text">
+                  <string>Use Command Window Font</string>
+                 </property>
+                 <property name="checked">
+                  <bool>true</bool>
+                 </property>
+                </widget>
+               </item>
+               <item row="0" column="4">
+                <widget class="QSpinBox" name="varedit_fontSize">
+                 <property name="value">
+                  <number>10</number>
+                 </property>
+                </widget>
+               </item>
+               <item row="0" column="1" colspan="2">
+                <widget class="QFontComboBox" name="varedit_font">
+                 <property name="currentFont">
+                  <font>
+                   <family>Liberation Mono</family>
+                  </font>
+                 </property>
+                </widget>
+               </item>
+               <item row="1" column="2">
+                <widget class="QCheckBox" name="varedit_autoFitColumnWidth">
+                 <property name="text">
+                  <string>Autofit</string>
+                 </property>
+                </widget>
+               </item>
+               <item row="1" column="3" colspan="2">
+                <widget class="QComboBox" name="varedit_autofitType">
+                 <property name="enabled">
+                  <bool>false</bool>
+                 </property>
+                 <property name="currentIndex">
+                  <number>0</number>
+                 </property>
+                 <item>
+                  <property name="text">
+                   <string>By Column</string>
+                  </property>
+                 </item>
+                 <item>
+                  <property name="text">
+                   <string>Uniform</string>
+                  </property>
+                 </item>
+                </widget>
+               </item>
+               <item row="2" column="6">
+                <spacer name="horizontalSpacer_ve">
+                 <property name="orientation">
+                  <enum>Qt::Horizontal</enum>
+                 </property>
+                 <property name="sizeHint" stdset="0">
+                  <size>
+                   <width>40</width>
+                   <height>20</height>
+                  </size>
+                 </property>
+                </spacer>
+               </item>
+               <item row="2" column="1">
+                <widget class="QSpinBox" name="varedit_rowHeight">
+                 <property name="value">
+                  <number>10</number>
+                 </property>
+                </widget>
+               </item>
+               <item row="1" column="1">
+                <widget class="QSpinBox" name="varedit_columnWidth">
+                 <property name="maximum">
+                  <number>500</number>
+                 </property>
+                 <property name="value">
+                  <number>100</number>
+                 </property>
+                </widget>
+               </item>
+              </layout>
+             </item>
+             <item>
+              <widget class="QGroupBox" name="varedit_colors_box">
+               <property name="title">
+                <string>Variable Editor Colors</string>
+               </property>
+              </widget>
+             </item>
+            </layout>
+           </item>
+           <item>
+            <widget class="QCheckBox" name="varedit_alternate">
+             <property name="enabled">
+              <bool>true</bool>
+             </property>
+             <property name="text">
+              <string>Use alternating row colors</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <spacer name="verticalSpacer_4">
+             <property name="orientation">
+              <enum>Qt::Vertical</enum>
+             </property>
+             <property name="sizeHint" stdset="0">
+              <size>
+               <width>20</width>
+               <height>40</height>
+              </size>
+             </property>
+            </spacer>
+           </item>
+          </layout>
+         </widget>
+        </widget>
+       </item>
+      </layout>
+     </widget>
      <widget class="QWidget" name="tab_shortcuts">
       <attribute name="title">
        <string>Shortcuts</string>
@@ -2338,7 +2552,7 @@
                   <string>Select this option to prevent conflicts with readline shortcuts</string>
                  </property>
                  <property name="text">
-                  <string>Disable global shortcuts when terminal window has focus</string>
+                  <string>Disable global shortcuts when Command Window has focus</string>
                  </property>
                  <property name="checked">
                   <bool>true</bool>
@@ -2660,208 +2874,6 @@
        </item>
       </layout>
      </widget>
-     <widget class="QWidget" name="tab_varedit">
-      <attribute name="title">
-       <string>Variable Editor</string>
-      </attribute>
-      <layout class="QVBoxLayout" name="verticalLayout_ve_manual">
-       <item>
-        <widget class="QScrollArea" name="scrollArea_8">
-         <property name="widgetResizable">
-          <bool>true</bool>
-         </property>
-         <widget class="QWidget" name="scrollAreaWidgetContents_3">
-          <property name="geometry">
-           <rect>
-            <x>0</x>
-            <y>0</y>
-            <width>658</width>
-            <height>573</height>
-           </rect>
-          </property>
-          <layout class="QVBoxLayout" name="verticalLayout_vesc_manual">
-           <property name="geometry" stdset="0">
-            <rect>
-             <x>0</x>
-             <y>0</y>
-             <width>678</width>
-             <height>384</height>
-            </rect>
-           </property>
-           <item>
-            <layout class="QVBoxLayout" name="verticalLayout_ve">
-             <item>
-              <layout class="QGridLayout" name="gridLayout_ve">
-               <item row="0" column="3">
-                <widget class="QLabel" name="label_26">
-                 <property name="text">
-                  <string>Font size</string>
-                 </property>
-                 <property name="alignment">
-                  <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
-                 </property>
-                </widget>
-               </item>
-               <item row="2" column="2" colspan="2">
-                <widget class="QCheckBox" name="varedit_rowAutofit">
-                 <property name="text">
-                  <string>Plus font height</string>
-                 </property>
-                 <property name="checked">
-                  <bool>true</bool>
-                 </property>
-                </widget>
-               </item>
-               <item row="2" column="0">
-                <widget class="QLabel" name="label_27">
-                 <property name="text">
-                  <string>Default row height</string>
-                 </property>
-                </widget>
-               </item>
-               <item row="0" column="0">
-                <widget class="QLabel" name="label_25">
-                 <property name="text">
-                  <string>Font</string>
-                 </property>
-                 <property name="alignment">
-                  <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
-                 </property>
-                </widget>
-               </item>
-               <item row="1" column="0">
-                <widget class="QLabel" name="label_ve_colwidth">
-                 <property name="text">
-                  <string>Default column width</string>
-                 </property>
-                 <property name="alignment">
-                  <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
-                 </property>
-                </widget>
-               </item>
-               <item row="0" column="5">
-                <widget class="QCheckBox" name="varedit_useTerminalFont">
-                 <property name="text">
-                  <string>Use Terminal Font</string>
-                 </property>
-                 <property name="checked">
-                  <bool>true</bool>
-                 </property>
-                </widget>
-               </item>
-               <item row="0" column="4">
-                <widget class="QSpinBox" name="varedit_fontSize">
-                 <property name="value">
-                  <number>10</number>
-                 </property>
-                </widget>
-               </item>
-               <item row="0" column="1" colspan="2">
-                <widget class="QFontComboBox" name="varedit_font">
-                 <property name="currentFont">
-                  <font>
-                   <family>Liberation Mono</family>
-                  </font>
-                 </property>
-                </widget>
-               </item>
-               <item row="1" column="2">
-                <widget class="QCheckBox" name="varedit_autoFitColumnWidth">
-                 <property name="text">
-                  <string>Autofit</string>
-                 </property>
-                </widget>
-               </item>
-               <item row="1" column="3" colspan="2">
-                <widget class="QComboBox" name="varedit_autofitType">
-                 <property name="enabled">
-                  <bool>false</bool>
-                 </property>
-                 <property name="currentIndex">
-                  <number>0</number>
-                 </property>
-                 <item>
-                  <property name="text">
-                   <string>By Column</string>
-                  </property>
-                 </item>
-                 <item>
-                  <property name="text">
-                   <string>Uniform</string>
-                  </property>
-                 </item>
-                </widget>
-               </item>
-               <item row="2" column="6">
-                <spacer name="horizontalSpacer_ve">
-                 <property name="orientation">
-                  <enum>Qt::Horizontal</enum>
-                 </property>
-                 <property name="sizeHint" stdset="0">
-                  <size>
-                   <width>40</width>
-                   <height>20</height>
-                  </size>
-                 </property>
-                </spacer>
-               </item>
-               <item row="2" column="1">
-                <widget class="QSpinBox" name="varedit_rowHeight">
-                 <property name="value">
-                  <number>10</number>
-                 </property>
-                </widget>
-               </item>
-               <item row="1" column="1">
-                <widget class="QSpinBox" name="varedit_columnWidth">
-                 <property name="maximum">
-                  <number>500</number>
-                 </property>
-                 <property name="value">
-                  <number>100</number>
-                 </property>
-                </widget>
-               </item>
-              </layout>
-             </item>
-             <item>
-              <widget class="QGroupBox" name="varedit_colors_box">
-               <property name="title">
-                <string>Variable Editor Colors</string>
-               </property>
-              </widget>
-             </item>
-            </layout>
-           </item>
-           <item>
-            <widget class="QCheckBox" name="varedit_alternate">
-             <property name="enabled">
-              <bool>true</bool>
-             </property>
-             <property name="text">
-              <string>Use alternating row colors</string>
-             </property>
-            </widget>
-           </item>
-           <item>
-            <spacer name="verticalSpacer_4">
-             <property name="orientation">
-              <enum>Qt::Vertical</enum>
-             </property>
-             <property name="sizeHint" stdset="0">
-              <size>
-               <width>20</width>
-               <height>40</height>
-              </size>
-             </property>
-            </spacer>
-           </item>
-          </layout>
-         </widget>
-        </widget>
-       </item>
-      </layout>
-     </widget>
     </widget>
    </item>
    <item>
@@ -2910,6 +2922,22 @@
   <connection>
    <sender>useProxyServer</sender>
    <signal>toggled(bool)</signal>
+   <receiver>proxyHostName</receiver>
+   <slot>setEnabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>249</x>
+     <y>59</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>291</x>
+     <y>124</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>useProxyServer</sender>
+   <signal>toggled(bool)</signal>
    <receiver>label_5</receiver>
    <slot>setEnabled(bool)</slot>
    <hints>
@@ -2942,22 +2970,6 @@
   <connection>
    <sender>useProxyServer</sender>
    <signal>toggled(bool)</signal>
-   <receiver>proxyHostName</receiver>
-   <slot>setEnabled(bool)</slot>
-   <hints>
-    <hint type="sourcelabel">
-     <x>249</x>
-     <y>59</y>
-    </hint>
-    <hint type="destinationlabel">
-     <x>291</x>
-     <y>124</y>
-    </hint>
-   </hints>
-  </connection>
-  <connection>
-   <sender>useProxyServer</sender>
-   <signal>toggled(bool)</signal>
    <receiver>proxyPort</receiver>
    <slot>setEnabled(bool)</slot>
    <hints>
@@ -3006,7 +3018,7 @@
   <connection>
    <sender>useProxyServer</sender>
    <signal>toggled(bool)</signal>
-   <receiver>proxyUserName</receiver>
+   <receiver>label_6</receiver>
    <slot>setEnabled(bool)</slot>
    <hints>
     <hint type="sourcelabel">
@@ -3014,8 +3026,8 @@
      <y>59</y>
     </hint>
     <hint type="destinationlabel">
-     <x>364</x>
-     <y>184</y>
+     <x>68</x>
+     <y>182</y>
     </hint>
    </hints>
   </connection>
@@ -3038,7 +3050,7 @@
   <connection>
    <sender>useProxyServer</sender>
    <signal>toggled(bool)</signal>
-   <receiver>label_6</receiver>
+   <receiver>proxyUserName</receiver>
    <slot>setEnabled(bool)</slot>
    <hints>
     <hint type="sourcelabel">
@@ -3046,8 +3058,8 @@
      <y>59</y>
     </hint>
     <hint type="destinationlabel">
-     <x>68</x>
-     <y>182</y>
+     <x>364</x>
+     <y>184</y>
     </hint>
    </hints>
   </connection>
@@ -3068,54 +3080,6 @@
    </hints>
   </connection>
   <connection>
-   <sender>editor_codeCompletion</sender>
-   <signal>toggled(bool)</signal>
-   <receiver>editor_label_ac_threshold</receiver>
-   <slot>setEnabled(bool)</slot>
-   <hints>
-    <hint type="sourcelabel">
-     <x>83</x>
-     <y>223</y>
-    </hint>
-    <hint type="destinationlabel">
-     <x>288</x>
-     <y>223</y>
-    </hint>
-   </hints>
-  </connection>
-  <connection>
-   <sender>editor_codeCompletion</sender>
-   <signal>toggled(bool)</signal>
-   <receiver>editor_spinbox_ac_threshold</receiver>
-   <slot>setEnabled(bool)</slot>
-   <hints>
-    <hint type="sourcelabel">
-     <x>83</x>
-     <y>223</y>
-    </hint>
-    <hint type="destinationlabel">
-     <x>412</x>
-     <y>223</y>
-    </hint>
-   </hints>
-  </connection>
-  <connection>
-   <sender>editor_highlightCurrentLine</sender>
-   <signal>toggled(bool)</signal>
-   <receiver>editor_label_cl_color</receiver>
-   <slot>setEnabled(bool)</slot>
-   <hints>
-    <hint type="sourcelabel">
-     <x>184</x>
-     <y>86</y>
-    </hint>
-    <hint type="destinationlabel">
-     <x>515</x>
-     <y>86</y>
-    </hint>
-   </hints>
-  </connection>
-  <connection>
    <sender>editor_ws_checkbox</sender>
    <signal>toggled(bool)</signal>
    <receiver>editor_ws_indent_checkbox</receiver>
@@ -3148,6 +3112,54 @@
    </hints>
   </connection>
   <connection>
+   <sender>editor_highlightCurrentLine</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>editor_label_cl_color</receiver>
+   <slot>setEnabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>184</x>
+     <y>86</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>515</x>
+     <y>86</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>editor_codeCompletion</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>editor_spinbox_ac_threshold</receiver>
+   <slot>setEnabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>83</x>
+     <y>223</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>412</x>
+     <y>223</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>editor_codeCompletion</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>editor_label_ac_threshold</receiver>
+   <slot>setEnabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>83</x>
+     <y>223</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>288</x>
+     <y>223</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
    <sender>cb_widget_custom_style</sender>
    <signal>toggled(bool)</signal>
    <receiver>label_fgtitle</receiver>
@@ -3326,16 +3338,16 @@
   <connection>
    <sender>cb_widget_custom_style</sender>
    <signal>toggled(bool)</signal>
-   <receiver>label_bgtitle_active</receiver>
+   <receiver>label_3d_title</receiver>
    <slot>setEnabled(bool)</slot>
    <hints>
     <hint type="sourcelabel">
      <x>260</x>
-     <y>190</y>
+     <y>186</y>
     </hint>
     <hint type="destinationlabel">
-     <x>525</x>
-     <y>190</y>
+     <x>419</x>
+     <y>236</y>
     </hint>
    </hints>
   </connection>
@@ -3358,16 +3370,16 @@
   <connection>
    <sender>cb_widget_custom_style</sender>
    <signal>toggled(bool)</signal>
-   <receiver>label_3d_title</receiver>
+   <receiver>label_bgtitle_active</receiver>
    <slot>setEnabled(bool)</slot>
    <hints>
     <hint type="sourcelabel">
      <x>260</x>
-     <y>186</y>
+     <y>190</y>
     </hint>
     <hint type="destinationlabel">
-     <x>419</x>
-     <y>236</y>
+     <x>525</x>
+     <y>190</y>
     </hint>
    </hints>
   </connection>
--- a/libgui/src/shortcut-manager.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/src/shortcut-manager.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -509,6 +509,19 @@
       qDebug () << "Key: " << key << " not found in m_action_hash";
   }
 
+  void shortcut_manager::do_shortcut (QShortcut *sc, const QString& key)
+  {
+    int index;
+
+    index = m_action_hash[key] - 1;
+
+    if (index > -1 && index < m_sc.count ())
+      sc->setKey (QKeySequence (m_settings->value ("shortcuts/" + key,
+                                m_sc.at (index).m_default_sc).toString ()));
+    else
+      qDebug () << "Key: " << key << " not found in m_action_hash";
+  }
+
   void shortcut_manager::do_fill_treewidget (QTreeWidget *tree_view)
   {
     m_dialog = nullptr;
@@ -537,6 +550,8 @@
     main_news->setText (0, tr ("News Menu"));
     QTreeWidgetItem *main_tabs = new QTreeWidgetItem (main);
     main_tabs->setText (0, tr ("Tab Handling in Dock Widgets"));
+    QTreeWidgetItem *main_find = new QTreeWidgetItem (main);
+    main_find->setText (0, tr ("Find & Replace in Dock Widgets"));
 
     m_level_hash["main_file"]   = main_file;
     m_level_hash["main_edit"]   = main_edit;
@@ -546,6 +561,7 @@
     m_level_hash["main_news"]   = main_news;
     m_level_hash["main_tabs"]   = main_tabs;
     m_level_hash["editor_tabs"]   = main_tabs;
+    m_level_hash["editor_find"]   = main_find;
 
     QTreeWidgetItem *editor = new QTreeWidgetItem (tree_view);
     editor->setText (0, tr ("Editor"));
@@ -587,6 +603,12 @@
             if (sc.m_settings_key.contains ("editor_file:close"))
               section = main_tabs;
           }
+        if (section == editor_edit)
+          {
+            // Find & replace now in global file & replace handling section
+            if (sc.m_settings_key.contains ("editor_edit:find"))
+              section = main_find;
+          }
 
         QTreeWidgetItem *tree_item = new QTreeWidgetItem (section);
 
@@ -627,12 +649,12 @@
 
         if (action == OSC_IMPORT)
           file = QFileDialog::getOpenFileName (this,
-                                               tr ("Import shortcuts from file ..."), QString (),
+                                               tr ("Import shortcuts from file..."), QString (),
                                                tr ("Octave Shortcut Files (*.osc);;All Files (*)"),
                                                nullptr, QFileDialog::DontUseNativeDialog);
         else if (action == OSC_EXPORT)
           file = QFileDialog::getSaveFileName (this,
-                                               tr ("Export shortcuts into file ..."), QString (),
+                                               tr ("Export shortcuts to file..."), QString (),
                                                tr ("Octave Shortcut Files (*.osc);;All Files (*)"),
                                                nullptr, QFileDialog::DontUseNativeDialog);
 
@@ -643,7 +665,7 @@
 
         if (! osc_settings)
           {
-            qWarning () << tr ("Failed to open %1 as octave shortcut file")
+            qWarning () << tr ("Failed to open %1 as Octave shortcut file")
                         .arg (file);
             return false;
           }
--- a/libgui/src/shortcut-manager.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/src/shortcut-manager.h	Fri Aug 10 09:09:51 2018 +0200
@@ -29,6 +29,7 @@
 #include <QKeyEvent>
 #include <QLabel>
 #include <QSettings>
+#include <QShortcut>
 
 namespace octave
 {
@@ -95,6 +96,12 @@
         instance->do_set_shortcut (action, key);
     }
 
+    static void shortcut (QShortcut *sc, const QString& key)
+    {
+      if (instance_ok () && sc)
+        instance->do_shortcut (sc, key);
+    }
+
     static void fill_treewidget (QTreeWidget *tree_view)
     {
       if (instance_ok ())
@@ -127,6 +134,7 @@
     void do_init_data ();
     void do_write_shortcuts (QSettings *settings, bool closing);
     void do_set_shortcut (QAction *action, const QString& key);
+    void do_shortcut (QShortcut *sc, const QString& key);
     void do_fill_treewidget (QTreeWidget *tree_view);
     bool do_import_export (int action);
     void shortcut_dialog (int);
--- a/libgui/src/terminal-dock-widget.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/src/terminal-dock-widget.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -38,12 +38,12 @@
 namespace octave
 {
   terminal_dock_widget::terminal_dock_widget (QWidget *p)
-    : octave_dock_widget (p), m_terminal (QTerminal::create (p))
+    : octave_dock_widget ("TerminalDockWidget", p),
+      m_terminal (QTerminal::create (p))
   {
     m_terminal->setObjectName ("OctaveTerminal");
     m_terminal->setFocusPolicy (Qt::StrongFocus);
 
-    setObjectName ("TerminalDockWidget");
     setWindowIcon (QIcon (":/actions/icons/logo.png"));
     set_title (tr ("Command Window"));
 
--- a/libgui/src/variable-editor-model.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/src/variable-editor-model.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -222,17 +222,6 @@
       case Qt::EditRole:
         return edit_display (idx, role);
         return edit_display (idx, role);
-
-#if 0
-      case Qt::StatusTipRole:
-        return elem (idx).m_status_tip;
-
-      case Qt::ToolTipRole:
-        return elem (idx).m_tool_tip;
-
-      case Qt::BackgroundRole:
-        return elem (idx).m_background;
-#endif
       }
 
     // Invalid.
@@ -1020,7 +1009,7 @@
 
     std::string expr = os.str ();
 
-    octave_link::post_event<variable_editor_model, std::string, std::string, QModelIndex>
+    octave_link::post_event
       (this, &variable_editor_model::set_data_oct, nm, expr, idx);
 
     return true;
@@ -1057,7 +1046,7 @@
   {
     // FIXME: cells?
 
-    octave_link::post_event <variable_editor_model, std::string, std::string>
+    octave_link::post_event
       (this, &variable_editor_model::eval_oct, name (),
        QString ("%1 = [ %1(1:%2,:) ; zeros(%3, columns(%1)) ; %1(%2+%3:end,:) ]")
        .arg (QString::fromStdString (name ()))
@@ -1079,7 +1068,7 @@
         return false;
       }
 
-    octave_link::post_event <variable_editor_model, std::string, std::string>
+    octave_link::post_event
       (this, &variable_editor_model::eval_oct, name (),
        QString ("%1(%2:%3, :) = []")
        .arg (QString::fromStdString (name ()))
@@ -1093,7 +1082,7 @@
   bool
   variable_editor_model::insertColumns (int col, int count, const QModelIndex&)
   {
-    octave_link::post_event <variable_editor_model, std::string, std::string>
+    octave_link::post_event
       (this, &variable_editor_model::eval_oct, name (),
        QString ("%1 = [ %1(:,1:%2) ; zeros(rows(%1), %3) %1(:,%2+%3:end) ]")
        .arg (QString::fromStdString (name ()))
@@ -1115,7 +1104,7 @@
         return false;
       }
 
-    octave_link::post_event <variable_editor_model, std::string, std::string>
+    octave_link::post_event
       (this, &variable_editor_model::eval_oct, name (),
        QString ("%1(:, %2:%3) = []")
        .arg (QString::fromStdString (name ()))
--- a/libgui/src/variable-editor.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/src/variable-editor.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -47,6 +47,7 @@
 #include <QToolButton>
 #include <QVBoxLayout>
 
+#include "dw-main-window.h"
 #include "resource-manager.h"
 #include "shortcut-manager.h"
 #include "variable-editor.h"
@@ -86,6 +87,11 @@
 
   variable_dock_widget::variable_dock_widget (QWidget *p)
     : label_dock_widget (p)
+// See  Octave bug #53807 and https://bugreports.qt.io/browse/QTBUG-44813
+#if (QT_VERSION >= 0x050302) && (QT_VERSION <= QTBUG_44813_FIX_VERSION)
+      , m_waiting_for_mouse_move (false)
+      , m_waiting_for_mouse_button_release (false)
+#endif
   {
     setFocusPolicy (Qt::StrongFocus);
     setAttribute (Qt::WA_DeleteOnClose);
@@ -109,28 +115,25 @@
     m_prev_floating = false;
     m_prev_geom = QRect (0, 0, 0, 0);
 
-    QHBoxLayout *h_layout = findChild<QHBoxLayout *> ();
-    if (h_layout != nullptr && titleBarWidget () != nullptr)
-      {
-        m_fullscreen_action = new QAction
-          (resource_manager::icon ("view-fullscreen", false), "", this);
-        m_fullscreen_action->setToolTip (tr (DOCKED_FULLSCREEN_BUTTON_TOOLTIP));
-        QToolButton *fullscreen_button = new QToolButton (titleBarWidget ());
-        fullscreen_button->setDefaultAction (m_fullscreen_action);
-        fullscreen_button->setFocusPolicy (Qt::NoFocus);
-        fullscreen_button->setIconSize (QSize (m_icon_size,m_icon_size));
-        QString css_button = QString ("QToolButton {background: transparent; border: 0px;}");
-        fullscreen_button->setStyleSheet (css_button);
+    QHBoxLayout *h_layout = m_title_widget->findChild<QHBoxLayout *> ();
+    m_fullscreen_action = new QAction
+      (resource_manager::icon ("view-fullscreen", false), "", this);
+    m_fullscreen_action->setToolTip (tr (DOCKED_FULLSCREEN_BUTTON_TOOLTIP));
+    QToolButton *fullscreen_button = new QToolButton (m_title_widget);
+    fullscreen_button->setDefaultAction (m_fullscreen_action);
+    fullscreen_button->setFocusPolicy (Qt::NoFocus);
+    fullscreen_button->setIconSize (QSize (m_icon_size,m_icon_size));
+    QString css_button = QString ("QToolButton {background: transparent; border: 0px;}");
+    fullscreen_button->setStyleSheet (css_button);
 
-        connect (m_fullscreen_action, SIGNAL (triggered ()),
-                 this, SLOT (change_fullscreen ()));
+    connect (m_fullscreen_action, SIGNAL (triggered ()),
+             this, SLOT (change_fullscreen ()));
 
-        int index = -1;
-        QToolButton *first = titleBarWidget ()->findChild<QToolButton *> ();
-        if (first != nullptr)
-          index = h_layout->indexOf (first);
-        h_layout->insertWidget (index, fullscreen_button);
-      }
+    int index = -1;
+    QToolButton *first = m_title_widget->findChild<QToolButton *> ();
+    if (first != nullptr)
+      index = h_layout->indexOf (first);
+    h_layout->insertWidget (index, fullscreen_button);
 #endif
 
     // Custom title bars cause loss of decorations, add a frame
@@ -176,15 +179,26 @@
         m_dock_action->setIcon (QIcon (":/actions/icons/widget-dock.png"));
         m_dock_action->setToolTip (tr ("Dock widget"));
 
-        activateWindow();
-        setFocus (Qt::OtherFocusReason);
+        activateWindow ();
+        setFocus ();
+
+// See  Octave bug #53807 and https://bugreports.qt.io/browse/QTBUG-44813
+#if (QT_VERSION >= 0x050302) && (QT_VERSION <= QTBUG_44813_FIX_VERSION)
+        m_waiting_for_mouse_move = true;
+#endif
       }
     else
       {
         m_dock_action->setIcon (QIcon (":/actions/icons/widget-undock.png"));
         m_dock_action->setToolTip (tr ("Undock widget"));
 
-        setFocus (Qt::OtherFocusReason);
+        setFocus ();
+
+// See  Octave bug #53807 and https://bugreports.qt.io/browse/QTBUG-44813
+#if (QT_VERSION >= 0x050302) && (QT_VERSION <= QTBUG_44813_FIX_VERSION)
+        m_waiting_for_mouse_move = false;
+        m_waiting_for_mouse_button_release = false;
+#endif
       }
   }
 
@@ -195,8 +209,6 @@
     if (! m_full_screen)
       {
         m_prev_floating = isFloating ();
-        m_prev_geom = geometry ();
-
         m_fullscreen_action->setIcon (resource_manager::icon ("view-restore", false));
         if (m_prev_floating)
           m_fullscreen_action->setToolTip (tr ("Restore geometry"));
@@ -205,6 +217,7 @@
             m_fullscreen_action->setToolTip (tr ("Redock"));
             setFloating (true);
           }
+        m_prev_geom = geometry ();
 
         // showFullscreen() and setWindowState() only work for QWindow objects.
         QScreen *pscreen = QGuiApplication::primaryScreen ();
@@ -244,23 +257,35 @@
   {
     octave_unused_parameter (now);
 
-    // The is a proxied test
+    // This is a proxied test
     if (hasFocus ())
       {
-        QLabel *label = titleBarWidget ()->findChild<QLabel *> ();
-        if (label != nullptr)
+        if (old == this)
+          return;
+
+        if (titleBarWidget () != nullptr)
           {
-            label->setBackgroundRole (QPalette::Highlight);
-            label->setAutoFillBackground (true);
+            QLabel *label = titleBarWidget ()->findChild<QLabel *> ();
+            if (label != nullptr)
+              {
+                label->setBackgroundRole (QPalette::Highlight);
+                label->setStyleSheet ("background-color: palette(highlight); color: palette(highlightedText);");
+              }
           }
 
         emit variable_focused_signal (objectName ());
       }
     else if (old == focusWidget())
       {
-        QLabel *label = titleBarWidget ()->findChild<QLabel *> ();
-        if (label != NULL)
-          label->setBackgroundRole (QPalette::NoRole);
+        if (titleBarWidget () != nullptr)
+          {
+            QLabel *label = titleBarWidget ()->findChild<QLabel *> ();
+            if (label != nullptr)
+              {
+                label->setBackgroundRole (QPalette::NoRole);
+                label->setStyleSheet (";");
+              }
+          }
       }
   }
 
@@ -270,6 +295,69 @@
       m_frame->resize (size ());
   }
 
+// See  Octave bug #53807 and https://bugreports.qt.io/browse/QTBUG-44813
+#if (QT_VERSION >= 0x050302) && (QT_VERSION <= QTBUG_44813_FIX_VERSION)
+
+  bool
+  variable_dock_widget::event (QEvent *event)
+  {
+    // low-level check of whether docked-widget became a window via
+    // via drag-and-drop
+    if (event->type () == QEvent::MouseButtonPress)
+      {
+        m_waiting_for_mouse_move = false;
+        m_waiting_for_mouse_button_release = false;
+      }
+    if (event->type () == QEvent::MouseMove && m_waiting_for_mouse_move)
+      {
+        m_waiting_for_mouse_move = false;
+        m_waiting_for_mouse_button_release = true;
+      }
+    if (event->type () == QEvent::MouseButtonRelease && m_waiting_for_mouse_button_release)
+      {
+        m_waiting_for_mouse_button_release = false;
+        bool retval = QDockWidget::event (event);
+        if (isFloating ())
+          emit queue_unfloat_float ();
+        return retval;
+      }
+
+    return QDockWidget::event (event);
+  }
+
+  void
+  variable_dock_widget::unfloat_float (void)
+  {
+    hide ();
+    setFloating (false);
+    // Avoid a Ubunty Unity issue by queuing this rather than direct.
+    emit queue_float ();
+    m_waiting_for_mouse_move = false;
+    m_waiting_for_mouse_button_release = false;
+  }
+
+  void
+  variable_dock_widget::refloat (void)
+  {
+    setFloating (true);
+    m_waiting_for_mouse_move = false;
+    m_waiting_for_mouse_button_release = false;
+    show ();
+    activateWindow ();
+    setFocus ();
+  }
+
+#else
+
+  void
+  variable_dock_widget::unfloat_float (void)
+  {}
+
+  void
+  variable_dock_widget::refloat (void)
+  {}
+
+#endif
 
   // Variable editor stack
 
@@ -495,12 +583,6 @@
                      tr ("Paste"),
                      this, SLOT (pasteClipboard ()));
 
-    // FIXME: Different icon for Paste Table?
-
-    menu->addAction (resource_manager::icon ("edit-paste"),
-                     tr ("Paste Table"),
-                     this, SLOT (pasteTableClipboard ()));
-
     menu->addSeparator ();
 
     menu->addAction (resource_manager::icon ("edit-delete"),
@@ -771,38 +853,6 @@
     QClipboard *clipboard = QApplication::clipboard ();
     QString text = clipboard->text ();
 
-    if (indices.isEmpty ())
-      {
-        if (size () == QSize (1,1))
-          mod->setData (mod->index (0,0), text.toDouble ());
-        else if (size () == QSize (0,0))
-          {
-            mod->insertColumn (0);
-            mod->insertRow (0);
-            mod->setData (mod->index (0,0), text.toDouble ());
-          }
-      }
-    else
-      {
-        QStringList cells = text.split(QRegExp("\n|\r\n|\r"));
-        int clen = cells.size ();
-        for (int i = 0; i < indices.size (); i++)
-          mod->setData (indices[i], cells.at (i % clen).toDouble ());
-      }
-  }
-
-  void variable_editor_view::pasteTableClipboard (void)
-  {
-    if (! hasFocus ())
-      return;
-
-    QAbstractItemModel *mod = model ();
-    QItemSelectionModel *sel = selectionModel ();
-    QList<QModelIndex> indices = sel->selectedIndexes ();
-
-    QClipboard *clipboard = QApplication::clipboard ();
-    QString text = clipboard->text ();
-
     QPoint start, end;
 
     QPoint tabsize = QPoint (mod->rowCount (), mod->columnCount ());
@@ -927,8 +977,7 @@
   {
     if (ev->type () == QEvent::HoverEnter)
       emit hovered_signal ();
-    else if (ev->type () == QEvent::MouseButtonPress ||
-             ev->type () == QEvent::MouseButtonPress)
+    else if (ev->type () == QEvent::MouseButtonPress)
       emit popup_shown_signal ();
 
     return QToolButton::eventFilter (obj, ev);
@@ -977,8 +1026,8 @@
   // Variable editor.
 
   variable_editor::variable_editor (QWidget *p)
-    : octave_dock_widget (p),
-      m_main (new QMainWindow ()),
+    : octave_dock_widget ("VariableEditor", p),
+      m_main (new dw_main_window ()),
       m_tool_bar (new QToolBar (m_main)),
       m_default_width (30),
       m_default_height (100),
@@ -991,9 +1040,9 @@
       m_table_colors (),
       m_current_focus_vname (""),
       m_hovered_focus_vname (""),
-      m_variable_focus_widget (nullptr)
+      m_focus_widget (nullptr),
+      m_focus_widget_vdw (nullptr)
   {
-    setObjectName ("VariableEditor");
     set_title (tr ("Variable Editor"));
     setStatusTip (tr ("Edit variables."));
     setWindowIcon (QIcon (":/actions/icons/logo.png"));
@@ -1040,19 +1089,33 @@
     octave_dock_widget::focusInEvent (ev);
 
     // set focus to the current variable or most recent if still valid
-    QWidget *fw = m_main->focusWidget ();
-    if (fw != nullptr)
-      fw->setFocus ();
-    else if (m_main->isAncestorOf (m_variable_focus_widget))
-      m_variable_focus_widget->setFocus ();
-  }
-
-  void variable_editor::focusOutEvent (QFocusEvent *ev)
-  {
-    // focusWidget() appears lost in transition to/from main window
-    m_variable_focus_widget = m_main->focusWidget ();
-
-    octave_dock_widget::focusOutEvent (ev);
+    if (m_focus_widget != nullptr)
+      {
+        // Activating a floating window causes problems.
+        if (! m_focus_widget_vdw->isFloating ())
+            activateWindow ();
+        m_focus_widget->setFocus ();
+      }
+    else
+      {
+        QWidget *fw = m_main->focusWidget ();
+        if (fw != nullptr)
+          {
+            activateWindow ();
+            fw->setFocus ();
+          }
+        else
+          {
+            QDockWidget *any_qdw = m_main->findChild<QDockWidget *> ();
+            if (any_qdw != nullptr)
+              {
+                activateWindow ();
+                any_qdw->setFocus ();
+              }
+            else
+              setFocus();
+          }
+      }
   }
 
   // Add an action to a menu or the widget itself.
@@ -1120,6 +1183,13 @@
              this, SLOT (variable_destroyed (QObject *)));
     connect (page, SIGNAL (variable_focused_signal (const QString&)),
              this, SLOT (variable_focused (const QString&)));
+// See  Octave bug #53807 and https://bugreports.qt.io/browse/QTBUG-44813
+#if (QT_VERSION >= 0x050302) && (QT_VERSION <= QTBUG_44813_FIX_VERSION)
+    connect (page, SIGNAL (queue_unfloat_float ()),
+             page, SLOT (unfloat_float ()), Qt::QueuedConnection);
+    connect (page, SIGNAL (queue_float ()),
+             page, SLOT (refloat ()), Qt::QueuedConnection);
+#endif
 
     variable_editor_stack *stack = new variable_editor_stack (page);
     stack->setObjectName (name);
@@ -1154,8 +1224,6 @@
              edit_view, SLOT (copyClipboard ()));
     connect (this, SIGNAL (paste_clipboard_signal ()),
              edit_view, SLOT (pasteClipboard ()));
-    connect (this, SIGNAL (paste_table_clipboard_signal ()),
-             edit_view, SLOT (pasteTableClipboard ()));
     connect (this, SIGNAL (selected_command_signal (const QString&)),
              edit_view, SLOT (selected_command_requested (const QString&)));
     connect (edit_view->horizontalHeader (),
@@ -1192,10 +1260,13 @@
     // to always supply a QLabl (initially empty) and then simply update its
     // contents.
     page->set_title (name);
-    QLabel *existing_ql = page->titleBarWidget ()->findChild<QLabel *> ();
-    connect (model, SIGNAL (update_label_signal (const QString&)),
-             existing_ql, SLOT (setText (const QString&)));
-    existing_ql->setMargin (2);
+    if (page->titleBarWidget () != nullptr)
+      {
+        QLabel *existing_ql = page->titleBarWidget ()->findChild<QLabel *> ();
+        connect (model, SIGNAL (update_label_signal (const QString&)),
+                 existing_ql, SLOT (setText (const QString&)));
+        existing_ql->setMargin (2);
+      }
 
     model->update_data (val);
 
@@ -1272,7 +1343,7 @@
   void
   variable_editor::notice_settings (const QSettings *settings)
   {
-    // FIXME: Why use object->tostring->toint?  Why not just 100?
+    m_main->notice_settings (settings); // update settings in parent main win
 
     m_default_width = settings->value ("variable_editor/column_width",
                                        100).toInt ();
@@ -1356,17 +1427,49 @@
   }
 
   void
-  variable_editor::variable_destroyed (QObject *)
+  variable_editor::variable_destroyed (QObject *obj)
   {
+    // Invalidate the focus-restoring widget pointer if currently active.
+    if (m_focus_widget_vdw == obj)
+      {
+        m_focus_widget = nullptr;
+        m_focus_widget_vdw = nullptr;
+      }
+
+    // If no variable pages remain, deactivate the tool bar.
     QList<variable_dock_widget *> vdwlist = findChildren<variable_dock_widget *> ();
     if (vdwlist.isEmpty ())
       m_tool_bar->setEnabled (false);
+
+    QFocusEvent ev (QEvent::FocusIn);
+    focusInEvent (&ev);
   }
 
   void
   variable_editor::variable_focused (const QString &name)
   {
     m_current_focus_vname = name;
+
+    // focusWidget() appears lost in transition to/from main window
+    // so keep a record of the widget.
+
+    QWidget *current = QApplication::focusWidget ();
+    m_focus_widget = nullptr;
+    m_focus_widget_vdw = nullptr;
+    if (current != nullptr)
+      {
+        QList<variable_dock_widget *> vdwlist = findChildren<variable_dock_widget *> ();
+        for (int i = 0; i < vdwlist.size (); i++)
+          {
+            variable_dock_widget *vdw = vdwlist.at (i);
+            if (vdw->isAncestorOf (current))
+              {
+                m_focus_widget = current;
+                m_focus_widget_vdw = vdw;
+                break;
+              }
+          }
+      }
   }
 
   void
@@ -1421,14 +1524,6 @@
   }
 
   void
-  variable_editor::pasteTableClipboard (void)
-  {
-    emit paste_table_clipboard_signal ();
-
-    emit updated ();
-  }
-
-  void
   variable_editor::levelUp (void)
   {
     emit level_up_signal ();
@@ -1535,13 +1630,6 @@
                                   tr ("Paste"), this, SLOT (pasteClipboard ()));
     action->setStatusTip(tr("Paste clipboard into variable data"));
 
-    // FIXME: Different icon for Paste Table?
-
-    action = add_tool_bar_button (resource_manager::icon ("edit-paste"),
-                                  tr ("Paste Table"),
-                                  this, SLOT (pasteTableClipboard ()));
-    action->setStatusTip(tr("Another paste clipboard into variable data"));
-
     m_tool_bar->addSeparator ();
 
     // FIXME: Add a print item?
--- a/libgui/src/variable-editor.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/src/variable-editor.h	Fri Aug 10 09:09:51 2018 +0200
@@ -32,6 +32,8 @@
 
 #include "octave-dock-widget.h"
 #include "tab-bar.h"
+#include "dw-main-window.h"
+
 
 class octave_value;
 
@@ -44,6 +46,7 @@
   class variable_editor_model;
   class variable_editor_view;
 
+
   // The individual variable subwindow class
 
   class variable_dock_widget : public label_dock_widget
@@ -93,6 +96,32 @@
     QRect m_prev_geom;
 
 #endif
+
+// See Octave bug #53807 and https://bugreports.qt.io/browse/QTBUG-44813
+#define QTBUG_44813_FIX_VERSION 0x999999
+  signals:
+
+    void queue_unfloat_float (void);
+
+    void queue_float (void);
+
+  protected slots:
+
+    void unfloat_float (void);
+
+    void refloat (void);
+
+#if (QT_VERSION >= 0x050302) && (QT_VERSION <= QTBUG_44813_FIX_VERSION)
+  protected:
+
+    bool event (QEvent *event);
+
+  private:
+
+    bool m_waiting_for_mouse_move;
+
+    bool m_waiting_for_mouse_button_release;
+#endif
   };
 
   class variable_editor_stack : public QStackedWidget
@@ -165,8 +194,6 @@
 
     void pasteClipboard (void);
 
-    void pasteTableClipboard (void);
-
     void handle_horizontal_scroll_action (int action);
 
     void handle_vertical_scroll_action (int action);
@@ -300,8 +327,6 @@
 
     void pasteClipboard (void);
 
-    void pasteTableClipboard (void);
-
     void levelUp (void);
 
     // Send command to Octave interpreter.
@@ -324,8 +349,6 @@
 
     void paste_clipboard_signal (void);
 
-    void paste_table_clipboard_signal (void);
-
     void level_up_signal (void);
 
     void save_signal (void);
@@ -338,14 +361,12 @@
 
     void focusInEvent (QFocusEvent *ev);
 
-    void focusOutEvent (QFocusEvent *ev);
-
   private:
 
     QAction * add_action (QMenu *menu, const QIcon& icon, const QString& text,
                           const char *member);
 
-    QMainWindow *m_main;
+    dw_main_window *m_main;
 
     QToolBar *m_tool_bar;
 
@@ -380,7 +401,9 @@
 
     QString m_hovered_focus_vname;
 
-    QWidget *m_variable_focus_widget;
+    QWidget *m_focus_widget;
+
+    variable_dock_widget *m_focus_widget_vdw;
   };
 }
 
--- a/libgui/src/workspace-view.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/src/workspace-view.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -48,9 +48,8 @@
 namespace octave
 {
   workspace_view::workspace_view (QWidget *p)
-    : octave_dock_widget (p), m_view (new QTableView (this))
+    : octave_dock_widget ("WorkspaceView", p), m_view (new QTableView (this))
   {
-    setObjectName ("WorkspaceView");
     setWindowIcon (QIcon (":/actions/icons/logo.png"));
     set_title (tr ("Workspace"));
     setStatusTip (tr ("View the variables in the active workspace."));
@@ -257,13 +256,6 @@
   }
 
   void
-  workspace_view::closeEvent (QCloseEvent *e)
-  {
-    emit active_changed (false);
-    QDockWidget::closeEvent (e);
-  }
-
-  void
   workspace_view::filter_update (const QString& expression)
   {
     m_filter_model.setFilterWildcard (expression);
--- a/libgui/src/workspace-view.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libgui/src/workspace-view.h	Fri Aug 10 09:09:51 2018 +0200
@@ -67,10 +67,6 @@
 
     void edit_variable_signal (const QString&, const octave_value&);
 
-  protected:
-
-    void closeEvent (QCloseEvent *event);
-
   protected slots:
 
     void filter_update (const QString& expression);
--- a/libinterp/corefcn/__dsearchn__.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/__dsearchn__.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -26,8 +26,6 @@
 
 #include <cmath>
 
-#include <iostream>
-#include <fstream>
 #include <string>
 
 #include "defun.h"
@@ -82,7 +80,7 @@
           if (d < d0)
             {
               d0 = d;
-              *pidx = static_cast<double>(j + 1);
+              *pidx = static_cast<double> (j + 1);
             }
           octave_quit ();
         }
--- a/libinterp/corefcn/__magick_read__.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/__magick_read__.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -1161,7 +1161,7 @@
   // From GM documentation:
   //  Color arguments are must be scaled to fit the Quantum size according to
   //  the range of MaxRGB
-  const double divisor = static_cast<double>((uint64_t (1) << bitdepth) - 1)
+  const double divisor = static_cast<double> ((uint64_t (1) << bitdepth) - 1)
                          / MaxRGB;
 
   const P *img_fvec = img.fortran_vec ();
--- a/libinterp/corefcn/base-text-renderer.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/base-text-renderer.h	Fri Aug 10 09:09:51 2018 +0200
@@ -32,8 +32,8 @@
 #include "dMatrix.h"
 #include "uint8NDArray.h"
 
+#include "text-engine.h"
 #include "text-renderer.h"
-#include "txt-eng.h"
 
 namespace octave
 {
--- a/libinterp/corefcn/c-file-ptr-stream.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/c-file-ptr-stream.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -24,7 +24,7 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <iomanip>
 
 #include "filepos-wrappers.h"
 
--- a/libinterp/corefcn/c-file-ptr-stream.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/c-file-ptr-stream.h	Fri Aug 10 09:09:51 2018 +0200
@@ -26,9 +26,7 @@
 #include "octave-config.h"
 
 #include <cstdio>
-
-#include <iostream>
-#include <streambuf>
+#include <istream>
 
 class
 c_file_ptr_buf : public std::streambuf
--- a/libinterp/corefcn/call-stack.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/call-stack.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -92,7 +92,7 @@
   {
     symbol_table& symtab = m_interpreter.get_symbol_table ();
 
-    push (nullptr, symtab.top_scope (), 0);
+    push (nullptr, nullptr, symtab.top_scope (), 0);
   }
 
   int
@@ -137,7 +137,7 @@
 
     size_t k = cs.size ();
 
-    for (const_reverse_iterator p = cs.rbegin (); p != cs.rend (); p++)
+    for (auto p = cs.crbegin (); p != cs.crend (); p++)
       {
         octave_function *f = (*p).m_fcn;
 
@@ -165,9 +165,9 @@
   {
     octave_user_code *retval = nullptr;
 
-    const_iterator p = cs.end ();
+    auto p = cs.cend ();
 
-    while (p != cs.begin ())
+    while (p != cs.cbegin ())
       {
         const stack_frame& elt = *(--p);
 
@@ -193,9 +193,9 @@
   {
     int retval = -1;
 
-    const_iterator p = cs.end ();
+    auto p = cs.cend ();
 
-    while (p != cs.begin ())
+    while (p != cs.cbegin ())
       {
         const stack_frame& elt = *(--p);
 
@@ -214,14 +214,32 @@
     return retval;
   }
 
+  unwind_protect *
+  call_stack::curr_fcn_unwind_protect_frame (void) const
+  {
+    auto p = cs.cend ();
+
+    while (p != cs.cbegin ())
+      {
+        const stack_frame& elt = *(--p);
+
+        octave_function *f = elt.m_fcn;
+
+        if (f && f->is_user_code ())
+          return elt.m_unwind_protect_frame;
+      }
+
+    return nullptr;
+  }
+
   int
   call_stack::caller_user_code_column (void) const
   {
     int retval = -1;
 
-    const_iterator p = cs.end ();
+    auto p = cs.cend ();
 
-    while (p != cs.begin ())
+    while (p != cs.cbegin ())
       {
         const stack_frame& elt = *(--p);
 
@@ -335,9 +353,9 @@
   {
     bool retval = true;
 
-    const_iterator p = cs.end ();
+    auto p = cs.cend ();
 
-    while (p != cs.begin ())
+    while (p != cs.cbegin ())
       {
         const stack_frame& elt = *(--p);
 
@@ -354,15 +372,16 @@
   }
 
   void
-  call_stack::push (octave_function *fcn)
+  call_stack::push (octave_function *fcn, unwind_protect *up_frame)
   {
     symbol_table& symtab = m_interpreter.get_symbol_table ();
 
-    push (fcn, symtab.current_scope (), symtab.current_context ());
+    push (fcn, up_frame, symtab.current_scope (), symtab.current_context ());
   }
 
   void
-  call_stack::push (octave_function *fcn, const symbol_scope& scope,
+  call_stack::push (octave_function *fcn, unwind_protect *up_frame,
+                    const symbol_scope& scope,
                     symbol_record::context_id context)
   {
     size_t prev_frame = curr_frame;
@@ -372,7 +391,7 @@
     if (curr_frame > static_cast<size_t> (m_max_stack_depth))
       error ("max_stack_depth exceeded");
 
-    cs.push_back (stack_frame (fcn, scope, context, prev_frame));
+    cs.push_back (stack_frame (fcn, up_frame, scope, context, prev_frame));
 
     symbol_table& symtab = m_interpreter.get_symbol_table ();
 
@@ -550,7 +569,7 @@
 
     if (nframes > 0)
       {
-        for (const_reverse_iterator p = cs.rbegin (); p != cs.rend (); p++)
+        for (auto p = cs.crbegin (); p != cs.crend (); p++)
           {
             const stack_frame& elt = *p;
 
--- a/libinterp/corefcn/call-stack.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/call-stack.h	Fri Aug 10 09:09:51 2018 +0200
@@ -40,6 +40,7 @@
 namespace octave
 {
   class interpreter;
+  class unwind_protect;
 
   class
   OCTINTERP_API
@@ -54,15 +55,20 @@
       friend class call_stack;
 
       stack_frame (octave_function *fcn = nullptr,
+                   unwind_protect *up_frame = nullptr,
                    const symbol_scope& scope = symbol_scope (),
                    symbol_record::context_id context = 0, size_t prev = 0)
-        : m_fcn (fcn), m_line (-1), m_column (-1), m_scope (scope),
+        : m_fcn (fcn), m_unwind_protect_frame (up_frame),
+          m_line (-1), m_column (-1), m_scope (scope),
           m_context (context), m_prev (prev)
       { }
 
       stack_frame (const stack_frame& elt)
-        : m_fcn (elt.m_fcn), m_line (elt.m_line), m_column (elt.m_column),
-          m_scope (elt.m_scope), m_context (elt.m_context), m_prev (elt.m_prev)
+        : m_fcn (elt.m_fcn),
+          m_unwind_protect_frame (elt.m_unwind_protect_frame),
+          m_line (elt.m_line), m_column (elt.m_column),
+          m_scope (elt.m_scope), m_context (elt.m_context),
+          m_prev (elt.m_prev)
       { }
 
       int line (void) const { return m_line; }
@@ -78,6 +84,7 @@
     private:
 
       octave_function *m_fcn;
+      unwind_protect *m_unwind_protect_frame;
       int m_line;
       int m_column;
       symbol_scope m_scope;
@@ -156,6 +163,8 @@
     // User code caller.
     octave_user_code * caller_user_code (size_t nskip = 0) const;
 
+    unwind_protect *curr_fcn_unwind_protect_frame (void) const;
+
     // Line in user code caller.
     int caller_user_code_line (void) const;
 
@@ -174,18 +183,15 @@
     // Return TRUE if all elements on the call stack are scripts.
     bool all_scripts (void) const;
 
-    void push (octave_function *fcn);
-    void push (octave_function *fcn, const symbol_scope& scope,
-               symbol_record::context_id context);
+    void push (octave_function *fcn = nullptr,
+               unwind_protect *up_frame = nullptr);
 
-    void push (void)
-    {
-      push (nullptr);
-    }
+    void push (octave_function *fcn, unwind_protect *up_frame,
+               const symbol_scope& scope, symbol_record::context_id context);
 
     void push (const symbol_scope& scope, symbol_record::context_id context)
     {
-      push (nullptr, scope, context);
+      push (nullptr, nullptr, scope, context);
     }
 
     void set_location (int l, int c)
--- a/libinterp/corefcn/cellfun.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/cellfun.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -99,7 +99,7 @@
           msg.assign ("message", last_error_message ());
           msg.assign ("index",
                       static_cast<double> (count
-                                           + static_cast<octave_idx_type>(1)));
+                                           + static_cast<octave_idx_type> (1)));
 
           octave_value_list errlist = inputlist;
           errlist.prepend (msg);
@@ -425,7 +425,7 @@
 
       std::string name = args(0).string_value ();
 
-      if (! valid_identifier (name))
+      if (! octave::valid_identifier (name))
         {
           std::string fcn_name = unique_symbol_name ("__cellfun_fcn__");
           std::string fname = "function y = " + fcn_name + "(x) y = ";
@@ -688,26 +688,34 @@
 /*
 
 %!function r = __f11 (x)
-%!  global __cellfun_test_num_outputs__;
-%!  __cellfun_test_num_outputs__ = nargout;
 %!  r = x;
 %!endfunction
 
 %!function __f01 (x)
-%!  global __cellfun_test_num_outputs__;
-%!  __cellfun_test_num_outputs__ = nargout;
+%!  ## Empty function
 %!endfunction
 
 %!test
-%! global __cellfun_test_num_outputs__;
-%! cellfun (@__f11, {1});
+%! __cellfun_test_num_outputs__ = -1;
+%!
+%! function r = __subf11 (x)
+%!   __cellfun_test_num_outputs__ = nargout;
+%!   r = x;
+%! endfunction
+%!
+%! cellfun ("__subf11", {1});
 %! assert (__cellfun_test_num_outputs__, 0);
-%! x = cellfun (@__f11, {1});
+%!
+%! __cellfun_test_num_outputs__ = -1;
+%! x = cellfun ("__subf11", {1});
 %! assert (__cellfun_test_num_outputs__, 1);
 
 %!test
-%! global __cellfun_test_num_outputs__;
-%! cellfun (@__f01, {1});
+%! __cellfun_test_num_outputs__ = -1;
+%! function __subf01 (x)
+%!   __cellfun_test_num_outputs__ = nargout;
+%! endfunction
+%! cellfun ("__subf01", {1});
 %! assert (__cellfun_test_num_outputs__, 0);
 
 %!error x = cellfun (@__f01, {1, 2})
@@ -1132,7 +1140,7 @@
       // See if we can convert the string into a function.
       std::string name = args(0).string_value ();
 
-      if (! valid_identifier (name))
+      if (! octave::valid_identifier (name))
         {
           std::string fcn_name = unique_symbol_name ("__arrayfun_fcn__");
           std::string fname = "function y = " + fcn_name + "(x) y = ";
@@ -1389,26 +1397,36 @@
 
 /*
 %!function r = __f11 (x)
-%!  global __arrayfun_test_num_outputs__;
-%!  __arrayfun_test_num_outputs__ = nargout;
 %!  r = x;
 %!endfunction
 
 %!function __f01 (x)
-%!  global __arrayfun_test_num_outputs__;
-%!  __arrayfun_test_num_outputs__ = nargout;
+%!  ## Empty function
 %!endfunction
 
 %!test
-%! global __arrayfun_test_num_outputs__;
-%! arrayfun (@__f11, {1});
+%! __arrayfun_test_num_outputs__ = -1;
+%!
+%! function r = __subf11 (x)
+%!   __arrayfun_test_num_outputs__ = nargout;
+%!   r = x;
+%! endfunction
+%!
+%! arrayfun ("__subf11", {1});
 %! assert (__arrayfun_test_num_outputs__, 0);
-%! x = arrayfun (@__f11, {1});
+%!
+%! __arrayfun_test_num_outputs__ = -1;
+%! x = arrayfun ("__subf11", {1});
 %! assert (__arrayfun_test_num_outputs__, 1);
 
 %!test
-%! global __arrayfun_test_num_outputs__;
-%! arrayfun (@__f01, {1});
+%! __arrayfun_test_num_outputs__ = -1;
+%!
+%! function __subf01 (x)
+%!   __arrayfun_test_num_outputs__ = nargout;
+%! endfunction
+%!
+%! arrayfun ("__subf01", {1});
 %! assert (__arrayfun_test_num_outputs__, 0);
 
 %!error x = arrayfun (@__f01, [1, 2])
--- a/libinterp/corefcn/daspk.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/daspk.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -26,9 +26,6 @@
 
 #include <string>
 
-#include <iomanip>
-#include <iostream>
-
 #include "DASPK.h"
 
 #include "defun.h"
--- a/libinterp/corefcn/dasrt.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/dasrt.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -24,7 +24,6 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
 #include <string>
 
 #include "DASRT.h"
--- a/libinterp/corefcn/dassl.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/dassl.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -26,9 +26,6 @@
 
 #include <string>
 
-#include <iomanip>
-#include <iostream>
-
 #include "DASSL.h"
 
 #include "defun.h"
--- a/libinterp/corefcn/data.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/data.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -2603,7 +2603,8 @@
     {
       // Don't use numel (const octave_value_list&) here as that corresponds to
       // an overloaded call, not to builtin!
-      retval = dims_to_numel (args(0).dims (), args.slice (1, nargin-1));
+      retval = octave::dims_to_numel (args(0).dims (),
+                                      args.slice (1, nargin-1));
     }
 
   return retval;
@@ -3871,7 +3872,7 @@
       break;
 
     case 1:
-      get_dimensions (args(0), fcn, dims);
+      octave::get_dimensions (args(0), fcn, dims);
       break;
 
     default:
@@ -3887,7 +3888,7 @@
 
   dims.chop_trailing_singletons ();
 
-  check_dimensions (dims, fcn);
+  octave::check_dimensions (dims, fcn);
 
   // FIXME: perhaps this should be made extensible by
   // using the class name to lookup a function to call to create
@@ -3981,7 +3982,7 @@
       break;
 
     case 1:
-      get_dimensions (args(0), fcn, dims);
+      octave::get_dimensions (args(0), fcn, dims);
       break;
 
     default:
@@ -3997,7 +3998,7 @@
 
   dims.chop_trailing_singletons ();
 
-  check_dimensions (dims, fcn);
+  octave::check_dimensions (dims, fcn);
 
   // Note that automatic narrowing will handle conversion from
   // NDArray to scalar.
@@ -4045,7 +4046,7 @@
       break;
 
     case 1:
-      get_dimensions (args(0), fcn, dims);
+      octave::get_dimensions (args(0), fcn, dims);
       break;
 
     default:
@@ -4061,7 +4062,7 @@
 
   dims.chop_trailing_singletons ();
 
-  check_dimensions (dims, fcn);
+  octave::check_dimensions (dims, fcn);
 
   // Note that automatic narrowing will handle conversion from
   // NDArray to scalar.
@@ -4110,7 +4111,7 @@
       break;
 
     case 1:
-      get_dimensions (args(0), fcn, dims);
+      octave::get_dimensions (args(0), fcn, dims);
       break;
 
     default:
@@ -4126,7 +4127,7 @@
 
   dims.chop_trailing_singletons ();
 
-  check_dimensions (dims, fcn);
+  octave::check_dimensions (dims, fcn);
 
   // Note that automatic narrowing will handle conversion from
   // NDArray to scalar.
@@ -4165,7 +4166,7 @@
       break;
 
     case 1:
-      get_dimensions (args(0), fcn, dims);
+      octave::get_dimensions (args(0), fcn, dims);
       break;
 
     default:
@@ -4181,7 +4182,7 @@
 
   dims.chop_trailing_singletons ();
 
-  check_dimensions (dims, fcn);
+  octave::check_dimensions (dims, fcn);
 
   // Note that automatic narrowing will handle conversion from
   // NDArray to scalar.
@@ -5009,14 +5010,14 @@
   else if (nargin == 1)
     {
       octave_idx_type nr, nc;
-      get_dimensions (args(0), "eye", nr, nc);
+      octave::get_dimensions (args(0), "eye", nr, nc);
 
       retval = identity_matrix (nr, nc, dt);
     }
   else
     {
       octave_idx_type nr, nc;
-      get_dimensions (args(0), args(1), "eye", nr, nc);
+      octave::get_dimensions (args(0), args(1), "eye", nr, nc);
 
       retval = identity_matrix (nr, nc, dt);
     }
@@ -5204,6 +5205,16 @@
 %!assert (linspace (10, 20, 2.1), [10 20])
 %!assert (linspace (10, 20, 2.9), [10 20])
 %!assert (1 ./ linspace (-0, 0, 4), [-Inf, Inf, Inf, Inf])
+%!assert (linspace (Inf, Inf, 3), [Inf, Inf, Inf])
+%!assert (linspace (-Inf, -Inf, 3), [-Inf, -Inf, -Inf])
+%!assert (linspace (-Inf, Inf, 3), [-Inf, NaN, Inf])
+%!assert (linspace (Inf + 1i, Inf + 1i, 3), [Inf + 1i, Inf + 1i, Inf + 1i])
+%!assert (linspace (-Inf + 1i, Inf + 1i, 3), [-Inf + 1i, NaN + 1i, Inf + 1i])
+%!assert (linspace (0, Inf, 3), [0, Inf, Inf])
+%!assert (linspace (0, -Inf, 3), [0, -Inf, -Inf])
+%!assert (linspace (-Inf, 0, 3), [-Inf, NaN, 0])
+%!assert (linspace (Inf, 0, 3), [Inf, NaN, 0])
+%!assert (linspace (Inf, -Inf, 3), [Inf, NaN, -Inf])
 
 %!error linspace ()
 %!error linspace (1, 2, 3, 4)
@@ -5898,14 +5909,12 @@
 {
   int nargin = args.length ();
 
-  if (nargin == 0)
+  if (nargin < 2)
     print_usage ();
 
   octave_value retval;
 
-  if (nargin == 1)
-    retval = args(0);
-  else if (nargin == 2)
+  if (nargin == 2)
     retval = do_binary_op (op, args(0), args(1));
   else
     {
@@ -5931,7 +5940,6 @@
 (@dots{}((@var{x1} + @var{x2}) + @var{x3}) + @dots{})
 @end example
 
-At least one argument is required.
 @seealso{minus, uplus}
 @end deftypefn */)
 {
@@ -5939,6 +5947,17 @@
                                      octave_value::op_add_eq, args);
 }
 
+/*
+%!assert (plus (1,1), 2)
+%!assert (plus (1:3, 1), 2:4)
+%!assert (plus (1:3, 1, 3), 5:7)
+%!assert (plus (1,2,3,4,5,6,7,8,9), sum (1:9))
+
+## Test input validation for all functions which use binary_assoc_op_defun_body
+%!error plus ()
+%!error plus (1)
+*/
+
 DEFUN (minus, args, ,
        doc: /* -*- texinfo -*-
 @deftypefn {} {} minus (@var{x}, @var{y})
@@ -5963,7 +5982,6 @@
 (@dots{}((@var{x1} * @var{x2}) * @var{x3}) * @dots{})
 @end example
 
-At least one argument is required.
 @seealso{times, plus, minus, rdivide, mrdivide, mldivide, mpower}
 @end deftypefn */)
 {
@@ -6085,7 +6103,6 @@
 (@dots{}((@var{x1} .* @var{x2}) .* @var{x3}) .* @dots{})
 @end example
 
-At least one argument is required.
 @seealso{mtimes, rdivide}
 @end deftypefn */)
 {
@@ -6150,7 +6167,6 @@
 (@dots{}((@var{x1} & @var{x2}) & @var{x3}) & @dots{})
 @end example
 
-At least one argument is required.
 @seealso{or, not, xor}
 @end deftypefn */)
 {
@@ -6172,7 +6188,6 @@
 (@dots{}((@var{x1} | @var{x2}) | @var{x3}) | @dots{})
 @end example
 
-At least one argument is required.
 @seealso{and, not, xor}
 @end deftypefn */)
 {
@@ -6742,14 +6757,14 @@
 
   std::string mode = arg.xstring_value ("issorted: MODE must be a string");
 
-  if (mode == "ascending")
+  if (mode == "ascend")
     smode = ASCENDING;
-  else if (mode == "descending")
+  else if (mode == "descend")
     smode = DESCENDING;
   else if (mode == "either")
     smode = UNSORTED;
   else
-    error (R"(issorted: MODE must be "ascending", "descending", or "either")");
+    error (R"(issorted: MODE must be "ascend", "descend", or "either")");
 
   return smode;
 }
@@ -6833,18 +6848,18 @@
 %!assert (! issorted (uv))
 %!assert (issorted (sv'))
 %!assert (! issorted (uv'))
-%!assert (issorted (sm, "rows", "ascending"))
-%!assert (! issorted (um, "rows", "ascending"))
-%!assert (issorted (sv, "ascending"))
-%!assert (! issorted (uv, "ascending"))
-%!assert (issorted (sv', "ascending"))
-%!assert (! issorted (uv', "ascending"))
-%!assert (! issorted (sm, "rows", "descending"))
-%!assert (issorted (flipud (sm), "rows", "descending"))
-%!assert (! issorted (sv, "descending"))
-%!assert (issorted (fliplr (sv), "descending"))
-%!assert (! issorted (sv', "descending"))
-%!assert (issorted (fliplr (sv)', "descending"))
+%!assert (issorted (sm, "rows", "ascend"))
+%!assert (! issorted (um, "rows", "ascend"))
+%!assert (issorted (sv, "ascend"))
+%!assert (! issorted (uv, "ascend"))
+%!assert (issorted (sv', "ascend"))
+%!assert (! issorted (uv', "ascend"))
+%!assert (! issorted (sm, "rows", "descend"))
+%!assert (issorted (flipud (sm), "rows", "descend"))
+%!assert (! issorted (sv, "descend"))
+%!assert (issorted (fliplr (sv), "descend"))
+%!assert (! issorted (sv', "descend"))
+%!assert (issorted (fliplr (sv)', "descend"))
 %!assert (! issorted (um, "rows", "either"))
 %!assert (! issorted (uv, "either"))
 %!assert (issorted (sm, "rows", "either"))
--- a/libinterp/corefcn/debug.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/debug.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -45,6 +45,7 @@
 #include "input.h"
 #include "interpreter-private.h"
 #include "interpreter.h"
+#include "lo-sysdep.h"
 #include "octave-preserve-stream-state.h"
 #include "ov-usr-fcn.h"
 #include "ov.h"
@@ -80,8 +81,8 @@
   return retval;
 }
 
-DEFUN (dbstop, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (dbstop, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn  {} {} dbstop @var{func}
 @deftypefnx {} {} dbstop @var{func} @var{line}
 @deftypefnx {} {} dbstop @var{func} @var{line1} @var{line2} @dots{}
@@ -121,7 +122,7 @@
 editor's context menu.)  For example:
 
 @example
-dbstop in strread at 209 if 'any (format == "%f")'
+dbstop in axis at 246 if 'any (opt == "x")'
 @end example
 
 The form specifying @var{event} does not cause a specific breakpoint at a
@@ -176,7 +177,9 @@
   std::string condition = "";
   octave_value retval;
 
-  octave::bp_table& bptab = octave::__get_bp_table__ ("Fdbstop");
+  octave::tree_evaluator& tw = interp.get_evaluator ();
+
+  octave::bp_table& bptab = tw.get_bp_table ();
 
   if (args.length() >= 1 && ! args(0).isstruct ())
     {
@@ -252,8 +255,8 @@
   return retval;
 }
 
-DEFUN (dbclear, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (dbclear, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn  {} {} dbclear @var{func}
 @deftypefnx {} {} dbclear @var{func} @var{line}
 @deftypefnx {} {} dbclear @var{func} @var{line1} @var{line2} @dots{}
@@ -302,7 +305,9 @@
 
   int nargin = args.length ();
 
-  octave::bp_table& bptab = octave::__get_bp_table__ ("Fdbclear");
+  octave::tree_evaluator& tw = interp.get_evaluator ();
+
+  octave::bp_table& bptab = tw.get_bp_table ();
 
   bptab.parse_dbfunction_params ("dbclear", args, symbol_name, lines, dummy);
 
@@ -374,7 +379,9 @@
   octave::bp_table::fname_bp_map bp_list;
   std::string symbol_name;
 
-  octave::bp_table& bptab = octave::__get_bp_table__ ("Fdbstatus");
+  octave::tree_evaluator& tw = interp.get_evaluator ();
+
+  octave::bp_table& bptab = tw.get_bp_table ();
 
   if (nargin == 1)
     {
@@ -390,7 +397,7 @@
 /*
       if (Vdebugging)
         {
-          octave_user_code *dbg_fcn = get_user_code ();
+          octave_user_code *dbg_fcn = tw.get_user_code ();
           if (dbg_fcn)
             {
               symbol_name = dbg_fcn->name ();
@@ -495,7 +502,7 @@
       retmap.assign ("line", line);
       retmap.assign ("cond", cond);
 
-      octave_map ew = bptab.stop_on_err_warn_status (false);
+      const octave_map ew = bptab.stop_on_err_warn_status (false);
       if (ew.isempty ())
         {
           retval = octave_value (retmap);
@@ -504,7 +511,7 @@
         {
           octave_map outer (dim_vector (3,1));
           outer.assign ("bkpt", Cell (retmap));
-          for (octave_map::const_iterator f = ew.begin (); f != ew.end (); f++)
+          for (auto f = ew.begin (); f != ew.end (); f++)
             outer.setfield (f->first, ew.contents (f));
 
           retval = octave_value (outer);
@@ -516,18 +523,28 @@
 
 /*
 %!test
-%! dbclear all;   # Clear out breakpoints before test
-%! dbstop @ftp/dir;
-%! dbstop @audioplayer/set 70;
-%! dbstop quantile>__quantile__;
-%! dbstop ls;
-%! s = dbstatus;
-%! dbclear all;
-%! assert (s(1).name, "@audioplayer/set>setproperty");
-%! assert (s(2).name, "@ftp/dir");
-%! assert (s(3).name, "ls");
-%! assert (s(4).name, "quantile>__quantile__");
-%! assert (s(2).file(end-10:end), [filesep "@ftp" filesep "dir.m"]);
+%! if (isguirunning ())
+%!   orig_show_dbg = __octave_link_gui_preference__ ("editor/show_dbg_file",
+%!                                                   "0");
+%! endif
+%! unwind_protect 
+%!   dbclear all;   # Clear out breakpoints before test
+%!   dbstop @ftp/dir;
+%!   dbstop @audioplayer/set 70;
+%!   dbstop quantile>__quantile__;
+%!   dbstop ls;
+%!   s = dbstatus;
+%!   dbclear all;
+%!   assert (s(1).name, "@audioplayer/set>setproperty");
+%!   assert (s(2).name, "@ftp/dir");
+%!   assert (s(3).name, "ls");
+%!   assert (s(4).name, "quantile>__quantile__");
+%!   assert (s(2).file(end-10:end), [filesep "@ftp" filesep "dir.m"]);
+%! unwind_protect_cleanup
+%!   if (isguirunning ())
+%!     __octave_link_gui_preference__ ("editor/show_dbg_file", orig_show_dbg);
+%!   endif
+%! end_unwind_protect
 */
 
 DEFMETHOD (dbwhere, interp, , ,
@@ -538,7 +555,9 @@
 @seealso{dbstack, dblist, dbstatus, dbcont, dbstep, dbup, dbdown}
 @end deftypefn */)
 {
-  octave_user_code *dbg_fcn = octave::get_user_code ();
+  octave::tree_evaluator& tw = interp.get_evaluator ();
+
+  octave_user_code *dbg_fcn = tw.get_user_code ();
 
   if (! dbg_fcn)
     {
@@ -579,13 +598,15 @@
 static void
 do_dbtype (std::ostream& os, const std::string& name, int start, int end)
 {
-  std::string ff = fcn_file_in_path (name);
+  std::string ff = octave::fcn_file_in_path (name);
 
   if (ff.empty ())
     os << "dbtype: unknown function " << name << "\n";
   else
     {
-      std::ifstream fs (ff.c_str (), std::ios::in);
+      std::string ascii_fname = octave::sys::get_ASCII_filename (ff);
+
+      std::ifstream fs (ascii_fname.c_str (), std::ios::in);
 
       if (! fs)
         os << "dbtype: unable to open '" << ff << "' for reading!\n";
@@ -607,8 +628,8 @@
   os.flush ();
 }
 
-DEFUN (dbtype, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (dbtype, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn  {} {} dbtype
 @deftypefnx {} {} dbtype @var{lineno}
 @deftypefnx {} {} dbtype @var{startl:endl}
@@ -635,10 +656,12 @@
 
   string_vector argv = args.make_argv ("dbtype");
 
+  octave::tree_evaluator& tw = interp.get_evaluator ();
+
   switch (args.length ())
     {
     case 0:  // dbtype
-      dbg_fcn = octave::get_user_code ();
+      dbg_fcn = tw.get_user_code ();
 
       if (! dbg_fcn)
         error ("dbtype: must be inside a user function to give no arguments to dbtype\n");
@@ -656,7 +679,7 @@
 
         if (ind != std::string::npos)  // (dbtype start:end)
           {
-            dbg_fcn = octave::get_user_code ();
+            dbg_fcn = tw.get_user_code ();
 
             if (dbg_fcn)
               {
@@ -686,7 +709,7 @@
 
             if (line == 0)  // (dbtype func)
               {
-                dbg_fcn = octave::get_user_code (arg);
+                dbg_fcn = tw.get_user_code (arg);
 
                 if (! dbg_fcn)
                   error ("dbtype: function <%s> not found\n", arg.c_str ());
@@ -699,7 +722,7 @@
                 if (line <= 0)
                   error ("dbtype: start and end lines must be >= 1\n");
 
-                dbg_fcn = octave::get_user_code ();
+                dbg_fcn = tw.get_user_code ();
 
                 if (dbg_fcn)
                   do_dbtype (octave_stdout, dbg_fcn->fcn_file_name (),
@@ -711,7 +734,7 @@
 
     case 2:  // (dbtype func start:end) || (dbtype func start)
       {
-        dbg_fcn = octave::get_user_code (argv[1]);
+        dbg_fcn = tw.get_user_code (argv[1]);
 
         if (! dbg_fcn)
           error ("dbtype: function <%s> not found\n", argv[1].c_str ());
@@ -784,7 +807,9 @@
         error ("dblist: N must be a non-negative integer");
     }
 
-  octave_user_code *dbg_fcn = octave::get_user_code ();
+  octave::tree_evaluator& tw = interp.get_evaluator ();
+
+  octave_user_code *dbg_fcn = tw.get_user_code ();
 
   if (! dbg_fcn)
     error ("dblist: must be inside a user function to use dblist\n");
@@ -1050,8 +1075,8 @@
   return ovl ();
 }
 
-DEFUN (dbstep, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (dbstep, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn  {} {} dbstep
 @deftypefnx {} {} dbstep @var{n}
 @deftypefnx {} {} dbstep in
@@ -1081,6 +1106,8 @@
   if (nargin > 1)
     print_usage ();
 
+  octave::tree_evaluator& tw = interp.get_evaluator ();
+
   if (nargin == 1)
     {
       std::string arg = args(0).xstring_value ("dbstep: input argument must be a string");
@@ -1090,14 +1117,14 @@
           Vdebugging = false;
           Vtrack_line_num = true;
 
-          octave::tree_evaluator::dbstep_flag = -1;
+          tw.set_dbstep_flag (-1);
         }
       else if (arg == "out")
         {
           Vdebugging = false;
           Vtrack_line_num = true;
 
-          octave::tree_evaluator::dbstep_flag = -2;
+          tw.set_dbstep_flag (-2);
         }
       else
         {
@@ -1109,7 +1136,7 @@
           Vdebugging = false;
           Vtrack_line_num = true;
 
-          octave::tree_evaluator::dbstep_flag = n;
+          tw.set_dbstep_flag (n);
         }
     }
   else
@@ -1117,7 +1144,7 @@
       Vdebugging = false;
       Vtrack_line_num = true;
 
-      octave::tree_evaluator::dbstep_flag = 1;
+      tw.set_dbstep_flag (1);
     }
 
   return ovl ();
@@ -1125,8 +1152,8 @@
 
 DEFALIAS (dbnext, dbstep);
 
-DEFUN (dbcont, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (dbcont, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} dbcont
 Leave command-line debugging mode and continue code execution normally.
 @seealso{dbstep, dbquit}
@@ -1141,13 +1168,15 @@
   Vdebugging = false;
   Vtrack_line_num = true;
 
-  octave::tree_evaluator::reset_debug_state ();
+  octave::tree_evaluator& tw = interp.get_evaluator ();
+
+  tw.reset_debug_state ();
 
   return ovl ();
 }
 
-DEFUN (dbquit, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (dbquit, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} dbquit
 Quit debugging mode immediately without further code execution and return to
 the Octave prompt.
@@ -1164,8 +1193,9 @@
 
   Vdebugging = false;
 
-  octave::tree_evaluator::reset_debug_state ();
-  octave::tree_evaluator::debug_mode = false;
+  octave::tree_evaluator& tw = interp.get_evaluator ();
+
+  tw.reset_debug_state (false);
 
   throw octave::interrupt_exception ();
 
@@ -1185,8 +1215,8 @@
   return ovl (Vdebugging);
 }
 
-DEFUN (__db_next_breakpoint_quiet__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__db_next_breakpoint_quiet__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn  {} {} __db_next_breakpoint_quiet__ ()
 @deftypefnx {} {} __db_next_breakpoint_quiet__ (@var{flag})
 Disable line info printing at the next breakpoint.
@@ -1204,7 +1234,9 @@
   if (nargin == 1)
     state = args(0).bool_value ();
 
-  octave::tree_evaluator::quiet_breakpoint_flag = state;
+  octave::tree_evaluator& tw = interp.get_evaluator ();
+
+  tw.quiet_breakpoint_flag (state);
 
   return ovl ();
 }
--- a/libinterp/corefcn/default-defs.in.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/default-defs.in.h	Fri Aug 10 09:09:51 2018 +0200
@@ -24,10 +24,6 @@
 // These are used by functions declared in defaults.h and defined in
 // defaults.cc.
 
-#if ! defined (OCTAVE_CANONICAL_HOST_TYPE)
-#  define OCTAVE_CANONICAL_HOST_TYPE %OCTAVE_CANONICAL_HOST_TYPE%
-#endif
-
 #if ! defined (OCTAVE_RELEASE)
 #  define OCTAVE_RELEASE %OCTAVE_RELEASE%
 #endif
--- a/libinterp/corefcn/defaults.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/defaults.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -27,7 +27,6 @@
 #include <cstdlib>
 
 #include <algorithm>
-#include <iostream>
 #include <string>
 
 #include "dir-ops.h"
@@ -45,278 +44,408 @@
 
 #include "default-defs.h"
 
-static bool initialized = false;
-
-static std::string Voctave_home;
-static std::string Voctave_exec_home;
-
-static std::string Vbin_dir;
-static std::string Vdata_dir;
-static std::string Vdataroot_dir;
-static std::string Vinclude_dir;
-static std::string Vlib_dir;
-static std::string Vlibexec_dir;
-
-static std::string Vlocal_ver_arch_lib_dir;
-static std::string Vlocal_api_arch_lib_dir;
-static std::string Vlocal_arch_lib_dir;
-static std::string Varch_lib_dir;
-
-static std::string Vlocal_ver_oct_file_dir;
-static std::string Vlocal_api_oct_file_dir;
-static std::string Vlocal_oct_file_dir;
-static std::string Voct_file_dir;
-
-static std::string Vlocal_ver_fcn_file_dir;
-static std::string Vlocal_api_fcn_file_dir;
-static std::string Vlocal_fcn_file_dir;
-static std::string Vfcn_file_dir;
-
-static std::string Voct_data_dir;
-static std::string Voct_doc_dir;
-static std::string Voct_etc_dir;
-static std::string Voct_fonts_dir;
-static std::string Voct_include_dir;
-static std::string Voct_lib_dir;
-static std::string Voct_locale_dir;
-static std::string Voct_tests_dir;
-
-static std::string Vinfo_dir;
-
-static std::string Vman_dir;
-static std::string Vman1_dir;
-static std::string Vman1_ext;
-
-static std::string Vimage_dir;
-
-static std::string Vlocal_startupfile_dir;
-static std::string Vstartupfile_dir;
-
-static std::string Vlocal_site_defaults_file;
-static std::string Vsite_defaults_file;
-
-// Variables that name directories or files are substituted into source
-// files with "${prefix}/" stripped from the beginning of the string.
-
-// All configure variables of this form should be specified as absolute
-// directory names.  The only ones that should not be absolute here are
-// ones that have had "${prefix}/" or "${exec_prefix} stripped.
-
-static std::string
-prepend_home_dir (const std::string& hd, const std::string& s)
-{
-  std::string retval = s;
-
-  char dir_sep_char = octave::sys::file_ops::dir_sep_char ();
-
-  if (! octave::sys::env::absolute_pathname (retval))
-    retval = hd + dir_sep_char + s;
-
-  if (dir_sep_char != '/')
-    std::replace (retval.begin (), retval.end (), '/', dir_sep_char);
-
-  return retval;
-}
-
-static void
-set_octave_home (void)
-{
-  std::string op = OCTAVE_PREFIX;
-  std::string oep = OCTAVE_EXEC_PREFIX;
-
-  std::string oh = octave::sys::env::getenv ("OCTAVE_HOME");
-  std::string oeh = octave::sys::env::getenv ("OCTAVE_EXEC_HOME");
-
-  // If OCTAVE_HOME is set in the enviornment, use that.  Otherwise,
-  // default to ${prefix} from configure.
-
-  Voctave_home = (oh.empty () ? op : oh);
-
-  // If OCTAVE_EXEC_HOME is set in the environment, use that.
-  // Otherwise, if ${prefix} and ${exec_prefix} from configure are set
-  // to the same value, use OCTAVE_HOME from the environment if it is set.
-  // Othewise, default to ${exec_prefix} from configure.
-
-  if (! oeh.empty ())
-    Voctave_exec_home = oeh;
-  else
-    {
-      if (op == oep && ! oh.empty ())
-        Voctave_exec_home = oh;
-      else
-        Voctave_exec_home = oep;
-    }
-}
-
-static void
-set_local_site_defaults_file (void)
-{
-  std::string lsf = octave::sys::env::getenv ("OCTAVE_SITE_INITFILE");
-
-  if (lsf.empty ())
-    Vlocal_site_defaults_file = Vlocal_startupfile_dir + "/octaverc";
-  else
-    Vlocal_site_defaults_file = lsf;
-}
-
-static void
-set_site_defaults_file (void)
-{
-  std::string sf = octave::sys::env::getenv ("OCTAVE_VERSION_INITFILE");
-
-  if (sf.empty ())
-    Vsite_defaults_file = Vstartupfile_dir + "/octaverc";
-  else
-    Vsite_defaults_file = sf;
-}
-
-static void
-init_defaults (void)
-{
-  if (initialized)
-    return;
-
-  // OCTAVE_HOME must be set first!
-
-  set_octave_home ();
-
-  Vbin_dir = octave::config::prepend_octave_exec_home (OCTAVE_BINDIR);
-  Vdata_dir = octave::config::prepend_octave_home (OCTAVE_DATADIR);
-  Vdataroot_dir = octave::config::prepend_octave_home (OCTAVE_DATAROOTDIR);
-  Vinclude_dir = octave::config::prepend_octave_home (OCTAVE_INCLUDEDIR);
-  Vlib_dir = octave::config::prepend_octave_exec_home (OCTAVE_LIBDIR);
-  Vlibexec_dir = octave::config::prepend_octave_exec_home (OCTAVE_LIBEXECDIR);
-
-  Vlocal_ver_arch_lib_dir
-    = octave::config::prepend_octave_exec_home (OCTAVE_LOCALVERARCHLIBDIR);
-  Vlocal_api_arch_lib_dir
-    = octave::config::prepend_octave_exec_home (OCTAVE_LOCALAPIARCHLIBDIR);
-  Vlocal_arch_lib_dir
-    = octave::config::prepend_octave_exec_home (OCTAVE_LOCALARCHLIBDIR);
-  Varch_lib_dir = octave::config::prepend_octave_exec_home (OCTAVE_ARCHLIBDIR);
-
-  Vlocal_ver_oct_file_dir
-    = octave::config::prepend_octave_exec_home (OCTAVE_LOCALVEROCTFILEDIR);
-  Vlocal_api_oct_file_dir
-    = octave::config::prepend_octave_exec_home (OCTAVE_LOCALAPIOCTFILEDIR);
-  Vlocal_oct_file_dir
-    = octave::config::prepend_octave_exec_home (OCTAVE_LOCALOCTFILEDIR);
-  Voct_file_dir = octave::config::prepend_octave_exec_home (OCTAVE_OCTFILEDIR);
-
-  Vlocal_ver_fcn_file_dir
-    = octave::config::prepend_octave_home (OCTAVE_LOCALVERFCNFILEDIR);
-  Vlocal_api_fcn_file_dir
-    = octave::config::prepend_octave_home (OCTAVE_LOCALAPIFCNFILEDIR);
-  Vlocal_fcn_file_dir
-    = octave::config::prepend_octave_home (OCTAVE_LOCALFCNFILEDIR);
-  Vfcn_file_dir = octave::config::prepend_octave_home (OCTAVE_FCNFILEDIR);
-
-  Voct_data_dir = octave::config::prepend_octave_home (OCTAVE_OCTDATADIR);
-  Voct_doc_dir = octave::config::prepend_octave_home (OCTAVE_OCTDOCDIR);
-  Voct_etc_dir = octave::config::prepend_octave_home (OCTAVE_OCTETCDIR);
-  Voct_fonts_dir = octave::config::prepend_octave_home (OCTAVE_OCTFONTSDIR);
-  Voct_include_dir = octave::config::prepend_octave_home (OCTAVE_OCTINCLUDEDIR);
-  Voct_lib_dir = octave::config::prepend_octave_exec_home (OCTAVE_OCTLIBDIR);
-  Voct_locale_dir = octave::config::prepend_octave_home (OCTAVE_OCTLOCALEDIR);
-  Voct_tests_dir = octave::config::prepend_octave_home (OCTAVE_OCTTESTSDIR);
-
-  Vinfo_dir = octave::config::prepend_octave_home (OCTAVE_INFODIR);
-
-  Vman_dir = octave::config::prepend_octave_home (OCTAVE_MANDIR);
-  Vman1_dir = octave::config::prepend_octave_home (OCTAVE_MAN1DIR);
-  Vman1_ext = OCTAVE_MAN1EXT;
-
-  Vimage_dir = octave::config::prepend_octave_home (OCTAVE_IMAGEDIR);
-
-  Vlocal_startupfile_dir
-    = octave::config::prepend_octave_home (OCTAVE_LOCALSTARTUPFILEDIR);
-  Vstartupfile_dir
-    = octave::config::prepend_octave_home (OCTAVE_STARTUPFILEDIR);
-
-  set_local_site_defaults_file ();
-
-  set_site_defaults_file ();
-
-  initialized = true;
-}
-
-#define RETURN(VAR)                             \
-  if (! initialized)                            \
-    init_defaults ();                           \
-  return VAR;
-
 namespace octave
 {
   namespace config
   {
-    std::string
-    prepend_octave_home (const std::string& s)
+    // Variables that name directories or files are substituted into source
+    // files with "${prefix}/" stripped from the beginning of the string.
+
+    // All configure variables of this form should be specified as absolute
+    // directory names.  The only ones that should not be absolute here are
+    // ones that have had "${prefix}/" or "${exec_prefix} stripped.
+
+    static std::string
+    prepend_home_dir (const std::string& hd, const std::string& s)
+    {
+      std::string retval = s;
+
+      char dir_sep_char = sys::file_ops::dir_sep_char ();
+
+      if (! sys::env::absolute_pathname (retval))
+        retval = hd + dir_sep_char + s;
+
+      if (dir_sep_char != '/')
+        std::replace (retval.begin (), retval.end (), '/', dir_sep_char);
+
+      return retval;
+    }
+
+    static std::string get_octave_home (void)
+    {
+      std::string op = OCTAVE_PREFIX;
+
+      std::string oh = sys::env::getenv ("OCTAVE_HOME");
+
+      // If OCTAVE_HOME is set in the enviornment, use that.  Otherwise,
+      // default to ${prefix} from configure.
+
+      return oh.empty () ? op : oh;
+    }
+
+    static std::string get_octave_exec_home (void)
     {
-      return prepend_home_dir (Voctave_home, s);
+      std::string op = OCTAVE_PREFIX;
+      std::string oep = OCTAVE_EXEC_PREFIX;
+
+      std::string oh = sys::env::getenv ("OCTAVE_HOME");
+      std::string oeh = sys::env::getenv ("OCTAVE_EXEC_HOME");
+
+      // If OCTAVE_EXEC_HOME is set in the environment, use that.
+      // Otherwise, if ${prefix} and ${exec_prefix} from configure are set
+      // to the same value, use OCTAVE_HOME from the environment if it is set.
+      // Othewise, default to ${exec_prefix} from configure.
+
+      if (! oeh.empty ())
+        return oeh;
+
+      if (op == oep && ! oh.empty ())
+        return oh;
+
+      return oep;
+    }
+
+    static std::string get_local_site_defaults_file (void)
+    {
+      std::string lsf = sys::env::getenv ("OCTAVE_SITE_INITFILE");
+
+      return lsf.empty () ? local_startupfile_dir () + "/octaverc" : lsf;
+    }
+
+    static std::string get_site_defaults_file (void)
+    {
+      std::string sf = sys::env::getenv ("OCTAVE_VERSION_INITFILE");
+
+      return sf.empty () ? startupfile_dir () + "/octaverc" : sf;
+    }
+
+    std::string prepend_octave_home (const std::string& s)
+    {
+      return prepend_home_dir (octave_home (), s);
+    }
+
+    std::string prepend_octave_exec_home (const std::string& s)
+    {
+      return prepend_home_dir (octave_exec_home (), s);
+    }
+
+    std::string canonical_host_type (void)
+    {
+      static const std::string s_canonical_host_type
+        = OCTAVE_CANONICAL_HOST_TYPE;
+
+      return s_canonical_host_type;
+    }
+
+    std::string release (void)
+    {
+      static const std::string s_octave_release = OCTAVE_RELEASE;
+
+      return s_octave_release;
     }
 
-    std::string
-    prepend_octave_exec_home (const std::string& s)
+    std::string default_pager (void)
+    {
+      static const std::string s_default_pager = OCTAVE_DEFAULT_PAGER;
+
+      return s_default_pager;
+    }
+
+    std::string octave_home (void)
+    {
+      static const std::string s_octave_home = get_octave_home ();
+
+      return s_octave_home;
+    }
+
+    std::string octave_exec_home (void)
+    {
+      static const std::string s_octave_exec_home = get_octave_exec_home ();
+
+      return s_octave_exec_home;
+    }
+
+    std::string bin_dir (void)
+    {
+      static const std::string s_bin_dir
+        = prepend_octave_exec_home (OCTAVE_BINDIR);
+
+      return s_bin_dir;
+    }
+
+    std::string data_dir (void)
+    {
+      static const std::string s_data_dir
+        = prepend_octave_home (OCTAVE_DATADIR);
+
+      return s_data_dir;
+    }
+
+    std::string dataroot_dir (void)
+    {
+      static const std::string s_dataroot_dir
+        = prepend_octave_home (OCTAVE_DATAROOTDIR);
+
+      return s_dataroot_dir;
+    }
+
+    std::string include_dir (void)
     {
-      return prepend_home_dir (Voctave_exec_home, s);
+      static const std::string s_include_dir
+        = prepend_octave_home (OCTAVE_INCLUDEDIR);
+
+      return s_include_dir;
+    }
+
+    std::string lib_dir (void)
+    {
+      static const std::string s_lib_dir
+        = prepend_octave_exec_home (OCTAVE_LIBDIR);
+
+      return s_lib_dir;
+    }
+
+    std::string libexec_dir (void)
+    {
+      static const std::string s_libexec_dir
+        = prepend_octave_exec_home (OCTAVE_LIBEXECDIR);
+
+      return s_libexec_dir;
+    }
+
+    std::string arch_lib_dir (void)
+    {
+      static const std::string s_arch_lib_dir
+        = prepend_octave_exec_home (OCTAVE_ARCHLIBDIR);
+
+      return s_arch_lib_dir;
+    }
+
+    std::string info_dir (void)
+    {
+      static const std::string s_info_dir
+        = prepend_octave_exec_home (OCTAVE_INFODIR);
+
+      return s_info_dir;
+    }
+
+    std::string local_ver_arch_lib_dir (void)
+    {
+      static const std::string s_local_ver_arch_lib_dir
+        = prepend_octave_exec_home (OCTAVE_LOCALVERARCHLIBDIR);
+
+      return s_local_ver_arch_lib_dir;
+    }
+
+    std::string local_api_arch_lib_dir (void)
+    {
+      static const std::string s_local_api_arch_lib_dir
+        = prepend_octave_exec_home (OCTAVE_LOCALAPIARCHLIBDIR);
+
+      return s_local_api_arch_lib_dir;
     }
 
-    std::string canonical_host_type (void) { return OCTAVE_CANONICAL_HOST_TYPE; }
+    std::string local_arch_lib_dir (void)
+    {
+      static const std::string s_local_arch_lib_dir
+        = prepend_octave_exec_home (OCTAVE_LOCALARCHLIBDIR);
+
+      return s_local_arch_lib_dir;
+    }
 
-    std::string release (void) { return OCTAVE_RELEASE; }
+    std::string local_ver_oct_file_dir (void)
+    {
+      static const std::string s_local_ver_oct_file_dir
+        = prepend_octave_exec_home (OCTAVE_LOCALVEROCTFILEDIR);
+
+      return s_local_ver_oct_file_dir;
+    }
+
+    std::string local_api_oct_file_dir (void)
+    {
+      static const std::string s_local_api_oct_file_dir
+        = prepend_octave_exec_home (OCTAVE_LOCALAPIOCTFILEDIR);
+
+      return s_local_api_oct_file_dir;
+    }
 
-    std::string default_pager (void) { return OCTAVE_DEFAULT_PAGER; }
+    std::string local_oct_file_dir (void)
+    {
+      static const std::string s_local_oct_file_dir
+        = prepend_octave_exec_home (OCTAVE_LOCALOCTFILEDIR);
+
+      return s_local_oct_file_dir;
+    }
 
-    std::string octave_home (void) { RETURN (Voctave_home); }
-    std::string octave_exec_home (void) { RETURN (Voctave_exec_home); }
+    std::string oct_file_dir (void)
+    {
+      static const std::string s_oct_file_dir
+        = prepend_octave_exec_home (OCTAVE_OCTFILEDIR);
+
+      return s_oct_file_dir;
+    }
+
+    std::string local_ver_fcn_file_dir (void)
+    {
+      static const std::string s_local_ver_fcn_file_dir
+        = prepend_octave_home (OCTAVE_LOCALVERFCNFILEDIR);
+
+      return s_local_ver_fcn_file_dir;
+    }
 
-    std::string bin_dir (void) { RETURN (Vbin_dir); }
-    std::string data_dir (void) { RETURN (Vdata_dir); }
-    std::string dataroot_dir (void) { RETURN (Vdataroot_dir); }
-    std::string include_dir (void) { RETURN (Vinclude_dir); }
-    std::string lib_dir (void) { RETURN (Vlib_dir); }
-    std::string libexec_dir (void) { RETURN (Vlibexec_dir); }
-    std::string arch_lib_dir (void) { RETURN (Varch_lib_dir); }
-    std::string info_dir (void) { RETURN (Vinfo_dir); }
+    std::string local_api_fcn_file_dir (void)
+    {
+      static const std::string s_local_api_fcn_file_dir
+        = prepend_octave_home (OCTAVE_LOCALAPIFCNFILEDIR);
+
+      return s_local_api_fcn_file_dir;
+    }
+
+    std::string local_fcn_file_dir (void)
+    {
+      static const std::string s_local_fcn_file_dir
+        = prepend_octave_home (OCTAVE_LOCALFCNFILEDIR);
+
+      return s_local_fcn_file_dir;
+    }
+
+    std::string fcn_file_dir (void)
+    {
+      static const std::string s_fcn_file_dir
+        = prepend_octave_home (OCTAVE_FCNFILEDIR);
+
+      return s_fcn_file_dir;
+    }
 
-    std::string local_ver_arch_lib_dir (void) { RETURN (Vlocal_ver_arch_lib_dir); }
-    std::string local_api_arch_lib_dir (void) { RETURN (Vlocal_api_arch_lib_dir); }
-    std::string local_arch_lib_dir (void) { RETURN (Vlocal_arch_lib_dir); }
+    std::string oct_data_dir (void)
+    {
+      static const std::string s_oct_data_dir
+        = prepend_octave_home (OCTAVE_OCTDATADIR);
+
+      return s_oct_data_dir;
+    }
+
+    std::string oct_doc_dir (void)
+    {
+      static const std::string s_oct_doc_dir
+        = prepend_octave_home (OCTAVE_OCTDOCDIR);
+
+      return s_oct_doc_dir;
+    }
+
+    std::string oct_etc_dir (void)
+    {
+      static const std::string s_oct_etc_dir
+        = prepend_octave_home (OCTAVE_OCTETCDIR);
+
+      return s_oct_etc_dir;
+    }
 
-    std::string local_ver_oct_file_dir (void) { RETURN (Vlocal_ver_oct_file_dir); }
-    std::string local_api_oct_file_dir (void) { RETURN (Vlocal_api_oct_file_dir); }
-    std::string local_oct_file_dir (void) { RETURN (Vlocal_oct_file_dir); }
-    std::string oct_file_dir (void) { RETURN (Voct_file_dir); }
+    std::string oct_fonts_dir (void)
+    {
+      static const std::string s_oct_fonts_dir
+        = prepend_octave_home (OCTAVE_OCTFONTSDIR);
+
+      return s_oct_fonts_dir;
+    }
+
+    std::string oct_include_dir (void)
+    {
+      static const std::string s_oct_include_dir
+        = prepend_octave_home (OCTAVE_OCTINCLUDEDIR);
+
+      return s_oct_include_dir;
+    }
+
+    std::string oct_lib_dir (void)
+    {
+      static const std::string s_oct_lib_dir
+        = prepend_octave_exec_home (OCTAVE_OCTLIBDIR);
+
+      return s_oct_lib_dir;
+    }
 
-    std::string local_ver_fcn_file_dir (void) { RETURN (Vlocal_ver_fcn_file_dir); }
-    std::string local_api_fcn_file_dir (void) { RETURN (Vlocal_api_fcn_file_dir); }
-    std::string local_fcn_file_dir (void) { RETURN (Vlocal_fcn_file_dir); }
-    std::string fcn_file_dir (void) { RETURN (Vfcn_file_dir); }
+    std::string oct_locale_dir (void)
+    {
+      static const std::string s_oct_locale_dir
+        = prepend_octave_home (OCTAVE_OCTLOCALEDIR);
+
+      return s_oct_locale_dir;
+    }
+
+    std::string oct_tests_dir (void)
+    {
+      static const std::string s_oct_tests_dir
+        = prepend_octave_home (OCTAVE_OCTTESTSDIR);
+
+      return s_oct_tests_dir;
+    }
+
+    std::string man_dir (void)
+    {
+      static const std::string s_man_dir
+        = prepend_octave_home (OCTAVE_MANDIR);
+
+      return s_man_dir;
+    }
 
-    std::string oct_data_dir (void) { RETURN (Voct_data_dir); }
-    std::string oct_doc_dir (void) { RETURN (Voct_doc_dir); }
-    std::string oct_etc_dir (void) { RETURN (Voct_etc_dir); }
-    std::string oct_fonts_dir (void) { RETURN (Voct_fonts_dir); }
-    std::string oct_include_dir (void) { RETURN (Voct_include_dir); }
-    std::string oct_lib_dir (void) { RETURN (Voct_lib_dir); }
-    std::string oct_locale_dir (void) { RETURN (Voct_locale_dir); }
-    std::string oct_tests_dir (void) { RETURN (Voct_tests_dir); }
+    std::string man1_dir (void)
+    {
+      static const std::string s_man1_dir
+        = prepend_octave_home (OCTAVE_MAN1DIR);
+
+      return s_man1_dir;
+    }
+
+    std::string man1_ext (void)
+    {
+      static const std::string s_man1_ext = OCTAVE_MAN1EXT;
+
+      return s_man1_ext;
+    }
+
+    std::string image_dir (void)
+    {
+      static const std::string s_image_dir
+        = prepend_octave_home (OCTAVE_IMAGEDIR);
+
+      return s_image_dir;
+    }
 
-    std::string man_dir (void) { RETURN (Vman_dir); }
-    std::string man1_dir (void) { RETURN (Vman1_dir); }
-    std::string man1_ext (void) { RETURN (Vman1_ext); }
+    std::string local_startupfile_dir (void)
+    {
+      static const std::string s_local_startupfile_dir
+        = prepend_octave_home (OCTAVE_LOCALSTARTUPFILEDIR);
+
+      return s_local_startupfile_dir;
+    }
 
-    std::string image_dir (void) { RETURN (Vimage_dir); }
+    std::string startupfile_dir (void)
+    {
+      static const std::string s_startupfile_dir
+        = prepend_octave_home (OCTAVE_STARTUPFILEDIR);
+
+      return s_startupfile_dir;
+    }
 
-    std::string local_startupfile_dir (void) { RETURN (Vlocal_startupfile_dir); }
-    std::string startupfile_dir (void) { RETURN (Vstartupfile_dir); }
+    std::string local_site_defaults_file (void)
+    {
+      static const std::string s_local_site_defaults_file
+        = get_local_site_defaults_file ();
+
+      return s_local_site_defaults_file;
+    }
 
-    std::string local_site_defaults_file (void) { RETURN (Vlocal_site_defaults_file); }
-    std::string site_defaults_file (void) { RETURN (Vsite_defaults_file); }
+    std::string site_defaults_file (void)
+    {
+      static const std::string s_site_defaults_file
+        = get_site_defaults_file ();
+
+      return s_site_defaults_file;
+    }
   }
 }
 
-#undef RETURN
 
 DEFUN (OCTAVE_HOME, args, ,
        doc: /* -*- texinfo -*-
--- a/libinterp/corefcn/defun.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/defun.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -24,8 +24,6 @@
 #  include "config.h"
 #endif
 
-#include <sstream>
-#include <iostream>
 #include <string>
 
 #include "call-stack.h"
--- a/libinterp/corefcn/dirfns.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/dirfns.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -187,16 +187,16 @@
 
   dirname = octave::sys::file_ops::tilde_expand (dirname);
 
-  octave::sys::dir_entry dir (dirname);
+  string_vector dirlist;
+  std::string msg;
 
-  if (dir)
+  if (octave::sys::get_dirlist (dirname, dirlist, msg))
     {
-      string_vector dirlist = dir.read ();
       retval(0) = Cell (dirlist.sort ());
       retval(1) = 0.0;
     }
   else
-    retval(2) = dir.error ();
+    retval(2) = msg;
 
   return retval;
 }
@@ -250,8 +250,8 @@
     }
 }
 
-DEFUNX ("rmdir", Frmdir, args, ,
-        doc: /* -*- texinfo -*-
+DEFMETHODX ("rmdir", Frmdir, interp, args, ,
+            doc: /* -*- texinfo -*-
 @deftypefn  {} {} rmdir @var{dir}
 @deftypefnx {} {} rmdir (@var{dir}, "s")
 @deftypefnx {} {[@var{status}, @var{msg}, @var{msgid}] =} rmdir (@dots{})
@@ -290,16 +290,26 @@
           && ! octave::application::forced_interactive ()
           && Vconfirm_recursive_rmdir)
         {
+          octave::input_system& input_sys = interp.get_input_system ();
+
           std::string prompt = "remove entire contents of " + fulldir + "? ";
 
-          doit = octave_yes_or_no (prompt);
+          doit = input_sys.yes_or_no (prompt);
         }
 
       if (doit)
-        status = octave::sys::recursive_rmdir (fulldir, msg);
+        {
+          octave_link::file_remove (fulldir, "");
+          status = octave::sys::recursive_rmdir (fulldir, msg);
+        }
     }
   else
-    status = octave::sys::rmdir (fulldir, msg);
+    {
+      octave_link::file_remove (fulldir, "");
+      status = octave::sys::rmdir (fulldir, msg);
+    }
+
+  octave_link::file_renamed (status >= 0);
 
   if (status < 0)
     return ovl (false, msg, "rmdir");
@@ -422,12 +432,20 @@
 
   std::string msg;
 
+  octave_link::file_remove (from, to);
+
   int status = octave::sys::rename (from, to, msg);
 
   if (status < 0)
-    return ovl (-1.0, msg);
+    {
+      octave_link::file_renamed (false);
+      return ovl (-1.0, msg);
+    }
   else
-    return ovl (status, "");
+    {
+      octave_link::file_renamed (true);
+      return ovl (status, "");
+    }
 }
 
 DEFUN (glob, args, ,
--- a/libinterp/corefcn/dlmread.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/dlmread.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -28,12 +28,14 @@
 #  include "config.h"
 #endif
 
+#include <cmath>
 #include <cctype>
 #include <fstream>
 #include <limits>
 
 #include "file-ops.h"
 #include "lo-ieee.h"
+#include "lo-sysdep.h"
 
 #include "defun.h"
 #include "interpreter.h"
@@ -190,7 +192,7 @@
 The @qcode{"emptyvalue"} option may be used to specify the value used to
 fill empty fields.  The default is zero.  Note that any non-numeric values,
 such as text, are also replaced by the @qcode{"emptyvalue"}.
-@seealso{csvread, textscan, textread, dlmwrite}
+@seealso{csvread, textscan, dlmwrite}
 @end deftypefn */)
 {
   int nargin = args.length ();
@@ -218,9 +220,11 @@
 
       std::string tname = octave::sys::file_ops::tilde_expand (fname);
 
-      tname = find_data_file_in_load_path ("dlmread", tname);
+      tname = octave::find_data_file_in_load_path ("dlmread", tname);
 
-      input_file.open (tname.c_str (), std::ios::in);
+      std::string ascii_fname = octave::sys::get_ASCII_filename (tname);
+
+      input_file.open (ascii_fname.c_str (), std::ios::in);
 
       if (! input_file)
         error ("dlmread: unable to open file '%s'", fname.c_str ());
@@ -246,7 +250,7 @@
   if (nargin > 1)
     {
       if (args(1).is_sq_string ())
-        sep = do_string_escapes (args(1).string_value ());
+        sep = octave::do_string_escapes (args(1).string_value ());
       else
         sep = args(1).string_value ();
     }
@@ -446,13 +450,28 @@
                   if (next_char == 'i' || next_char == 'j')
                     {
                       // Process pure imaginary numbers.
-                      if (! iscmplx)
+                      tmp_stream.get ();
+                      next_char = tmp_stream.peek ();
+                      if (next_char == std::istringstream::traits_type::eof ())
                         {
-                          iscmplx = true;
-                          cdata = ComplexMatrix (rdata);
+                          if (! iscmplx)
+                            {
+                              iscmplx = true;
+                              cdata = ComplexMatrix (rdata);
+                            }
+
+                          cdata(i,j++) = Complex (0, x);
                         }
-
-                      cdata(i,j++) = Complex (0, x);
+                      else
+                        {
+                          // Parsing failed, <number>i|j<extra text>
+                          j++;  // Leave data initialized to empty_value
+                        }
+                    }
+                  else if (std::isalpha (next_char) && ! std::isfinite (x))
+                    {
+                      // Parsing failed, <Inf|NA|NaN><extra text>
+                      j++;  // Leave data initialized to empty_value
                     }
                   else
                     {
@@ -471,10 +490,11 @@
                     }
                 }
             }
-          else if (iscmplx)
-            cdata(i,j++) = empty_value;
           else
-            rdata(i,j++) = empty_value;
+            {
+              // octave_read_double() parsing failed
+              j++;  // Leave data initialized to empty_value
+            }
 
           pos1 = pos2 + 1;
         }
@@ -631,4 +651,56 @@
 %!   unlink (file);
 %! end_unwind_protect
 
+## NA was not properly read from a file
+%!test
+%! file = tempname ();
+%! unwind_protect
+%!   fid = fopen (file, "wt");
+%!   fwrite (fid, "1,NA,3");
+%!   fclose (fid);
+%!
+%!   assert (dlmread (file), [1, NA, 3]);
+%! unwind_protect_cleanup
+%!   unlink (file);
+%! end_unwind_protect
+
+## "Name" was read as NA rather than parse error
+%!test <*54029>
+%! file = tempname ();
+%! unwind_protect
+%!   fid = fopen (file, "wt");
+%!   fwrite (fid, "NaNe,bNa,Name,c\n1,NaN,3,Inftest\n-Inf,6,NA,8");
+%!   fclose (fid);
+%!
+%!   assert (dlmread (file), [0, 0, 0, 0; 1, NaN, 3, 0; -Inf, 6, NA, 8]);
+%! unwind_protect_cleanup
+%!   unlink (file);
+%! end_unwind_protect
+
+## Infinity incorrectly changed matrix to complex, rather than parse error
+%!test
+%! file = tempname ();
+%! unwind_protect
+%!   fid = fopen (file, "wt");
+%!   fwrite (fid, "1,Infinity,3");
+%!   fclose (fid);
+%!
+%!   assert (dlmread (file), [1, 0, 3]);
+%! unwind_protect_cleanup
+%!   unlink (file);
+%! end_unwind_protect
+
+## Purely complex numbers with trailing garbage produced complex matrix
+%!test
+%! file = tempname ();
+%! unwind_protect
+%!   fid = fopen (file, "wt");
+%!   fwrite (fid, "1,2jack,3");
+%!   fclose (fid);
+%!
+%!   assert (dlmread (file), [1, 0, 3]);
+%! unwind_protect_cleanup
+%!   unlink (file);
+%! end_unwind_protect
+
 */
--- a/libinterp/corefcn/dynamic-ld.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/dynamic-ld.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -31,7 +31,6 @@
 #include "oct-env.h"
 #include "oct-time.h"
 
-#include "defaults.h"
 #include "defun.h"
 #include "dynamic-ld.h"
 #include "interpreter-private.h"
@@ -60,7 +59,7 @@
   {
     std::list<std::string> removed_fcns;
 
-    for (iterator p = m_lib_list.begin (); p != m_lib_list.end (); p++)
+    for (auto p = m_lib_list.begin (); p != m_lib_list.end (); p++)
       {
         if (*p == shl)
           {
--- a/libinterp/corefcn/environment.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/environment.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -105,7 +105,7 @@
   {
     std::string retval = "emacs";
 
-    std::string env_editor = octave::sys::env::getenv ("EDITOR");
+    std::string env_editor = sys::env::getenv ("EDITOR");
 
     if (! env_editor.empty ())
       retval = env_editor;
@@ -115,9 +115,9 @@
 
   std::string environment::init_exec_path (void)
   {
-    std::string exec_path = octave::sys::env::getenv ("OCTAVE_EXEC_PATH");
+    std::string exec_path = sys::env::getenv ("OCTAVE_EXEC_PATH");
 
-    std::string path_sep = octave::directory_path::path_sep_str ();
+    std::string path_sep = directory_path::path_sep_str ();
 
     if (exec_path.empty ())
       exec_path = (config::local_ver_arch_lib_dir () + path_sep
@@ -135,14 +135,14 @@
   {
     std::string image_path = ".";
 
-    std::string path_sep = octave::directory_path::path_sep_str ();
+    std::string path_sep = directory_path::path_sep_str ();
 
-    std::string env_path = octave::sys::env::getenv ("OCTAVE_IMAGE_PATH");
+    std::string env_path = sys::env::getenv ("OCTAVE_IMAGE_PATH");
 
     if (! env_path.empty ())
       image_path += path_sep + env_path;
 
-    std::string gen_path = octave::genpath (config::image_dir (), "");
+    std::string gen_path = genpath (config::image_dir (), "");
 
     if (! gen_path.empty ())
       image_path += path_sep + gen_path;
--- a/libinterp/corefcn/error.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/error.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -166,7 +166,7 @@
 
   std::ostringstream output_buf;
 
-  octave_vformat (output_buf, fmt, args);
+  octave::vformat (output_buf, fmt, args);
 
   std::string base_msg = output_buf.str ();
 
@@ -368,9 +368,11 @@
       frame.protect_var (Vdebug_on_error);
       Vdebug_on_error = false;
 
-      octave::tree_evaluator::debug_mode = true;
+      octave::tree_evaluator& tw
+        = octave::__get_evaluator__ ("maybe_enter_debugger");
 
-      octave::tree_evaluator::current_frame = cs.current_frame ();
+      tw.debug_mode (true);
+      tw.current_frame (cs.current_frame ());
 
       if (show_stack_trace)
         {
@@ -384,7 +386,10 @@
             }
         }
 
-      do_keyboard (octave_value_list ());
+      octave::input_system& input_sys
+        = octave::__get_input_system__ ("maybe_enter_debugger");
+
+      input_sys.keyboard ();
     }
 }
 
@@ -400,7 +405,7 @@
 
   std::ostringstream output_buf;
 
-  octave_vformat (output_buf, fmt, args);
+  octave::vformat (output_buf, fmt, args);
 
   // FIXME: we really want to capture the message before it has all the
   //        formatting goop attached to it.  We probably also want just the
@@ -478,21 +483,6 @@
 }
 
 void
-vusage (const char *fmt, va_list args)
-{
-  usage_1 ("", fmt, args);
-}
-
-void
-usage (const char *fmt, ...)
-{
-  va_list args;
-  va_start (args, fmt);
-  usage_1 ("", fmt, args);
-  va_end (args);
-}
-
-void
 vusage_with_id (const char *id, const char *fmt, va_list args)
 {
   usage_1 (id, fmt, args);
@@ -782,11 +772,16 @@
           frame.protect_var (Vdebug_on_warning);
           Vdebug_on_warning = false;
 
-          octave::tree_evaluator::debug_mode = true;
+          octave::tree_evaluator& tw
+            = octave::__get_evaluator__ ("warning_1");
 
-          octave::tree_evaluator::current_frame = cs.current_frame ();
+          tw.debug_mode (true);
+          tw.current_frame (cs.current_frame ());
 
-          do_keyboard (octave_value_list ());
+          octave::input_system& input_sys
+            = octave::__get_input_system__ ("warning_1");
+
+          input_sys.keyboard ();
         }
     }
 }
--- a/libinterp/corefcn/error.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/error.h	Fri Aug 10 09:09:51 2018 +0200
@@ -52,14 +52,6 @@
 
 extern OCTINTERP_API void message (const char *name, const char *fmt, ...);
 
-OCTAVE_DEPRECATED (4.2, "use 'print_usage' or 'verror' instead")
-OCTAVE_NORETURN OCTINTERP_API extern
-void vusage (const char *fmt, va_list args);
-
-OCTAVE_DEPRECATED (4.2, "use 'print_usage' or 'error' instead")
-OCTAVE_NORETURN OCTINTERP_API extern
-void usage (const char *fmt, ...);
-
 extern OCTINTERP_API void vwarning (const char *fmt, va_list args);
 extern OCTINTERP_API void warning (const char *fmt, ...);
 
--- a/libinterp/corefcn/event-queue.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/event-queue.h	Fri Aug 10 09:09:51 2018 +0200
@@ -51,11 +51,6 @@
 
     ~event_queue (void) { run (); }
 
-    void add (elem *new_elem)
-    {
-      fifo.push (new_elem);
-    }
-
     void run_first (void)
     {
       if (! empty ())
@@ -81,6 +76,11 @@
 
   protected:
 
+    void add_action (elem *new_elem)
+    {
+      fifo.push (new_elem);
+    }
+
     std::queue<elem *> fifo;
   };
 
--- a/libinterp/corefcn/fcn-info.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/fcn-info.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -196,7 +196,7 @@
                 const std::list<std::string>& plist =
                   symtab.parent_classes (dispatch_type);
 
-                std::list<std::string>::const_iterator it = plist.begin ();
+                auto it = plist.begin ();
 
                 while (it != plist.end ())
                   {
@@ -398,7 +398,7 @@
 
             if (! fcn_file.empty ())
               {
-                str_val_iterator r = local_functions.find (fcn_file);
+                auto r = local_functions.find (fcn_file);
 
                 if (r != local_functions.end ())
                   {
@@ -420,7 +420,7 @@
 
             if (! dir_name.empty ())
               {
-                str_val_iterator q = private_functions.find (dir_name);
+                auto q = private_functions.find (dir_name);
 
                 if (q == private_functions.end ())
                   {
@@ -464,7 +464,7 @@
 
     // Class constructors.  The class name and function name are the same.
 
-    str_val_iterator q = class_constructors.find (name);
+    auto q = class_constructors.find (name);
 
     if (q == class_constructors.end ())
       {
@@ -601,7 +601,7 @@
 
         if (! dir_name.empty ())
           {
-            str_val_iterator q = private_functions.find (dir_name);
+            auto q = private_functions.find (dir_name);
 
             if (q == private_functions.end ())
               {
@@ -638,7 +638,7 @@
 
         if (! fcn_file.empty ())
           {
-            str_val_iterator r = local_functions.find (fcn_file);
+            auto r = local_functions.find (fcn_file);
 
             if (r != local_functions.end ())
               {
@@ -671,7 +671,7 @@
   {
     octave_value retval;
 
-    str_val_iterator q = class_methods.find (dispatch_type);
+    auto q = class_methods.find (dispatch_type);
 
     if (q == class_methods.end ())
       {
--- a/libinterp/corefcn/fcn-info.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/fcn-info.h	Fri Aug 10 09:09:51 2018 +0200
@@ -131,7 +131,7 @@
       void
       clear_map (std::map<T, octave_value>& map, bool force = false)
       {
-        typename std::map<T, octave_value>::iterator p = map.begin ();
+        auto p = map.begin ();
 
         while (p != map.end ())
           {
--- a/libinterp/corefcn/fft.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/fft.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -33,12 +33,6 @@
 #include "ovl.h"
 #include "utils.h"
 
-#if defined (HAVE_FFTW)
-#  define FFTSRC "@sc{fftw}"
-#else
-#  define FFTSRC "@sc{fftpack}"
-#endif
-
 static octave_value
 do_fft (const octave_value_list& args, const char *fcn, int type)
 {
@@ -161,21 +155,35 @@
 }
 
 /*
-%!assert (fft ([]), [])
-%!assert (fft (zeros (10,0)), zeros (10,0))
-%!assert (fft (zeros (0,10)), zeros (0,10))
-%!assert (fft (0), 0)
-%!assert (fft (1), 1)
-%!assert (fft (ones (2,2)), [2,2; 0,0])
-%!assert (fft (eye (2,2)), [1,1; 1,-1])
+%!testif HAVE_FFTW
+%! assert (fft ([]), [])
+%!testif HAVE_FFTW
+%! assert (fft (zeros (10,0)), zeros (10,0))
+%!testif HAVE_FFTW
+%! assert (fft (zeros (0,10)), zeros (0,10))
+%!testif HAVE_FFTW
+%! assert (fft (0), 0)
+%!testif HAVE_FFTW
+%! assert (fft (1), 1)
+%!testif HAVE_FFTW
+%! assert (fft (ones (2,2)), [2,2; 0,0])
+%!testif HAVE_FFTW
+%! assert (fft (eye (2,2)), [1,1; 1,-1])
 
-%!assert (fft (single ([])), single ([]))
-%!assert (fft (zeros (10,0,"single")), zeros (10,0,"single"))
-%!assert (fft (zeros (0,10,"single")), zeros (0,10,"single"))
-%!assert (fft (single (0)), single (0))
-%!assert (fft (single (1)), single (1))
-%!assert (fft (ones (2,2,"single")), single ([2,2; 0,0]))
-%!assert (fft (eye (2,2,"single")), single ([1,1; 1,-1]))
+%!testif HAVE_FFTW
+%! assert (fft (single ([])), single ([]))
+%!testif HAVE_FFTW
+%! assert (fft (zeros (10,0,"single")), zeros (10,0,"single"))
+%!testif HAVE_FFTW
+%! assert (fft (zeros (0,10,"single")), zeros (0,10,"single"))
+%!testif HAVE_FFTW
+%! assert (fft (single (0)), single (0))
+%!testif HAVE_FFTW
+%! assert (fft (single (1)), single (1))
+%!testif HAVE_FFTW
+%! assert (fft (ones (2,2,"single")), single ([2,2; 0,0]))
+%!testif HAVE_FFTW
+%! assert (fft (eye (2,2,"single")), single ([1,1; 1,-1]))
 
 %!error (fft ())
 */
@@ -242,7 +250,7 @@
 ## Author: David Billinghurst (David.Billinghurst@riotinto.com.au)
 ##         Comalco Research and Technology
 ##         02 May 2000
-%!test
+%!testif HAVE_FFTW
 %! N = 64;
 %! n = 4;
 %! t = 2*pi*(0:1:N-1)/N;
@@ -258,7 +266,7 @@
 ## Author: David Billinghurst (David.Billinghurst@riotinto.com.au)
 ##         Comalco Research and Technology
 ##         02 May 2000
-%!test
+%!testif HAVE_FFTW
 %! N = 64;
 %! n = 7;
 %! t = 2*pi*(0:1:N-1)/N;
@@ -273,7 +281,7 @@
 ## Author: David Billinghurst (David.Billinghurst@riotinto.com.au)
 ##         Comalco Research and Technology
 ##         02 May 2000
-%!test
+%!testif HAVE_FFTW
 %! N = 64;
 %! n = 4;
 %! t = single (2*pi*(0:1:N-1)/N);
@@ -289,7 +297,7 @@
 ## Author: David Billinghurst (David.Billinghurst@riotinto.com.au)
 ##         Comalco Research and Technology
 ##         02 May 2000
-%!test
+%!testif HAVE_FFTW
 %! N = 64;
 %! n = 7;
 %! t = 2*pi*(0:1:N-1)/N;
--- a/libinterp/corefcn/fft2.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/fft2.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -35,12 +35,6 @@
 
 // This function should be merged with Fifft.
 
-#if defined (HAVE_FFTW)
-#  define FFTSRC "@sc{fftw}"
-#else
-#  define FFTSRC "@sc{fftpack}"
-#endif
-
 static octave_value
 do_fft2 (const octave_value_list& args, const char *fcn, int type)
 {
@@ -182,7 +176,7 @@
 ## Author: David Billinghurst (David.Billinghurst@riotinto.com.au)
 ##         Comalco Research and Technology
 ##         02 May 2000
-%!test
+%!testif HAVE_FFTW
 %! M = 16;
 %! N = 8;
 %!
@@ -201,7 +195,7 @@
 ## Author: David Billinghurst (David.Billinghurst@riotinto.com.au)
 ##         Comalco Research and Technology
 ##         02 May 2000
-%!test
+%!testif HAVE_FFTW
 %! M = 12;
 %! N = 7;
 %!
@@ -223,7 +217,7 @@
 ## Author: David Billinghurst (David.Billinghurst@riotinto.com.au)
 ##         Comalco Research and Technology
 ##         02 May 2000
-%!test
+%!testif HAVE_FFTW
 %! M = 16;
 %! N = 8;
 %!
@@ -242,7 +236,7 @@
 ## Author: David Billinghurst (David.Billinghurst@riotinto.com.au)
 ##         Comalco Research and Technology
 ##         02 May 2000
-%!test
+%!testif HAVE_FFTW
 %! M = 12;
 %! N = 7;
 %!
--- a/libinterp/corefcn/fftn.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/fftn.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -34,12 +34,6 @@
 
 // This function should be merged with Fifft.
 
-#if defined (HAVE_FFTW)
-#  define FFTSRC "@sc{fftw}"
-#else
-#  define FFTSRC "@sc{fftpack}"
-#endif
-
 static octave_value
 do_fftn (const octave_value_list& args, const char *fcn, int type)
 {
--- a/libinterp/corefcn/file-io.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/file-io.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -41,8 +41,7 @@
 #include <cerrno>
 #include <cstdio>
 
-#include <iostream>
-#include <limits>
+#include <iomanip>
 #include <stack>
 #include <string>
 #include <vector>
@@ -425,7 +424,7 @@
   octave::sys::file_stat fs (fname);
 
   if (! (md & std::ios::out))
-    fname = find_data_file_in_load_path ("fopen", fname);
+    fname = octave::find_data_file_in_load_path ("fopen", fname);
 
   if (! fs.is_dir ())
     {
@@ -1199,7 +1198,7 @@
       fmt = args(1).string_value ();
 
       if (args(1).is_sq_string ())
-        fmt = do_string_escapes (fmt);
+        fmt = octave::do_string_escapes (fmt);
 
       nskip++;
     }
@@ -3080,7 +3079,7 @@
   if (args.length () != 0)
     print_usage ();
 
-  return ovl (get_P_tmpdir ());
+  return ovl (octave::get_P_tmpdir ());
 }
 
 // NOTE: the values of SEEK_SET, SEEK_CUR, and SEEK_END have to be
--- a/libinterp/corefcn/ft-text-renderer.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/ft-text-renderer.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -48,11 +48,11 @@
 
 #include <clocale>
 #include <cwchar>
-#include <iostream>
 #include <map>
 #include <utility>
 
 #include "singleton-cleanup.h"
+#include "unistr-wrappers.h"
 
 #include "defaults.h"
 #include "error.h"
@@ -226,7 +226,7 @@
 
       if (! fonts_dir.empty ())
         {
-          file = fonts_dir + octave::sys::file_ops::dir_sep_str () + "FreeSans";
+          file = fonts_dir + sys::file_ops::dir_sep_str () + "FreeSans";
 
           if (weight == "bold")
             file += "Bold";
@@ -347,7 +347,7 @@
   static void
   ft_face_destroyed (void *object)
   {
-    octave::ft_manager::font_destroyed (reinterpret_cast<FT_Face> (object));
+    ft_manager::font_destroyed (reinterpret_cast<FT_Face> (object));
   }
 
   class
@@ -728,31 +728,38 @@
       {
         glyph_index = FT_Get_Char_Index (face, code);
 
-        if (code != '\n'
+        if (code != '\n' && code != '\t'
             && (! glyph_index
                 || FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT)))
           {
             glyph_index = 0;
             warn_missing_glyph (code);
           }
+        else if ((code == '\n') || (code == '\t'))
+          {
+            glyph_index = FT_Get_Char_Index (face, ' ');
+            if (! glyph_index
+                || FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT))
+              {
+                glyph_index = 0;
+                warn_missing_glyph (' ');
+              }
+            else if (code == '\n')
+              push_new_line ();
+            else
+              {
+                // Advance to next multiple of 4 times the width of the "space"
+                // character.
+                int x_tab = 4 * (face->glyph->advance.x >> 6);
+                xoffset = (1 + std::floor (1. * xoffset / x_tab)) * x_tab;
+              }
+          }
         else
           {
             switch (mode)
               {
               case MODE_RENDER:
-                if (code == '\n')
-                  {
-                    glyph_index = FT_Get_Char_Index (face, ' ');
-                    if (! glyph_index
-                        || FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT))
-                      {
-                        glyph_index = 0;
-                        warn_missing_glyph (' ');
-                      }
-                    else
-                      push_new_line ();
-                  }
-                else if (FT_Render_Glyph (face->glyph, FT_RENDER_MODE_NORMAL))
+                if (FT_Render_Glyph (face->glyph, FT_RENDER_MODE_NORMAL))
                   {
                     glyph_index = 0;
                     warn_glyph_render (code);
@@ -775,9 +782,9 @@
                     y0 = line_yoffset + 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've allocated
-                    // the right amount of horizontal space in the bbox.
+                    // face->glyph->bitmap_left, this is so we don't index out
+                    // of bound, and assumes we've allocated the right amount of
+                    // horizontal space in the bbox.
                     if (x0 < 0)
                       x0 = 0;
 
@@ -805,41 +812,26 @@
                 break;
 
               case MODE_BBOX:
-                if (code == '\n')
+                Matrix& bb = line_bbox.back ();
+
+                // If we have a previous glyph, use kerning information.  This
+                // usually means moving a bit backward before adding the next
+                // glyph.  That is, "delta.x" is usually < 0.
+                if (previous)
                   {
-                    glyph_index = FT_Get_Char_Index (face, ' ');
-                    if (! glyph_index
-                        || FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT))
-                      {
-                        glyph_index = 0;
-                        warn_missing_glyph (' ');
-                      }
-                    else
-                      push_new_line ();
-                  }
-                else
-                  {
-                    Matrix& bb = line_bbox.back ();
+                    FT_Vector delta;
 
-                    // If we have a previous glyph, use kerning information.
-                    // This usually means moving a bit backward before adding
-                    // the next glyph.  That is, "delta.x" is usually < 0.
-                    if (previous)
-                      {
-                        FT_Vector delta;
+                    FT_Get_Kerning (face, previous, glyph_index,
+                                    FT_KERNING_DEFAULT, &delta);
 
-                        FT_Get_Kerning (face, previous, glyph_index,
-                                        FT_KERNING_DEFAULT, &delta);
+                    xoffset += (delta.x >> 6);
+                  }
 
-                        xoffset += (delta.x >> 6);
-                      }
+                // Extend current X offset box by the width of the current
+                // glyph.  Then extend the line bounding box if necessary.
 
-                    // Extend current X offset box by the width of the current
-                    // glyph.  Then extend the line bounding box if necessary.
-
-                    xoffset += (face->glyph->advance.x >> 6);
-                    bb(2) = math::max (bb(2), xoffset);
-                  }
+                xoffset += (face->glyph->advance.x >> 6);
+                bb(2) = math::max (bb(2), xoffset);
                 break;
               }
           }
@@ -872,67 +864,61 @@
         FT_UInt glyph_index, previous = 0;
 
         std::string str = e.string_value ();
-        size_t n = str.length ();
+        size_t n;
+        // convert str to UTF-32
+        uint32_t *u32_str;
+        u32_str = octave_u8_to_u32_wrapper (reinterpret_cast<const uint8_t *> (str.c_str ()), str.length (), nullptr, &n);
+        if (! u32_str)
+          error ("ft_text_renderer: converting from UTF-8 to UTF-32: %s",
+                 std::strerror (errno));
         size_t curr = 0;
         size_t idx = 0;
-        mbstate_t ps;
-        memset (&ps, 0, sizeof (ps));  // Initialize state to 0.
-        wchar_t wc;
         std::string fname = font.get_face ()->family_name;
         text_renderer::string fs (str, font, xoffset, yoffset);
         std::vector<double> xdata;
 
         while (n > 0)
           {
-            size_t r = std::mbrtowc (&wc, str.data () + curr, n, &ps);
+            n -= 1;
 
-            if (r > 0
-                && r != static_cast<size_t> (-1)
-                && r != static_cast<size_t> (-2))
+            if (u32_str[curr] == 10)
               {
-                n -= r;
-                curr += r;
-
-                if (wc == L'\n')
+                // Finish previous string in strlist before processing
+                // the newline character
+                fs.set_y (line_yoffset + yoffset);
+                fs.set_color (color);
+                // FIXME: Do we have to convert back to UTF-8 and keep strlist
+                // in sync? Might fail with multi-byte characters as it is now.
+                std::string s = str.substr (idx, curr - idx);
+                if (! s.empty ())
                   {
-                    // Finish previous string in strlist before processing
-                    // the newline character
-                    fs.set_y (line_yoffset + yoffset);
-                    fs.set_color (color);
-                    std::string s = str.substr (idx, curr - idx - 1);
-                    if (! s.empty ())
-                      {
-                        fs.set_string (s);
-                        fs.set_xdata (xdata);
-                        fs.set_family (fname);
-                        strlist.push_back (fs);
-                      }
+                    fs.set_string (s);
+                    fs.set_xdata (xdata);
+                    fs.set_family (fname);
+                    strlist.push_back (fs);
                   }
-                else
-                  xdata.push_back (xoffset);
-
-                glyph_index = process_character (wc, previous);
-
-                if (wc == L'\n')
-                  {
-                    previous = 0;
-                    // Start a new string in strlist
-                    idx = curr;
-                    xdata.clear ();
-                    fs = text_renderer::string (str.substr (idx), font,
-                                                line_xoffset, yoffset);
-                  }
-                else
-                  previous = glyph_index;
               }
             else
+              xdata.push_back (xoffset);
+
+            glyph_index = process_character (u32_str[curr], previous);
+
+
+            if (u32_str[curr] == 10)
               {
-                if (r != 0)
-                  ::warning ("ft_text_renderer: failed to decode string `%s' with "
-                             "locale `%s'", str.c_str (),
-                             std::setlocale (LC_CTYPE, nullptr));
-                break;
+                previous = 0;
+                // Start a new string in strlist
+                idx = curr+1;
+                xdata.clear ();
+                // FIXME: Do we have to convert back to UTF-8 and keep strlist
+                // in sync? Might fail with multi-byte characters as it is now.
+                fs = text_renderer::string (str.substr (idx), font,
+                                            line_xoffset, yoffset);
               }
+            else
+              previous = glyph_index;
+
+            curr += 1;
           }
 
         if (! fs.get_string ().empty ())
--- a/libinterp/corefcn/genprops.awk	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/genprops.awk	Fri Aug 10 09:09:51 2018 +0200
@@ -137,7 +137,7 @@
 ##
 ##   f:  The property does not have any factory default value.
 ##
-## The 'o' and 'O' qualifiers are only useful when the the property type
+## The 'o' and 'O' qualifiers are only useful when the property type
 ## is something other than octave_value.
 
 ## simple accessor
--- a/libinterp/corefcn/gl-render.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/gl-render.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -24,7 +24,7 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <sstream>
 
 #if defined (HAVE_WINDOWS_H)
 #  define WIN32_LEAN_AND_MEAN
@@ -1942,17 +1942,12 @@
           {
             if (go.isa ("light") && ! selecting)
               {
-                if (num_lights < max_lights)
+                if (current_light-GL_LIGHT0 < max_lights)
                   {
-                    current_light = GL_LIGHT0 + num_lights;
                     set_clipping (p.is_clipping ());
                     draw (go);
-                    num_lights++;
+                    current_light++;
                   }
-                else
-                  warning_with_id ("Octave:max-lights-exceeded",
-                                   "light: Maximum number of lights (%d) in these axes is "
-                                   "exceeded.", max_lights);
               }
             else if (go.isa ("hggroup")
                      && ! (selecting && p.pickableparts_is ("none")))
@@ -2017,12 +2012,16 @@
     // Start with the last element of the array of child objects to
     // display them in the order they were added to the array.
 
-    num_lights = 0;
+    if (props.get_num_lights () > max_lights)
+      warning_with_id ("Octave:max-lights-exceeded",
+                       "light: Maximum number of lights (%d) in these axes is "
+                       "exceeded.", max_lights);
+
     current_light = GL_LIGHT0;
     draw_all_lights (props, obj_list);
 
     // disable other OpenGL lights
-    for (int i = num_lights; i < max_lights; i++)
+    for (unsigned int i = props.get_num_lights (); i < max_lights; i++)
       glDisable (GL_LIGHT0 + i);
 
     // save camera position and set ambient light color before drawing
@@ -2338,6 +2337,7 @@
                    (props.edgealpha_is ("flat") ? 1 : 2));
     int bfl_mode = (props.backfacelighting_is ("lit") ? 0 :
                     (props.backfacelighting_is ("reverselit") ? 1 : 2));
+    bool do_lighting = props.get_do_lighting ();
 
     Matrix fcolor = (fc_mode == TEXTURE ? Matrix (1, 3, 1.0)
                                         : props.get_facecolor_rgb ());
@@ -2416,7 +2416,7 @@
                   }
               }
 
-            if ((fl_mode > 0) && (num_lights > 0))
+            if ((fl_mode > 0) && do_lighting)
               glEnable (GL_LIGHTING);
             glShadeModel ((fc_mode == INTERP || fl_mode == GOURAUD)
                           ? GL_SMOOTH : GL_FLAT);
@@ -2592,7 +2592,7 @@
             if (fc_mode == TEXTURE)
               glDisable (GL_TEXTURE_2D);
 
-            if ((fl_mode > 0) && (num_lights > 0))
+            if ((fl_mode > 0) && do_lighting)
               glDisable (GL_LIGHTING);
           }
         else
@@ -2624,7 +2624,7 @@
                   }
               }
 
-            if ((el_mode > 0) && (num_lights > 0))
+            if ((el_mode > 0) && do_lighting)
               glEnable (GL_LIGHTING);
             glShadeModel ((ec_mode == INTERP || el_mode == GOURAUD)
                           ? GL_SMOOTH : GL_FLAT);
@@ -2832,7 +2832,7 @@
             set_linestyle ("-");  // Disable LineStipple
             set_linewidth (0.5f);
 
-            if ((el_mode > 0) && (num_lights > 0))
+            if ((el_mode > 0) && do_lighting)
               glDisable (GL_LIGHTING);
           }
         else
@@ -2972,6 +2972,7 @@
                    (props.edgealpha_is ("flat") ? 1 : 2));
     int bfl_mode = (props.backfacelighting_is ("lit") ? 0 :
                     (props.backfacelighting_is ("reverselit") ? 1 : 2));
+    bool do_lighting = props.get_do_lighting ();
 
     Matrix fcolor = props.get_facecolor_rgb ();
     Matrix ecolor = props.get_edgecolor_rgb ();
@@ -3097,6 +3098,8 @@
     if (fl_mode > 0 || el_mode > 0)
       glMaterialf (LIGHT_MODE, GL_SHININESS, se);
 
+    std::list<std::list<octave_idx_type>>::const_iterator it1;
+
     if (draw_all || ! props.facecolor_is ("none"))
       {
         // FIXME: adapt to double-radio property
@@ -3123,71 +3126,110 @@
                   }
               }
 
-            if ((fl_mode > 0) && (num_lights > 0) && has_normals)
+            if ((fl_mode > 0) && do_lighting && has_normals)
               glEnable (GL_LIGHTING);
 
-            // NOTE: Push filled part of patch backwards to avoid Z-fighting with
-            // tesselator outline.  A value of 1.0 seems to work fine.  Value
-            // can't be too large or the patch will be pushed below the axes
-            // planes at +2.5.
+            // NOTE: Push filled part of patch backwards to avoid Z-fighting
+            // with tesselator outline.  A value of 1.0 seems to work fine.
+            // Value can't be too large or the patch will be pushed below the
+            // axes planes at +2.5.
             patch_tesselator tess (this, fc_mode, fl_mode, 1.0);
 
+            it1 = props.coplanar_last_idx.begin ();
+            std::list<octave_idx_type>::const_iterator it2;
+            octave_idx_type i_start, i_end;
+
             for (int i = 0; i < nf; i++)
               {
                 if (clip_f(i))
                   continue;
 
-                tess.begin_polygon (true);
-                tess.begin_contour ();
-
-                // Add vertices in reverse order for Matlab compatibility
-                for (int j = count_f(i)-1; j > 0; j--)
+                bool is_non_planar = false;
+                if (props.coplanar_last_idx.size () > 0 && (*it1).size () > 1)
+                  {
+                    is_non_planar = true;
+                    it2 = (*it1).end ();
+                    it2--;
+                  }
+
+                // loop over planar subsets of face
+                do
                   {
-                    vertex_data::vertex_data_rep *vv = vdata[i+j*fr].get_rep ();
-
-                    tess.add_vertex (vv->coords.fortran_vec (), vv);
-                  }
-
-                if (count_f(i) > 0)
-                  {
-                    vertex_data::vertex_data_rep *vv = vdata[i].get_rep ();
-
-                    if (fc_mode == FLAT)
+                    if (is_non_planar)
+                      {
+                        i_end = *it2;
+                        if (it2 == (*it1).begin ())
+                          i_start = 0;
+                        else
+                          {
+                            it2--;
+                            i_start = *it2 - 1;
+                          }
+                      }
+                    else
+                      {
+                        i_end = count_f(i) - 1;
+                        i_start = 0;
+                      }
+
+                    tess.begin_polygon (true);
+                    tess.begin_contour ();
+
+                    // Add vertices in reverse order for Matlab compatibility
+                    for (int j = i_end; j > i_start; j--)
                       {
-                        // For "flat" shading, use color of 1st vertex.
-                        Matrix col = vv->color;
-
-                        if (col.numel () == 3)
+                        vertex_data::vertex_data_rep *vv =
+                          vdata[i+j*fr].get_rep ();
+
+                        tess.add_vertex (vv->coords.fortran_vec (), vv);
+                      }
+
+                    if (count_f(i) > 0)
+                      {
+                        vertex_data::vertex_data_rep *vv = vdata[i].get_rep ();
+
+                        if (fc_mode == FLAT)
                           {
-                            glColor4d (col(0), col(1), col(2), fa);
-                            if (fl_mode > 0)
+                            // For "flat" shading, use color of 1st vertex.
+                            Matrix col = vv->color;
+
+                            if (col.numel () == 3)
                               {
-                                float cb[4] = { 0, 0, 0, 1 };
-
-                                for (int k = 0; k < 3; k++)
-                                  cb[k] = (vv->ambient * col(k));
-                                glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
-
-                                for (int k = 0; k < 3; k++)
-                                  cb[k] = (vv->diffuse * col(k));
-                                glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
-
-                                for (int k = 0; k < 3; k++)
-                                  cb[k] = vv->specular * (vv->specular_color_refl
-                                                          + (1-vv->specular_color_refl) * col(k));
-                                glMaterialfv (LIGHT_MODE, GL_SPECULAR, cb);
+                                glColor4d (col(0), col(1), col(2), fa);
+                                if (fl_mode > 0)
+                                  {
+                                    float cb[4] = { 0, 0, 0, 1 };
+
+                                    for (int k = 0; k < 3; k++)
+                                      cb[k] = (vv->ambient * col(k));
+                                    glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
+
+                                    for (int k = 0; k < 3; k++)
+                                      cb[k] = (vv->diffuse * col(k));
+                                    glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
+
+                                    for (int k = 0; k < 3; k++)
+                                      cb[k] = vv->specular *
+                                              (vv->specular_color_refl
+                                               + (1-vv->specular_color_refl) *
+                                              col(k));
+                                    glMaterialfv (LIGHT_MODE, GL_SPECULAR, cb);
+                                  }
                               }
                           }
+
+                        tess.add_vertex (vv->coords.fortran_vec (), vv);
                       }
 
-                    tess.add_vertex (vv->coords.fortran_vec (), vv);
-                  }
-
-                tess.end_contour ();
-                tess.end_polygon ();
+                    tess.end_contour ();
+                    tess.end_polygon ();
+                  } while (i_start > 0);
+
+                if (is_non_planar)
+                  it1++;
               }
 
-            if ((fl_mode > 0) && (num_lights > 0) && has_normals)
+            if ((fl_mode > 0) && do_lighting && has_normals)
               glDisable (GL_LIGHTING);
           }
         else
@@ -3223,7 +3265,7 @@
                   }
               }
 
-            if ((el_mode > 0) && (num_lights > 0) && has_normals)
+            if ((el_mode > 0) && do_lighting && has_normals)
               glEnable (GL_LIGHTING);
 
             double linewidth = props.get_linewidth ();
@@ -3239,11 +3281,17 @@
             // not supported by glPolygonOffset which is used to do Z offsets.
             patch_tesselator tess (this, ec_mode, el_mode);
 
+            it1 = props.coplanar_last_idx.begin ();
+
             for (int i = 0; i < nf; i++)
               {
-                if (clip_f(i))
+                bool is_non_planar = false;
+                if (props.coplanar_last_idx.size () > 0 && (*it1).size () > 1)
+                  is_non_planar = true;
+                if (clip_f(i) || is_non_planar)
                   {
-                    // This is an unclosed contour.  Draw it as a line.
+                    // This is an unclosed contour or a non-planar face.
+                    // Draw it as a line.
                     bool flag = false;
 
                     glShadeModel ((ec_mode == INTERP || el_mode == GOURAUD)
@@ -3313,12 +3361,14 @@
                     tess.end_contour ();
                     tess.end_polygon ();
                   }
+                if (is_non_planar)
+                  it1++;
               }
 
             set_linestyle ("-");  // Disable LineStipple
             set_linewidth (0.5f);
 
-            if ((el_mode > 0) && (num_lights > 0) && has_normals)
+            if ((el_mode > 0) && do_lighting && has_normals)
               glDisable (GL_LIGHTING);
           }
         else
@@ -4292,7 +4342,7 @@
           if (sz > 0 && sz < 3)
             sz = 3;
 
-          int div = static_cast <int> (M_PI * sz / 12);
+          int div = static_cast<int> (M_PI * sz / 12);
           if (! (div % 2))
             div += 1;               // ensure odd number for left/right symmetry
           div = std::max (div, 3);  // ensure at least a few vertices are drawn
@@ -4314,7 +4364,7 @@
         break;
       case 'o':
         {
-          int div = static_cast <int> (M_PI * sz / 4);
+          int div = static_cast<int> (M_PI * sz / 4);
           if (! (div % 2))
             div += 1;               // ensure odd number for left/right symmetry
           div = std::max (div, 5);  // ensure at least a few vertices are drawn
--- a/libinterp/corefcn/gl-render.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/gl-render.h	Fri Aug 10 09:09:51 2018 +0200
@@ -216,9 +216,8 @@
     text_renderer txt_renderer;
 
     // light object present and visible
-    int num_lights;
     unsigned int current_light;
-    int max_lights;
+    unsigned int max_lights;
 
     // Indicate we are drawing for selection purpose
     bool selecting;
--- a/libinterp/corefcn/gl2ps-print.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/gl2ps-print.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -54,7 +54,7 @@
   safe_pclose (FILE *f)
   {
     if (f)
-      octave_pclose (f);
+      octave::pclose (f);
   }
 
   static void
@@ -265,12 +265,12 @@
     // Build an svg text element from a list of parsed strings.
     std::string strlist_to_svg (double x, double y, double z, Matrix box,
                                 double rotation,
-                                std::list<octave::text_renderer::string>& lst);
+                                std::list<text_renderer::string>& lst);
 
     // Build a list of postscript commands from a list of parsed strings.
     std::string strlist_to_ps (double x, double y, double z, Matrix box,
                                double rotation,
-                               std::list<octave::text_renderer::string>& lst);
+                               std::list<text_renderer::string>& lst);
 
     int alignment_to_mode (int ha, int va) const;
     FILE *fp;
@@ -781,7 +781,7 @@
   std::string
   gl2ps_renderer::strlist_to_svg (double x, double y, double z,
                                   Matrix box, double rotation,
-                                  std::list<octave::text_renderer::string>& lst)
+                                  std::list<text_renderer::string>& lst)
   {
     if (lst.empty ())
       return "";
@@ -877,7 +877,7 @@
   std::string
   gl2ps_renderer::strlist_to_ps (double x, double y, double z,
                                  Matrix box, double rotation,
-                                 std::list<octave::text_renderer::string>& lst)
+                                 std::list<text_renderer::string>& lst)
   {
     // Translate and rotate coordinates in order to use bottom-left alignment
     fix_strlist_position (x, y, z, box, rotation, lst);
@@ -1105,7 +1105,7 @@
 
         std::string cmd = stream.substr (1);
 
-        fp = octave_popen (cmd.c_str (), "w");
+        fp = octave::popen (cmd.c_str (), "w");
 
         if (! fp)
           error (R"(print: failed to open pipe "%s")", stream.c_str ());
@@ -1116,7 +1116,7 @@
       {
         // Write gl2ps output directly to file.
 
-        fp = std::fopen (stream.c_str (), "w");
+        fp = octave::sys::fopen (stream.c_str (), "w");
 
         if (! fp)
           error (R"(gl2ps_print: failed to create file "%s")", stream.c_str ());
--- a/libinterp/corefcn/gl2ps-print.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/gl2ps-print.h	Fri Aug 10 09:09:51 2018 +0200
@@ -36,16 +36,4 @@
                const std::string& term);
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::gl2ps_print' instead")
-inline void
-gl2ps_print (const graphics_object& fig, const std::string& stream,
-             const std::string& term)
-{
-  return octave::gl2ps_print (fig, stream, term);
-}
-
 #endif
-
-#endif
--- a/libinterp/corefcn/graphics.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/graphics.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -59,6 +59,7 @@
 #include "ov-fcn-handle.h"
 #include "pager.h"
 #include "parse.h"
+#include "text-engine.h"
 #include "text-renderer.h"
 #include "unwind-prot.h"
 #include "utils.h"
@@ -1728,13 +1729,8 @@
 void
 children_property::do_delete_children (bool clear)
 {
-  for (auto& hchild : children_list)
-    {
-      graphics_object go = gh_manager::get_object (hchild);
-
-      if (go.valid_object () && ! go.get_properties ().is_beingdeleted ())
-        gh_manager::free (hchild);
-    }
+  while (! children_list.empty ())
+    gh_manager::free (children_list.front ());
 
   if (clear)
     children_list.clear ();
@@ -2205,7 +2201,7 @@
 
           if (remove)
             {
-              pval_map_iterator p = pval_map.find (pname);
+              auto p = pval_map.find (pname);
 
               if (p != pval_map.end ())
                 pval_map.erase (p);
@@ -2318,7 +2314,7 @@
 {
   octave_scalar_map m;
 
-  for (plist_map_const_iterator p = begin (); p != end (); p++)
+  for (auto p = begin (); p != end (); p++)
     {
       std::string prefix = prefix_arg + p->first;
 
@@ -2622,7 +2618,7 @@
       // fractional part.  To avoid running out of integers, we recycle the
       // integer part but tack on a new random part each time.
 
-      free_list_iterator p = handle_free_list.begin ();
+      auto p = handle_free_list.begin ();
 
       if (p != handle_free_list.end ())
         {
@@ -2648,17 +2644,27 @@
       if (h.value () == 0)
         error ("graphics_handle::free: can't delete root figure");
 
-      iterator p = handle_map.find (h);
+      auto p = handle_map.find (h);
 
       if (p == handle_map.end ())
         error ("graphics_handle::free: invalid object %g", h.value ());
 
       base_properties& bp = p->second.get_properties ();
 
+      if (!p->second.valid_object () || bp.is_beingdeleted ())
+        return;
+
+      graphics_handle parent_h = p->second.get_parent ();
+      graphics_object parent_go = gh_manager::get_object (parent_h);
+
       bp.set_beingdeleted (true);
 
+      // delete listeners before invalidating object
+      p->second.remove_all_listeners ();
+
       bp.delete_children ();
 
+      // NOTE: Call the delete function while the object's state is still valid.
       octave_value val = bp.get_deletefcn ();
 
       bp.execute_deletefcn ();
@@ -2666,6 +2672,11 @@
       // Notify graphics toolkit.
       p->second.finalize ();
 
+      // NOTE: Call remove_child before erasing the go from the map.
+      // A callback function might have already deleted the parent
+      if (parent_go.valid_object () && h.ok ())
+        parent_go.remove_child (h);
+
       // Note: this will be valid only for first explicitly deleted
       // object.  All its children will then have an
       // unknown graphics toolkit.
@@ -2687,7 +2698,7 @@
 gh_manager::do_renumber_figure (const graphics_handle& old_gh,
                                 const graphics_handle& new_gh)
 {
-  iterator p = handle_map.find (old_gh);
+  auto p = handle_map.find (old_gh);
 
   if (p == handle_map.end ())
     error ("graphics_handle::free: invalid object %g", old_gh.value ());
@@ -2801,20 +2812,11 @@
       // Don't do recursive deleting, due to callbacks
       if (! go.get_properties ().is_beingdeleted ())
         {
-          graphics_handle parent_h = go.get_parent ();
-
-          graphics_object parent_go = gh_manager::get_object (parent_h);
-
-          // NOTE: free the handle before removing it from its parent's
-          //       children, such that the object's state is correct when the
-          //       deletefcn callback is executed
+          // NOTE: Freeing the handle also calls any deletefcn.  It also calls
+          //       the parent's delete_child function.
 
           gh_manager::free (h);
 
-          // A callback function might have already deleted the parent
-          if (parent_go.valid_object ())
-            parent_go.remove_child (h);
-
           Vdrawnow_requested = true;
         }
     }
@@ -3134,8 +3136,7 @@
 base_properties::set_dynamic (const caseless_str& pname,
                               const octave_value& val)
 {
-  std::map<caseless_str, property, cmp_caseless_str>::iterator it =
-    all_props.find (pname);
+  auto it = all_props.find (pname);
 
   if (it == all_props.end ())
     error (R"(set: unknown property "%s")", pname.c_str ());
@@ -3398,6 +3399,34 @@
     p.delete_listener (val, mode);
 }
 
+void
+base_properties::get_children_of_type (const caseless_str& chtype,
+                                       bool get_invisible,
+                                       bool traverse,
+                                       std::list<graphics_object> &children_list) const
+{
+  Matrix ch = get_children ();
+  for (octave_idx_type i = 0; i < ch.numel (); i++)
+    {
+      graphics_handle hkid = gh_manager::lookup (ch(i));
+
+      if (hkid.ok ())
+        {
+          graphics_object go = gh_manager::get_object (hkid);
+          if ( get_invisible || go.get_properties ().is_visible () )
+            {
+              if (go.isa (chtype))
+                children_list.push_back (go);
+              else if (traverse && go.isa ("hggroup"))
+                go.get_properties ().get_children_of_type (chtype,
+                                                           get_invisible,
+                                                           traverse,
+                                                           children_list);
+            }
+        }
+    }
+}
+
 // ---------------------------------------------------------------------
 
 void
@@ -3853,6 +3882,15 @@
     }
 }
 
+octave_value
+figure::properties::get_number (void) const
+{
+  if (integerhandle.is_on ())
+    return __myhandle__.value ();
+  else
+    return Matrix ();
+}
+
 graphics_toolkit
 figure::properties::get_toolkit (void) const
 {
@@ -4670,7 +4708,8 @@
 std::string
 figure::properties::get_title (void) const
 {
-  if (is_numbertitle ())
+  std::string title;
+  if (! get_number ().isempty () && is_numbertitle ())
     {
       std::ostringstream os;
       std::string nm = get_name ();
@@ -4679,10 +4718,17 @@
       if (! nm.empty ())
         os << ": " << get_name ();
 
-      return os.str ();
+      title = os.str ();
     }
   else
-    return get_name ();
+    title = get_name ();
+
+  // Qt will use QCoreApplication name (set in main-window.cc)
+  // if the name is empty, so force blank.
+  if (title.empty ())
+    title = " ";
+
+  return title;
 }
 
 octave_value
@@ -5027,8 +5073,6 @@
 
   gh_manager::free (hp.handle_value ());
 
-  base_properties::remove_child (hp.handle_value ());
-
   hp = val;
 
   adopt (hp.handle_value ());
@@ -5326,8 +5370,6 @@
 
       if (go.valid_object ())
         gh_manager::free (h);
-
-      base_properties::remove_child (h);
     }
 
   // FIXME: is it necessary to check whether the axes object is
@@ -5349,6 +5391,11 @@
 void
 axes::properties::remove_child (const graphics_handle& h)
 {
+  graphics_object go = gh_manager::get_object (h);
+
+  if (go.isa ("light") && go.get_properties ().is_visible ())
+    decrease_num_lights ();
+
   if (xlabel.handle_value ().ok () && h == xlabel.handle_value ())
     {
       delete_text_child (xlabel);
@@ -5369,8 +5416,21 @@
       delete_text_child (title);
       update_title_position ();
     }
-  else
-    base_properties::remove_child (h);
+
+  if (go.valid_object ())
+      base_properties::remove_child (h);
+
+}
+
+void
+axes::properties::adopt (const graphics_handle& h)
+{
+  graphics_object go (gh_manager::get_object (h));
+  if (go.isa ("light") && go.get_properties ().is_visible ())
+    increase_num_lights ();
+
+  base_properties::adopt (h);
+
 }
 
 inline Matrix
@@ -8611,6 +8671,37 @@
 }
 
 void
+axes::properties::trigger_normals_calc (void)
+{
+  // Find all patch (and surface) objects within axes
+  std::list<graphics_object> children_list;
+  std::list<graphics_object>::iterator children_list_iter;
+  get_children_of_type ("patch", false, true, children_list);
+  // FIXME: Un-comment when surface is ready:
+  // get_children_of_type ("surface", false, true, children_list);
+
+  // trigger normals calculation for these objects
+  for (children_list_iter = children_list.begin ();
+       children_list_iter != children_list.end (); children_list_iter++)
+    {
+      graphics_object kid = *children_list_iter;
+      if (kid.isa ("patch"))
+        {
+          patch::properties& patch_props =
+              dynamic_cast<patch::properties&> (kid.get_properties ());
+          patch_props.update_normals (false);
+        }
+      else
+        {
+          // FIXME: Un-comment when surface is ready:
+          // surface::properties& surface_props =
+          //     dynamic_cast<surface::properties&> (kid.get_properties ());
+          // surface_props.update_normals (false);
+        }
+    }
+}
+
+void
 axes::reset_default_properties (void)
 {
   // empty list of local defaults
@@ -8859,6 +8950,41 @@
 
 // ---------------------------------------------------------------------
 
+void
+light::initialize (const graphics_object& go)
+{
+  base_graphics_object::initialize (go);
+
+  // trigger normals calculation for the respective children of this axes object
+  axes::properties& parent_axes_prop =
+    dynamic_cast<axes::properties&> (go.get_ancestor ("axes").get_properties ());
+  parent_axes_prop.trigger_normals_calc ();
+}
+
+void
+light::properties::update_visible (void)
+{
+  graphics_object go = gh_manager::get_object (get___myhandle__ ());
+  axes::properties& ax_props = dynamic_cast<axes::properties&>
+    (go.get_ancestor ("axes").get_properties ());
+  if (is_visible ())
+    ax_props.increase_num_lights ();
+  else
+    ax_props.decrease_num_lights ();
+}
+
+// ---------------------------------------------------------------------
+
+bool
+patch::properties::get_do_lighting (void) const
+{
+  graphics_object go = gh_manager::get_object (get___myhandle__ ());
+  axes::properties& ax_props = dynamic_cast<axes::properties&>
+    (go.get_ancestor ("axes").get_properties ());
+
+  return (ax_props.get_num_lights () > 0);
+}
+
 octave_value
 patch::properties::get_color_data (void) const
 {
@@ -8995,6 +9121,53 @@
         }
     }
 
+  // check coplanarity for 3d-faces with more than 3 corners
+  int fcmax = idx.rows ();
+  if (fcmax > 3 && vert.columns () > 2)
+    {
+      for (octave_idx_type jj = 0; jj < idx.columns (); jj++)
+        {
+          if (! octave::math::isnan (idx(3,jj)))
+            {
+              // find first element that is NaN to get number of corners
+              octave_idx_type nc = 3;
+              while (! octave::math::isnan (idx(nc,jj)) && nc < fcmax)
+                nc++;
+
+              std::list<octave_idx_type> coplanar_ends;
+
+              octave_idx_type i_start = 1;
+              octave_idx_type i_end = 2;
+              while (i_end < nc - 1)
+                {
+                  // look for coplanar subsets
+                  for (i_end = nc-1; i_end > i_start+1; i_end--)
+                    {
+                      Matrix fc = Matrix (i_end - i_start + 1, 3, 0.0);
+                      for (octave_idx_type j = 0; j <= i_end-i_start; j++)
+                        for (octave_idx_type i = 0; i < 3; i++)
+                          fc(j,i) = vert(idx(j + i_start,jj)-1,i)
+                                    - vert(idx(0,jj)-1,i);
+
+                      // calculate rank of matrix
+                      octave::math::svd<Matrix> result
+                        (fc,
+                         octave::math::svd<Matrix>::Type::sigma_only,
+                         octave::math::svd<Matrix>::Driver::GESVD);
+                      DiagMatrix sigma = result.singular_values ();
+                      double tol = nc * sigma(0,0)
+                                   * std::numeric_limits<double>::epsilon ();
+                      if (sigma(2,2) < tol)
+                        break;
+                    }
+                  coplanar_ends.push_back (i_end);
+                  i_start = i_end;
+                }
+              coplanar_last_idx.push_back (coplanar_ends);
+            }
+        }
+    }
+
   // Build cdata
   dim_vector dv = dim_vector::alloc (3);
   NDArray cd;
@@ -9055,14 +9228,9 @@
   set_ydata (yd);
   set_zdata (zd);
   set_cdata (cd);
-}
-
-// ---------------------------------------------------------------------
-
-octave_value
-surface::properties::get_color_data (void) const
-{
-  return convert_cdata (*this, get_cdata (), cdatamapping_is ("scaled"), 3);
+
+  // Update normals
+  update_normals (true);
 }
 
 inline void
@@ -9076,6 +9244,267 @@
 }
 
 void
+patch::properties::calc_face_normals (Matrix& fn)
+{
+  Matrix v = get_vertices ().matrix_value ();
+  Matrix f = get_faces ().matrix_value ();
+
+  bool is_3d = (v.columns () == 3); // 2d or 3d patches
+  octave_idx_type num_f = f.rows (); // number of faces
+  octave_idx_type max_nc = f.columns (); // maximum number of polygon corners
+
+  // In which cases can we skip updating the normals?
+  if (max_nc < 3)
+    {
+      fn = Matrix ();
+      return;
+    }
+
+  // Calculate normals for all faces
+  std::list<std::list<octave_idx_type>>::const_iterator
+    cp_it = coplanar_last_idx.begin ();
+  octave_idx_type i1, i2, i3;
+  octave_idx_type j1, j2;
+  for (octave_idx_type i = 0; i < num_f; i++)
+    {
+      bool is_coplanar = true;
+      if (coplanar_last_idx.size () > 0)
+        {
+          if ((*cp_it).size () > 1)
+          {
+            is_coplanar = false;
+          }
+          cp_it++;
+        }
+
+      // get number of corners
+      octave_idx_type nc = 3;
+      if (max_nc > 3)
+        {
+          while (! octave::math::isnan (f(i,nc)) && nc < max_nc)
+            nc++;
+        }
+
+      RowVector fnc (3, 0.0);
+      double& nx = fnc(0);
+      double& ny = fnc(1);
+      double& nz = fnc(2);
+
+      if (is_coplanar)
+        {
+          // fast way for coplanar polygons
+          i1 = f(i,0) - 1; i2 = f(i,1) - 1; i3 = f(i,nc-1) - 1;
+
+          if (is_3d)
+            cross_product
+              (v(i3,0) - v(i1,0), v(i3,1) - v(i1,1), v(i3,2) - v(i1,2),
+               v(i2,0) - v(i1,0), v(i2,1) - v(i1,1), v(i2,2) - v(i1,2),
+               nx, ny, nz);
+          else
+            {
+              nz = (v(i2,0) - v(i1,0)) * (v(i3,1) - v(i1,1)) -
+                   (v(i2,1) - v(i1,1)) * (v(i3,0) - v(i1,0));
+              // 2-d vertices always point towards +z
+              nz = (nz < 0) ? -nz : nz;
+            }
+        }
+      else
+        {
+          // more general for non-planar polygons
+
+          // calculate face normal with Newill method
+          // https://courses.cit.cornell.edu/cs417-land/SECTIONS/normals.html
+
+          j1 = nc - 1; j2 = 0;
+          i1 = f(i,j1) - 1; i2 = f(i,j2) - 1;
+
+          nx = (v(i2,1) - v(i1,1)) * (v(i1,2) + v(i2,2));
+          ny = (v(i2,2) - v(i1,2)) * (v(i1,0) + v(i2,0));
+          nz = (v(i2,0) - v(i1,0)) * (v(i1,1) + v(i2,1));
+
+          for (octave_idx_type j = 1; j < nc; j++)
+            {
+              j1 = j-1; j2 = j;
+              i1 = f(i,j1) - 1; i2 = f(i,j2) - 1;
+
+              nx += (v(i2,1) - v(i1,1)) * (v(i1,2) + v(i2,2));
+              ny += (v(i2,2) - v(i1,2)) * (v(i1,0) + v(i2,0));
+              nz += (v(i2,0) - v(i1,0)) * (v(i1,1) + v(i2,1));
+            }
+        }
+
+      // normalize normal vector
+      double n_len = sqrt (nx*nx+ny*ny+nz*nz);
+
+      // assign normal to current face
+      if ( n_len < std::numeric_limits<double>::epsilon () )
+        for (octave_idx_type j = 0; j < 3; j++)
+          fn(i,j) = 0.0;
+      else
+        for (octave_idx_type j = 0; j < 3; j++)
+          fn(i,j) = fnc(j) / n_len;
+    }
+}
+
+void
+patch::properties::update_face_normals (bool reset)
+{
+  if (updating_patch_data || ! facenormalsmode_is ("auto"))
+    return;
+
+  if ((facelighting_is ("flat") || edgelighting_is ("flat")) &&
+      get_do_lighting ())
+    {
+      Matrix f = get_faces ().matrix_value ();
+
+      octave_idx_type num_f = f.rows (); // number of faces
+      Matrix fn (num_f, 3, 0.0);
+
+      calc_face_normals (fn);
+      facenormals = fn;
+    }
+  else if (reset)
+    facenormals = Matrix ();
+}
+
+void
+patch::properties::update_vertex_normals (bool reset)
+{
+  if (updating_patch_data || ! vertexnormalsmode_is ("auto"))
+    return;
+
+  if ((facelighting_is ("gouraud") || facelighting_is ("phong") ||
+      edgelighting_is ("gouraud") || edgelighting_is ("phong")) &&
+      get_do_lighting ())
+    {
+      Matrix v = get_vertices ().matrix_value ();
+      Matrix f = get_faces ().matrix_value ();
+
+      octave_idx_type num_v = v.rows (); // number of vertices
+      octave_idx_type num_f = f.rows (); // number of faces
+      octave_idx_type max_nc = f.columns (); // maximum number of polygon corners
+
+      // In which cases can we skip updating the normals?
+      if (max_nc < 3)
+        return;
+
+      // First step: Calculate the normals for all faces
+      Matrix fn = get_facenormals ().matrix_value ();
+      if ( fn.isempty () )
+        {
+          // calculate facenormals here
+          fn = Matrix (num_f, 3, 0.0);
+          calc_face_normals (fn);
+        }
+
+      // Second step: assign normals to the respective vertices
+      std::vector<RowVector> vec_vn [num_v]; // list of normals for vertices
+      for (octave_idx_type i = 0; i < num_f; i++)
+        {
+          // get number of corners
+          octave_idx_type nc = 3;
+          if (max_nc > 3)
+            {
+              while (! octave::math::isnan (f(i,nc)) && nc < max_nc)
+                nc++;
+            }
+
+          for (octave_idx_type j = 0; j < nc; j++)
+            vec_vn[static_cast<octave_idx_type> (f(i,j) - 1)].push_back (fn.row (i));
+        }
+
+      // Third step: Calculate the normal for the vertices taking the average
+      // of the normals determined from all adjacent faces
+      Matrix vn (num_v, 3, 0.0);
+      for (octave_idx_type i = 0; i < num_v; i++)
+        {
+          std::vector<RowVector>::iterator it = vec_vn[i].begin ();
+
+          // The normal of unused vertices is NaN.
+          RowVector vn0 (3, octave_NaN);
+
+          if (it != vec_vn[i].end ())
+            {
+              // FIXME: Currently, the first vector also determines the
+              // direction of the normal.  How to determine the inner and outer
+              // faces of all parts of the patch and point the normals outwards?
+              // (Necessary for correct lighting with "backfacelighting" set to
+              // "lit" or "unlit".) Matlab does not seem to do it correctly
+              // either.  So bother here?
+
+              vn0 = *it;
+
+              for (++it; it != vec_vn[i].end (); ++it)
+                {
+                  RowVector vn1 = *it;
+                  // Use sign of dot product to point vectors in a similar
+                  // direction before taking the average.
+                  double dir =
+                    (vn0(0)*vn1(0) + vn0(1)*vn1(1) + vn0(2)*vn1(2) < 0) ? -1
+                                                                        : 1;
+                  for (octave_idx_type j = 0; j < 3; j++)
+                    vn0(j) += dir * vn1(j);
+                }
+
+              // normalize normal vector
+              double n_len = sqrt (vn0(0)*vn0(0)+vn0(1)*vn0(1)+vn0(2)*vn0(2));
+
+              // save normal in matrix
+              for (octave_idx_type j = 0; j < 3; j++)
+                vn(i,j) = vn0(j)/n_len;
+            }
+        }
+
+      vertexnormals = vn;
+    }
+  else if (reset)
+    vertexnormals = Matrix ();
+}
+
+void
+patch::initialize (const graphics_object& go)
+{
+  base_graphics_object::initialize (go);
+
+  // calculate normals for default data
+  // This is done because the normals for the default data do not match
+  // get(0, "DefaultPatchVertexNormals") in Matlab.
+  xproperties.update_normals (true);
+}
+
+
+void
+patch::reset_default_properties (void)
+{
+  // empty list of local defaults
+  default_properties = property_list ();
+  xreset_default_properties (get_handle (), xproperties.factory_defaults ());
+
+  // calculate normals for default data
+  // This is done because the normals for the default data do not match
+  // get(0, "DefaultPatchVertexNormals") in Matlab.
+  xproperties.update_normals (true);
+}
+
+// ---------------------------------------------------------------------
+
+octave_value
+surface::properties::get_color_data (void) const
+{
+  return convert_cdata (*this, get_cdata (), cdatamapping_is ("scaled"), 3);
+}
+
+bool
+surface::properties::get_do_lighting (void) const
+{
+  graphics_object go = gh_manager::get_object (get___myhandle__ ());
+  axes::properties& ax_prop = dynamic_cast<axes::properties&>
+    (go.get_ancestor ("axes").get_properties ());
+
+  return (ax_prop.get_num_lights () > 0);
+}
+
+void
 surface::properties::update_vertex_normals (void)
 {
   if (vertexnormalsmode_is ("auto"))
@@ -9169,6 +9598,36 @@
 // ---------------------------------------------------------------------
 
 void
+hggroup::properties::remove_child (const graphics_handle& h)
+{
+  graphics_object go = gh_manager::get_object (h);
+  if (go.isa ("light") && go.get_properties ().is_visible ())
+    {
+      axes::properties& ax_props =
+        dynamic_cast<axes::properties&>
+        (go.get_ancestor ("axes").get_properties ());
+      ax_props.decrease_num_lights ();
+    }
+  base_properties::remove_child (h);
+  update_limits ();
+}
+
+void
+hggroup::properties::adopt (const graphics_handle& h)
+{
+  graphics_object go = gh_manager::get_object (h);
+  if (go.isa ("light") && go.get_properties ().is_visible ())
+    {
+      axes::properties& ax_props =
+        dynamic_cast<axes::properties&>
+        (go.get_ancestor ("axes").get_properties ());
+      ax_props.increase_num_lights ();
+    }
+  base_properties::adopt (h);
+  update_limits (h);
+}
+
+void
 hggroup::properties::update_limits (void) const
 {
   graphics_object go = gh_manager::get_object (__myhandle__);
@@ -9463,14 +9922,14 @@
 void
 uicontrol::properties::update_text_extent (void)
 {
-  text_element *elt;
+  octave::text_element *elt;
   octave::text_renderer txt_renderer;
   Matrix box;
 
   // FIXME: parsed content should be cached for efficiency
   // FIXME: support multiline text
 
-  elt = text_parser::parse (get_string_string (), "none");
+  elt = octave::text_parser::parse (get_string_string (), "none");
 
   gh_manager::auto_lock guard;
   txt_renderer.set_font (get_fontname (), get_fontweight (),
@@ -12356,7 +12815,7 @@
             break;
         }
 
-      octave_sleep (0.1); // FIXME: really needed?
+      octave::sleep (0.1); // FIXME: really needed?
 
       octave_quit ();
 
--- a/libinterp/corefcn/graphics.in.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/graphics.in.h	Fri Aug 10 09:09:51 2018 +0200
@@ -2287,6 +2287,10 @@
     return children.get_hidden ();
   }
 
+  void get_children_of_type (const caseless_str& type, bool get_invisible,
+                             bool traverse,
+                             std::list<graphics_object> &children_list) const;
+
   void set_modified (const octave_value& val) { set___modified__ (val); }
 
   void set___modified__ (const octave_value& val) { __modified__ = val; }
@@ -2857,6 +2861,8 @@
                                  listener_mode mode = POSTSET)
   { rep->delete_property_listener (nm, v, mode); }
 
+  void remove_all_listeners (void) { rep->remove_all_listeners (); }
+
   void initialize (void) { rep->initialize (*this); }
 
   void finalize (void) { rep->finalize (*this); }
@@ -3124,8 +3130,7 @@
       callback_property keyreleasefcn , Matrix ()
       radio_property menubar , "{figure}|none"
       string_property name , ""
-      // FIXME: Need RO property which returns current figure number.
-      // double_property number r ,
+      array_property number rG , Matrix ()
       radio_property nextplot , "{add}|new|replace|replacechildren"
       bool_property numbertitle , "on"
       array_property outerposition s , Matrix (1, 4, -1.0)
@@ -3401,6 +3406,8 @@
 
     void remove_child (const graphics_handle& h);
 
+    void adopt (const graphics_handle& h);
+
     const scaler& get_x_scaler (void) const { return sx; }
     const scaler& get_y_scaler (void) const { return sy; }
     const scaler& get_z_scaler (void) const { return sz; }
@@ -3524,6 +3531,10 @@
 
     void update_fontunits (const caseless_str& old_fontunits);
 
+    void increase_num_lights (void) { num_lights++; }
+    void decrease_num_lights (void) { num_lights--; }
+    unsigned int get_num_lights (void) const { return num_lights; }
+
   private:
 
     scaler sx = scaler ();
@@ -3581,6 +3592,8 @@
     bool zSign = false;
     bool nearhoriz = false;
 
+    unsigned int num_lights = 0;
+
     // Text renderer, used for calculation of text (tick labels) size
     octave::text_renderer txt_renderer;
 
@@ -3661,8 +3674,7 @@
       // FIXME: uicontextmenu should be moved here.
       radio_property units SU , "{normalized}|inches|centimeters|points|pixels|characters"
       array_property view u , default_axes_view ()
-      // FIXME: DEPRECATED: Remove "zero" in version 5.
-      radio_property xaxislocation u , "{bottom}|top|origin|zero"
+      radio_property xaxislocation u , "{bottom}|top|origin"
       color_property xcolor mu , color_values (0.15, 0.15, 0.15)
       radio_property xcolormode , "{auto}|manual"
       radio_property xdir u , "{normal}|reverse"
@@ -3679,8 +3691,7 @@
       radio_property xticklabelmode u , "{auto}|manual"
       double_property xticklabelrotation , 0.0
       radio_property xtickmode u , "{auto}|manual"
-      // FIXME: DEPRECATED: Remove "zero" in version 5.
-      radio_property yaxislocation u , "{left}|right|origin|zero"
+      radio_property yaxislocation u , "{left}|right|origin"
       color_property ycolor mu , color_values (0.15, 0.15, 0.15)
       radio_property ycolormode , "{auto}|manual"
       radio_property ydir u , "{normal}|reverse"
@@ -3822,11 +3833,6 @@
     }
     void update_yaxislocation (void)
     {
-      // FIXME: DEPRECATED: Remove warning with "zero" in version 5.
-      if (yaxislocation_is ("zero"))
-        warning_with_id ("Octave:deprecated-property",
-                         "Setting 'yaxislocation' to 'zero' is deprecated, "
-                         "set to 'origin' instead.");
       sync_positions ();
       update_axes_layout ();
       if (xticklabelmode.is ("auto"))
@@ -3847,11 +3853,6 @@
     }
     void update_xaxislocation (void)
     {
-      // FIXME: DEPRECATED: Remove warning with "zero" in version 5.
-      if (xaxislocation_is ("zero"))
-        warning_with_id ("Octave:deprecated-property",
-                         "Setting 'xaxislocation' to 'zero' is deprecated, "
-                         "set to 'origin' instead.");
       sync_positions ();
       update_axes_layout ();
       if (xticklabelmode.is ("auto"))
@@ -4188,6 +4189,8 @@
       update_axes_layout ();
     }
 
+    void trigger_normals_calc (void);
+
   };
 
 private:
@@ -4785,6 +4788,7 @@
       color_property color , color_values (1, 1, 1)
       array_property position , default_light_position ()
       radio_property style , "{infinite}|local"
+      bool_property visible U , "on"
     END_PROPERTIES
 
   protected:
@@ -4817,6 +4821,9 @@
       retval = base_properties::has_readonly_property (pname);
     return retval;
   }
+
+protected:
+  void initialize (const graphics_object& go);
 };
 
 // ---------------------------------------------------------------------
@@ -4847,6 +4854,10 @@
     std::string get_climinclude (void) const
     { return climinclude.current_value (); }
 
+    bool get_do_lighting (void) const;
+
+    std::list<std::list<octave_idx_type>> coplanar_last_idx;
+
     // See the genprops.awk script for an explanation of the
     // properties declarations.
     // Programming note: Keep property list sorted if new ones are added.
@@ -4861,13 +4872,13 @@
       string_property displayname , ""
       double_radio_property edgealpha , double_radio_property (1.0, radio_values ("flat|interp"))
       color_property edgecolor , color_property (color_values (0, 0, 0), radio_values ("none|flat|interp"))
-      radio_property edgelighting , "{none}|flat|gouraud|phong"
+      radio_property edgelighting u , "{none}|flat|gouraud|phong"
       radio_property erasemode h , "{normal}|none|xor|background"
       double_radio_property facealpha , double_radio_property (1.0, radio_values ("flat|interp"))
       color_property facecolor , color_property (color_values (0, 0, 0), radio_values ("none|flat|interp"))
-      radio_property facelighting , "none|{flat}|gouraud|phong"
+      radio_property facelighting u , "none|{flat}|gouraud|phong"
       array_property facenormals m , Matrix ()
-      radio_property facenormalsmode , "{auto}|manual"
+      radio_property facenormalsmode u , "{auto}|manual"
       array_property faces u , default_patch_faces ()
       array_property facevertexalphadata , Matrix ()
       array_property facevertexcdata u , Matrix ()
@@ -4879,12 +4890,11 @@
       color_property markeredgecolor , color_property (radio_values ("none|{auto}|flat"), color_values (0, 0, 0))
       color_property markerfacecolor , color_property (radio_values ("{none}|auto|flat"), color_values (0, 0, 0))
       double_property markersize , 6
-      radio_property normalmode hsg , "{auto}|manual"
       double_property specularcolorreflectance , 1.0
       double_property specularexponent , 10.0
       double_property specularstrength , 0.9
       array_property vertexnormals m , Matrix ()
-      radio_property vertexnormalsmode , "{auto}|manual"
+      radio_property vertexnormalsmode u , "{auto}|manual"
       array_property vertices u , default_patch_vertices ()
       array_property xdata u , default_patch_xdata ()
       array_property ydata u , default_patch_ydata ()
@@ -4935,12 +4945,20 @@
       specularstrength.add_constraint ("max", 1.0, true);
     }
 
+  public:
+    void update_normals (bool reset)
+    {
+      update_face_normals (reset);
+      update_vertex_normals (reset);
+    }
+
+
   private:
     std::string bad_data_msg;
 
     void update_faces (void) { update_data ();}
 
-    void update_vertices (void)  { update_data ();}
+    void update_vertices (void) { update_data ();}
 
     void update_facevertexcdata (void) { update_data ();}
 
@@ -4959,7 +4977,10 @@
           set_faces (Matrix ());
         }
       else
-        update_fvc ();
+        {
+          update_fvc ();
+          update_normals (true);
+        }
 
       set_xlim (xdata.get_limits ());
     }
@@ -4974,7 +4995,10 @@
           set_faces (Matrix ());
         }
       else
-        update_fvc ();
+        {
+          update_fvc ();
+          update_normals (true);
+        }
 
       set_ylim (ydata.get_limits ());
     }
@@ -4982,12 +5006,14 @@
     void update_zdata (void)
     {
       update_fvc ();
+      update_normals (true);
       set_zlim (zdata.get_limits ());
     }
 
     void update_cdata (void)
     {
       update_fvc ();
+      update_normals (false);
 
       if (cdatamapping_is ("scaled"))
         set_clim (cdata.get_limits ());
@@ -4997,25 +5023,34 @@
 
     void update_data (void);
 
-    void set_normalmode (const octave_value& val)
+    void calc_face_normals (Matrix& normals);
+    void update_face_normals (bool reset);
+    void update_vertex_normals (bool reset);
+
+    void update_edgelighting (void)
     {
-      warning_with_id ("Octave:deprecated-property",
-        "patch: Property 'normalmode' is deprecated and will be removed "
-        "from a future version of Octave.  Use 'vertexnormalsmode' instead.");
-      set_vertexnormalsmode (val);
+      update_face_normals (false);
     }
 
-    std::string get_normalmode (void) const
+    void update_facelighting (void)
+    {
+      update_normals (false);
+    }
+
+    void update_facenormalsmode (void)
     {
-      warning_with_id ("Octave:deprecated-property",
-        "patch: Property 'normalmode' is deprecated and will be removed "
-        "from a future version of Octave.  Use 'vertexnormalsmode' instead.");
-      return vertexnormalsmode.current_value ();
+      update_face_normals (false);
+    }
+
+    void update_vertexnormalsmode (void)
+    {
+      update_vertex_normals (false);
     }
   };
 
 private:
   properties xproperties;
+  property_list default_properties;
 
 public:
   patch (const graphics_handle& mh, const graphics_handle& p)
@@ -5037,6 +5072,12 @@
       retval = base_properties::has_readonly_property (pname);
     return retval;
   }
+
+  void reset_default_properties (void);
+
+protected:
+  void initialize (const graphics_object& go);
+
 };
 
 // ---------------------------------------------------------------------
@@ -5059,6 +5100,8 @@
     std::string get_climinclude (void) const
     { return climinclude.current_value (); }
 
+    bool get_do_lighting (void) const;
+
     // See the genprops.awk script for an explanation of the
     // properties declarations.
     // Programming note: Keep property list sorted if new ones are added.
@@ -5091,7 +5134,6 @@
       color_property markerfacecolor , color_property (radio_values ("{none}|auto|flat"), color_values (0, 0, 0))
       double_property markersize , 6
       radio_property meshstyle , "{both}|row|column"
-      radio_property normalmode hsg , "{auto}|manual"
       double_property specularcolorreflectance , 1
       double_property specularexponent , 10
       double_property specularstrength , 0.9
@@ -5187,22 +5229,6 @@
 
     void update_vertexnormalsmode (void)
     { update_vertex_normals (); }
-
-    void set_normalmode (const octave_value& val)
-    {
-      warning_with_id ("Octave:deprecated-property",
-        "surface: Property 'normalmode' is deprecated and will be removed "
-        "from a future version of Octave.  Use 'vertexnormalsmode' instead.");
-      set_vertexnormalsmode (val);
-    }
-
-    std::string get_normalmode (void) const
-    {
-      warning_with_id ("Octave:deprecated-property",
-        "surface: Property 'normalmode' is deprecated and will be removed "
-        "from a future version of Octave.  Use 'vertexnormalsmode' instead.");
-      return vertexnormalsmode.current_value ();
-    }
   };
 
 private:
@@ -5238,18 +5264,9 @@
   class OCTINTERP_API properties : public base_properties
   {
   public:
-    void remove_child (const graphics_handle& h)
-    {
-      base_properties::remove_child (h);
-      update_limits ();
-    }
-
-    void adopt (const graphics_handle& h)
-    {
-
-      base_properties::adopt (h);
-      update_limits (h);
-    }
+    void remove_child (const graphics_handle& h);
+
+    void adopt (const graphics_handle& h);
 
     // See the genprops.awk script for an explanation of the
     // properties declarations.
@@ -5470,7 +5487,7 @@
     // Programming note: Keep property list sorted if new ones are added.
 
     BEGIN_PROPERTIES (uicontrol)
-      color_property backgroundcolor , color_values (1, 1, 1)
+      color_property backgroundcolor , color_values (0.94, 0.94, 0.94)
       callback_property callback , Matrix ()
       array_property cdata , Matrix ()
       bool_property clipping , "on"
@@ -5582,7 +5599,7 @@
     // Programming note: Keep property list sorted if new ones are added.
 
     BEGIN_PROPERTIES (uibuttongroup)
-      color_property backgroundcolor , color_values (1, 1, 1)
+      color_property backgroundcolor , color_values (0.94, 0.94, 0.94)
       radio_property bordertype , "none|{etchedin}|etchedout|beveledin|beveledout|line"
       double_property borderwidth , 1
       bool_property clipping , "on"
@@ -5597,7 +5614,7 @@
       callback_property resizefcn , Matrix ()
       handle_property selectedobject S , graphics_handle ()
       callback_property selectionchangedfcn , Matrix ()
-      color_property shadowcolor , color_values (0, 0, 0)
+      color_property shadowcolor , color_values (0.7, 0.7, 0.7)
       callback_property sizechangedfcn , Matrix ()
       radio_property units S , "{normalized}|inches|centimeters|points|pixels|characters"
       string_property title , ""
@@ -5679,7 +5696,7 @@
     // Programming note: Keep property list sorted if new ones are added.
 
     BEGIN_PROPERTIES (uipanel)
-      color_property backgroundcolor , color_values (1, 1, 1)
+      color_property backgroundcolor , color_values (0.94, 0.94, 0.94)
       radio_property bordertype , "none|{etchedin}|etchedout|beveledin|beveledout|line"
       double_property borderwidth , 1
       radio_property fontangle , "{normal}|italic|oblique"
@@ -5691,7 +5708,7 @@
       color_property highlightcolor , color_values (1, 1, 1)
       array_property position , default_panel_position ()
       callback_property resizefcn , Matrix ()
-      color_property shadowcolor , color_values (0, 0, 0)
+      color_property shadowcolor , color_values (0.7, 0.7, 0.7)
       string_property title , ""
       radio_property titleposition , "{lefttop}|centertop|righttop|leftbottom|centerbottom|rightbottom"
       radio_property units S , "{normalized}|inches|centimeters|points|pixels|characters"
--- a/libinterp/corefcn/gripes.cc	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,467 +0,0 @@
-/*
-
-Copyright (C) 1993-2018 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
-<https://www.gnu.org/licenses/>.
-
-*/
-
-// FIXME: All gripe_XXX functions deprecated in 4.2.  Remove file in
-// version 5.
-
-#if defined (HAVE_CONFIG_H)
-#  include "config.h"
-#endif
-
-#include "defun.h"
-#include "error.h"
-#include "gripes.h"
-#include "ovl.h"
-#include "utils.h"
-
-////////////////////////////////////////////////////////////////////////////////
-// Alphabetized list of gripes.
-////////////////////////////////////////////////////////////////////////////////
-
-void
-gripe_2_or_3_dim_plot (void)
-{
-  error ("plot: can only plot in 2 or 3 dimensions");
-}
-
-void
-gripe_data_conversion (const char *from, const char *to)
-{
-  error ("unable to convert from %s to %s format", from, to);
-}
-
-void
-gripe_data_file_in_path (const std::string& fcn, const std::string& file)
-{
-  warning_with_id ("Octave:data-file-in-path",
-                   "%s: '%s' found by searching load path",
-                   fcn.c_str (), file.c_str ());
-}
-
-void
-gripe_disabled_feature (const std::string& fcn, const std::string& feature,
-                        const std::string& pkg /*="Octave"*/)
-{
-  error ("%s: support for %s was unavailable or disabled when %s was built",
-         fcn.c_str (), feature.c_str (), pkg.c_str ());
-}
-
-void
-gripe_divide_by_zero (void)
-{
-  warning_with_id ("Octave:divide-by-zero", "division by zero");
-}
-
-void
-gripe_empty_arg (const char *name, bool is_error)
-{
-  if (is_error)
-    error ("%s: empty matrix is invalid as an argument", name);
-  else
-    warning ("%s: argument is empty matrix", name);
-}
-
-void
-gripe_implicit_conversion (const char *id, const char *from, const char *to)
-{
-  warning_with_id (id, "implicit conversion from %s to %s", from, to);
-}
-
-void
-gripe_implicit_conversion (const std::string& id,
-                           const std::string& from, const std::string& to)
-{
-  warning_with_id (id.c_str (),
-                   "implicit conversion from %s to %s",
-                   from.c_str (), to.c_str ());
-}
-
-void
-gripe_indexed_cs_list (void)
-{
-  error ("a cs-list cannot be further indexed");
-}
-
-void
-gripe_invalid_conversion (const std::string& from, const std::string& to)
-{
-  error ("invalid conversion from %s to %s", from.c_str (), to.c_str ());
-}
-
-void
-gripe_invalid_inquiry_subscript (void)
-{
-  error ("invalid dimension inquiry of a non-existent value");
-}
-
-void
-gripe_invalid_value_specified (const char *name)
-{
-  warning ("invalid value specified for '%s'", name);
-}
-
-void
-gripe_logical_conversion (void)
-{
-  warning_with_id ("Octave:logical-conversion",
-                   "value not equal to 1 or 0 converted to logical 1");
-}
-
-void
-gripe_nonbraced_cs_list_assignment (void)
-{
-  error ("invalid assignment to cs-list outside multiple assignment");
-}
-
-void
-gripe_nonconformant (void)
-{
-  error ("nonconformant matrices");
-}
-
-void
-gripe_nonconformant (octave_idx_type r1, octave_idx_type c1,
-                     octave_idx_type r2, octave_idx_type c2)
-{
-  error ("nonconformant matrices (op1 is %dx%d, op2 is %dx%d)",
-         r1, c1, r2, c2);
-}
-
-void
-gripe_not_implemented (const char *fcn)
-{
-  error ("%s: not implemented", fcn);
-}
-
-void
-gripe_not_supported (const char *fcn)
-{
-  error ("%s: not supported on this system", fcn);
-}
-
-void
-gripe_range_invalid (void)
-{
-  error ("range constant used in invalid context");
-}
-
-void
-gripe_square_matrix_required (const char *name)
-{
-  error ("%s: argument must be a square matrix", name);
-}
-
-void
-gripe_string_invalid (void)
-{
-  error ("std::string constant used in invalid context");
-}
-
-void
-gripe_unrecognized_data_fmt (const char *warn_for)
-{
-  error ("%s: unrecognized data format requested", warn_for);
-}
-
-void
-gripe_unrecognized_float_fmt (void)
-{
-  error ("unrecognized floating point format requested");
-}
-
-void
-gripe_user_returned_invalid (const char *name)
-{
-  error ("%s: user-supplied function returned invalid value", name);
-}
-
-void
-gripe_user_supplied_eval (const char *name)
-{
-  octave::execution_exception e;
-
-#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
-#  pragma GCC diagnostic push
-#  pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-
-  gripe_user_supplied_eval (e, name);
-
-#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
-#  pragma GCC diagnostic pop
-#endif
-}
-
-void
-gripe_user_supplied_eval (octave::execution_exception& e,
-                          const char *name)
-{
-  error (e, "%s: evaluation of user-supplied function failed", name);
-}
-
-void
-gripe_warn_complex_cmp (void)
-{
-  warning_with_id ("Octave:language-extension",
-                   "comparing complex numbers is not supported in Matlab");
-}
-
-void
-gripe_wrong_type_arg (const char *name, const char *s, bool is_error)
-{
-  octave::execution_exception e;
-
-#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
-#  pragma GCC diagnostic push
-#  pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-
-  gripe_wrong_type_arg (e, name, s, is_error);
-
-#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
-#  pragma GCC diagnostic pop
-#endif
-}
-
-void
-gripe_wrong_type_arg (octave::execution_exception& e,
-                      const char *name, const char *s, bool is_error)
-{
-  if (is_error)
-    error (e, "%s: wrong type argument '%s'", name, s);
-  else
-    warning ("%s: wrong type argument '%s'", name, s);
-}
-
-void
-gripe_wrong_type_arg (const char *name, const std::string& s, bool is_error)
-{
-  octave::execution_exception e;
-
-#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
-#  pragma GCC diagnostic push
-#  pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-
-  gripe_wrong_type_arg (e, name, s.c_str (), is_error);
-
-#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
-#  pragma GCC diagnostic pop
-#endif
-}
-
-void
-gripe_wrong_type_arg (octave::execution_exception& e,
-                      const char *name, const std::string& s, bool is_error)
-{
-#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
-#  pragma GCC diagnostic push
-#  pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-
-  gripe_wrong_type_arg (e, name, s.c_str (), is_error);
-
-#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
-#  pragma GCC diagnostic pop
-#endif
-}
-
-void
-gripe_wrong_type_arg (const char *name, const octave_value& tc,
-                      bool is_error)
-{
-  octave::execution_exception e;
-
-#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
-#  pragma GCC diagnostic push
-#  pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-
-  gripe_wrong_type_arg (e, name, tc, is_error);
-
-#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
-#  pragma GCC diagnostic pop
-#endif
-}
-
-void
-gripe_wrong_type_arg (octave::execution_exception& e,
-                      const char *name, const octave_value& tc,
-                      bool is_error)
-{
-  std::string type = tc.type_name ();
-
-#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
-#  pragma GCC diagnostic push
-#  pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-
-  gripe_wrong_type_arg (e, name, type, is_error);
-
-#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
-#  pragma GCC diagnostic pop
-#endif
-}
-
-void
-gripe_wrong_type_arg (const std::string& name, const octave_value& tc,
-                      bool is_error)
-{
-  octave::execution_exception e;
-
-#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
-#  pragma GCC diagnostic push
-#  pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-
-  gripe_wrong_type_arg (e, name, tc, is_error);
-
-#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
-#  pragma GCC diagnostic pop
-#endif
-}
-
-void
-gripe_wrong_type_arg (octave::execution_exception& e,
-                      const std::string& name, const octave_value& tc,
-                      bool is_error)
-{
-#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
-#  pragma GCC diagnostic push
-#  pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-
-  gripe_wrong_type_arg (e, name.c_str (), tc, is_error);
-
-#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
-#  pragma GCC diagnostic pop
-#endif
-}
-
-void
-gripe_wrong_type_arg (const char *s, bool is_error)
-{
-  octave::execution_exception e;
-
-#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
-#  pragma GCC diagnostic push
-#  pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-
-  gripe_wrong_type_arg (e, s, is_error);
-
-#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
-#  pragma GCC diagnostic pop
-#endif
-}
-
-void
-gripe_wrong_type_arg (octave::execution_exception& e,
-                      const char *s, bool is_error)
-{
-  if (is_error)
-    error (e, "wrong type argument '%s'", s);
-  else
-    warning ("wrong type argument '%s'", s);
-}
-
-void
-gripe_wrong_type_arg (const std::string& s, bool is_error)
-{
-  octave::execution_exception e;
-
-#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
-#  pragma GCC diagnostic push
-#  pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-
-  gripe_wrong_type_arg (e, s, is_error);
-
-#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
-#  pragma GCC diagnostic pop
-#endif
-}
-
-void
-gripe_wrong_type_arg (octave::execution_exception& e,
-                      const std::string& s, bool is_error)
-{
-#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
-#  pragma GCC diagnostic push
-#  pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-
-  gripe_wrong_type_arg (e, s.c_str (), is_error);
-
-#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
-#  pragma GCC diagnostic pop
-#endif
-}
-
-void
-gripe_wrong_type_arg (const octave_value& tc, bool is_error)
-{
-  octave::execution_exception e;
-
-#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
-#  pragma GCC diagnostic push
-#  pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-
-  gripe_wrong_type_arg (e, tc, is_error);
-
-#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
-#  pragma GCC diagnostic pop
-#endif
-}
-
-void
-gripe_wrong_type_arg (octave::execution_exception& e,
-                      const octave_value& tc, bool is_error)
-{
-  std::string type = tc.type_name ();
-
-#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
-#  pragma GCC diagnostic push
-#  pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-
-  gripe_wrong_type_arg (e, type, is_error);
-
-#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
-#  pragma GCC diagnostic pop
-#endif
-}
-
-void
-gripe_wrong_type_arg_for_binary_op (const octave_value& op)
-{
-  std::string type = op.type_name ();
-  error ("invalid operand '%s' for binary operator", type.c_str ());
-}
-
-void
-gripe_wrong_type_arg_for_unary_op (const octave_value& op)
-{
-  std::string type = op.type_name ();
-  error ("invalid operand '%s' for unary operator", type.c_str ());
-}
--- a/libinterp/corefcn/gripes.h	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,237 +0,0 @@
-/*
-
-Copyright (C) 1993-2018 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
-<https://www.gnu.org/licenses/>.
-
-*/
-
-// FIXME: All gripe_XXX functions deprecated in 4.2.  Remove file in
-// version 5.
-
-#if ! defined (octave_gripes_h)
-#define octave_gripes_h 1
-
-#include "octave-config.h"
-
-#include <string>
-
-#include "lo-array-gripes.h"
-
-class octave_value;
-namespace octave
-{
-  class execution_exception;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Alphabetized list of gripes.
-////////////////////////////////////////////////////////////////////////////////
-
-OCTAVE_DEPRECATED (4.2, "use 'err_2_or_3_dim_plot' instead")
-OCTAVE_NORETURN OCTINTERP_API extern void
-gripe_2_or_3_dim_plot (void);
-
-OCTAVE_DEPRECATED (4.2, "use 'err_data_conversion' instead")
-OCTAVE_NORETURN OCTINTERP_API extern void
-gripe_data_conversion (const char *from, const char *to);
-
-OCTAVE_DEPRECATED (4.2, "use 'warn_data_file_in_path' instead")
-OCTINTERP_API extern void
-gripe_data_file_in_path (const std::string& fcn, const std::string& file);
-
-OCTAVE_DEPRECATED (4.2, "use 'err_disabled_feature' or 'warn_disabled_feature' instead")
-OCTAVE_NORETURN OCTINTERP_API extern void
-gripe_disabled_feature (const std::string& fcn,
-                        const std::string& feature,
-                        const std::string& pkg="Octave");
-
-OCTAVE_DEPRECATED (4.2, "use 'warn_divide_by_zero' instead")
-OCTINTERP_API extern void
-gripe_divide_by_zero (void);
-
-OCTAVE_DEPRECATED (4.2, "use 'warn_empty_arg' instead")
-OCTINTERP_API extern void
-gripe_empty_arg (const char *name, bool is_error);
-
-OCTAVE_DEPRECATED (4.2, "use 'warn_implicit_conversion' instead")
-OCTINTERP_API extern void
-gripe_implicit_conversion (const char *id, const char *from, const char *to);
-
-OCTAVE_DEPRECATED (4.2, "use 'warn_implicit_conversion' instead")
-OCTINTERP_API extern void
-gripe_implicit_conversion (const std::string& id, const std::string& from,
-                           const std::string& to);
-
-OCTAVE_DEPRECATED (4.2, "use 'err_indexed_cs_list' instead")
-OCTAVE_NORETURN OCTINTERP_API extern void
-gripe_indexed_cs_list (void);
-
-OCTAVE_DEPRECATED (4.2, "use 'err_invalid_conversion' instead")
-OCTAVE_NORETURN OCTINTERP_API extern void
-gripe_invalid_conversion (const std::string& from, const std::string& to);
-
-OCTAVE_DEPRECATED (4.2, "use 'err_invalid_inquiry_subscript' instead")
-OCTAVE_NORETURN OCTINTERP_API extern void
-gripe_invalid_inquiry_subscript (void);
-
-OCTAVE_DEPRECATED (4.2, "use 'warn_invalid_value_specified' instead")
-OCTINTERP_API extern void
-gripe_invalid_value_specified (const char *name);
-
-OCTAVE_DEPRECATED (4.2, "use 'warn_logical_conversion' instead")
-OCTINTERP_API extern void
-gripe_logical_conversion (void);
-
-OCTAVE_DEPRECATED (4.2, "use 'err_nonbraced_cs_list_assignment' instead")
-OCTAVE_NORETURN OCTINTERP_API extern void
-gripe_nonbraced_cs_list_assignment (void);
-
-OCTAVE_DEPRECATED (4.2, "use 'err_nonconformant' instead")
-OCTAVE_NORETURN OCTINTERP_API extern void
-gripe_nonconformant (void);
-
-OCTAVE_DEPRECATED (4.2, "use 'err_nonconformant' instead")
-OCTAVE_NORETURN OCTINTERP_API extern void
-gripe_nonconformant (octave_idx_type r1, octave_idx_type c1,
-                     octave_idx_type r2, octave_idx_type c2);
-
-OCTAVE_DEPRECATED (4.2, "use 'err_not_implemented' instead")
-OCTAVE_NORETURN OCTINTERP_API extern void
-gripe_not_implemented (const char *);
-
-// FIXME: DEPRECATED: Deprecated in 4.2, remove in 5.0
-OCTAVE_DEPRECATED (4.2, "use 'err_disabled_feature' or 'warn_disabled_feature' instead")
-OCTAVE_NORETURN OCTINTERP_API extern void
-gripe_not_supported (const char *);
-
-OCTAVE_DEPRECATED (4.2, "use 'err_range_invalid' instead")
-OCTAVE_NORETURN OCTINTERP_API extern void
-gripe_range_invalid (void);
-
-OCTAVE_DEPRECATED (4.2, "use 'err_square_matrix_required' instead")
-OCTAVE_NORETURN OCTINTERP_API extern void
-gripe_square_matrix_required (const char *name);
-
-OCTAVE_DEPRECATED (4.2, "use 'err_string_invalid' instead")
-OCTAVE_NORETURN OCTINTERP_API extern void
-gripe_string_invalid (void);
-
-OCTAVE_DEPRECATED (4.2, "use 'err_unrecognized_data_fmt' instead")
-OCTAVE_NORETURN OCTINTERP_API extern void
-gripe_unrecognized_data_fmt (const char *warn_for);
-
-OCTAVE_DEPRECATED (4.2, "use 'err_unrecognized_float_fmt' instead")
-OCTAVE_NORETURN OCTINTERP_API extern void
-gripe_unrecognized_float_fmt (void);
-
-OCTAVE_DEPRECATED (4.2, "use 'err_user_returned_invalid' instead")
-OCTAVE_NORETURN OCTINTERP_API extern void
-gripe_user_returned_invalid (const char *name);
-
-OCTAVE_DEPRECATED (4.2, "use 'err_user_supplied_eval' instead")
-OCTAVE_NORETURN OCTINTERP_API extern void
-gripe_user_supplied_eval (const char *name);
-
-OCTAVE_DEPRECATED (4.2, "use 'err_user_supplied_eval' instead")
-OCTAVE_NORETURN OCTINTERP_API extern void
-gripe_user_supplied_eval (octave::execution_exception& e, const char *name);
-
-OCTAVE_DEPRECATED (4.2, "use 'warn_complex_cmp' instead")
-OCTINTERP_API extern void
-gripe_warn_complex_cmp (void);
-
-OCTAVE_DEPRECATED (4.2, "use 'err_wrong_type_arg' instead")
-OCTINTERP_API extern void
-gripe_wrong_type_arg (const char *name, const char *s,
-                      bool is_error = true);
-
-OCTAVE_DEPRECATED (4.2, "use 'err_wrong_type_arg' instead")
-OCTINTERP_API extern void
-gripe_wrong_type_arg (octave::execution_exception& e,
-                      const char *name, const char *s,
-                      bool is_error = true);
-
-OCTAVE_DEPRECATED (4.2, "use 'err_wrong_type_arg' instead")
-OCTINTERP_API extern void
-gripe_wrong_type_arg (const char *name, const std::string& s,
-                      bool is_error = true);
-
-OCTAVE_DEPRECATED (4.2, "use 'err_wrong_type_arg' instead")
-OCTINTERP_API extern void
-gripe_wrong_type_arg (octave::execution_exception& e,
-                      const char *name, const std::string& s,
-                      bool is_error = true);
-
-OCTAVE_DEPRECATED (4.2, "use 'err_wrong_type_arg' or 'warn_wrong_type_arg' instead")
-OCTINTERP_API extern void
-gripe_wrong_type_arg (const char *name, const octave_value& tc,
-                      bool is_error = true);
-
-OCTAVE_DEPRECATED (4.2, "use 'err_wrong_type_arg' instead")
-OCTINTERP_API extern void
-gripe_wrong_type_arg (octave::execution_exception& e,
-                      const char *name, const octave_value& tc,
-                      bool is_error = true);
-
-OCTAVE_DEPRECATED (4.2, "use 'err_wrong_type_arg' instead")
-OCTINTERP_API extern void
-gripe_wrong_type_arg (const std::string& name, const octave_value& tc,
-                      bool is_error = true);
-
-OCTAVE_DEPRECATED (4.2, "use 'err_wrong_type_arg' instead")
-OCTINTERP_API extern void
-gripe_wrong_type_arg (octave::execution_exception& e,
-                      const std::string& name, const octave_value& tc,
-                      bool is_error = true);
-
-OCTAVE_DEPRECATED (4.2, "use 'err_wrong_type_arg' instead")
-OCTINTERP_API extern void
-gripe_wrong_type_arg (const char *s, bool is_error = true);
-
-OCTAVE_DEPRECATED (4.2, "use 'err_wrong_type_arg' instead")
-OCTINTERP_API extern void
-gripe_wrong_type_arg (octave::execution_exception& e, const char *s,
-                      bool is_error = true);
-
-OCTAVE_DEPRECATED (4.2, "use 'err_wrong_type_arg' instead")
-OCTINTERP_API extern void
-gripe_wrong_type_arg (const std::string& s, bool is_error = true);
-
-OCTAVE_DEPRECATED (4.2, "use 'err_wrong_type_arg' instead")
-OCTINTERP_API extern void
-gripe_wrong_type_arg (octave::execution_exception& e, const std::string& s,
-                      bool is_error = true);
-
-OCTAVE_DEPRECATED (4.2, "use 'err_wrong_type_arg' instead")
-OCTINTERP_API extern void
-gripe_wrong_type_arg (const octave_value& tc, bool is_error = true);
-
-OCTAVE_DEPRECATED (4.2, "use 'err_wrong_type_arg' instead")
-OCTINTERP_API extern void
-gripe_wrong_type_arg (octave::execution_exception& e, const octave_value& tc,
-                      bool is_error = true);
-
-OCTAVE_DEPRECATED (4.2, "use 'err_wrong_type_arg_for_binary_op' instead")
-OCTAVE_NORETURN OCTINTERP_API extern void
-gripe_wrong_type_arg_for_binary_op (const octave_value& op);
-
-OCTAVE_DEPRECATED (4.2, "use 'err_wrong_type_arg_for_unary_op' instead")
-OCTAVE_NORETURN OCTINTERP_API extern void
-gripe_wrong_type_arg_for_unary_op (const octave_value& op);
-
-#endif
--- a/libinterp/corefcn/gsvd.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/gsvd.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -180,29 +180,29 @@
         {
           if (argA.is_single_type () || argB.is_single_type ())
             {
-              retval(0) = float_identity_matrix (nc, nc);
-              retval(1) = float_identity_matrix (nc, nc);
+              retval(0) = octave::float_identity_matrix (nc, nc);
+              retval(1) = octave::float_identity_matrix (nc, nc);
               if (nargout > 2)
-                retval(2) = float_identity_matrix (nr, nr);
+                retval(2) = octave::float_identity_matrix (nr, nr);
               if (nargout > 3)
                 retval(3) = FloatMatrix (nr, nc);
               if (nargout > 4)
-                retval(4) = float_identity_matrix (nr, nr);
+                retval(4) = octave::float_identity_matrix (nr, nr);
               if (nargout > 5)
-                retval(5) = float_identity_matrix (nr, nr);
+                retval(5) = octave::float_identity_matrix (nr, nr);
             }
           else
             {
-              retval(0) = identity_matrix (nc, nc);
-              retval(1) = identity_matrix (nc, nc);
+              retval(0) = octave::identity_matrix (nc, nc);
+              retval(1) = octave::identity_matrix (nc, nc);
               if (nargout > 2)
-                retval(2) = identity_matrix (nr, nr);
+                retval(2) = octave::identity_matrix (nr, nr);
               if (nargout > 3)
                 retval(3) = Matrix (nr, nc);
               if (nargout > 4)
-                retval(4) = identity_matrix (nr, nr);
+                retval(4) = octave::identity_matrix (nr, nr);
               if (nargout > 5)
-                retval(5) = identity_matrix (nr, nr);
+                retval(5) = octave::identity_matrix (nr, nr);
             }
         }
     }
--- a/libinterp/corefcn/gtk-manager.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/gtk-manager.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -52,7 +52,7 @@
 
         octave_value_list args;
         args(0) = dtk;
-        octave::feval ("graphics_toolkit", args);
+        feval ("graphics_toolkit", args);
 
         pl = loaded_toolkits.find (dtk);
 
@@ -89,18 +89,18 @@
           dtk.clear ();
         else
           {
-            const_available_toolkits_iterator pa = available_toolkits.begin ();
+            auto pa = available_toolkits.cbegin ();
 
             dtk = *pa++;
 
-            while (pa != available_toolkits.end ())
+            while (pa != available_toolkits.cend ())
               {
                 std::string tk_name = *pa++;
 
                 if (tk_name == "qt"
                     || (tk_name == "fltk"
                         && (available_toolkits.find ("qt")
-                            == available_toolkits.end ())))
+                            == available_toolkits.cend ())))
                   dtk = tk_name;
               }
           }
--- a/libinterp/corefcn/gtk-manager.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/gtk-manager.h	Fri Aug 10 09:09:51 2018 +0200
@@ -97,7 +97,7 @@
     {
       while (! loaded_toolkits.empty ())
         {
-          loaded_toolkits_iterator p = loaded_toolkits.begin ();
+          auto p = loaded_toolkits.begin ();
 
           std::string name = p->first;
 
--- a/libinterp/corefcn/help.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/help.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -29,7 +29,7 @@
 
 #include <algorithm>
 #include <fstream>
-#include <iostream>
+#include <istream>
 #include <map>
 #include <sstream>
 #include <string>
@@ -37,6 +37,7 @@
 #include "cmd-edit.h"
 #include "file-ops.h"
 #include "file-stat.h"
+#include "lo-sysdep.h"
 #include "oct-env.h"
 #include "oct-locbuf.h"
 #include "str-vec.h"
@@ -61,7 +62,6 @@
 #include "parse.h"
 #include "pathsearch.h"
 #include "procstream.h"
-#include "pt-pr-code.h"
 #include "quit.h"
 #include "sighandlers.h"
 #include "symtab.h"
@@ -554,7 +554,7 @@
   {
     bool retval = false;
 
-    h = octave::get_help_from_file (nm, symbol_found, file);
+    h = get_help_from_file (nm, symbol_found, file);
 
     if (h.length () > 0)
       retval = true;
@@ -582,7 +582,10 @@
 
     if (! initialized)
       {
-        std::ifstream file (m_built_in_docstrings_file.c_str (),
+        std::string ascii_fname
+          = octave::sys::get_ASCII_filename (m_built_in_docstrings_file);
+
+        std::ifstream file (ascii_fname.c_str (),
                             std::ios::in | std::ios::binary);
 
         if (! file)
@@ -665,7 +668,10 @@
         std::streampos beg = txt_limits.first;
         std::streamoff len = txt_limits.second;
 
-        std::ifstream file (m_built_in_docstrings_file.c_str (),
+        std::string ascii_fname
+          = octave::sys::get_ASCII_filename (m_built_in_docstrings_file);
+
+        std::ifstream file (ascii_fname.c_str (),
                             std::ios::in | std::ios::binary);
 
         if (! file)
@@ -693,8 +699,7 @@
 
   string_vector make_name_list (void)
   {
-    octave::help_system& help_sys
-      = octave::__get_help_system__ ("make_name_list");
+    help_system& help_sys = __get_help_system__ ("make_name_list");
 
     return help_sys.make_name_list ();
   }
--- a/libinterp/corefcn/hook-fcn.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/hook-fcn.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -25,6 +25,7 @@
 #endif
 
 #include "hook-fcn.h"
+#include "parse.h"
 
 hook_function::hook_function (const octave_value& f, const octave_value& d)
 {
@@ -41,3 +42,24 @@
   else
     error ("invalid hook function");
 }
+
+void named_hook_function::eval (const octave_value_list& initial_args)
+{
+  octave_value_list args = initial_args;
+
+  if (data.is_defined ())
+    args.append (data);
+
+  octave::feval (name, args, 0);
+}
+
+void fcn_handle_hook_function::eval (const octave_value_list& initial_args)
+{
+  octave_value_list args = initial_args;
+
+  if (data.is_defined ())
+    args.append (data);
+
+  octave::feval (fcn_handle, args, 0);
+}
+
--- a/libinterp/corefcn/hook-fcn.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/hook-fcn.h	Fri Aug 10 09:09:51 2018 +0200
@@ -30,7 +30,6 @@
 #include "ovl.h"
 #include "ov.h"
 #include "ov-fcn-handle.h"
-#include "parse.h"
 #include "variables.h"
 
 class
@@ -46,9 +45,9 @@
 
   virtual ~base_hook_function (void) = default;
 
-  virtual std::string id (void) { return ""; }
+  virtual std::string id (void) const { return ""; }
 
-  virtual bool is_valid (void) { return false; }
+  virtual bool is_valid (void) const { return false; }
 
   virtual void eval (const octave_value_list&) { }
 
@@ -98,9 +97,9 @@
     return *this;
   }
 
-  std::string id (void) { return rep->id (); }
+  std::string id (void) const { return rep->id (); }
 
-  bool is_valid (void) { return rep->is_valid (); }
+  bool is_valid (void) const { return rep->is_valid (); }
 
   void eval (const octave_value_list& initial_args)
   {
@@ -121,19 +120,11 @@
     : name (n), data (d)
   { }
 
-  void eval (const octave_value_list& initial_args)
-  {
-    octave_value_list args = initial_args;
-
-    if (data.is_defined ())
-      args.append (data);
+  void eval (const octave_value_list& initial_args);
 
-    octave::feval (name, args, 0);
-  }
+  std::string id (void) const { return name; }
 
-  std::string id (void) { return name; }
-
-  bool is_valid (void) { return is_valid_function (name); }
+  bool is_valid (void) const { return is_valid_function (name); }
 
 private:
 
@@ -162,19 +153,11 @@
       }
   }
 
-  void eval (const octave_value_list& initial_args)
-  {
-    octave_value_list args = initial_args;
-
-    if (data.is_defined ())
-      args.append (data);
+  void eval (const octave_value_list& initial_args);
 
-    octave::feval (fcn_handle, args, 0);
-  }
+  std::string id (void) const { return ident; }
 
-  std::string id (void) { return ident; }
-
-  bool is_valid (void) { return valid; }
+  bool is_valid (void) const { return valid; }
 
 private:
 
@@ -240,14 +223,14 @@
 
   void run (const octave_value_list& initial_args = octave_value_list ())
   {
-    iterator p = fcn_map.begin ();
+    auto p = fcn_map.begin ();
 
     while (p != fcn_map.end ())
       {
         std::string hook_fcn_id = p->first;
         hook_function hook_fcn = p->second;
 
-        iterator q = p++;
+        auto q = p++;
 
         if (hook_fcn.is_valid ())
           hook_fcn.eval (initial_args);
--- a/libinterp/corefcn/input.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/input.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -37,10 +37,12 @@
 
 #include "cmd-edit.h"
 #include "file-ops.h"
+#include "iconv-wrappers.h"
+#include "localcharset-wrapper.h"
 #include "quit.h"
 #include "str-vec.h"
+#include "uniconv-wrappers.h"
 
-#include "bp-table.h"
 #include "builtin-defun-decls.h"
 #include "call-stack.h"
 #include "defun.h"
@@ -74,18 +76,9 @@
 #include "utils.h"
 #include "variables.h"
 
-// Primary prompt string.
-static std::string VPS1;
-
-// Secondary prompt string.
-static std::string VPS2;
-
 // The time we last printed a prompt.
 octave::sys::time Vlast_prompt_time = 0.0;
 
-// Character to append after successful command-line completion attempts.
-static char Vcompletion_append_char = ' ';
-
 // TRUE after a call to completion_matches.
 bool octave_completion_matches_called = false;
 
@@ -101,275 +94,182 @@
 // the terminal.
 bool Vtrack_line_num = true;
 
-// If we are in debugging mode, this is the last command entered, so
-// that we can repeat the previous command if the user just types RET.
-static std::string last_debugging_command = "\n";
-
-// TRUE if we are running in the Emacs GUD mode.
-static bool Vgud_mode = false;
-
-static hook_function_list input_event_hook_functions;
-
-// For octave_quit.
-void
-remove_input_event_hook_functions (void)
+static std::string
+quoting_filename (const std::string& text, int, char quote)
 {
-  input_event_hook_functions.clear ();
+  if (quote)
+    return text;
+  else
+    return ("'" + text);
 }
 
-void
-set_default_prompts (void)
+// Try to parse a partial command line in reverse, excluding trailing TEXT.
+// If it appears a variable has been indexed by () or {},
+// return that expression,
+// to allow autocomplete of field names of arrays of structures.
+static std::string
+find_indexed_expression (const std::string& text)
 {
-  // Use literal "octave" instead of "\\s" to avoid setting the prompt
-  // to "octave.exe" or "octave-gui", etc.
+  std::string line = octave::command_editor::get_line_buffer ();
+
+  int pos = line.length () - text.length ();
+  int curly_count = 0;
+  int paren_count = 0;
+
+  int last = --pos;
+
+  while (pos >= 0 && (line[pos] == ')' || line[pos] == '}'))
+    {
+      if (line[pos] == ')')
+        paren_count++;
+      else if (line[pos] == '}')
+        curly_count++;
 
-  VPS1 = R"(octave:\#> )";
-  VPS2 = "> ";
-  std::string VPS4 = "+ ";
+      while (curly_count + paren_count > 0 && --pos >= 0)
+        {
+          if (line[pos] == ')')
+            paren_count++;
+          else if (line[pos] == '(')
+            paren_count--;
+          else if (line[pos] == '}')
+            curly_count++;
+          else if (line[pos] == '{')
+            curly_count--;
+        }
 
-  octave_link::set_default_prompts (VPS1, VPS2, VPS4);
+      while (--pos >= 0 && line[pos] == ' ')
+        ;
+    }
+
+  while (pos >= 0 && (isalnum (line[pos]) || line[pos] == '_'))
+    pos--;
+
+  if (++pos >= 0)
+    return (line.substr (pos, last + 1 - pos));
+  else
+    return std::string ();
 }
 
-static std::string
-gnu_readline (const std::string& s, bool& eof)
+static inline bool
+is_variable (octave::symbol_table& symtab, const std::string& name)
 {
-  octave_quit ();
+  bool retval = false;
 
-  eof = false;
+  if (! name.empty ())
+    {
+      octave::symbol_scope scope = symtab.current_scope ();
 
-  std::string retval = octave::command_editor::readline (s, eof);
+      octave_value val = scope ? scope.varval (name) : octave_value ();
 
-  if (! eof && retval.empty ())
-    retval = "\n";
+      retval = val.is_defined ();
+    }
 
   return retval;
 }
 
-static inline std::string
-interactive_input (const std::string& s, bool& eof)
+static string_vector
+generate_struct_completions (const std::string& text,
+                             std::string& prefix, std::string& hint)
 {
-  Vlast_prompt_time.stamp ();
+  string_vector names;
+
+  size_t pos = text.rfind ('.');
+  bool array = false;
 
-  if (Vdrawnow_requested && octave::application::interactive ())
+  if (pos != std::string::npos)
     {
-      bool eval_error = false;
+      if (pos == text.length ())
+        hint = "";
+      else
+        hint = text.substr (pos+1);
 
-      try
+      prefix = text.substr (0, pos);
+
+      if (prefix == "")
         {
-          Fdrawnow ();
-        }
-      catch (const octave::execution_exception& e)
-        {
-          eval_error = true;
-
-          std::string stack_trace = e.info ();
-
-          if (! stack_trace.empty ())
-            std::cerr << stack_trace;
-
-          if (octave::application::interactive ())
-            octave::interpreter::recover_from_exception ();
+          array = true;
+          prefix = find_indexed_expression (text);
         }
 
-      octave::flush_stdout ();
+      std::string base_name = prefix;
+
+      pos = base_name.find_first_of ("{(. ");
+
+      if (pos != std::string::npos)
+        base_name = base_name.substr (0, pos);
 
-      // We set Vdrawnow_requested to false even if there is an error in
-      // drawnow so that the error doesn't reappear at every prompt.
+      octave::symbol_table& symtab
+        = octave::__get_symbol_table__ ("generate_struct_completions");
+
+      if (is_variable (symtab, base_name))
+        {
+          int parse_status;
+
+          octave::unwind_protect frame;
+
+          frame.protect_var (discard_error_messages);
+          frame.protect_var (discard_warning_messages);
 
-      Vdrawnow_requested = false;
+          discard_error_messages = true;
+          discard_warning_messages = true;
+
+          try
+            {
+              octave_value tmp = octave::eval_string (prefix, true, parse_status);
+
+              frame.run ();
 
-      if (eval_error)
-        return "\n";
+              if (tmp.is_defined ()
+                  && (tmp.isstruct () || tmp.isjava () || tmp.is_classdef_object ()))
+                names = tmp.map_keys ();
+            }
+          catch (const octave::execution_exception&)
+            {
+              octave::interpreter::recover_from_exception ();
+            }
+        }
     }
 
-  return gnu_readline (s, eof);
+  // Undo look-back that found the array expression,
+  // but insert an extra "." to distinguish from the non-struct case.
+  if (array)
+    prefix = ".";
+
+  return names;
 }
 
-namespace octave
+// FIXME: this will have to be much smarter to work "correctly".
+static bool
+looks_like_struct (const std::string& text, char prev_char)
 {
-  std::string base_reader::octave_gets (bool& eof)
-  {
-    octave_quit ();
-
-    eof = false;
-
-    std::string retval;
-
-    // Process pre input event hook function prior to flushing output and
-    // printing the prompt.
-
-    if (application::interactive ())
-      {
-        if (! Vdebugging)
-          octave_link::exit_debugger_event ();
-
-        octave_link::pre_input_event ();
-
-        octave_link::set_workspace ();
-      }
-
-    bool history_skip_auto_repeated_debugging_command = false;
-
-    std::string ps = (m_pflag > 0) ? VPS1 : VPS2;
-
-    std::string prompt = command_editor::decode_prompt_string (ps);
-
-    pipe_handler_error_count = 0;
-
-    flush_stdout ();
-
-    pager_stream::reset ();
-    diary_stream::reset ();
-
-    octave_diary << prompt;
-
-    retval = interactive_input (prompt, eof);
+  bool retval = (! text.empty ()
+                 && (text != "." || prev_char == ')' || prev_char == '}')
+                 && text.find_first_of (octave::sys::file_ops::dir_sep_chars ()) == std::string::npos
+                 && text.find ("..") == std::string::npos
+                 && text.rfind ('.') != std::string::npos);
 
-    // There is no need to update the load_path cache if there is no
-    // user input.
-    if (retval != "\n"
-        && retval.find_first_not_of (" \t\n\r") != std::string::npos)
-      {
-        load_path& lp = __get_load_path__ ("base_reader::octave_gets");
-
-        lp.update ();
-
-        if (Vdebugging)
-          last_debugging_command = retval;
-        else
-          last_debugging_command = "\n";
-      }
-    else if (Vdebugging)
-      {
-        retval = last_debugging_command;
-        history_skip_auto_repeated_debugging_command = true;
-      }
-
-    if (retval != "\n")
-      {
-        if (! history_skip_auto_repeated_debugging_command)
-          {
-            if (command_history::add (retval))
-              octave_link::append_history (retval);
-          }
-
-        octave_diary << retval;
-
-        if (retval.back () != '\n')
-          octave_diary << "\n";
-      }
-    else
-      octave_diary << "\n";
-
-    // Process post input event hook function after the internal history
-    // list has been updated.
-
-    if (application::interactive ())
-      octave_link::post_input_event ();
-
-    return retval;
-  }
-
-  bool base_reader::reading_fcn_file (void) const
-  {
-    return m_lexer ? m_lexer->m_reading_fcn_file : false;
-  }
+#if 0
+  symbol_record *sr = curr_sym_tab->lookup (text);
 
-  bool base_reader::reading_classdef_file (void) const
-  {
-    return m_lexer ? m_lexer->m_reading_classdef_file : false;
-  }
-
-  bool base_reader::reading_script_file (void) const
-  {
-    return m_lexer ? m_lexer->m_reading_script_file : false;
-  }
-
-  class
-  terminal_reader : public base_reader
-  {
-  public:
-
-    terminal_reader (base_lexer *lxr = nullptr)
-      : base_reader (lxr)
-    { }
-
-    std::string get_input (bool& eof);
-
-    std::string input_source (void) const { return s_in_src; }
+  if (sr && ! sr->is_function ())
+    {
+      int parse_status;
 
-    bool input_from_terminal (void) const { return true; }
-
-  private:
-
-    static const std::string s_in_src;
-  };
-
-  class
-  file_reader : public base_reader
-  {
-  public:
+      octave::unwind_protect frame;
 
-    file_reader (FILE *f_arg, base_lexer *lxr = nullptr)
-      : base_reader (lxr), m_file (f_arg) { }
-
-    std::string get_input (bool& eof);
+      frame.protect_var (discard_error_messages);
 
-    std::string input_source (void) const { return s_in_src; }
-
-    bool input_from_file (void) const { return true; }
-
-  private:
-
-    FILE *m_file;
+      discard_error_messages = true;
 
-    static const std::string s_in_src;
-  };
-
-  class
-  eval_string_reader : public base_reader
-  {
-  public:
+      octave_value tmp = eval_string (text, true, parse_status);
 
-    eval_string_reader (const std::string& str, base_lexer *lxr = nullptr)
-      : base_reader (lxr), m_eval_string (str)
-    { }
-
-    std::string get_input (bool& eof);
-
-    std::string input_source (void) const { return s_in_src; }
-
-    bool input_from_eval_string (void) const { return true; }
-
-  private:
-
-    std::string m_eval_string;
+      frame.run ();
 
-    static const std::string s_in_src;
-  };
-
-  input_reader::input_reader (base_lexer *lxr)
-    : m_rep (new terminal_reader (lxr))
-  { }
-
-  input_reader::input_reader (FILE *file, base_lexer *lxr)
-    : m_rep (new file_reader (file, lxr))
-  { }
+      retval = (tmp.is_defined () && tmp.isstruct ());
+    }
+#endif
 
-  input_reader::input_reader (const std::string& str, base_lexer *lxr)
-    : m_rep (new eval_string_reader (str, lxr))
-  { }
-}
-
-// Fix things up so that input can come from the standard input.  This
-// may need to become much more complicated, which is why it's in a
-// separate function.
-
-FILE *
-get_input_from_stdin (void)
-{
-  octave::command_editor::set_input_stream (stdin);
-  return octave::command_editor::get_input_stream ();
+  return retval;
 }
 
 // FIXME: make this generate filenames when appropriate.
@@ -509,8 +409,13 @@
                   octave::command_editor::set_completion_append_character ('\0');
                 }
               else
-                octave::command_editor::set_completion_append_character
-                  (Vcompletion_append_char);
+                {
+                  octave::input_system& input_sys
+                    = octave::__get_input_system__ ("generate_completion");
+
+                  octave::command_editor::set_completion_append_character
+                    (input_sys.completion_append_char ());
+                }
 
               break;
             }
@@ -520,240 +425,667 @@
   return retval;
 }
 
-static std::string
-quoting_filename (const std::string& text, int, char quote)
+namespace octave
 {
-  if (quote)
-    return text;
-  else
-    return ("'" + text);
-}
-
-// Try to parse a partial command line in reverse, excluding trailing TEXT.
-// If it appears a variable has been indexed by () or {},
-// return that expression,
-// to allow autocomplete of field names of arrays of structures.
-std::string
-find_indexed_expression (const std::string& text)
-{
-  std::string line = octave::command_editor::get_line_buffer ();
+  // Use literal "octave" in default setting for PS1 instead of
+  // "\\s" to avoid setting the prompt to "octave.exe" or
+  // "octave-gui", etc.
 
-  int pos = line.length () - text.length ();
-  int curly_count = 0;
-  int paren_count = 0;
+  input_system::input_system (interpreter& interp)
+    : m_interpreter (interp), m_PS1 (R"(octave:\#> )"), m_PS2 ("> "),
+      m_completion_append_char (' '), m_gud_mode (false),
+      m_mfile_encoding ("utf-8"), m_last_debugging_command ("\n"),
+      m_input_event_hook_functions ()
+  {
+#if defined (OCTAVE_USE_WINDOWS_API)
+    m_mfile_encoding = "system";
+#endif
+  }
 
-  int last = --pos;
-
-  while (pos >= 0 && (line[pos] == ')' || line[pos] == '}'))
+    void input_system::initialize (bool line_editing)
     {
-      if (line[pos] == ')')
-        paren_count++;
-      else if (line[pos] == '}')
-        curly_count++;
-
-      while (curly_count + paren_count > 0 && --pos >= 0)
+// Force default line editor if we don't want readline editing.
+      if (! line_editing)
         {
-          if (line[pos] == ')')
-            paren_count++;
-          else if (line[pos] == '(')
-            paren_count--;
-          else if (line[pos] == '}')
-            curly_count++;
-          else if (line[pos] == '{')
-            curly_count--;
+          command_editor::force_default_editor ();
+          return;
         }
 
-      while (--pos >= 0 && line[pos] == ' ')
-        ;
-    }
+      // If we are using readline, this allows conditional parsing of the
+      // .inputrc file.
+
+      octave::command_editor::set_name ("Octave");
+
+      // FIXME: this needs to include a comma too, but that
+      // causes trouble for the new struct element completion code.
+
+      static const char *s = "\t\n !\"\'*+-/:;<=>(){}[\\]^`~";
+
+      octave::command_editor::set_basic_word_break_characters (s);
+
+      octave::command_editor::set_completer_word_break_characters (s);
 
-  while (pos >= 0 && (isalnum (line[pos]) || line[pos] == '_'))
-    pos--;
+      octave::command_editor::set_basic_quote_characters (R"(")");
+
+      octave::command_editor::set_filename_quote_characters (" \t\n\\\"'@<>=;|&()#$`?*[!:{");
+
+      octave::command_editor::set_completer_quote_characters (R"('")");
+
+      octave::command_editor::set_completion_function (generate_completion);
+
+      octave::command_editor::set_quoting_function (quoting_filename);
+  }
+
+  octave_value
+  input_system::PS1 (const octave_value_list& args, int nargout)
+  {
+    return set_internal_variable (m_PS1, args, nargout, "PS1");
+  }
 
-  if (++pos >= 0)
-    return (line.substr (pos, last + 1 - pos));
-  else
-    return std::string ();
-}
+  octave_value
+  input_system::PS2 (const octave_value_list& args, int nargout)
+  {
+    return set_internal_variable (m_PS2, args, nargout, "PS2");
+  }
+
+  octave_value
+  input_system::completion_append_char (const octave_value_list& args,
+                                        int nargout)
+  {
+    return set_internal_variable (m_completion_append_char, args, nargout,
+                                  "completion_append_char");
+  }
 
-void
-initialize_command_input (void)
-{
-  // If we are using readline, this allows conditional parsing of the
-  // .inputrc file.
+  octave_value
+  input_system::gud_mode (const octave_value_list& args, int nargout)
+  {
+    return set_internal_variable (m_gud_mode, args, nargout, "__gud_mode__");
+  }
 
-  octave::command_editor::set_name ("Octave");
+  octave_value
+  input_system::mfile_encoding (const octave_value_list& args, int nargout)
+  {
+    // Save current value in case there is an error in the additional
+    // validation below.
+
+    std::string saved_encoding = m_mfile_encoding;
+
+    // We must pass the actual variable to change here for temporary
+    // "local" settings to work properly.
+
+    octave_value retval
+      = set_internal_variable (m_mfile_encoding, args, nargout,
+                               "__mfile_encoding__");
+
+    // Additional validation if the encoding has changed.
 
-  // FIXME: this needs to include a comma too, but that
-  // causes trouble for the new struct element completion code.
+    if (m_mfile_encoding != saved_encoding)
+      {
+        if (m_mfile_encoding.empty ())
+          {
+#if defined (OCTAVE_USE_WINDOWS_API)
+            m_mfile_encoding = "system";
+#else
+            m_mfile_encoding = "utf-8";
+#endif
+          }
+        else
+          {
+            std::transform (m_mfile_encoding.begin (),
+                            m_mfile_encoding.end (),
+                            m_mfile_encoding.begin (), ::tolower);
 
-  static const char *s = "\t\n !\"\'*+-/:;<=>(){}[\\]^`~";
+            std::string codepage = (m_mfile_encoding.compare ("system") == 0)
+              ? octave_locale_charset_wrapper () : m_mfile_encoding;
 
-  octave::command_editor::set_basic_word_break_characters (s);
+            // Check for valid codepage.
+            void *codec
+              = octave_iconv_open_wrapper (codepage.c_str (), "utf-8");
+
+            if (errno == EINVAL)
+              {
+                m_mfile_encoding = saved_encoding;
+
+                error ("__mfile_encoding__: conversion from codepage '%s' not supported",
+                       codepage.c_str ());
+              }
 
-  octave::command_editor::set_completer_word_break_characters (s);
+            octave_iconv_close_wrapper (codec);
+          }
+
+      }
 
-  octave::command_editor::set_basic_quote_characters (R"(")");
+    // Synchronize the related gui preference for editor encoding
+    octave::feval ("__octave_link_gui_preference__",
+                   ovl ("editor/default_encoding", m_mfile_encoding));
+
+    return retval;
+  }
 
-  octave::command_editor::set_filename_quote_characters (" \t\n\\\"'@<>=;|&()#$`?*[!:{");
-  octave::command_editor::set_completer_quote_characters (R"('")");
+  bool input_system::yes_or_no (const std::string& prompt)
+  {
+    std::string prompt_string = prompt + "(yes or no) ";
+
+    while (1)
+      {
+        bool eof = false;
+
+        std::string input_buf = interactive_input (prompt_string, eof);
 
-  octave::command_editor::set_completion_function (generate_completion);
+        if (input_buf == "yes")
+          return true;
+        else if (input_buf == "no")
+          return false;
+        else
+          message (nullptr, "Please answer yes or no.");
+      }
+  }
+
+  std::string input_system::interactive_input (const std::string& s, bool& eof)
+  {
+    Vlast_prompt_time.stamp ();
 
-  octave::command_editor::set_quoting_function (quoting_filename);
-}
+    if (Vdrawnow_requested && octave::application::interactive ())
+      {
+        bool eval_error = false;
 
-static void
-execute_in_debugger_handler (const std::pair<std::string, int>& arg)
-{
-  octave_link::execute_in_debugger_event (arg.first, arg.second);
-}
+        try
+          {
+            Fdrawnow ();
+          }
+        catch (const octave::execution_exception& e)
+          {
+            eval_error = true;
+
+            std::string stack_trace = e.info ();
+
+            if (! stack_trace.empty ())
+              std::cerr << stack_trace;
+
+            if (octave::application::interactive ())
+              octave::interpreter::recover_from_exception ();
+          }
+
+        octave::flush_stdout ();
 
-static void
-get_debug_input (octave::interpreter& interp, const std::string& prompt)
-{
-  octave::unwind_protect frame;
+        // We set Vdrawnow_requested to false even if there is an error in
+        // drawnow so that the error doesn't reappear at every prompt.
+
+        Vdrawnow_requested = false;
+
+        if (eval_error)
+          return "\n";
+      }
+
+    return gnu_readline (s, eof);
+  }
+
+  // If the user simply hits return, this will produce an empty matrix.
+
+  octave_value_list
+  input_system::get_user_input (const octave_value_list& args, int nargout)
+  {
+    octave_value_list retval;
 
-  bool silent = octave::tree_evaluator::quiet_breakpoint_flag;
-  octave::tree_evaluator::quiet_breakpoint_flag = false;
+    int read_as_string = 0;
+
+    if (args.length () == 2)
+      read_as_string++;
+
+    std::string prompt = args(0).xstring_value ("input: unrecognized argument");
+
+    output_system& output_sys = __get_output_system__ ("do_sync");
 
-  octave::call_stack& cs = interp.get_call_stack ();
+    output_sys.reset ();
+
+    octave_diary << prompt;
+
+    bool eof = false;
+
+    std::string input_buf = interactive_input (prompt.c_str (), eof);
+
+    if (input_buf.empty ())
+      error ("input: reading user-input failed!");
 
-  octave_user_code *caller = cs.caller_user_code ();
-  std::string nm;
-  int curr_debug_line;
+    size_t len = input_buf.length ();
+
+    octave_diary << input_buf;
+
+    if (input_buf[len - 1] != '\n')
+      octave_diary << "\n";
+
+    if (len < 1)
+      return read_as_string ? octave_value ("") : octave_value (Matrix ());
 
-  if (caller)
-    {
-      nm = caller->fcn_file_name ();
+    if (read_as_string)
+      {
+        // FIXME: fix gnu_readline and octave_gets instead!
+        if (input_buf.length () == 1 && input_buf[0] == '\n')
+          retval(0) = "";
+        else
+          retval(0) = input_buf;
+      }
+    else
+      {
+        int parse_status = 0;
+
+        retval = octave::eval_string (input_buf, true, parse_status, nargout);
 
-      if (nm.empty ())
-        nm = caller->name ();
+        if (! Vdebugging && retval.empty ())
+          retval(0) = Matrix ();
+      }
+
+    return retval;
+  }
+
+  octave_value input_system::keyboard (const octave_value_list& args)
+  {
+    octave_value retval;
+
+    int nargin = args.length ();
+
+    assert (nargin == 0 || nargin == 1);
 
-      curr_debug_line = cs.caller_user_code_line ();
-    }
-  else
-    curr_debug_line = cs.current_line ();
+    octave::unwind_protect frame;
+
+    frame.add_fcn (octave::command_history::ignore_entries,
+                   octave::command_history::ignoring_entries ());
+
+    octave::command_history::ignore_entries (false);
+
+    frame.protect_var (Vdebugging);
+
+    octave::call_stack& cs = m_interpreter.get_call_stack ();
+
+    frame.add_method (cs, &octave::call_stack::restore_frame,
+                      cs.current_frame ());
 
-  std::ostringstream buf;
+    // FIXME: probably we just want to print one line, not the
+    // entire statement, which might span many lines...
+    //
+    // tree_print_code tpc (octave_stdout);
+    // stmt.accept (tpc);
+
+    Vdebugging = true;
+    Vtrack_line_num = false;
 
-  if (! nm.empty ())
-    {
-      if (Vgud_mode)
-        {
-          static char ctrl_z = 'Z' & 0x1f;
+    std::string prompt = "debug> ";
+    if (nargin > 0)
+      prompt = args(0).string_value ();
+
+    get_debug_input (prompt);
+
+    return retval;
+  }
+
+  bool input_system::have_input_event_hooks (void) const
+  {
+    return ! m_input_event_hook_functions.empty ();
+  }
 
-          buf << ctrl_z << ctrl_z << nm << ':' << curr_debug_line;
-        }
-      else
-        {
-          // FIXME: we should come up with a clean way to detect
-          // that we are stopped on the no-op command that marks the
-          // end of a function or script.
+  void input_system::add_input_event_hook (const hook_function& hook_fcn)
+  {
+    m_input_event_hook_functions.insert (hook_fcn.id (), hook_fcn);
+  }
+
+  bool input_system::remove_input_event_hook (const std::string& hook_fcn_id)
+  {
+    hook_function_list::iterator p
+      = m_input_event_hook_functions.find (hook_fcn_id);
+
+    if (p == m_input_event_hook_functions.end ())
+      return false;
+
+    m_input_event_hook_functions.erase (p);
+    return true;
+  }
 
-          if (! silent)
-            {
-              buf << "stopped in " << nm;
+  void input_system::clear_input_event_hooks (void)
+  {
+    m_input_event_hook_functions.clear ();
+  }
+
+  void input_system::run_input_event_hooks (void)
+  {
+    m_input_event_hook_functions.run ();
+  }
 
-              if (curr_debug_line > 0)
-                buf << " at line " << curr_debug_line;
-            }
+  std::string
+  input_system::gnu_readline (const std::string& s, bool& eof) const
+  {
+    octave_quit ();
+
+    eof = false;
+
+    std::string retval = octave::command_editor::readline (s, eof);
+
+    if (! eof && retval.empty ())
+      retval = "\n";
+
+    return retval;
+  }
 
-          octave_link::enter_debugger_event (nm, curr_debug_line);
+  static void
+  execute_in_debugger_handler (const std::pair<std::string, int>& arg)
+  {
+    octave_link::execute_in_debugger_event (arg.first, arg.second);
+  }
 
-          octave_link::set_workspace ();
+  void input_system::get_debug_input (const std::string& prompt)
+  {
+    octave::unwind_protect frame;
+
+    octave::tree_evaluator& tw = m_interpreter.get_evaluator ();
+
+    bool silent = tw.quiet_breakpoint_flag (false);
+
+    octave::call_stack& cs = m_interpreter.get_call_stack ();
 
-          frame.add_fcn (execute_in_debugger_handler,
-                         std::pair<std::string, int> (nm, curr_debug_line));
+    octave_user_code *caller = cs.caller_user_code ();
+    std::string nm;
+    int curr_debug_line;
+
+    if (caller)
+      {
+        nm = caller->fcn_file_name ();
 
-          if (! silent)
-            {
-              std::string line_buf;
+        if (nm.empty ())
+          nm = caller->name ();
+
+        curr_debug_line = cs.caller_user_code_line ();
+      }
+    else
+      curr_debug_line = cs.current_line ();
+
+    std::ostringstream buf;
 
-              if (caller)
-                line_buf = caller->get_code_line (curr_debug_line);
+    if (! nm.empty ())
+      {
+        if (m_gud_mode)
+          {
+            static char ctrl_z = 'Z' & 0x1f;
+
+            buf << ctrl_z << ctrl_z << nm << ':' << curr_debug_line;
+          }
+        else
+          {
+            // FIXME: we should come up with a clean way to detect
+            // that we are stopped on the no-op command that marks the
+            // end of a function or script.
+
+            if (! silent)
+              {
+                buf << "stopped in " << nm;
+
+                if (curr_debug_line > 0)
+                  buf << " at line " << curr_debug_line;
+              }
 
-              if (! line_buf.empty ())
-                buf << "\n" << curr_debug_line << ": " << line_buf;
-            }
-        }
-    }
+            octave_link::enter_debugger_event (nm, curr_debug_line);
+
+            octave_link::set_workspace ();
+
+            frame.add_fcn (execute_in_debugger_handler,
+                           std::pair<std::string, int> (nm, curr_debug_line));
+
+            if (! silent)
+              {
+                std::string line_buf;
 
-  if (silent)
-    octave::command_editor::erase_empty_line (true);
+                if (caller)
+                  line_buf = caller->get_code_line (curr_debug_line);
+
+                if (! line_buf.empty ())
+                  buf << "\n" << curr_debug_line << ": " << line_buf;
+              }
+          }
+      }
+
+    if (silent)
+      octave::command_editor::erase_empty_line (true);
 
-  std::string msg = buf.str ();
+    std::string msg = buf.str ();
+
+    if (! msg.empty ())
+      std::cerr << msg << std::endl;
+
+    frame.add_method (*this, &octave::input_system::set_PS1, m_PS1);
+    m_PS1 = prompt;
 
-  if (! msg.empty ())
-    std::cerr << msg << std::endl;
+    // FIXME: should debugging be possible in an embedded interpreter?
+
+    octave::application *app = octave::application::app ();
+
+    if (! app->interactive ())
+      {
+
+        frame.add_method (app, &octave::application::interactive,
+                          app->interactive ());
 
-  frame.protect_var (VPS1);
-  VPS1 = prompt;
+        frame.add_method (app, &octave::application::forced_interactive,
+                          app->forced_interactive ());
+
+        app->interactive (true);
+
+        app->forced_interactive (true);
+      }
+
+    octave::parser curr_parser (m_interpreter);
 
-  // FIXME: should debugging be possible in an embedded interpreter?
+    while (Vdebugging)
+      {
+        try
+          {
+            Vtrack_line_num = false;
+
+            reset_error_handler ();
+
+            curr_parser.reset ();
 
-  octave::application *app = octave::application::app ();
+            int retval = curr_parser.run ();
 
-  if (! app->interactive ())
-    {
+            if (octave::command_editor::interrupt (false))
+              break;
+            else
+              {
+                if (retval == 0 && curr_parser.m_stmt_list)
+                  {
+                    curr_parser.m_stmt_list->accept (tw);
+
+                    if (octave_completion_matches_called)
+                      octave_completion_matches_called = false;
+                  }
 
-      frame.add_method (app, &octave::application::interactive,
-                        app->interactive ());
+                octave_quit ();
+              }
+          }
+        catch (const octave::execution_exception& e)
+          {
+            std::string stack_trace = e.info ();
+
+            if (! stack_trace.empty ())
+              std::cerr << stack_trace;
 
-      frame.add_method (app, &octave::application::forced_interactive,
-                        app->forced_interactive ());
+            // Ignore errors when in debugging mode;
+            octave::interpreter::recover_from_exception ();
+          }
+      }
+  }
 
-      app->interactive (true);
+  std::string base_reader::octave_gets (bool& eof)
+  {
+    octave_quit ();
+
+    eof = false;
+
+    std::string retval;
+
+    // Process pre input event hook function prior to flushing output and
+    // printing the prompt.
 
-      app->forced_interactive (true);
-    }
+    if (application::interactive ())
+      {
+        if (! Vdebugging)
+          octave_link::exit_debugger_event ();
+
+        octave_link::pre_input_event ();
+
+        octave_link::set_workspace ();
+      }
+
+    bool history_skip_auto_repeated_debugging_command = false;
+
+    input_system& input_sys = __get_input_system__ ("base_reader::octave_gets");
+
+    std::string ps = (m_pflag > 0) ? input_sys.PS1 () : input_sys.PS2 ();
+
+    std::string prompt = command_editor::decode_prompt_string (ps);
 
-  octave::parser curr_parser;
+    pipe_handler_error_count = 0;
+
+    output_system& output_sys = __get_output_system__ ("do_sync");
+
+    output_sys.reset ();
+
+    octave_diary << prompt;
 
-  octave::tree_evaluator& tw = interp.get_evaluator ();
+    retval = input_sys.interactive_input (prompt, eof);
+
+    // There is no need to update the load_path cache if there is no
+    // user input.
+    if (retval != "\n"
+        && retval.find_first_not_of (" \t\n\r") != std::string::npos)
+      {
+        load_path& lp = __get_load_path__ ("base_reader::octave_gets");
+
+        lp.update ();
 
-  while (Vdebugging)
-    {
-      try
-        {
-          Vtrack_line_num = false;
+        if (Vdebugging)
+          input_sys.last_debugging_command (retval);
+        else
+          input_sys.last_debugging_command ("\n");
+      }
+    else if (Vdebugging)
+      {
+        retval = input_sys.last_debugging_command ();
+        history_skip_auto_repeated_debugging_command = true;
+      }
+
+    if (retval != "\n")
+      {
+        if (! history_skip_auto_repeated_debugging_command)
+          {
+            if (command_history::add (retval))
+              octave_link::append_history (retval);
+          }
 
-          reset_error_handler ();
+        octave_diary << retval;
+
+        if (retval.back () != '\n')
+          octave_diary << "\n";
+      }
+    else
+      octave_diary << "\n";
+
+    // Process post input event hook function after the internal history
+    // list has been updated.
 
-          curr_parser.reset ();
+    if (application::interactive ())
+      octave_link::post_input_event ();
 
-          int retval = curr_parser.run ();
+    return retval;
+  }
+
+  bool base_reader::reading_fcn_file (void) const
+  {
+    return m_lexer ? m_lexer->m_reading_fcn_file : false;
+  }
 
-          if (octave::command_editor::interrupt (false))
-            break;
-          else
-            {
-              if (retval == 0 && curr_parser.m_stmt_list)
-                {
-                  curr_parser.m_stmt_list->accept (tw);
+  bool base_reader::reading_classdef_file (void) const
+  {
+    return m_lexer ? m_lexer->m_reading_classdef_file : false;
+  }
+
+  bool base_reader::reading_script_file (void) const
+  {
+    return m_lexer ? m_lexer->m_reading_script_file : false;
+  }
+
+  class
+  terminal_reader : public base_reader
+  {
+  public:
+
+    terminal_reader (base_lexer *lxr = nullptr)
+      : base_reader (lxr)
+    { }
+
+    std::string get_input (bool& eof);
 
-                  if (octave_completion_matches_called)
-                    octave_completion_matches_called = false;
-                }
+    std::string input_source (void) const { return s_in_src; }
+
+    bool input_from_terminal (void) const { return true; }
+
+  private:
+
+    static const std::string s_in_src;
+  };
+
+  class
+  file_reader : public base_reader
+  {
+  public:
+
+    file_reader (FILE *f_arg, base_lexer *lxr = nullptr)
+      : base_reader (lxr), m_file (f_arg) { }
+
+    std::string get_input (bool& eof);
+
+    std::string input_source (void) const { return s_in_src; }
 
-              octave_quit ();
-            }
-        }
-      catch (const octave::execution_exception& e)
-        {
-          std::string stack_trace = e.info ();
+    bool input_from_file (void) const { return true; }
+
+  private:
+
+    FILE *m_file;
+
+    static const std::string s_in_src;
+  };
+
+  class
+  eval_string_reader : public base_reader
+  {
+  public:
+
+    eval_string_reader (const std::string& str, base_lexer *lxr = nullptr)
+      : base_reader (lxr), m_eval_string (str)
+    { }
+
+    std::string get_input (bool& eof);
+
+    std::string input_source (void) const { return s_in_src; }
 
-          if (! stack_trace.empty ())
-            std::cerr << stack_trace;
+    bool input_from_eval_string (void) const { return true; }
+
+  private:
+
+    std::string m_eval_string;
+
+    static const std::string s_in_src;
+  };
 
-          // Ignore errors when in debugging mode;
-          octave::interpreter::recover_from_exception ();
-        }
-    }
-}
+  input_reader::input_reader (base_lexer *lxr)
+    : m_rep (new terminal_reader (lxr))
+  { }
 
-namespace octave
-{
+  input_reader::input_reader (FILE *file, base_lexer *lxr)
+    : m_rep (new file_reader (file, lxr))
+  { }
+
+  input_reader::input_reader (const std::string& str, base_lexer *lxr)
+    : m_rep (new eval_string_reader (str, lxr))
+  { }
+
   const std::string base_reader::s_in_src ("invalid");
 
   const std::string terminal_reader::s_in_src ("terminal");
@@ -777,7 +1109,46 @@
 
     eof = false;
 
-    return octave_fgets (m_file, eof);
+    std::string src_str = octave_fgets (m_file, eof);
+
+    octave::input_system& input_sys
+      = octave::__get_input_system__ ("get_input");
+
+    std::string mfile_encoding = input_sys.mfile_encoding ();
+
+    std::string encoding
+      = (mfile_encoding.compare ("system") == 0
+         ? octave_locale_charset_wrapper () : mfile_encoding);
+
+    if (encoding.compare ("utf-8") == 0)
+    {
+      // Check for BOM and strip it
+      if (src_str.compare (0, 3, "\xef\xbb\xbf") == 0)
+        src_str.erase (0, 3);
+    }
+    else
+    {
+      // convert encoding to UTF-8 before returning string
+      const char *src = src_str.c_str ();
+      size_t srclen = src_str.length ();
+
+      size_t length;
+      uint8_t *utf8_str = nullptr;
+
+      utf8_str = octave_u8_conv_from_encoding (encoding.c_str (), src, srclen,
+                                               &length);
+
+      if (! utf8_str)
+        error ("file_reader::get_input: converting from codepage '%s' to UTF-8: %s",
+               encoding.c_str (), std::strerror (errno));
+
+      octave::unwind_protect frame;
+      frame.add_fcn (::free, static_cast<void *> (utf8_str));
+
+      src_str = std::string (reinterpret_cast<char *> (utf8_str), length);
+    }
+
+    return src_str;
   }
 
   const std::string eval_string_reader::s_in_src ("eval_string");
@@ -804,67 +1175,8 @@
   }
 }
 
-// If the user simply hits return, this will produce an empty matrix.
-
-static octave_value_list
-get_user_input (const octave_value_list& args, int nargout)
-{
-  octave_value_list retval;
-
-  int read_as_string = 0;
-
-  if (args.length () == 2)
-    read_as_string++;
-
-  std::string prompt = args(0).xstring_value ("input: unrecognized argument");
-
-  octave::flush_stdout ();
-
-  octave::pager_stream::reset ();
-  octave::diary_stream::reset ();
-
-  octave_diary << prompt;
-
-  bool eof = false;
-
-  std::string input_buf = interactive_input (prompt.c_str (), eof);
-
-  if (input_buf.empty ())
-    error ("input: reading user-input failed!");
-
-  size_t len = input_buf.length ();
-
-  octave_diary << input_buf;
-
-  if (input_buf[len - 1] != '\n')
-    octave_diary << "\n";
-
-  if (len < 1)
-    return read_as_string ? octave_value ("") : octave_value (Matrix ());
-
-  if (read_as_string)
-    {
-      // FIXME: fix gnu_readline and octave_gets instead!
-      if (input_buf.length () == 1 && input_buf[0] == '\n')
-        retval(0) = "";
-      else
-        retval(0) = input_buf;
-    }
-  else
-    {
-      int parse_status = 0;
-
-      retval = octave::eval_string (input_buf, true, parse_status, nargout);
-
-      if (! Vdebugging && retval.empty ())
-        retval(0) = Matrix ();
-    }
-
-  return retval;
-}
-
-DEFUN (input, args, nargout,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (input, interp, args, nargout,
+           doc: /* -*- texinfo -*-
 @deftypefn  {} {@var{ans} =} input (@var{prompt})
 @deftypefnx {} {@var{ans} =} input (@var{prompt}, "s")
 Print @var{prompt} and wait for user input.
@@ -907,31 +1219,13 @@
   if (nargin < 1 || nargin > 2)
     print_usage ();
 
-  return get_user_input (args, std::max (nargout, 1));
+  octave::input_system& input_sys = interp.get_input_system ();
+
+  return input_sys.get_user_input (args, std::max (nargout, 1));
 }
 
-bool
-octave_yes_or_no (const std::string& prompt)
-{
-  std::string prompt_string = prompt + "(yes or no) ";
-
-  while (1)
-    {
-      bool eof = false;
-
-      std::string input_buf = interactive_input (prompt_string, eof);
-
-      if (input_buf == "yes")
-        return true;
-      else if (input_buf == "no")
-        return false;
-      else
-        message (nullptr, "Please answer yes or no.");
-    }
-}
-
-DEFUN (yes_or_no, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (yes_or_no, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {@var{ans} =} yes_or_no ("@var{prompt}")
 Ask the user a yes-or-no question.
 
@@ -949,61 +1243,14 @@
   if (nargin > 1)
     print_usage ();
 
+  octave::input_system& input_sys = interp.get_input_system ();
+
   std::string prompt;
 
   if (nargin == 1)
     prompt = args(0).xstring_value ("yes_or_no: PROMPT must be a string");
 
-  return ovl (octave_yes_or_no (prompt));
-}
-
-octave_value
-do_keyboard (octave::interpreter& interp, const octave_value_list& args)
-{
-  octave_value retval;
-
-  int nargin = args.length ();
-
-  assert (nargin == 0 || nargin == 1);
-
-  octave::unwind_protect frame;
-
-  frame.add_fcn (octave::command_history::ignore_entries,
-                 octave::command_history::ignoring_entries ());
-
-  octave::command_history::ignore_entries (false);
-
-  frame.protect_var (Vdebugging);
-
-  octave::call_stack& cs = interp.get_call_stack ();
-
-  frame.add_method (cs, &octave::call_stack::restore_frame,
-                    cs.current_frame ());
-
-  // FIXME: probably we just want to print one line, not the
-  // entire statement, which might span many lines...
-  //
-  // tree_print_code tpc (octave_stdout);
-  // stmt.accept (tpc);
-
-  Vdebugging = true;
-  Vtrack_line_num = false;
-
-  std::string prompt = "debug> ";
-  if (nargin > 0)
-    prompt = args(0).string_value ();
-
-  get_debug_input (interp, prompt);
-
-  return retval;
-}
-
-octave_value
-do_keyboard (const octave_value_list& args)
-{
-  octave::interpreter& interp = octave::__get_interpreter__ ("do_keyboard");
-
-  return do_keyboard (interp, args);
+  return ovl (input_sys.yes_or_no (prompt));
 }
 
 DEFMETHOD (keyboard, interp, args, ,
@@ -1037,12 +1284,15 @@
   // Skip the frame assigned to the keyboard function.
   cs.goto_frame_relative (0);
 
-  octave::tree_evaluator::debug_mode = true;
-  octave::tree_evaluator::quiet_breakpoint_flag = false;
+  octave::tree_evaluator& tw = interp.get_evaluator ();
 
-  octave::tree_evaluator::current_frame = cs.current_frame ();
+  tw.debug_mode (true);
+  tw.quiet_breakpoint_flag (false);
+  tw.current_frame (cs.current_frame ());
 
-  do_keyboard (interp, args);
+  octave::input_system& input_sys = interp.get_input_system ();
+
+  input_sys.keyboard (args);
 
   return ovl ();
 }
@@ -1182,16 +1432,19 @@
 static int
 internal_input_event_hook_fcn (void)
 {
-  input_event_hook_functions.run ();
+  octave::input_system& input_sys
+    = octave::__get_input_system__ ("internal_input_event_hook_fcn");
 
-  if (input_event_hook_functions.empty ())
+  input_sys.run_input_event_hooks ();
+
+  if (! input_sys.have_input_event_hooks ())
     octave::command_editor::remove_event_hook (internal_input_event_hook_fcn);
 
   return 0;
 }
 
-DEFUN (add_input_event_hook, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (add_input_event_hook, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn  {} {@var{id} =} add_input_event_hook (@var{fcn})
 @deftypefnx {} {@var{id} =} add_input_event_hook (@var{fcn}, @var{data})
 Add the named function or function handle @var{fcn} to the list of functions
@@ -1220,18 +1473,20 @@
   if (nargin == 2)
     user_data = args(1);
 
+  octave::input_system& input_sys = interp.get_input_system ();
+
   hook_function hook_fcn (args(0), user_data);
 
-  if (input_event_hook_functions.empty ())
+  if (! input_sys.have_input_event_hooks ())
     octave::command_editor::add_event_hook (internal_input_event_hook_fcn);
 
-  input_event_hook_functions.insert (hook_fcn.id (), hook_fcn);
+  input_sys.add_input_event_hook (hook_fcn);
 
   return ovl (hook_fcn.id ());
 }
 
-DEFUN (remove_input_event_hook, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (remove_input_event_hook, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn  {} {} remove_input_event_hook (@var{name})
 @deftypefnx {} {} remove_input_event_hook (@var{fcn_id})
 Remove the named function or function handle with the given identifier
@@ -1249,23 +1504,20 @@
 
   bool warn = (nargin < 2);
 
-  hook_function_list::iterator p
-    = input_event_hook_functions.find (hook_fcn_id);
+  octave::input_system& input_sys = interp.get_input_system ();
 
-  if (p != input_event_hook_functions.end ())
-    input_event_hook_functions.erase (p);
-  else if (warn)
+  if (! input_sys.remove_input_event_hook (hook_fcn_id) && warn)
     warning ("remove_input_event_hook: %s not found in list",
              hook_fcn_id.c_str ());
 
-  if (input_event_hook_functions.empty ())
+  if (! input_sys.have_input_event_hooks ())
     octave::command_editor::remove_event_hook (internal_input_event_hook_fcn);
 
   return ovl ();
 }
 
-DEFUN (PS1, args, nargout,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (PS1, interp, args, nargout,
+           doc: /* -*- texinfo -*-
 @deftypefn  {} {@var{val} =} PS1 ()
 @deftypefnx {} {@var{old_val} =} PS1 (@var{new_val})
 @deftypefnx {} {} PS1 (@var{new_val}, "local")
@@ -1303,11 +1555,13 @@
 @seealso{PS2, PS4}
 @end deftypefn */)
 {
-  return SET_INTERNAL_VARIABLE (PS1);
+  octave::input_system& input_sys = interp.get_input_system ();
+
+  return input_sys.PS1 (args, nargout);
 }
 
-DEFUN (PS2, args, nargout,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (PS2, interp, args, nargout,
+           doc: /* -*- texinfo -*-
 @deftypefn  {} {@var{val} =} PS2 ()
 @deftypefnx {} {@var{old_val} =} PS2 (@var{new_val})
 @deftypefnx {} {} PS2 (@var{new_val}, "local")
@@ -1325,11 +1579,13 @@
 @seealso{PS1, PS4}
 @end deftypefn */)
 {
-  return SET_INTERNAL_VARIABLE (PS2);
+  octave::input_system& input_sys = interp.get_input_system ();
+
+  return input_sys.PS2 (args, nargout);
 }
 
-DEFUN (completion_append_char, args, nargout,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (completion_append_char, interp, args, nargout,
+           doc: /* -*- texinfo -*-
 @deftypefn  {} {@var{val} =} completion_append_char ()
 @deftypefnx {} {@var{old_val} =} completion_append_char (@var{new_val})
 @deftypefnx {} {} completion_append_char (@var{new_val}, "local")
@@ -1343,11 +1599,13 @@
 The original variable value is restored when exiting the function.
 @end deftypefn */)
 {
-  return SET_INTERNAL_VARIABLE (completion_append_char);
+  octave::input_system& input_sys = interp.get_input_system ();
+
+  return input_sys.completion_append_char (args, nargout);
 }
 
-DEFUN (__request_drawnow__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__request_drawnow__, , args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn  {} {} __request_drawnow__ ()
 @deftypefnx {} {} __request_drawnow__ (@var{flag})
 Undocumented internal function.
@@ -1366,23 +1624,70 @@
   return ovl ();
 }
 
-DEFUN (__gud_mode__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__gud_mode__, interp, args, nargout,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __gud_mode__ ()
 Undocumented internal function.
 @end deftypefn */)
 {
-  int nargin = args.length ();
+  octave::input_system& input_sys = interp.get_input_system ();
+
+  return input_sys.gud_mode (args, nargout);
+}
+
+DEFMETHOD (__mfile_encoding__, interp, args, nargout,
+           doc: /* -*- texinfo -*-
+@deftypefn {} {@var{current_encoding} =} __mfile_encoding__ (@var{new_encoding})
+Set and query the codepage that is used for reading .m files.
+@end deftypefn */)
+{
+  octave::input_system& input_sys = interp.get_input_system ();
 
-  if (nargin > 1)
-    print_usage ();
+  return input_sys.mfile_encoding (args, nargout);
+}
+
+// Always define these functions.  The macro is intended to allow the
+// declarations to be hidden, not so that Octave will not provide the
+// functions if they are requested.
+
+// #if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
 
-  octave_value_list retval;
+bool
+octave_yes_or_no (const std::string& prompt)
+{
+  octave::input_system& input_sys
+    = octave::__get_input_system__ ("set_default_prompts");
+
+  return input_sys.yes_or_no (prompt);
+}
 
-  if (nargin == 0)
-    retval = ovl (Vgud_mode);
-  else
-    Vgud_mode = args(0).bool_value ();
+octave_value
+do_keyboard (const octave_value_list& args)
+{
+  octave::input_system& input_sys
+    = octave::__get_input_system__ ("do_keyboard");
+
+  return input_sys.keyboard (args);
+}
+
+void
+remove_input_event_hook_functions (void)
+{
+  octave::input_system& input_sys
+    = octave::__get_input_system__ ("remove_input_event_hook_functions");
 
-  return retval;
+  input_sys.clear_input_event_hooks ();
 }
+
+// Fix things up so that input can come from the standard input.  This
+// may need to become much more complicated, which is why it's in a
+// separate function.
+
+FILE *
+get_input_from_stdin (void)
+{
+  octave::command_editor::set_input_stream (stdin);
+  return octave::command_editor::get_input_stream ();
+}
+
+// #endif
--- a/libinterp/corefcn/input.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/input.h	Fri Aug 10 09:09:51 2018 +0200
@@ -31,19 +31,12 @@
 
 #include <string>
 
+#include "hook-fcn.h"
 #include "oct-refcount.h"
 #include "oct-time.h"
 #include "ovl.h"
 #include "pager.h"
 
-class octave_value;
-namespace octave
-{
-  class base_lexer;
-}
-
-extern OCTINTERP_API FILE * get_input_from_stdin (void);
-
 // TRUE after a call to completion_matches.
 extern bool octave_completion_matches_called;
 
@@ -57,25 +50,157 @@
 // TRUE if we are not executing a command direct from debug> prompt.
 extern OCTINTERP_API bool Vtrack_line_num;
 
-extern std::string find_indexed_expression (const std::string& text);
-
-extern void initialize_command_input (void);
-
-extern bool octave_yes_or_no (const std::string& prompt);
+extern octave::sys::time Vlast_prompt_time;
 
-extern octave_value do_keyboard (const octave_value_list& args
-                                 = octave_value_list ());
-
-extern void remove_input_event_hook_functions (void);
-
-extern void set_default_prompts (void);
-
-extern octave::sys::time Vlast_prompt_time;
+class octave_value;
 
 namespace octave
 {
-  class
-  base_reader
+  class interpreter;
+  class base_lexer;
+
+  class input_system
+  {
+  public:
+
+    input_system (interpreter& interp);
+
+    void initialize (bool line_editing);
+
+    octave_value PS1 (const octave_value_list& args, int nargout);
+
+    std::string PS1 (void) const { return m_PS1; }
+
+    std::string PS1 (const std::string& s)
+    {
+      std::string val = m_PS1;
+      m_PS1 = s;
+      return val;
+    }
+
+    void set_PS1 (const std::string& s) { m_PS1 = s; }
+
+    octave_value PS2 (const octave_value_list& args, int nargout);
+
+    std::string PS2 (void) const { return m_PS2; }
+
+    std::string PS2 (const std::string& s)
+    {
+      std::string val = m_PS2;
+      m_PS2 = s;
+      return val;
+    }
+
+    void set_PS2 (const std::string& s) { m_PS2 = s; }
+
+    std::string last_debugging_command (void) const
+    {
+      return m_last_debugging_command;
+    }
+
+    std::string last_debugging_command (const std::string& s)
+    {
+      std::string val = m_last_debugging_command;
+      m_last_debugging_command = s;
+      return val;
+    }
+
+    octave_value
+    completion_append_char (const octave_value_list& args, int nargout);
+
+    char completion_append_char (void) const
+    {
+      return m_completion_append_char;
+    }
+
+    char completion_append_char (char c)
+    {
+      char val = m_completion_append_char;
+      m_completion_append_char = c;
+      return val;
+    }
+
+    void set_completion_append_char (char c) { m_completion_append_char = c; }
+
+    octave_value gud_mode (const octave_value_list& args, int nargout);
+
+    bool gud_mode (void) const { return m_gud_mode; }
+
+    bool gud_mode (bool flag)
+    {
+      bool val = m_gud_mode;
+      m_gud_mode = flag;
+      return val;
+    }
+
+    void set_gud_mode (bool flag) { m_gud_mode = flag; }
+
+    octave_value mfile_encoding (const octave_value_list& args, int nargout);
+
+    std::string mfile_encoding (void) const { return m_mfile_encoding; }
+
+    std::string mfile_encoding (const std::string& s)
+    {
+      std::string val = m_mfile_encoding;
+      m_mfile_encoding = s;
+      return val;
+    }
+
+    void set_mfile_encoding (const std::string& s) { m_mfile_encoding = s; }
+
+    bool yes_or_no (const std::string& prompt);
+
+    std::string interactive_input (const std::string& s, bool& eof);
+
+    octave_value_list
+    get_user_input (const octave_value_list& args, int nargout);
+
+    octave_value
+    keyboard (const octave_value_list& args = octave_value_list ());
+
+    bool have_input_event_hooks (void) const;
+
+    void add_input_event_hook (const hook_function& hook_fcn);
+
+    bool remove_input_event_hook (const std::string& hook_fcn_id);
+
+    void clear_input_event_hooks (void);
+
+    void run_input_event_hooks (void);
+
+  private:
+
+    interpreter& m_interpreter;
+
+    // Primary prompt string.
+    std::string m_PS1;
+
+    // Secondary prompt string.
+    std::string m_PS2;
+
+    // Character to append after successful command-line completion
+    // attempts.
+    char m_completion_append_char;
+
+    // TRUE if we are running in the Emacs GUD mode.
+    bool m_gud_mode;
+
+    // Codepage which is used to read .m files
+    std::string m_mfile_encoding;
+
+    // If we are in debugging mode, this is the last command entered,
+    // so that we can repeat the previous command if the user just
+    // types RET.
+    std::string m_last_debugging_command;
+
+    hook_function_list m_input_event_hook_functions;
+
+    std::string gnu_readline (const std::string& s, bool& eof) const;
+
+    void get_debug_input (const std::string& prompt);
+  };
+
+  class base_reader
   {
   public:
 
@@ -135,8 +260,7 @@
     static const std::string s_in_src;
   };
 
-  class
-  input_reader
+  class input_reader
   {
   public:
 
@@ -210,4 +334,21 @@
   };
 }
 
+#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
+
+OCTAVE_DEPRECATED (5, "use 'octave::input_system::yes_or_no' instead")
+extern bool octave_yes_or_no (const std::string& prompt);
+
+OCTAVE_DEPRECATED (5, "use 'octave::input_system::keyboard' instead")
+extern octave_value do_keyboard (const octave_value_list& args
+                                 = octave_value_list ());
+
+OCTAVE_DEPRECATED (5, "use 'octave::input_system::clear_input_event_hooks' instead")
+extern void remove_input_event_hook_functions (void);
+
+OCTAVE_DEPRECATED (5, "this function will be removed in a future version of Octave")
+extern OCTINTERP_API FILE * get_input_from_stdin (void);
+
 #endif
+
+#endif
--- a/libinterp/corefcn/interpreter-private.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/interpreter-private.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -32,10 +32,12 @@
 #include "error.h"
 #include "gtk-manager.h"
 #include "help.h"
+#include "input.h"
 #include "interpreter-private.h"
 #include "interpreter.h"
 #include "load-path.h"
 #include "ov-classdef.h"
+#include "pager.h"
 #include "symtab.h"
 
 namespace octave
@@ -67,6 +69,20 @@
     return interp.get_help_system ();
   }
 
+  input_system& __get_input_system__ (const std::string& who)
+  {
+    interpreter& interp = __get_interpreter__ (who);
+
+    return interp.get_input_system ();
+  }
+
+  output_system& __get_output_system__ (const std::string& who)
+  {
+    interpreter& interp = __get_interpreter__ (who);
+
+    return interp.get_output_system ();
+  }
+
   load_path& __get_load_path__ (const std::string& who)
   {
     interpreter& interp = __get_interpreter__ (who);
@@ -114,9 +130,9 @@
 
   bp_table& __get_bp_table__ (const std::string& who)
   {
-    interpreter& interp = __get_interpreter__ (who);
+    tree_evaluator& tw = __get_evaluator__ (who);
 
-    return interp.get_bp_table ();
+    return tw.get_bp_table ();
   }
 
   call_stack& __get_call_stack__ (const std::string& who)
--- a/libinterp/corefcn/interpreter-private.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/interpreter-private.h	Fri Aug 10 09:09:51 2018 +0200
@@ -39,8 +39,10 @@
   class dynamic_loader;
   class gtk_manager;
   class help_system;
+  class input_system;
   class interpreter;
   class load_path;
+  class output_system;
   class tree_evaluator;
   class type_info;
 
@@ -50,8 +52,12 @@
 
   extern help_system& __get_help_system__ (const std::string& who);
 
+  extern input_system& __get_input_system__ (const std::string& who);
+
   extern load_path& __get_load_path__ (const std::string& who);
 
+  extern output_system& __get_output_system__ (const std::string& who);
+
   extern type_info& __get_type_info__ (const std::string& who);
 
   extern symbol_table& __get_symbol_table__ (const std::string& who);
--- a/libinterp/corefcn/interpreter.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/interpreter.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -29,7 +29,6 @@
 
 #include "cmd-edit.h"
 #include "cmd-hist.h"
-#include "file-ops.h"
 #include "file-stat.h"
 #include "fpucw-wrappers.h"
 #include "lo-blas-proto.h"
@@ -49,6 +48,7 @@
 #include "file-io.h"
 #include "graphics.h"
 #include "help.h"
+#include "input.h"
 #include "interpreter-private.h"
 #include "interpreter.h"
 #include "load-path.h"
@@ -64,8 +64,8 @@
 #include "parse.h"
 #include "pt-eval.h"
 #include "pt-jump.h"
-#include "pt-mat.h"
 #include "pt-stmt.h"
+#include "settings.h"
 #include "sighandlers.h"
 #include "sysdep.h"
 #include "unwind-prot.h"
@@ -275,26 +275,6 @@
     return 0;
   }
 
-  static void execute_pkg_add (const std::string& dir)
-  {
-    std::string file_name = sys::file_ops::concat (dir, "PKG_ADD");
-
-    load_path& lp = __get_load_path__ ("execute_pkg_add");
-
-    try
-      {
-        lp.execute_pkg_add (dir);
-      }
-    catch (const interrupt_exception&)
-      {
-        interpreter::recover_from_exception ();
-      }
-    catch (const execution_exception&)
-      {
-        interpreter::recover_from_exception ();
-      }
-  }
-
   static void initialize_version_info (void)
   {
     octave_value_list args;
@@ -378,13 +358,15 @@
   interpreter::interpreter (application *app_context)
     : m_app_context (app_context),
       m_environment (),
+      m_settings (),
       m_help_system (*this),
+      m_input_system (*this),
+      m_output_system (*this),
       m_dynamic_loader (*this),
       m_load_path (),
       m_type_info (),
       m_symbol_table (),
       m_evaluator (*this),
-      m_bp_table (),
       m_stream_list (*this),
       m_child_list (),
       m_url_handle_manager (),
@@ -421,8 +403,6 @@
 
     thread::init ();
 
-    set_default_prompts ();
-
     // Initialize default warning state before --traditional option
     // that may reset them.
 
@@ -531,11 +511,7 @@
           Ftexi_macros_file (*this, octave_value (texi_macros_file));
       }
 
-    // Force default line editor if we don't want readline editing.
-    if (line_editing)
-      initialize_command_input ();
-    else
-      command_editor::force_default_editor ();
+    m_input_system.initialize (line_editing);
 
     // These can come after command line args since none of them set any
     // defaults that might be changed by command line options.
@@ -627,7 +603,8 @@
         frame.add_method (m_load_path, &load_path::set_add_hook,
                           m_load_path.get_add_hook ());
 
-        m_load_path.set_add_hook (execute_pkg_add);
+        m_load_path.set_add_hook ([this] (const std::string& dir)
+                                  { this->execute_pkg_add (dir); });
 
         m_load_path.initialize (set_initial_path);
 
@@ -969,119 +946,7 @@
 
     // The big loop.
 
-    lexer *lxr = (application::interactive () ? new lexer ()
-                                              : new lexer (stdin));
-
-    parser parser (*lxr);
-
-    int retval = 0;
-    do
-      {
-        try
-          {
-            reset_error_handler ();
-
-            parser.reset ();
-
-            if (m_symbol_table.at_top_level ())
-              tree_evaluator::reset_debug_state ();
-
-            retval = parser.run ();
-
-            if (retval == 0)
-              {
-                if (parser.m_stmt_list)
-                  {
-                    parser.m_stmt_list->accept (m_evaluator);
-
-                    octave_quit ();
-
-                    if (! application::interactive ())
-                      {
-                        bool quit = (tree_return_command::returning
-                                     || tree_break_command::breaking);
-
-                        if (tree_return_command::returning)
-                          tree_return_command::returning = 0;
-
-                        if (tree_break_command::breaking)
-                          tree_break_command::breaking--;
-
-                        if (quit)
-                          break;
-                      }
-
-                    if (octave_completion_matches_called)
-                      octave_completion_matches_called = false;
-                    else
-                      command_editor::increment_current_command_number ();
-                  }
-                else if (parser.m_lexer.m_end_of_input)
-                  {
-                    retval = EOF;
-                    break;
-                  }
-              }
-          }
-        catch (const interrupt_exception&)
-          {
-            recover_from_exception ();
-
-            // Required newline when the user does Ctrl+C at the prompt.
-            if (application::interactive ())
-              octave_stdout << "\n";
-          }
-        catch (const index_exception& e)
-          {
-            recover_from_exception ();
-
-            std::cerr << "error: unhandled index exception: "
-                      << e.message () << " -- trying to return to prompt"
-                      << std::endl;
-          }
-        catch (const execution_exception& e)
-          {
-            std::string stack_trace = e.info ();
-
-            if (! stack_trace.empty ())
-              std::cerr << stack_trace;
-
-            if (application::interactive ())
-              recover_from_exception ();
-            else
-              {
-                // We should exit with a nonzero status.
-                retval = 1;
-                break;
-              }
-          }
-        catch (const std::bad_alloc&)
-          {
-            recover_from_exception ();
-
-            std::cerr << "error: out of memory -- trying to return to prompt"
-                      << std::endl;
-          }
-
-#if defined (DBSTOP_NANINF)
-        if (Vdebug_on_naninf)
-          {
-            if (setjump (naninf_jump) != 0)
-              debug_or_throw_exception (true);  // true = stack trace
-          }
-#endif
-      }
-    while (retval == 0);
-
-    if (retval == EOF)
-      {
-        if (application::interactive ())
-          octave_stdout << "\n";
-
-        retval = 0;
-      }
-
-    return retval;
+    return m_evaluator.repl (application::interactive ());
   }
 
   // Call a function with exceptions handled to avoid problems with
@@ -1126,7 +991,7 @@
     octave_link::process_events (true);
     octave_link::disconnect_link ();
 
-    OCTAVE_SAFE_CALL (remove_input_event_hook_functions, ());
+    OCTAVE_SAFE_CALL (m_input_system.clear_input_event_hooks, ());
 
     while (! atexit_functions.empty ())
       {
@@ -1308,8 +1173,8 @@
 
   void interpreter::maximum_braindamage (void)
   {
-    FPS1 (octave_value (">> "));
-    FPS2 (octave_value (""));
+    m_input_system.PS1 (">> ");
+    m_input_system.PS2 ("");
 
     m_evaluator.PS4 ("");
 
@@ -1330,4 +1195,20 @@
     disable_warning ("Octave:function-name-clash");
     disable_warning ("Octave:possible-matlab-short-circuit-operator");
   }
+
+  void interpreter::execute_pkg_add (const std::string& dir)
+  {
+    try
+      {
+        m_load_path.execute_pkg_add (dir);
+      }
+    catch (const octave::interrupt_exception&)
+      {
+        octave::interpreter::recover_from_exception ();
+      }
+    catch (const octave::execution_exception&)
+      {
+        octave::interpreter::recover_from_exception ();
+      }
+  }
 }
--- a/libinterp/corefcn/interpreter.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/interpreter.h	Fri Aug 10 09:09:51 2018 +0200
@@ -31,16 +31,18 @@
 #include "quit.h"
 #include "str-vec.h"
 
-#include "bp-table.h"
 #include "dynamic-ld.h"
 #include "environment.h"
 #include "gtk-manager.h"
 #include "help.h"
+#include "input.h"
 #include "load-path.h"
 #include "oct-stream.h"
 #include "ov-classdef.h"
 #include "ov-typeinfo.h"
+#include "pager.h"
 #include "pt-eval.h"
+#include "settings.h"
 #include "symtab.h"
 #include "url-handle-manager.h"
 
@@ -58,7 +60,6 @@
   class profiler;
   class call_stack;
   class child_list;
-  class tree_evaluator;
 
   // The application object contains a pointer to the current
   // interpreter and the interpreter contains a pointer back to the
@@ -151,11 +152,26 @@
       return m_environment;
     }
 
+    settings& get_settings (void)
+    {
+      return m_settings;
+    }
+
     help_system& get_help_system (void)
     {
       return m_help_system;
     }
 
+    input_system& get_input_system (void)
+    {
+      return m_input_system;
+    }
+
+    output_system& get_output_system (void)
+    {
+      return m_output_system;
+    }
+
     dynamic_loader& get_dynamic_loader (void)
     {
       return m_dynamic_loader;
@@ -179,11 +195,6 @@
     symbol_scope get_current_scope (void);
     symbol_scope require_current_scope (const std::string& who);
 
-    bp_table& get_bp_table (void)
-    {
-      return m_bp_table;
-    }
-
     call_stack& get_call_stack (void);
 
     profiler& get_profiler (void);
@@ -253,8 +264,14 @@
 
     environment m_environment;
 
+    settings m_settings;
+
     help_system m_help_system;
 
+    input_system m_input_system;
+
+    output_system m_output_system;
+
     dynamic_loader m_dynamic_loader;
 
     load_path m_load_path;
@@ -265,8 +282,6 @@
 
     tree_evaluator m_evaluator;
 
-    bp_table m_bp_table;
-
     stream_list m_stream_list;
 
     child_list m_child_list;
@@ -295,6 +310,8 @@
     bool m_initialized;
 
     void maximum_braindamage (void);
+
+    void execute_pkg_add (const std::string& dir);
   };
 }
 
--- a/libinterp/corefcn/kron.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/kron.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -64,13 +64,17 @@
   T *cv = c.fortran_vec ();
 
   for (octave_idx_type ja = 0; ja < nca; ja++)
-    for (octave_idx_type jb = 0; jb < ncb; jb++)
-      for (octave_idx_type ia = 0; ia < nra; ia++)
+    {
+      octave_quit ();
+      for (octave_idx_type jb = 0; jb < ncb; jb++)
         {
-          octave_quit ();
-          mx_inline_mul (nrb, cv, a(ia, ja), b.data () + nrb*jb);
-          cv += nrb;
+          for (octave_idx_type ia = 0; ia < nra; ia++)
+            {
+              mx_inline_mul (nrb, cv, a(ia, ja), b.data () + nrb*jb);
+              cv += nrb;
+            }
         }
+    }
 
   return c;
 }
@@ -90,12 +94,14 @@
   MArray<T> c (dim_vector (nra*nrb, nca*ncb), T ());
 
   for (octave_idx_type ja = 0; ja < dla; ja++)
-    for (octave_idx_type jb = 0; jb < ncb; jb++)
-      {
-        octave_quit ();
-        mx_inline_mul (nrb, &c.xelem (ja*nrb, ja*ncb + jb), a.dgelem (ja),
-                       b.data () + nrb*jb);
-      }
+    {
+      octave_quit ();
+      for (octave_idx_type jb = 0; jb < ncb; jb++)
+        {
+          mx_inline_mul (nrb, &c.xelem (ja*nrb, ja*ncb + jb), a.dgelem (ja),
+                         b.data () + nrb*jb);
+        }
+    }
 
   return c;
 }
@@ -111,22 +117,24 @@
   C.cidx (0) = 0;
 
   for (octave_idx_type Aj = 0; Aj < A.columns (); Aj++)
-    for (octave_idx_type Bj = 0; Bj < B.columns (); Bj++)
-      {
-        octave_quit ();
-        for (octave_idx_type Ai = A.cidx (Aj); Ai < A.cidx (Aj+1); Ai++)
-          {
-            octave_idx_type Ci = A.ridx (Ai) * B.rows ();
-            const T v = A.data (Ai);
+    {
+      octave_quit ();
+      for (octave_idx_type Bj = 0; Bj < B.columns (); Bj++)
+        {
+          for (octave_idx_type Ai = A.cidx (Aj); Ai < A.cidx (Aj+1); Ai++)
+            {
+              octave_idx_type Ci = A.ridx (Ai) * B.rows ();
+              const T v = A.data (Ai);
 
-            for (octave_idx_type Bi = B.cidx (Bj); Bi < B.cidx (Bj+1); Bi++)
-              {
-                C.data (idx) = v * B.data (Bi);
-                C.ridx (idx++) = Ci + B.ridx (Bi);
-              }
-          }
-        C.cidx (Aj * B.columns () + Bj + 1) = idx;
-      }
+              for (octave_idx_type Bi = B.cidx (Bj); Bi < B.cidx (Bj+1); Bi++)
+                {
+                  C.data (idx) = v * B.data (Bi);
+                  C.ridx (idx++) = Ci + B.ridx (Bi);
+                }
+            }
+          C.cidx (Aj * B.columns () + Bj + 1) = idx;
+        }
+    }
 
   return C;
 }
--- a/libinterp/corefcn/load-path.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/load-path.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -42,6 +42,7 @@
 #include "ov-usr-fcn.h"
 #include "pager.h"
 #include "parse.h"
+#include "sysdep.h"
 #include "unwind-prot.h"
 #include "utils.h"
 
@@ -148,23 +149,6 @@
   return retval;
 }
 
-static void
-execute_pkg_add_or_del (const std::string& dir,
-                        const std::string& script_file)
-{
-  if (! octave_interpreter_ready)
-    return;
-
-  octave::unwind_protect frame;
-
-  std::string file = octave::sys::file_ops::concat (dir, script_file);
-
-  octave::sys::file_stat fs (file);
-
-  if (fs.exists ())
-    octave::source_file (file, "base");
-}
-
 // True if a path is contained in a path list separated by path_sep_char
 
 static bool
@@ -205,6 +189,13 @@
   std::string load_path::sys_path;
   load_path::abs_dir_cache_type load_path::abs_dir_cache;
 
+  load_path::load_path (void)
+    : package_map (), top_level_package (), dir_info_list (), init_dirs (),
+      m_command_line_path (),
+      add_hook ([this] (const std::string& dir) { this->execute_pkg_add (dir); }),
+      remove_hook ([this] (const std::string& dir) { this->execute_pkg_del (dir); })
+  { }
+
   void
   load_path::initialize (bool set_initial_path)
   {
@@ -338,7 +329,7 @@
 
             dir = strip_trailing_separators (dir);
 
-            dir_info_list_iterator i = find_dir_info (dir);
+            auto i = find_dir_info (dir);
 
             if (i != dir_info_list.end ())
               {
@@ -845,6 +836,22 @@
     execute_pkg_add_or_del (dir, "PKG_DEL");
   }
 
+  void load_path::execute_pkg_add_or_del (const std::string& dir,
+                                          const std::string& script_file)
+  {
+    if (! octave_interpreter_ready)
+      return;
+
+    octave::unwind_protect frame;
+
+    std::string file = octave::sys::file_ops::concat (dir, script_file);
+
+    octave::sys::file_stat fs (file);
+
+    if (fs.exists ())
+      octave::source_file (file, "base");
+  }
+
   // FIXME: maybe we should also maintain a map to speed up this method of access.
 
   load_path::const_dir_info_list_iterator
@@ -852,9 +859,9 @@
   {
     std::string dir = sys::file_ops::tilde_expand (dir_arg);
 
-    const_dir_info_list_iterator retval = dir_info_list.begin ();
-
-    while (retval != dir_info_list.end ())
+    auto retval = dir_info_list.cbegin ();
+
+    while (retval != dir_info_list.cend ())
       {
         if (retval->dir_name == dir)
           break;
@@ -870,7 +877,7 @@
   {
     std::string dir = sys::file_ops::tilde_expand (dir_arg);
 
-    dir_info_list_iterator retval = dir_info_list.begin ();
+    auto retval = dir_info_list.begin ();
 
     while (retval != dir_info_list.end ())
       {
@@ -940,7 +947,7 @@
 
     dir = strip_trailing_separators (dir);
 
-    dir_info_list_iterator i = find_dir_info (dir);
+    auto i = find_dir_info (dir);
 
     if (i != dir_info_list.end ())
       move (i, at_end);
@@ -1068,12 +1075,13 @@
   {
     load_path::dir_info::fcn_file_map_type retval;
 
-    sys::dir_entry dir (d);
-
-    if (dir)
+    string_vector flist;
+    std::string msg;
+
+    if (! octave::sys::get_dirlist (d, flist, msg))
+      warning ("load_path: %s: %s", d.c_str (), msg.c_str ());
+    else
       {
-        string_vector flist = dir.read ();
-
         octave_idx_type len = flist.numel ();
 
         for (octave_idx_type i = 0; i < len; i++)
@@ -1112,11 +1120,6 @@
               }
           }
       }
-    else
-      {
-        std::string msg = dir.error ();
-        warning ("load_path: %s: %s", d.c_str (), msg.c_str ());
-      }
 
     return retval;
   }
@@ -1360,8 +1363,7 @@
   {
     std::string dir_name = di.dir_name;
 
-    std::list<std::string>::iterator s =
-      std::find (dir_list.begin (), dir_list.end (), dir_name);
+    auto s = std::find (dir_list.begin (), dir_list.end (), dir_name);
 
     if (s != dir_list.end ())
       {
@@ -1673,7 +1675,7 @@
 
         file_info_list_type& file_info_list = fcn_map[base];
 
-        file_info_list_iterator p = file_info_list.begin ();
+        auto p = file_info_list.begin ();
 
         while (p != file_info_list.end ())
           {
@@ -1790,7 +1792,7 @@
 
             file_info_list_type& file_info_list = fm[base];
 
-            file_info_list_iterator p2 = file_info_list.begin ();
+            auto p2 = file_info_list.begin ();
             while (p2 != file_info_list.end ())
               {
                 if (p2->dir_name == full_dir_name)
@@ -1960,7 +1962,7 @@
   void
   load_path::package_info::remove_private_fcn_map (const std::string& dir)
   {
-    private_fcn_map_iterator p = private_fcn_map.find (dir);
+    auto p = private_fcn_map.find (dir);
 
     if (p != private_fcn_map.end ())
       private_fcn_map.erase (p);
@@ -2146,42 +2148,42 @@
   genpath (const std::string& dirname, const string_vector& skip)
   {
     std::string retval;
-
-    sys::dir_entry dir (dirname);
-
-    if (dir)
-      {
-        retval = dirname;
-
-        string_vector dirlist = dir.read ().sort (false);
-
-        octave_idx_type len = dirlist.numel ();
-
-        for (octave_idx_type i = 0; i < len; i++)
-          {
-            std::string elt = dirlist[i];
-
-            bool skip_p = (elt == "." || elt == ".." || elt[0] == '@'
-                           || elt[0] == '+');
+  string_vector dirlist;
+  std::string msg;
+
+  if (! sys::get_dirlist (dirname, dirlist, msg))
+    return retval;
+
+  retval = dirname;
+
+  dirlist = dirlist.sort (false);
+
+  octave_idx_type len = dirlist.numel ();
+
+  for (octave_idx_type i = 0; i < len; i++)
+    {
+      std::string elt = dirlist[i];
+
+      bool skip_p = (elt == "." || elt == ".." || elt[0] == '@'
+                     || elt[0] == '+');
+
+      if (! skip_p)
+        {
+          for (octave_idx_type j = 0; j < skip.numel (); j++)
+            {
+              skip_p = (elt == skip[j]);
+              if (skip_p)
+                break;
+            }
 
             if (! skip_p)
               {
-                for (octave_idx_type j = 0; j < skip.numel (); j++)
-                  {
-                    skip_p = (elt == skip[j]);
-                    if (skip_p)
-                      break;
-                  }
-
-                if (! skip_p)
-                  {
-                    std::string nm = sys::file_ops::concat (dirname, elt);
-
-                    sys::file_stat fs (nm);
-
-                    if (fs && fs.is_dir ())
-                      retval += directory_path::path_sep_str () + genpath (nm, skip);
-                  }
+                std::string nm = sys::file_ops::concat (dirname, elt);
+
+                sys::file_stat fs (nm);
+
+                if (fs && fs.is_dir ())
+                  retval += directory_path::path_sep_str () + genpath (nm, skip);
               }
           }
       }
@@ -2439,7 +2441,7 @@
       for (auto dir : dir_elts)
         {
           // Remove duplicate directory separators
-          std::string::iterator it_start = dir.begin ();
+          auto it_start = dir.begin ();
 #if defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM)
           // In Windows, start check at second character (for UNC paths).
           it_start++;
--- a/libinterp/corefcn/load-path.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/load-path.h	Fri Aug 10 09:09:51 2018 +0200
@@ -26,6 +26,7 @@
 
 #include "octave-config.h"
 
+#include <functional>
 #include <iosfwd>
 #include <list>
 #include <map>
@@ -44,11 +45,7 @@
   {
   public:
 
-    load_path (void)
-      : package_map (), top_level_package (), dir_info_list (), init_dirs (),
-        m_command_line_path (), add_hook (load_path::execute_pkg_add),
-        remove_hook (load_path::execute_pkg_del)
-    { }
+    load_path (void);
 
     typedef void (*hook_fcn_ptr) (const std::string& dir);
 
@@ -169,14 +166,28 @@
 
     void display (std::ostream& os) const;
 
-    hook_fcn_ptr get_add_hook (void) { return add_hook; }
-    hook_fcn_ptr get_remove_hook (void) { return remove_hook; }
+    std::function<void (const std::string&)> get_add_hook (void)
+    {
+      return add_hook;
+    }
+
+    std::function<void (const std::string&)> get_remove_hook (void)
+    {
+      return remove_hook;
+    }
 
-    void set_add_hook (hook_fcn_ptr f) { add_hook = f; }
-    void set_remove_hook (hook_fcn_ptr f) { remove_hook = f; }
+    void set_add_hook (const std::function<void (const std::string&)>& f)
+    {
+      add_hook = f;
+    }
 
-    static void execute_pkg_add (const std::string& dir);
-    static void execute_pkg_del (const std::string& dir);
+    void set_remove_hook (const std::function<void (const std::string&)>& f)
+    {
+      remove_hook = f;
+    }
+
+    void execute_pkg_add (const std::string& dir);
+    void execute_pkg_del (const std::string& dir);
 
     void set_command_line_path (const std::string& p)
     {
@@ -510,9 +521,12 @@
 
     static abs_dir_cache_type abs_dir_cache;
 
-    hook_fcn_ptr add_hook;
+    std::function<void (const std::string&)> add_hook;
 
-    hook_fcn_ptr remove_hook;
+    std::function<void (const std::string&)> remove_hook;
+
+    void execute_pkg_add_or_del (const std::string& dir,
+                                 const std::string& script_file);
 
     const_dir_info_list_iterator find_dir_info (const std::string& dir) const;
     dir_info_list_iterator find_dir_info (const std::string& dir);
--- a/libinterp/corefcn/load-save.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/load-save.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -64,7 +64,6 @@
 #include "oct-map.h"
 #include "ov-cell.h"
 #include "pager.h"
-#include "pt-exp.h"
 #include "symtab.h"
 #include "sysdep.h"
 #include "unwind-prot.h"
@@ -227,7 +226,10 @@
 {
   bool retval = false;
 
-  std::ifstream file (fname.c_str (), std::ios::in | std::ios::binary);
+  std::string ascii_fname = octave::sys::get_ASCII_filename (fname);
+
+  std::ifstream file (ascii_fname.c_str (),
+                      std::ios::in | std::ios::binary);
 
   unsigned char magic[2];
   if (file.read (reinterpret_cast<char *> (&magic[0]), 2)
@@ -313,9 +315,11 @@
 {
   load_save_format retval = LS_UNKNOWN;
 
+  std::string ascii_fname = octave::sys::get_ASCII_filename (fname);
+
 #if defined (HAVE_HDF5)
   // check this before we open the file
-  if (H5Fis_hdf5 (fname.c_str ()) > 0)
+  if (H5Fis_hdf5 (ascii_fname.c_str ()) > 0)
     return LS_HDF5;
 #endif
 
@@ -327,7 +331,8 @@
 
   if (! use_zlib)
     {
-      std::ifstream file (fname.c_str (), std::ios::in | std::ios::binary);
+      std::ifstream file (ascii_fname.c_str (),
+                          std::ios::in | std::ios::binary);
       if (file)
         {
           retval = get_file_format (file, orig_fname);
@@ -504,7 +509,7 @@
 static std::string
 find_file_to_load (const std::string& name, const std::string& orig_name)
 {
-  std::string fname = find_data_file_in_load_path ("load", name, true);
+  std::string fname = octave::find_data_file_in_load_path ("load", name, true);
 
   size_t dot_pos = fname.rfind ('.');
   size_t sep_pos = fname.find_last_of (octave::sys::file_ops::dir_sep_chars ());
@@ -835,7 +840,9 @@
           else
 #endif
             {
-              std::ifstream file (fname.c_str (), mode);
+              std::string ascii_fname = octave::sys::get_ASCII_filename (fname);
+
+              std::ifstream file (ascii_fname.c_str (), mode);
 
               if (! file)
                 error ("load: unable to open input file '%s'",
@@ -993,7 +1000,7 @@
 
   size_t saved = 0;
 
-  for (octave_scalar_map::const_iterator it = m.begin (); it != m.end (); it++)
+  for (auto it = m.begin (); it != m.end (); it++)
     {
       std::string empty_str;
 
@@ -1697,8 +1704,10 @@
           if (append)
             error ("save: appending to HDF5 files is not implemented");
 
+          std::string ascii_fname = octave::sys::get_ASCII_filename (fname);
+
           bool write_header_info
-            = ! (append && H5Fis_hdf5 (fname.c_str ()) > 0);
+            = ! (append && H5Fis_hdf5 (ascii_fname.c_str ()) > 0);
 
           hdf5_ofstream hdf5_file (fname.c_str (), mode);
 
--- a/libinterp/corefcn/ls-ascii-helper.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/ls-ascii-helper.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -26,7 +26,7 @@
 
 #include "ls-ascii-helper.h"
 
-#include <iostream>
+#include <istream>
 #include <sstream>
 
 // Helper functions when reading from ascii files.
--- a/libinterp/corefcn/ls-hdf5.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/ls-hdf5.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -31,8 +31,9 @@
 #include <cctype>
 
 #include <iomanip>
-#include <iostream>
+#include <istream>
 #include <limits>
+#include <ostream>
 #include <string>
 #include <vector>
 
@@ -59,7 +60,6 @@
 #include "oct-map.h"
 #include "ov-cell.h"
 #include "pager.h"
-#include "pt-exp.h"
 #include "sysdep.h"
 #include "unwind-prot.h"
 #include "utils.h"
@@ -88,19 +88,7 @@
   : file_id (-1), current_item (-1)
 {
 #if defined (HAVE_HDF5)
-
-  if (mode & std::ios::in)
-    file_id = H5Fopen (name, H5F_ACC_RDONLY, octave_H5P_DEFAULT);
-  else if (mode & std::ios::out)
-    {
-      if (mode & std::ios::app && H5Fis_hdf5 (name) > 0)
-        file_id = H5Fopen (name, H5F_ACC_RDWR, octave_H5P_DEFAULT);
-      else
-        file_id = H5Fcreate (name, H5F_ACC_TRUNC, octave_H5P_DEFAULT,
-                             octave_H5P_DEFAULT);
-    }
-  if (file_id < 0)
-    std::ios::setstate (std::ios::badbit);
+  open_create (name, mode);
 
   current_item = 0;
 
@@ -136,20 +124,105 @@
 
   clear ();
 
+  open_create (name, mode);
+
+  current_item = 0;
+
+#else
+  // This shouldn't happen because construction of hdf5_fstreambase
+  // objects is supposed to be impossible if HDF5 is not available.
+
+  panic_impossible ();
+#endif
+}
+
+void
+hdf5_fstreambase::open_create (const char *name, int mode)
+{
+#if defined (HAVE_HDF5)
+  // Open the HDF5 file NAME. If it does not exist, create the file.
+
+  std::string fname_str (name);
+  std::string ascii_fname_str = octave::sys::get_ASCII_filename (fname_str);
+  const char *ascii_fname = ascii_fname_str.c_str ();
+
   if (mode & std::ios::in)
-    file_id = H5Fopen (name, H5F_ACC_RDONLY, octave_H5P_DEFAULT);
+    file_id = H5Fopen (ascii_fname, H5F_ACC_RDONLY, octave_H5P_DEFAULT);
   else if (mode & std::ios::out)
     {
-      if (mode & std::ios::app && H5Fis_hdf5 (name) > 0)
-        file_id = H5Fopen (name, H5F_ACC_RDWR, octave_H5P_DEFAULT);
+      if (mode & std::ios::app && H5Fis_hdf5 (ascii_fname) > 0)
+        file_id = H5Fopen (ascii_fname, H5F_ACC_RDWR, octave_H5P_DEFAULT);
       else
+#  if defined (OCTAVE_USE_WINDOWS_API)
+        {
+          // Check whether file already exists
+          std::string abs_ascii_fname
+            = octave::sys::canonicalize_file_name (ascii_fname_str);
+          if (! abs_ascii_fname.empty ())
+            {
+              // Use the existing file
+              file_id = H5Fcreate (ascii_fname, H5F_ACC_TRUNC,
+                                   octave_H5P_DEFAULT, octave_H5P_DEFAULT);
+              if (file_id < 0)
+                std::ios::setstate (std::ios::badbit);
+
+              return;
+            }
+
+          // Check whether filename contains non-ASCII (UTF-8) characters.
+          std::string::const_iterator first_non_ASCII
+            = std::find_if (fname_str.begin (), fname_str.end (),
+                            [](char c) { return (c < 0 || c >= 128); });
+          if (first_non_ASCII == fname_str.end ())
+            {
+              // No non-ASCII characters
+              file_id = H5Fcreate (name, H5F_ACC_TRUNC, octave_H5P_DEFAULT,
+                                   octave_H5P_DEFAULT);
+              if (file_id < 0)
+                std::ios::setstate (std::ios::badbit);
+
+              return;
+            }
+
+          // Create file in temp folder
+          std::string tmp_name = octave::sys::tempnam ("", "oct-");
+          octave_hdf5_id hdf5_fid = H5Fcreate (tmp_name.c_str (), H5F_ACC_TRUNC,
+                                               octave_H5P_DEFAULT,
+                                               octave_H5P_DEFAULT);
+          if (hdf5_fid < 0)
+            {
+              file_id = -1;
+              std::ios::setstate (std::ios::badbit);
+              return;
+            }
+
+          // Close file
+          H5Fclose (hdf5_fid);
+
+          // Move temporary file to final destination
+          std::string msg;
+          int res = octave::sys::rename (tmp_name, name, msg);
+          if (res < 0)
+            {
+              std::ios::setstate (std::ios::badbit);
+              file_id = -1;
+              return;
+            }
+
+          // Open file at final location
+          ascii_fname_str = octave::sys::get_ASCII_filename (fname_str);
+          ascii_fname = ascii_fname_str.c_str ();
+          file_id = H5Fopen (ascii_fname, H5F_ACC_RDWR, octave_H5P_DEFAULT);
+        }
+#  else
         file_id = H5Fcreate (name, H5F_ACC_TRUNC, octave_H5P_DEFAULT,
                              octave_H5P_DEFAULT);
+#  endif
     }
   if (file_id < 0)
     std::ios::setstate (std::ios::badbit);
-
-  current_item = 0;
+  
+  return;
 
 #else
   // This shouldn't happen because construction of hdf5_fstreambase
@@ -363,7 +436,7 @@
 
   H5G_stat_t info;
   herr_t retval = 0;
-  bool ident_valid = valid_identifier (name);
+  bool ident_valid = octave::valid_identifier (name);
 
   std::string vname = name;
 
@@ -379,7 +452,7 @@
       vname = make_valid_identifier (vname);
 
       // check again (in case vname was null, empty, or some such thing):
-      ident_valid = valid_identifier (vname);
+      ident_valid = octave::valid_identifier (vname);
     }
 
   H5Gget_objinfo (group_id, name, 1, &info);
--- a/libinterp/corefcn/ls-hdf5.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/ls-hdf5.h	Fri Aug 10 09:09:51 2018 +0200
@@ -25,7 +25,7 @@
 
 #include "octave-config.h"
 
-#include <iostream>
+#include <iosfwd>
 
 #include "oct-hdf5-types.h"
 #include "ov.h"
@@ -55,6 +55,8 @@
   void close (void);
 
   void open (const char *name, int mode, int);
+
+  void open_create (const char *name, int mode);
 };
 
 // input and output streams, subclassing istream and ostream
--- a/libinterp/corefcn/ls-mat-ascii.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/ls-mat-ascii.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -27,7 +27,8 @@
 #include <cctype>
 
 #include <iomanip>
-#include <iostream>
+#include <istream>
+#include <ostream>
 #include <sstream>
 #include <string>
 
@@ -54,7 +55,6 @@
 #include "ov-cell.h"
 #include "ov.h"
 #include "pager.h"
-#include "pt-exp.h"
 #include "sysdep.h"
 #include "utils.h"
 #include "variables.h"
@@ -251,7 +251,7 @@
   if (octave::is_keyword (varname) || ! isalpha (varname[0]))
     varname.insert (0, "X");
 
-  if (! valid_identifier (varname))
+  if (! octave::valid_identifier (varname))
     error ("load: unable to convert filename '%s' to valid identifier",
            filename.c_str ());
 
--- a/libinterp/corefcn/ls-mat4.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/ls-mat4.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -25,7 +25,8 @@
 #endif
 
 #include <iomanip>
-#include <iostream>
+#include <istream>
+#include <ostream>
 #include <string>
 
 #include "byte-swap.h"
@@ -51,7 +52,6 @@
 #include "ov-cell.h"
 #include "ovl.h"
 #include "pager.h"
-#include "pt-exp.h"
 #include "sysdep.h"
 #include "unwind-prot.h"
 #include "utils.h"
--- a/libinterp/corefcn/ls-mat5.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/ls-mat5.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -29,8 +29,9 @@
 #include <cstring>
 
 #include <iomanip>
-#include <iostream>
+#include <istream>
 #include <limits>
+#include <ostream>
 #include <sstream>
 #include <string>
 #include <vector>
@@ -69,7 +70,6 @@
 #include "ovl.h"
 #include "pager.h"
 #include "parse.h"
-#include "pt-exp.h"
 #include "sysdep.h"
 #include "unwind-prot.h"
 #include "utils.h"
@@ -962,7 +962,7 @@
               = m1.contents ("workspace").scalar_map_value ();
             uint32NDArray MCOS = m2.contents ("MCOS").uint32_array_value ();
             octave_idx_type off
-              = static_cast<octave_idx_type>(MCOS(4).double_value ());
+              = static_cast<octave_idx_type> (MCOS(4).double_value ());
             m2 = subsys_ov.scalar_map_value ();
             m2 = m2.contents ("MCOS").scalar_map_value ();
             tc2 = m2.contents ("MCOS").cell_value ()(1 + off).cell_value ()(1);
@@ -989,8 +989,7 @@
               {
                 octave_value tmp;
 
-                for (octave_map::iterator p0 = m2.begin () ;
-                     p0 != m2.end (); p0++)
+                for (auto p0 = m2.begin (); p0 != m2.end (); p0++)
                   {
                     std::string key = m2.key (p0);
                     octave_value val = m2.contents (p0);
@@ -2189,7 +2188,7 @@
           ret += 8 + PAD (classlen > max_namelen ? max_namelen : classlen);
         }
 
-      for (octave_map::const_iterator i = m.begin (); i != m.end (); i++)
+      for (auto i = m.begin (); i != m.end (); i++)
         fieldcnt++;
 
       ret += 16 + fieldcnt * (max_namelen + 1);
@@ -2197,7 +2196,7 @@
       for (octave_idx_type j = 0; j < nel; j++)
         {
 
-          for (octave_map::const_iterator i = m.begin (); i != m.end (); i++)
+          for (auto i = m.begin (); i != m.end (); i++)
             {
               const Cell elts = m.contents (i);
 
--- a/libinterp/corefcn/ls-oct-binary.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/ls-oct-binary.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -24,7 +24,8 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <istream>
+#include <ostream>
 #include <string>
 
 #include "byte-swap.h"
@@ -47,7 +48,6 @@
 #include "ov-cell.h"
 #include "ov.h"
 #include "pager.h"
-#include "pt-exp.h"
 #include "sysdep.h"
 #include "utils.h"
 #include "variables.h"
--- a/libinterp/corefcn/ls-oct-text.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/ls-oct-text.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -31,7 +31,8 @@
 
 #include <fstream>
 #include <iomanip>
-#include <iostream>
+#include <istream>
+#include <ostream>
 #include <sstream>
 #include <string>
 
@@ -58,7 +59,6 @@
 #include "oct-map.h"
 #include "ov-cell.h"
 #include "pager.h"
-#include "pt-exp.h"
 #include "unwind-prot.h"
 #include "utils.h"
 #include "variables.h"
@@ -252,7 +252,7 @@
     }
 
   if (! (name == ".nargin." || name == ".nargout."
-         || name == CELL_ELT_TAG || valid_identifier (name)))
+         || name == CELL_ELT_TAG || octave::valid_identifier (name)))
     error ("load: invalid identifier '%s' found in file '%s'",
            name.c_str (), filename.c_str ());
 
--- a/libinterp/corefcn/lsode.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/lsode.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -26,9 +26,6 @@
 
 #include <string>
 
-#include <iomanip>
-#include <iostream>
-
 #include "LSODE.h"
 #include "lo-mappers.h"
 
--- a/libinterp/corefcn/mappers.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/mappers.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -1214,6 +1214,7 @@
 %! result(double ("0":"9") + 1) = true;
 %! result(double ("a":"z") + 1) = true;
 %! assert (isalnum (charset), result);
+%!assert (isalnum(["Ä8Aa?"; "(Uß ;"]), logical ([1 1 1 1 1 0; 0 1 1 1 0 0]));
 
 %!error isalnum ()
 %!error isalnum (1, 2)
@@ -1242,6 +1243,7 @@
 %! result(double ("A":"Z") + 1) = true;
 %! result(double ("a":"z") + 1) = true;
 %! assert (isalpha (charset), result);
+%!assert (isalpha("Ä8Aa(Uß ;"), logical ([1 1 0 1 1 0 1 1 1 0 0]));
 
 %!error isalpha ()
 %!error isalpha (1, 2)
@@ -1317,6 +1319,7 @@
 %! result = false (1, 128);
 %! result(double ("0":"9") + 1) = true;
 %! assert (isdigit (charset), result);
+%!assert (isdigit("Ä8Aa(Uß ;"), logical ([0 0 1 0 0 0 0 0 0 0 0]));
 
 %!error isdigit ()
 %!error isdigit (1, 2)
@@ -1383,6 +1386,7 @@
 %! result = false (1, 128);
 %! result(34:127) = true;
 %! assert (isgraph (charset), result);
+%!assert (isgraph("Ä8Aa(Uß ;"), logical ([1 1 1 1 1 1 1 1 1 0 1]));
 
 %!error isgraph ()
 %!error isgraph (1, 2)
@@ -1408,6 +1412,7 @@
 %! result = false (1, 128);
 %! result(double ("a":"z") + 1) = true;
 %! assert (islower (charset), result);
+%!assert (islower("Ä8Aa(Uß ;"), logical ([0 0 0 0 1 0 0 1 1 0 0]));
 
 %!error islower ()
 %!error islower (1, 2)
@@ -1514,6 +1519,7 @@
 %! result = false (1, 128);
 %! result(33:127) = true;
 %! assert (isprint (charset), result);
+%!assert (isprint("Ä8Aa(Uß ;"), logical ([1 1 1 1 1 1 1 1 1 1 1]));
 
 %!error isprint ()
 %!error isprint (1, 2)
@@ -1542,6 +1548,7 @@
 %! result(92:97) = true;
 %! result(124:127) = true;
 %! assert (ispunct (charset), result);
+%!assert (ispunct("Ä8Aa(Uß ;"), logical ([0 0 0 0 0 1 0 0 0 0 1]));
 
 %!error ispunct ()
 %!error ispunct (1, 2)
@@ -1568,6 +1575,7 @@
 %! result = false (1, 128);
 %! result(double (" \f\n\r\t\v") + 1) = true;
 %! assert (isspace (charset), result);
+%!assert (isspace("Ä8Aa(Uß ;"), logical ([0 0 0 0 0 0 0 0 0 1 0]));
 
 %!error isspace ()
 %!error isspace (1, 2)
@@ -1593,6 +1601,7 @@
 %! result = false (1, 128);
 %! result(double ("A":"Z") + 1) = true;
 %! assert (isupper (charset), result);
+%!assert (isupper("Ä8Aa(Uß ;"), logical ([1 1 0 1 0 0 1 0 0 0 0]));
 
 %!error isupper ()
 %!error isupper (1, 2)
@@ -1620,6 +1629,7 @@
 %! result(double ("0":"9") + 1) = true;
 %! result(double ("a":"f") + 1) = true;
 %! assert (isxdigit (charset), result);
+%!assert (isxdigit("Ä8Aa(Uß ;"), logical ([0 0 1 1 1 0 0 0 0 0 0]));
 
 %!error isxdigit ()
 %!error isxdigit (1, 2)
@@ -2139,6 +2149,8 @@
 %!assert (tolower ({"ABC", "DEF", {"GHI", {"JKL"}}}), {"abc", "def", {"ghi", {"jkl"}}})
 %!assert (tolower (["ABC"; "DEF"]), ["abc"; "def"])
 %!assert (tolower ({["ABC"; "DEF"]}), {["abc";"def"]})
+%!assert (tolower (["ABCÄÖÜSS"; "abcäöüß"]), ["abcäöüss"; "abcäöüß"])
+%!assert (tolower (repmat ("ÄÖÜ", 2, 1, 3)), repmat ("äöü", 2, 1, 3))
 %!assert (tolower (68), 68)
 %!assert (tolower ({[68, 68; 68, 68]}), {[68, 68; 68, 68]})
 %!assert (tolower (68i), 68i)
@@ -2203,6 +2215,8 @@
 %!assert (toupper ({"abc", "def", {"ghi", {"jkl"}}}), {"ABC", "DEF", {"GHI", {"JKL"}}})
 %!assert (toupper (["abc"; "def"]), ["ABC"; "DEF"])
 %!assert (toupper ({["abc"; "def"]}), {["ABC";"DEF"]})
+%!assert (toupper (["ABCÄÖÜSS"; "abcäöüß"]), ["ABCÄÖÜSS"; "ABCÄÖÜSS"])
+%!assert (toupper (repmat ("äöü", 2, 1, 3)), repmat ("ÄÖÜ", 2, 1, 3))
 %!assert (toupper (100), 100)
 %!assert (toupper ({[100, 100; 100, 100]}), {[100, 100; 100, 100]})
 %!assert (toupper (100i), 100i)
--- a/libinterp/corefcn/mex.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/mex.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -1163,7 +1163,7 @@
         for (size_t i = 0; i < tmp_len; i++)
           cpr[m*i+j] = static_cast<mxChar> (ptr[i]);
 
-        for (size_t i = tmp_len; i < static_cast<size_t>(nc); i++)
+        for (size_t i = tmp_len; i < static_cast<size_t> (nc); i++)
           cpr[m*i+j] = static_cast<mxChar> (' ');
       }
   }
@@ -2132,7 +2132,7 @@
     // We can't use mex::free here because it modifies memlist.
     while (! memlist.empty ())
       {
-        std::set<void *>::iterator p = memlist.begin ();
+        auto p = memlist.begin ();
         xfree (*p);
         memlist.erase (p);
       }
@@ -2140,7 +2140,7 @@
     // We can't use mex::free_value here because it modifies arraylist.
     while (! arraylist.empty ())
       {
-        std::set<mxArray *>::iterator p = arraylist.begin ();
+        auto p = arraylist.begin ();
         delete *p;
         arraylist.erase (p);
       }
@@ -2230,7 +2230,7 @@
       {
         v = std::realloc (ptr, n);
 
-        std::set<void *>::iterator p = memlist.find (ptr);
+        auto p = memlist.find (ptr);
 
         if (v && p != memlist.end ())
           {
@@ -2259,7 +2259,7 @@
       {
         unmark (ptr);
 
-        std::set<void *>::iterator p = global_memlist.find (ptr);
+        auto p = global_memlist.find (ptr);
 
         if (p != global_memlist.end ())
           {
@@ -2296,7 +2296,7 @@
   // made persistent, or because it was already freed.
   void unmark (void *ptr)
   {
-    std::set<void *>::iterator p = memlist.find (ptr);
+    auto p = memlist.find (ptr);
 
     if (p != memlist.end ())
       memlist.erase (p);
@@ -2314,7 +2314,7 @@
 
   void unmark_array (mxArray *ptr)
   {
-    std::set<mxArray *>::iterator p = arraylist.find (ptr);
+    auto p = arraylist.find (ptr);
 
     if (p != arraylist.end ())
       arraylist.erase (p);
@@ -2334,7 +2334,7 @@
   // Unmark a pointer as one we allocated.
   void unmark_foreign (void *ptr)
   {
-    std::set<void *>::iterator p = foreign_memlist.find (ptr);
+    auto p = foreign_memlist.find (ptr);
 
     if (p != foreign_memlist.end ())
       foreign_memlist.erase (p);
@@ -2357,7 +2357,7 @@
   {
     bool inlist = false;
 
-    std::set<mxArray *>::iterator p = arraylist.find (ptr);
+    auto p = arraylist.find (ptr);
 
     if (p != arraylist.end ())
       {
@@ -2416,7 +2416,7 @@
   // Unmark a pointer as one we allocated.
   void global_unmark (void *ptr)
   {
-    std::set<void *>::iterator p = global_memlist.find (ptr);
+    auto p = global_memlist.find (ptr);
 
     if (p != global_memlist.end ())
       global_memlist.erase (p);
@@ -3374,8 +3374,18 @@
 void
 mexErrMsgTxt (const char *s)
 {
-  if (s && strlen (s) > 0)
-    error ("%s: %s", mexFunctionName (), s);
+  size_t len;
+
+  if (s && (len = strlen (s)) > 0)
+    {
+      if (s[len - 1] == '\n')
+        {
+          std::string s_tmp (s, len - 1);
+          error ("%s: %s\n", mexFunctionName (), s_tmp.c_str ());
+        }
+      else
+        error ("%s: %s", mexFunctionName (), s);
+    }
   else
     {
       // For compatibility with Matlab, print an empty message.
@@ -3409,7 +3419,24 @@
 void
 mexWarnMsgTxt (const char *s)
 {
-  warning ("%s", s);
+  size_t len;
+
+  if (s && (len = strlen (s)) > 0)
+    {
+      if (s[len - 1] == '\n')
+        {
+          std::string s_tmp (s, len - 1);
+          warning ("%s\n", s_tmp.c_str ());
+        }
+      else
+        warning ("%s", s);
+    }
+  else
+    {
+      // For compatibility with Matlab, print an empty message.
+      // Octave's warning routine requires a non-null input so use a SPACE.
+      warning (" ");
+    }
 }
 
 void
@@ -3437,7 +3464,7 @@
   int retval;
   va_list args;
   va_start (args, fmt);
-  retval = octave_vformat (octave_stdout, fmt, args);
+  retval = octave::vformat (octave_stdout, fmt, args);
   va_end (args);
   return retval;
 }
@@ -3662,7 +3689,7 @@
     {
       const char *fname = mexFunctionName ();
 
-      std::map<std::string,int>::iterator p = mex_lock_count.find (fname);
+      auto p = mex_lock_count.find (fname);
 
       if (p != mex_lock_count.end ())
         {
--- a/libinterp/corefcn/module.mk	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/module.mk	Fri Aug 10 09:09:51 2018 +0200
@@ -41,7 +41,6 @@
   %reldir%/gl2ps-print.h \
   %reldir%/graphics-handle.h \
   %reldir%/graphics-toolkit.h \
-  %reldir%/gripes.h \
   %reldir%/gtk-manager.h \
   %reldir%/help.h \
   %reldir%/hook-fcn.h \
@@ -79,6 +78,7 @@
   %reldir%/pr-flt-fmt.h \
   %reldir%/pr-output.h \
   %reldir%/procstream.h \
+  %reldir%/settings.h \
   %reldir%/sighandlers.h \
   %reldir%/sparse-xdiv.h \
   %reldir%/sparse-xpow.h \
@@ -86,6 +86,7 @@
   %reldir%/symscope.h \
   %reldir%/symtab.h \
   %reldir%/sysdep.h \
+  %reldir%/text-engine.h \
   %reldir%/text-renderer.h \
   %reldir%/toplev.h \
   %reldir%/txt-eng.h \
@@ -165,7 +166,6 @@
   %reldir%/gl2ps-print.cc \
   %reldir%/graphics-toolkit.cc \
   %reldir%/graphics.cc \
-  %reldir%/gripes.cc \
   %reldir%/gsvd.cc \
   %reldir%/gtk-manager.cc \
   %reldir%/hash.cc \
@@ -224,6 +224,7 @@
   %reldir%/rcond.cc \
   %reldir%/regexp.cc \
   %reldir%/schur.cc \
+  %reldir%/settings.cc \
   %reldir%/sighandlers.cc \
   %reldir%/sparse-xdiv.cc \
   %reldir%/sparse-xpow.cc \
@@ -242,11 +243,11 @@
   %reldir%/syscalls.cc \
   %reldir%/sysdep.cc \
   %reldir%/time.cc \
+  %reldir%/text-engine.cc \
   %reldir%/text-renderer.cc \
   %reldir%/toplev.cc \
   %reldir%/tril.cc \
   %reldir%/tsearch.cc \
-  %reldir%/txt-eng.cc \
   %reldir%/typecast.cc \
   %reldir%/urlwrite.cc \
   %reldir%/url-handle-manager.cc \
@@ -260,8 +261,8 @@
 
 ## Special rules for sources which must be built before rest of compilation.
 
-%reldir%/default-defs.h: %reldir%/default-defs.in.h build-aux/subst-default-vals.sh | %reldir%/$(octave_dirstamp)
-	$(AM_V_GEN)$(call simple-filter-rule,build-aux/subst-default-vals.sh)
+%reldir%/default-defs.h: %reldir%/default-defs.in.h build-aux/subst-config-vals.sh | %reldir%/$(octave_dirstamp)
+	$(AM_V_GEN)$(call simple-filter-rule,build-aux/subst-config-vals.sh)
 
 %reldir%/graphics.h: %reldir%/graphics.in.h %reldir%/genprops.awk | %reldir%/$(octave_dirstamp)
 	$(AM_V_GEN)rm -f $@-t && \
@@ -299,9 +300,6 @@
 
 %reldir%/oct-tex-lexer.cc: LEX_OUTPUT_ROOT := lex.octave_tex_
 
-%reldir%/oct-tex-parser.yy: %reldir%/oct-tex-parser.in.yy
-	$(AM_V_GEN)$(call subst-bison-api-decls,octave_tex_)
-
 noinst_LTLIBRARIES += \
   %reldir%/libcorefcn.la
 
@@ -316,10 +314,6 @@
   $(LLVM_CPPFLAGS) \
   $(Z_CPPFLAGS)
 
-%canon_reldir%_libcorefcn_la_CFLAGS = $(AM_CFLAGS) $(WARN_CFLAGS)
-
-%canon_reldir%_libcorefcn_la_CXXFLAGS = $(AM_CXXFLAGS) $(WARN_CXXFLAGS) $(LLVM_CXXFLAGS)
-
 libinterp_EXTRA_DIST += \
   %reldir%/default-defs.in.h \
   %reldir%/genprops.awk \
@@ -329,7 +323,6 @@
   %reldir%/mxarray.in.h \
   %reldir%/oct-errno.in.cc \
   %reldir%/oct-tex-lexer.in.ll \
-  %reldir%/oct-tex-parser.in.yy \
   %reldir%/oct-tex-symbols.in
 
 GEN_CONFIG_SHELL += \
--- a/libinterp/corefcn/mxarray.in.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/mxarray.in.h	Fri Aug 10 09:09:51 2018 +0200
@@ -303,12 +303,6 @@
 
   mxArray_base (const mxArray_base&) { }
 
-  OCTAVE_DEPRECATED (4.2, "use 'err_invalid_type' instead")
-  void invalid_type_error (void) const
-  {
-    error ("invalid type for operation");
-  }
-
   OCTAVE_NORETURN void err_invalid_type (void) const
   {
     error ("invalid type for operation");
--- a/libinterp/corefcn/oct-hist.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/oct-hist.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -50,7 +50,6 @@
 #include "str-vec.h"
 #include "unistd-wrappers.h"
 
-#include "defaults.h"
 #include "defun.h"
 #include "error.h"
 #include "errwarn.h"
--- a/libinterp/corefcn/oct-iostrm.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/oct-iostrm.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -24,7 +24,8 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <istream>
+#include <ostream>
 
 #include "error.h"
 #include "oct-iostrm.h"
--- a/libinterp/corefcn/oct-map.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/oct-map.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -65,14 +65,14 @@
 octave_idx_type
 octave_fields::getfield (const std::string& field) const
 {
-  fields_rep::iterator p = rep->find (field);
+  auto p = rep->find (field);
   return (p != rep->end ()) ? p->second : -1;
 }
 
 octave_idx_type
 octave_fields::getfield (const std::string& field)
 {
-  fields_rep::iterator p = rep->find (field);
+  auto p = rep->find (field);
   if (p != rep->end ())
     return p->second;
   else
@@ -86,7 +86,7 @@
 octave_idx_type
 octave_fields::rmfield (const std::string& field)
 {
-  fields_rep::iterator p = rep->find (field);
+  auto p = rep->find (field);
   if (p == rep->end ())
     return -1;
   else
@@ -126,8 +126,8 @@
 {
   bool retval = true;
 
-  iterator p = begin ();
-  iterator q = other.begin ();
+  auto p = begin ();
+  auto q = other.begin ();
   for (; p != end () && q != other.end (); p++, q++)
     {
       if (p->first == q->first)
@@ -1193,7 +1193,7 @@
                     const Cell& rhs)
 {
   Cell tmp;
-  iterator p = seek (k);
+  auto p = seek (k);
   Cell& ref = (p != end () ? contents (p) : tmp);
 
   if (&ref == &tmp)
@@ -1322,11 +1322,11 @@
 {
   if (nfields () == rb.nfields ())
     {
-      for (const_iterator pa = begin (); pa != end (); pa++)
+      for (auto pa = cbegin (); pa != cend (); pa++)
         {
-          const_iterator pb = rb.seek (key (pa));
+          auto pb = rb.seek (key (pa));
 
-          if (pb == rb.end ())
+          if (pb == rb.cend ())
             error ("field name mismatch in structure concatenation");
 
           contents(pa).insert (rb.contents (pb), ra_idx);
--- a/libinterp/corefcn/oct-map.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/oct-map.h	Fri Aug 10 09:09:51 2018 +0200
@@ -103,6 +103,9 @@
   const_iterator begin (void) const { return rep->begin (); }
   const_iterator end (void) const { return rep->end (); }
 
+  const_iterator cbegin (void) const { return rep->cbegin (); }
+  const_iterator cend (void) const { return rep->cend (); }
+
   std::string key (const_iterator p) const { return p->first; }
   octave_idx_type index (const_iterator p) const { return p->second; }
 
@@ -184,6 +187,9 @@
   const_iterator begin (void) const { return xkeys.begin (); }
   const_iterator end (void) const { return xkeys.end (); }
 
+  const_iterator cbegin (void) const { return xkeys.cbegin (); }
+  const_iterator cend (void) const { return xkeys.cend (); }
+
   const_iterator seek (const std::string& k) const { return xkeys.seek (k); }
 
   std::string key (const_iterator p) const
@@ -307,6 +313,9 @@
   const_iterator begin (void) const { return xkeys.begin (); }
   const_iterator end (void) const { return xkeys.end (); }
 
+  const_iterator cbegin (void) const { return xkeys.cbegin (); }
+  const_iterator cend (void) const { return xkeys.cend (); }
+
   const_iterator seek (const std::string& k) const { return xkeys.seek (k); }
 
   std::string key (const_iterator p) const
--- a/libinterp/corefcn/oct-prcstrm.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/oct-prcstrm.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -39,8 +39,8 @@
 octave_iprocstream::octave_iprocstream (const std::string& n,
                                         std::ios::openmode arg_md,
                                         octave::mach_info::float_format ff)
-  : octave_stdiostream (n, octave_popen (n.c_str (), "r"),
-                        arg_md, ff, octave_pclose)
+  : octave_stdiostream (n, octave::popen (n.c_str (), "r"),
+                        arg_md, ff, octave::pclose)
 { }
 
 octave_iprocstream::~octave_iprocstream (void)
@@ -58,8 +58,8 @@
 octave_oprocstream::octave_oprocstream (const std::string& n,
                                         std::ios::openmode arg_md,
                                         octave::mach_info::float_format ff)
-  : octave_stdiostream (n, octave_popen (n.c_str (), "w"),
-                        arg_md, ff, octave_pclose)
+  : octave_stdiostream (n, octave::popen (n.c_str (), "w"),
+                        arg_md, ff, octave::pclose)
 { }
 
 octave_oprocstream::~octave_oprocstream (void)
--- a/libinterp/corefcn/oct-procbuf.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/oct-procbuf.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -26,7 +26,7 @@
 
 #include <cerrno>
 
-#include <iostream>
+#include <iomanip>
 
 // FIXME: we would prefer to avoid including these directly in Octave
 // sources, but eliminating them is complicated by the mingling of
@@ -78,7 +78,7 @@
   if (is_open ())
     return 0;
 
-  f = (octave_popen (command, (mode & std::ios::in) ? "r" : "w"));
+  f = (octave::popen (command, (mode & std::ios::in) ? "r" : "w"));
 
   if (! f)
     return 0;
@@ -183,7 +183,7 @@
 
   if (f)
     {
-      wstatus = octave_pclose (f);
+      wstatus = octave::pclose (f);
       f = 0;
     }
 
--- a/libinterp/corefcn/oct-stdstrm.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/oct-stdstrm.h	Fri Aug 10 09:09:51 2018 +0200
@@ -25,6 +25,8 @@
 
 #include "octave-config.h"
 
+#include <iomanip>
+
 #include "oct-stream.h"
 #include "c-file-ptr-stream.h"
 
--- a/libinterp/corefcn/oct-stream.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/oct-stream.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -91,9 +91,9 @@
       {
         dval = tc.double_value ();
       }
-    catch (const octave::execution_exception&)
-      {
-        octave::interpreter::recover_from_exception ();
+    catch (const execution_exception&)
+      {
+        interpreter::recover_from_exception ();
 
         conv_err = 1;
       }
@@ -102,7 +102,7 @@
       {
         if (! lo_ieee_isnan (dval))
           {
-            int ival = octave::math::nint (dval);
+            int ival = math::nint (dval);
 
             if (ival == dval)
               retval = ival;
@@ -122,9 +122,9 @@
     octave_idx_type retval = -1;
 
     if (lo_ieee_isnan (d))
-      ::error ("%s: NaN is invalid as size specification", who.c_str ());
-
-    if (octave::math::isinf (d))
+      ::error ("%s: NaN invalid as size specification", who.c_str ());
+
+    if (math::isinf (d))
       retval = -1;
     else
       {
@@ -136,7 +136,7 @@
           ::error ("%s: dimension too large for Octave's index type",
                    who.c_str ());
 
-        retval = octave::math::nint_big (d);
+        retval = math::nint_big (d);
       }
 
     return retval;
@@ -169,18 +169,26 @@
       {
         dnr = size(0);
 
-        if (octave::math::isinf (dnr))
-          ::error ("%s: invalid size specification", who.c_str ());
+        if (math::isinf (dnr))
+          ::error ("%s: infinite value invalid as size specification",
+                   who.c_str ());
 
         dnc = size(1);
       }
     else
-      ::error ("%s: invalid size specification", who.c_str ());
+      ::error ("%s: invalid size specification (must be 2-D)", who.c_str ());
 
     nr = get_size (dnr, who);
 
     if (dnc >= 0.0)
-      nc = get_size (dnc, who);
+      {
+        nc = get_size (dnc, who);
+
+        // Check for overflow.
+        if (nr > 0 && nc > 0
+            && nc > std::numeric_limits<octave_idx_type>::max () / nr)
+          ::error ("%s: size too large for Octave's index type", who.c_str ());
+      }
   }
 
   static std::string
@@ -3391,7 +3399,7 @@
                               Array<octave_idx_type> row, int& done_after)
   {
     const textscan_format_elt *elem = fmt_list.first ();
-    std::list<octave_value>::iterator out = retval.begin ();
+    auto out = retval.begin ();
     bool no_conversions = true;
     bool done = false;
     bool conversion_failed = false;       // Record for ReturnOnError
@@ -4574,7 +4582,7 @@
                          octave_idx_type& conversion_count,
                          const std::string& who)
   {
-    if (octave::application::interactive () && file_number () == 0)
+    if (application::interactive () && file_number () == 0)
       ::error ("%s: unable to read from stdin while running interactively",
                who.c_str ());
 
@@ -4902,8 +4910,8 @@
                       is.clear (is.rdstate () & (~std::ios::failbit));
 
                     // FIXME: is this the right thing to do?
-                    if (octave::application::interactive ()
-                        && ! octave::application::forced_interactive ()
+                    if (application::interactive ()
+                        && ! application::forced_interactive ()
                         && name () == "stdin")
                       {
                         is.clear ();
@@ -5198,8 +5206,8 @@
 
         // FIXME: is this the right thing to do?
 
-        if (octave::application::interactive ()
-            && ! octave::application::forced_interactive ()
+        if (application::interactive ()
+            && ! application::forced_interactive ()
             && name () == "stdin")
           {
             // Skip to end of line.
@@ -5292,7 +5300,7 @@
                             const std::string& who,
                             octave_idx_type& read_count)
   {
-    if (octave::application::interactive () && file_number () == 0)
+    if (application::interactive () && file_number () == 0)
       ::error ("%s: unable to read from stdin while running interactively",
                who.c_str ());
 
@@ -5304,7 +5312,7 @@
       invalid_operation (who, "reading");
     else
       {
-        octave::textscan scanner (who);
+        textscan scanner (who);
 
         retval = scanner.scan (*isp, fmt, ntimes, options, read_count);
       }
@@ -5437,7 +5445,7 @@
                       {
                         double dval = val(idx);
 
-                        if (octave::math::x_nint (dval) != dval || dval < 0 || dval > 255)
+                        if (math::x_nint (dval) != dval || dval < 0 || dval > 255)
                           break;
                       }
 
@@ -5464,7 +5472,7 @@
                   {
                     double dval = retval.double_value ();
 
-                    if (octave::math::x_nint (dval) == dval && dval >= 0 && dval < 256)
+                    if (math::x_nint (dval) == dval && dval >= 0 && dval < 256)
                       retval = static_cast<char> (dval);
                   }
               }
@@ -5513,8 +5521,8 @@
 
     double dval = val.double_value (true);
 
-    if (octave::math::x_nint (dval) == dval)
-      retval = octave::math::nint (dval);
+    if (math::x_nint (dval) == dval)
+      retval = math::nint (dval);
     else
       curr_state = conversion_error;
 
@@ -5533,15 +5541,15 @@
     switch (nsa)
       {
       case 2:
-        retval = octave_format (os, fmt, sa_1, sa_2, arg);
+        retval = octave::format (os, fmt, sa_1, sa_2, arg);
         break;
 
       case 1:
-        retval = octave_format (os, fmt, sa_1, arg);
+        retval = octave::format (os, fmt, sa_1, arg);
         break;
 
       case 0:
-        retval = octave_format (os, fmt, arg);
+        retval = octave::format (os, fmt, arg);
         break;
 
       default:
@@ -5553,7 +5561,7 @@
   }
 
   static size_t
-  do_printf_string (std::ostream& os, const octave::printf_format_elt *elt,
+  do_printf_string (std::ostream& os, const printf_format_elt *elt,
                     int nsa, int sa_1, int sa_2, const std::string& arg,
                     const std::string& who)
   {
@@ -5608,7 +5616,7 @@
       {
         double dval = val.double_value (true);
 
-        if (dval == octave::math::round (dval) && dval <= limit)
+        if (dval == math::round (dval) && dval <= limit)
           return true;
       }
 
@@ -5635,7 +5643,7 @@
 
         uint64_t limit = std::numeric_limits<uint64_t>::max ();
 
-        if (dval == octave::math::round (dval) && dval >= 0 && dval <= limit)
+        if (dval == math::round (dval) && dval >= 0 && dval <= limit)
           return true;
       }
 
@@ -5643,7 +5651,7 @@
   }
 
   static std::string
-  switch_to_g_format (const octave::printf_format_elt *elt)
+  switch_to_g_format (const printf_format_elt *elt)
   {
     std::string tfmt = elt->text;
 
@@ -6303,7 +6311,7 @@
                     octave_idx_type elts_read,
                     octave_idx_type nr, octave_idx_type nc, bool swap,
                     bool do_float_fmt_conv, bool do_NA_conv,
-                    octave::mach_info::float_format from_flt_fmt)
+                    mach_info::float_format from_flt_fmt)
   {
     typedef typename DST_T::element_type dst_elt_type;
 
@@ -6313,8 +6321,7 @@
 
     octave_idx_type j = 0;
 
-    for (std::list<void *>::const_iterator it = input_buf_list.begin ();
-         it != input_buf_list.end (); it++)
+    for (auto it = input_buf_list.cbegin (); it != input_buf_list.cend (); it++)
       {
         SRC_T *data = static_cast<SRC_T *> (*it);
 
@@ -6330,7 +6337,7 @@
                     else if (do_float_fmt_conv)
                       do_float_format_conversion (&data[i], sizeof (SRC_T),
                                                   1, from_flt_fmt,
-                                                  octave::mach_info::native_float_format ());
+                                                  mach_info::native_float_format ());
 
                     dst_elt_type tmp (data[i]);
 
@@ -6350,7 +6357,7 @@
                     else if (do_float_fmt_conv)
                       do_float_format_conversion (&data[i], sizeof (SRC_T),
                                                   1, from_flt_fmt,
-                                                  octave::mach_info::native_float_format ());
+                                                  mach_info::native_float_format ());
 
                     conv_data[j] = data[i];
                   }
@@ -6394,7 +6401,7 @@
     (std::list<void *>& input_buf_list, octave_idx_type input_buf_elts,
      octave_idx_type elts_read, octave_idx_type nr, octave_idx_type nc,
      bool swap, bool do_float_fmt_conv, bool do_NA_conv,
-     octave::mach_info::float_format from_flt_fmt);
+     mach_info::float_format from_flt_fmt);
 
 #define TABLE_ELT(T, U, V, W)                                           \
   conv_fptr_table[oct_data_conv::T][oct_data_conv::U] = convert_and_copy<V, W>
@@ -6512,19 +6519,19 @@
   {
     octave_value retval;
 
+    if (! stream_ok ())
+      return retval;
+
     octave_idx_type nr = -1;
     octave_idx_type nc = -1;
 
     bool one_elt_size_spec = false;
 
-    if (! stream_ok ())
-      return retval;
-
-    // FIXME: we may eventually want to make this extensible.
-
-    // FIXME: we need a better way to ensure that this
-    // numbering stays consistent with the order of the elements in the
-    // data_type enum in the oct_data_conv class.
+    // FIXME: We may eventually want to make this extensible.
+
+    // FIXME: We need a better way to ensure that this numbering stays
+    // consistent with the order of the elements in the data_type enum in the
+    // oct_data_conv class.
 
     // Expose this in a future version?
     size_t char_count = 0;
@@ -6569,9 +6576,6 @@
           nr = nc = 0;
       }
 
-    // FIXME: Ensure that this does not overflow.
-    //        Maybe try comparing nr * nc computed in double with
-    //        std::numeric_limits<octave_idx_type>::max ();
     octave_idx_type elts_to_read = nr * nc;
 
     bool read_to_eof = elts_to_read < 0;
@@ -6596,8 +6600,7 @@
 
     assert (input_buf_size >= 0);
 
-    // Must also work and return correct type object
-    // for 0 elements to read.
+    // Must also work and return correct type object for 0 elements to read.
     std::istream *isp = input_stream ();
 
     if (! isp)
@@ -6606,7 +6609,18 @@
       {
         std::istream& is = *isp;
 
-        std::list <void *> input_buf_list;
+        // Initialize eof_pos variable just once per function call
+        off_t eof_pos = 0;
+        off_t cur_pos = 0;
+        if (skip != 0 && is && ! is.eof ())
+          {
+            cur_pos = is.tellg ();
+            is.seekg (0, is.end);
+            eof_pos = is.tellg ();
+            is.seekg (cur_pos, is.beg);
+          }
+
+        std::list<void *> input_buf_list;
 
         while (is && ! is.eof ()
                && (read_to_eof || tmp_count < elts_to_read))
@@ -6626,6 +6640,7 @@
             size_t gcount = is.gcount ();
 
             char_count += gcount;
+            cur_pos += gcount;
 
             octave_idx_type nel = gcount / input_elt_size;
 
@@ -6633,30 +6648,22 @@
 
             input_buf_list.push_back (input_buf);
 
-            if (is && skip != 0 && nel == block_size)
+            if (skip != 0 && nel == block_size && is)
               {
-                // Seek to skip.
+                // Attempt to skip.
                 // If skip would move past EOF, position at EOF.
-
-                off_t orig_pos = tell ();
-
-                seek (0, SEEK_END);
-
-                off_t eof_pos = tell ();
-
-                // Is it possible for this to fail to return us to
-                // the original position?
-                seek (orig_pos, SEEK_SET);
-
-                off_t remaining = eof_pos - orig_pos;
+                off_t remaining = eof_pos - cur_pos;
 
                 if (remaining < skip)
-                  seek (0, SEEK_END);
+                  {
+                    is.seekg (0, is.end);
+                    cur_pos = eof_pos;
+                  }
                 else
-                  seek (skip, SEEK_CUR);
-
-                if (! is)
-                  break;
+                  {
+                    is.seekg (skip, is.cur);
+                    cur_pos += skip;
+                  }
               }
           }
 
@@ -6777,18 +6784,18 @@
   static bool
   convert_data (const T *data, void *conv_data, octave_idx_type n_elts,
                 oct_data_conv::data_type output_type,
-                octave::mach_info::float_format flt_fmt)
+                mach_info::float_format flt_fmt)
   {
     bool retval = true;
 
     bool swap = false;
 
-    if (octave::mach_info::words_big_endian ())
-      swap = (flt_fmt == octave::mach_info::flt_fmt_ieee_little_endian);
+    if (mach_info::words_big_endian ())
+      swap = (flt_fmt == mach_info::flt_fmt_ieee_little_endian);
     else
-      swap = (flt_fmt == octave::mach_info::flt_fmt_ieee_big_endian);
-
-    bool do_float_conversion = flt_fmt != octave::mach_info::float_format ();
+      swap = (flt_fmt == mach_info::flt_fmt_ieee_big_endian);
+
+    bool do_float_conversion = flt_fmt != mach_info::float_format ();
 
     typedef typename ultimate_element_type<T>::type ult_elt_type;
 
@@ -7283,7 +7290,7 @@
     return retval;
   }
 
-  stream_list::stream_list (interpreter&)
+  stream_list::stream_list (interpreter& interp)
     : list (), lookup_cache (list.end ()), m_stdin_file (-1),
       m_stdout_file (-1), m_stderr_file (-1)
   {
@@ -7294,7 +7301,10 @@
 
     // FIXME: we should be accessing octave_stdout from the interpreter.
 
-    stream stdout_stream = octave_ostream::create (&octave_stdout, "stdout");
+    output_system& output_sys = interp.get_output_system ();
+
+    stream stdout_stream
+      = octave_ostream::create (&(output_sys.__stdout__ ()), "stdout");
 
     stream stderr_stream = octave_ostream::create (&std::cerr, "stderr");
 
@@ -7385,7 +7395,7 @@
     if (fid < 3)
       err_invalid_file_id (fid, who);
 
-    ostrl_map::iterator iter = list.find (fid);
+    auto iter = list.find (fid);
 
     if (iter == list.end ())
       err_invalid_file_id (fid, who);
@@ -7432,7 +7442,7 @@
         list[2].flush ();
       }
 
-    for (ostrl_map::iterator iter = list.begin (); iter != list.end (); )
+    for (auto iter = list.begin (); iter != list.end (); )
       {
         int fid = iter->first;
         if (fid < 3)  // Don't delete stdin, stdout, stderr
--- a/libinterp/corefcn/oct-tex-lexer.in.ll	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/oct-tex-lexer.in.ll	Fri Aug 10 09:09:51 2018 +0200
@@ -62,7 +62,9 @@
 
 #include "unistd-wrappers.h"
 
-#include "txt-eng.h"
+#include "text-engine.h"
+
+// oct-tex-parser.h must be included after text-engine.h
 #include "oct-tex-parser.h"
 
 // FIXME: with bison 3.x, OCTAVE_TEX_STYPE appears in the generated
@@ -200,7 +202,7 @@
 void *
 octave_tex_realloc (void *ptr, yy_size_t size, yyscan_t)
 {
-  return realloc (ptr, size);
+return realloc (ptr, size);
 }
 
 void
@@ -209,40 +211,41 @@
   free (ptr);
 }
 
-bool
-text_parser_tex::init_lexer (const std::string& s)
+namespace octave
 {
-  if (! scanner)
-    octave_tex_lex_init (&scanner);
+  bool text_parser_tex::init_lexer (const std::string& s)
+  {
+    if (! scanner)
+      octave_tex_lex_init (&scanner);
 
-  if (scanner)
-    {
-      if (buffer_state)
-        {
-          octave_tex__delete_buffer (reinterpret_cast<YY_BUFFER_STATE> (buffer_state),
-                                     scanner);
-          buffer_state = nullptr;
-        }
+    if (scanner)
+      {
+        if (buffer_state)
+          {
+            octave_tex__delete_buffer (reinterpret_cast<YY_BUFFER_STATE> (buffer_state),
+                                       scanner);
+            buffer_state = nullptr;
+          }
 
-      buffer_state = octave_tex__scan_bytes (s.data (), s.length (), scanner);
-    }
+        buffer_state = octave_tex__scan_bytes (s.data (), s.length (), scanner);
+      }
 
-  return (scanner && buffer_state);
-}
+    return (scanner && buffer_state);
+  }
 
-void
-text_parser_tex::destroy_lexer (void)
-{
-  if (buffer_state)
-    {
-      octave_tex__delete_buffer (reinterpret_cast<YY_BUFFER_STATE> (buffer_state),
-                                 scanner);
-      buffer_state = nullptr;
-    }
+  void text_parser_tex::destroy_lexer (void)
+  {
+    if (buffer_state)
+      {
+        octave_tex__delete_buffer (reinterpret_cast<YY_BUFFER_STATE> (buffer_state),
+                                   scanner);
+        buffer_state = nullptr;
+      }
 
-  if (scanner)
-    {
-      octave_tex_lex_destroy (scanner);
-      scanner = nullptr;
-    }
+    if (scanner)
+      {
+        octave_tex_lex_destroy (scanner);
+        scanner = nullptr;
+      }
+  }
 }
--- a/libinterp/corefcn/oct-tex-parser.in.yy	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,229 +0,0 @@
-/*
-
-Copyright (C) 2013-2018 Michael Goffioul
-
-This file is part of Octave.
-
-Octave is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-Octave is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<https://www.gnu.org/licenses/>.
-
-*/
-
-%{
-
-#define YYDEBUG 1
-
-#if defined (HAVE_CONFIG_H)
-#  include "config.h"
-#endif
-
-#include "txt-eng.h"
-#include "oct-tex-parser.h"
-
-extern int octave_tex_lex (YYSTYPE *, void *);
-static void yyerror (text_parser_tex& parser, const char *s);
-
-#define scanner parser.get_scanner ()
-#define yyalloc octave_tex_yyalloc
-
-#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
-   // Disable this warning for code that is generated by Bison,
-   // including grammar rules.  Push the current state so we can
-   // restore the warning state prior to functions we define at
-   // the bottom of the file.
-#  pragma GCC diagnostic push
-#  pragma GCC diagnostic ignored "-Wold-style-cast"
-#endif
-
-%}
-
-%API_PREFIX_DECL%
-
-%define api.pure
-%parse-param { text_parser_tex& parser }
-%lex-param { void *scanner }
-
-%code requires {#include <string>}
-
-%union
-{
-  // Leaf symbols produced by the scanner.
-  char                       ch;
-  double                     num;
-  int                        sym;
-
-  // Used for string buffering.
-  std::string*               str;
-
-  // Objects produced by the parser.
-  text_element*              e_base;
-  text_element_list*         e_list;
-}
-
-%token BF IT SL RM
-%token FONTNAME FONTSIZE
-%token COLOR COLOR_RGB
-%token START END SUPER SUB
-%token<ch> CH
-%token<num> NUM
-%token<sym> SYM
-
-%type<str> simple_string
-%type<e_base> string_element symbol_element
-%type<e_base> superscript_element subscript_element combined_script_element
-%type<e_base> font_modifier_element fontname_element fontsize_element
-%type<e_base> color_element
-%type<e_list> string_element_list scoped_string_element_list
-
-// Make sure there's no memory leak on parse error.
-%destructor { } <ch> <num> <sym>
-%destructor { delete $$; } <*>
-
-%nonassoc SCRIPT
-%nonassoc SUB SUPER
-
-%nonassoc STR
-%nonassoc CH
-
-%start string
-
-%%
-
-simple_string                   : CH
-                                  { $$ = new std::string (1, $1); }
-                                | simple_string CH
-                                  { $1->append (1, $2); $$ = $1; }
-                                ;
-
-symbol_element                  : SYM
-                                  { $$ = new text_element_symbol ($1); }
-                                ;
-
-font_modifier_element           : BF
-                                  { $$ = new text_element_fontstyle (text_element_fontstyle::bold); }
-                                | IT
-                                  { $$ = new text_element_fontstyle (text_element_fontstyle::italic); }
-                                | SL
-                                  { $$ = new text_element_fontstyle (text_element_fontstyle::oblique); }
-                                | RM
-                                  { $$ = new text_element_fontstyle (text_element_fontstyle::normal); }
-                                ;
-
-fontsize_element                : FONTSIZE START NUM END
-                                  { $$ = new text_element_fontsize ($3); }
-                                ;
-
-fontname_element                : FONTNAME START simple_string END
-                                  {
-                                    $$ = new text_element_fontname (*$3);
-                                    delete $3;
-                                  }
-                                ;
-
-color_element                   : COLOR START simple_string END
-                                  {
-                                    $$ = new text_element_color (*$3);
-                                    delete $3;
-                                  }
-                                | COLOR_RGB START NUM NUM NUM END
-                                  {
-                                    $$ = new text_element_color ($3, $4, $5);
-                                  }
-                                ;
-
-string_element                  : simple_string %prec STR
-                                  {
-                                    $$ = new text_element_string (*$1);
-                                    delete $1;
-                                  }
-                                | scoped_string_element_list
-                                  { $$ = $1; }
-                                | symbol_element
-                                | font_modifier_element
-                                | fontsize_element
-                                | fontname_element
-                                | color_element
-                                | superscript_element %prec SCRIPT
-                                | subscript_element %prec SCRIPT
-                                | combined_script_element
-                                ;
-
-superscript_element             : SUPER CH
-                                  { $$ = new text_element_superscript ($2); }
-                                | SUPER scoped_string_element_list
-                                  { $$ = new text_element_superscript ($2); }
-                                | SUPER symbol_element
-                                  { $$ = new text_element_superscript ($2); }
-                                ;
-
-subscript_element               : SUB CH
-                                  { $$ = new text_element_subscript ($2); }
-                                | SUB scoped_string_element_list
-                                  { $$ = new text_element_subscript ($2); }
-                                | SUB symbol_element
-                                  { $$ = new text_element_subscript ($2); }
-                                ;
-
-combined_script_element         : subscript_element superscript_element
-                                  { $$ = new text_element_combined ($1, $2); }
-                                | superscript_element subscript_element
-                                  { $$ = new text_element_combined ($1, $2); }
-                                ;
-
-string_element_list             : string_element
-                                  { $$ = new text_element_list ($1); }
-                                | string_element_list string_element
-                                  { $1->push_back ($2); $$ = $1; }
-                                ;
-
-scoped_string_element_list      : START string_element_list END
-                                  { $$ = $2; }
-                                | START END
-                                  { $$ = new text_element_list (); }
-                                ;
-
-string                          : // empty
-                                  { parser.set_parse_result (new text_element_string ("")); }
-                                | string_element_list
-                                  { parser.set_parse_result ($1); }
-                                ;
-
-%%
-
-#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
-   // Restore prevailing warning state for remainder of the file.
-#  pragma GCC diagnostic pop
-#endif
-
-text_element*
-text_parser_tex::parse (const std::string& s)
-{
-  octave_tex_debug = 0;
-
-  if (init_lexer (s))
-    {
-      result = nullptr;
-
-      if (octave_tex_parse (*this) == 0)
-        return result;
-    }
-
-  return new text_element_string (s);
-}
-
-static void
-yyerror (text_parser_tex&, const char *s)
-{
-  fprintf (stderr, "TeX parse error: %s\n", s);
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/corefcn/oct-tex-parser.yy	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,235 @@
+/*
+
+Copyright (C) 2013-2018 Michael Goffioul
+
+This file is part of Octave.
+
+Octave is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Octave is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<https://www.gnu.org/licenses/>.
+
+*/
+
+%{
+
+#define YYDEBUG 1
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include "text-engine.h"
+
+// oct-tex-parser.h must be included after text-engine.h
+#include "oct-tex-parser.h"
+
+extern int octave_tex_lex (YYSTYPE *, void *);
+ static void yyerror (octave::text_parser_tex& parser, const char *s);
+
+#define scanner parser.get_scanner ()
+#define yyalloc octave_tex_yyalloc
+
+#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
+   // Disable this warning for code that is generated by Bison,
+   // including grammar rules.  Push the current state so we can
+   // restore the warning state prior to functions we define at
+   // the bottom of the file.
+#  pragma GCC diagnostic push
+#  pragma GCC diagnostic ignored "-Wold-style-cast"
+#endif
+
+%}
+
+%define api.pure
+// No spaces inside the braces for the prefix definition!
+%define api.prefix {octave_tex_}
+%parse-param { octave::text_parser_tex& parser }
+%lex-param { void *scanner }
+
+%code requires {#include <string>}
+
+%union
+{
+  // Leaf symbols produced by the scanner.
+  char ch;
+  double num;
+  int sym;
+
+  // Used for string buffering.
+  std::string *str;
+
+  // Objects produced by the parser.
+  octave::text_element *e_base;
+  octave::text_element_list *e_list;
+}
+
+%token BF IT SL RM
+%token FONTNAME FONTSIZE
+%token COLOR COLOR_RGB
+%token START END SUPER SUB
+%token<ch> CH
+%token<num> NUM
+%token<sym> SYM
+
+%type<str> simple_string
+%type<e_base> string_element symbol_element
+%type<e_base> superscript_element subscript_element combined_script_element
+%type<e_base> font_modifier_element fontname_element fontsize_element
+%type<e_base> color_element
+%type<e_list> string_element_list scoped_string_element_list
+
+// Make sure there's no memory leak on parse error.
+%destructor { } <ch> <num> <sym>
+%destructor { delete $$; } <*>
+
+%nonassoc SCRIPT
+%nonassoc SUB SUPER
+
+%nonassoc STR
+%nonassoc CH
+
+%start string
+
+%%
+
+simple_string           : CH
+                          { $$ = new std::string (1, $1); }
+                        | simple_string CH
+                          { $1->append (1, $2); $$ = $1; }
+                        ;
+
+symbol_element          : SYM
+                          { $$ = new octave::text_element_symbol ($1); }
+                        ;
+
+font_modifier_element   : BF
+                          { $$ = new octave::text_element_fontstyle (octave::text_element_fontstyle::bold); }
+                        | IT
+                          { $$ = new octave::text_element_fontstyle (octave::text_element_fontstyle::italic); }
+                        | SL
+                          { $$ = new octave::text_element_fontstyle (octave::text_element_fontstyle::oblique); }
+                        | RM
+                          { $$ = new octave::text_element_fontstyle (octave::text_element_fontstyle::normal); }
+                        ;
+
+fontsize_element        : FONTSIZE START NUM END
+                          { $$ = new octave::text_element_fontsize ($3); }
+                        ;
+
+fontname_element        : FONTNAME START simple_string END
+                          {
+                            $$ = new octave::text_element_fontname (*$3);
+                            delete $3;
+                          }
+                        ;
+
+color_element           : COLOR START simple_string END
+                          {
+                            $$ = new octave::text_element_color (*$3);
+                            delete $3;
+                          }
+                        | COLOR_RGB START NUM NUM NUM END
+                          {
+                            $$ = new octave::text_element_color ($3, $4, $5);
+                          }
+                        ;
+
+string_element          : simple_string %prec STR
+                          {
+                            $$ = new octave::text_element_string (*$1);
+                            delete $1;
+                          }
+                        | scoped_string_element_list
+                          { $$ = $1; }
+                        | symbol_element
+                        | font_modifier_element
+                        | fontsize_element
+                        | fontname_element
+                        | color_element
+                        | superscript_element %prec SCRIPT
+                        | subscript_element %prec SCRIPT
+                        | combined_script_element
+                        ;
+
+superscript_element     : SUPER CH
+                          { $$ = new octave::text_element_superscript ($2); }
+                        | SUPER scoped_string_element_list
+                          { $$ = new octave::text_element_superscript ($2); }
+                        | SUPER symbol_element
+                          { $$ = new octave::text_element_superscript ($2); }
+                        ;
+
+subscript_element       : SUB CH
+                          { $$ = new octave::text_element_subscript ($2); }
+                        | SUB scoped_string_element_list
+                          { $$ = new octave::text_element_subscript ($2); }
+                        | SUB symbol_element
+                          { $$ = new octave::text_element_subscript ($2); }
+                        ;
+
+combined_script_element : subscript_element superscript_element
+                          { $$ = new octave::text_element_combined ($1, $2); }
+                        | superscript_element subscript_element
+                          { $$ = new octave::text_element_combined ($1, $2); }
+                        ;
+
+string_element_list     : string_element
+                          { $$ = new octave::text_element_list ($1); }
+                        | string_element_list string_element
+                          { $1->push_back ($2); $$ = $1; }
+                        ;
+
+scoped_string_element_list
+                        : START string_element_list END
+                          { $$ = $2; }
+                        | START END
+                          { $$ = new octave::text_element_list (); }
+                        ;
+
+string                  : // empty
+                          { parser.set_parse_result (new octave::text_element_string ("")); }
+                        | string_element_list
+                          { parser.set_parse_result ($1); }
+                        ;
+
+%%
+
+#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
+   // Restore prevailing warning state for remainder of the file.
+#  pragma GCC diagnostic pop
+#endif
+
+namespace octave
+{
+  text_element*
+  text_parser_tex::parse (const std::string& s)
+  {
+    octave_tex_debug = 0;
+
+    if (init_lexer (s))
+      {
+        result = nullptr;
+
+        if (octave_tex_parse (*this) == 0)
+          return result;
+      }
+
+    return new text_element_string (s);
+  }
+}
+
+static void
+yyerror (octave::text_parser_tex&, const char *s)
+{
+  fprintf (stderr, "TeX parse error: %s\n", s);
+}
--- a/libinterp/corefcn/oct.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/oct.h	Fri Aug 10 09:09:51 2018 +0200
@@ -32,9 +32,6 @@
 #include "defun-dld.h"
 #include "error.h"
 #include "errwarn.h"
-// FIXME: gripes.h was deprecated in version 4.2 and will be removed
-// in version 5.
-#include "gripes.h"
 #include "help.h"
 #include "ovl.h"
 #include "pager.h"
--- a/libinterp/corefcn/octave-link.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/octave-link.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -257,7 +257,7 @@
       nel -= 2;
       Cell items (dim_vector (1, nel));
 
-      std::list<std::string>::iterator it = items_lst.begin ();
+      auto it = items_lst.begin ();
 
       for (int idx = 0; idx < nel; idx++, it++)
         items.xelem (idx) = *it;
@@ -382,6 +382,27 @@
   return ovl (octave_link::show_preferences ());
 }
 
+DEFUN (__octave_link_gui_preference__, args, ,
+       doc: /* -*- texinfo -*-
+@deftypefn {} {} __octave_link_gui_preference__ ()
+Undocumented internal function.
+@end deftypefn */)
+{
+  std::string key;
+  std::string value = "";
+
+  if (args.length () >= 1)
+    key = args(0).string_value();
+  else
+    error ("__octave_link_gui_preference__: "
+           "first argument must be the preference key");
+
+  if (args.length () >= 2)
+    value = args(1).string_value();
+
+  return ovl (octave_link::gui_preference (key, value));
+}
+
 DEFMETHOD (openvar, interp, args, ,
            doc: /* -*- texinfo -*-
 @deftypefn {} {} openvar (@var{name})
--- a/libinterp/corefcn/octave-link.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/octave-link.h	Fri Aug 10 09:09:51 2018 +0200
@@ -31,7 +31,7 @@
 #include <string>
 
 #include "oct-mutex.h"
-
+#include "octave.h"
 #include "event-queue.h"
 
 class octave_value;
@@ -103,53 +103,12 @@
     return retval;
   }
 
-  template <typename T>
-  static void post_event (T *obj, void (T::*method) (void))
-  {
-    if (enabled ())
-      instance->do_post_event (obj, method);
-  }
-
-  template <typename T, typename A>
-  static void post_event (T *obj, void (T::*method) (A), A arg)
-  {
-    if (enabled ())
-      instance->do_post_event (obj, method, arg);
-  }
-
-  template <typename T, typename A>
-  static void post_event (T *obj, void (T::*method) (const A&), const A& arg)
+  template <typename T, typename... Params, typename... Args>
+  static void
+  post_event (T *obj, void (T::*method) (Params...), Args&&... args)
   {
     if (enabled ())
-      instance->do_post_event (obj, method, arg);
-  }
-
-  template <class T, class A, class B>
-  static void post_event (T *obj, void (T::*method) (const A&, const B&),
-                          const A& arg_a, const B& arg_b)
-  {
-    if (enabled ())
-      instance->do_post_event<T, A, B> (obj, method, arg_a, arg_b);
-  }
-
-  template <class T, class A, class B, class C>
-  static void post_event (T *obj,
-                          void (T::*method) (const A&, const B&, const C&),
-                          const A& arg_a, const B& arg_b, const C& arg_c)
-  {
-    if (enabled ())
-      instance->do_post_event<T, A, B, C> (obj, method, arg_a, arg_b, arg_c);
-  }
-
-  template <class T, class A, class B, class C, class D>
-  static void
-  post_event (T *obj,
-              void (T::*method) (const A&, const B&, const C&, const D&),
-              const A& arg_a, const B& arg_b, const C& arg_c, const D& arg_d)
-  {
-    if (enabled ())
-      instance->do_post_event<T, A, B, C, D>
-        (obj, method, arg_a, arg_b, arg_c, arg_d);
+      instance->do_post_event (obj, method, std::forward<Args> (args)...);
   }
 
   static void
@@ -262,6 +221,20 @@
       instance->do_change_directory (dir);
   }
 
+  // Methods for removing/renaming files which might be open in editor
+  static void file_remove (const std::string& old_name,
+                           const std::string& new_name)
+  {
+    if (octave::application::is_gui_running () && enabled ())
+      instance->do_file_remove (old_name, new_name);
+  }
+
+  static void file_renamed (bool load_new)
+  {
+    if (octave::application::is_gui_running () && enabled ())
+      instance->do_file_renamed (load_new);
+  }
+
   // Preserves pending input.
   static void execute_command_in_terminal (const std::string& command)
   {
@@ -368,13 +341,6 @@
       }
   }
 
-  static void set_default_prompts (std::string& ps1, std::string& ps2,
-                                   std::string& ps4)
-  {
-    if (enabled ())
-      instance->do_set_default_prompts (ps1, ps2, ps4);
-  }
-
   static bool enable (void)
   {
     return instance_ok () ? instance->do_enable () : false;
@@ -416,6 +382,18 @@
       return false;
   }
 
+  static std::string
+  gui_preference (const std::string& key,
+                  const std::string& value)
+  {
+    if (enabled ())
+      {
+        return instance->do_gui_preference (key, value);
+      }
+    else
+      return "";
+  }
+
   static bool
   show_doc (const std::string & file)
   {
@@ -486,49 +464,10 @@
   void do_process_events (void);
   void do_discard_events (void);
 
-  template <typename T>
-  void do_post_event (T *obj, void (T::*method) (void))
-  {
-    gui_event_queue.add_method (obj, method);
-  }
-
-  template <typename T, typename A>
-  void do_post_event (T *obj, void (T::*method) (A), A arg)
-  {
-    gui_event_queue.add_method (obj, method, arg);
-  }
-
-  template <typename T, typename A>
-  void do_post_event (T *obj, void (T::*method) (const A&), const A& arg)
-  {
-    gui_event_queue.add_method (obj, method, arg);
-  }
-
-  template <class T, class A, class B>
-  void do_post_event (T *obj, void (T::*method) (const A&, const B&),
-                      const A& arg_a, const B& arg_b)
+  template <typename T, typename... Params, typename... Args>
+  void do_post_event (T *obj, void (T::*method) (Params...), Args&&... args)
   {
-    gui_event_queue.add_method<T, A, B>
-      (obj, method, arg_a, arg_b);
-  }
-
-  template <class T, class A, class B, class C>
-  void do_post_event (T *obj,
-                      void (T::*method) (const A&, const B&, const C&),
-                      const A& arg_a, const B& arg_b, const C& arg_c)
-  {
-    gui_event_queue.add_method<T, A, B, C>
-      (obj, method, arg_a, arg_b, arg_c);
-  }
-
-  template <class T, class A, class B, class C, class D>
-  void
-  do_post_event (T *obj,
-                 void (T::*method) (const A&, const B&, const C&, const D&),
-                 const A& arg_a, const B& arg_b, const C& arg_c, const D& arg_d)
-  {
-    gui_event_queue.add_method<T, A, B, C, D>
-      (obj, method, arg_a, arg_b, arg_c, arg_d);
+    gui_event_queue.add_method (obj, method, std::forward<Args> (args)...);
   }
 
   void
@@ -591,6 +530,10 @@
 
   virtual void do_change_directory (const std::string& dir) = 0;
 
+  virtual void do_file_remove (const std::string& old_name,
+                               const std::string& new_name) = 0;
+  virtual void do_file_renamed (bool) = 0;
+
   virtual void do_execute_command_in_terminal (const std::string& command) = 0;
 
   virtual void
@@ -619,10 +562,10 @@
                                      const std::string& file, int line,
                                      const std::string& cond) = 0;
 
-  virtual void do_set_default_prompts (std::string& ps1, std::string& ps2,
-                                       std::string& ps4) = 0;
+  virtual void do_show_preferences (void) = 0;
 
-  virtual void do_show_preferences (void) = 0;
+  virtual std::string do_gui_preference (const std::string& key,
+                                         const std::string& value) = 0;
 
   virtual void do_show_doc (const std::string& file) = 0;
 
--- a/libinterp/corefcn/ordschur.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/ordschur.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -71,7 +71,7 @@
 [@var{U}, @var{S}] = ordschur (@var{U}, @var{S}, [0,1])
 @end example
 
-@seealso{schur}
+@seealso{schur, ordeig}
 @end deftypefn */)
 {
   if (args.length () != 3)
--- a/libinterp/corefcn/pager.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/pager.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -32,13 +32,13 @@
 #include "cmd-edit.h"
 #include "oct-env.h"
 #include "oct-syscalls.h"
-#include "singleton-cleanup.h"
 
 #include "defaults.h"
 #include "defun.h"
 #include "error.h"
 #include "errwarn.h"
 #include "input.h"
+#include "interpreter.h"
 #include "interpreter-private.h"
 #include "octave.h"
 #include "ovl.h"
@@ -49,226 +49,93 @@
 #include "utils.h"
 #include "variables.h"
 
-// Our actual connection to the external pager.
-static oprocstream *external_pager = nullptr;
-
-// TRUE means we write to the diary file.
-static bool write_to_diary_file = false;
-
-// The name of the current diary file.
-static std::string diary_file ("diary");
-
-// The diary file.
-static std::ofstream external_diary_file;
-
-static std::string
-default_pager (void)
-{
-  std::string pager_binary = octave::sys::env::getenv ("PAGER");
-
-  if (pager_binary.empty ())
-    pager_binary = octave::config::default_pager ();
-
-  return pager_binary;
-}
-
-// The shell command to run as the pager.
-static std::string VPAGER = default_pager ();
-
-// The options to pass to the pager.
-static std::string VPAGER_FLAGS;
-
-// TRUE means that if output is going to the pager, it is sent as soon
-// as it is available.  Otherwise, it is buffered and only sent to the
-// pager when it is time to print another prompt.
-static bool Vpage_output_immediately = false;
-
-// TRUE means all output intended for the screen should be passed
-// through the pager.
-static bool Vpage_screen_output = false;
-
-static bool really_flush_to_pager = false;
-
-static bool flushing_output_to_pager = false;
-
-static void
-clear_external_pager (void)
-{
-  if (external_pager)
-    {
-      octave::child_list& kids
-        = octave::__get_child_list__ ("clear_external_pager");
-
-      kids.remove (external_pager->pid ());
-
-      delete external_pager;
-      external_pager = nullptr;
-    }
-}
-
-static bool
-pager_event_handler (pid_t pid, int status)
-{
-  bool retval = false;
-
-  if (pid > 0)
-    {
-      if (octave::sys::wifexited (status) || octave::sys::wifsignaled (status))
-        {
-          // Avoid warning() since that will put us back in the pager,
-          // which would be bad news.
-
-          std::cerr << "warning: connection to external pager lost (pid = "
-                    << pid << ')' << std::endl;
-          std::cerr << "warning: flushing pending output (please wait)"
-                    << std::endl;
-
-          // Request removal of this PID from the list of child
-          // processes.
-
-          retval = true;
-        }
-    }
-
-  return retval;
-}
-
-static std::string
-pager_command (void)
-{
-  std::string cmd = VPAGER;
-
-  if (! (cmd.empty () || VPAGER_FLAGS.empty ()))
-    cmd += ' ' + VPAGER_FLAGS;
-
-  return cmd;
-}
-
-static void
-do_sync (const char *msg, int len, bool bypass_pager)
-{
-  if (msg && len > 0)
-    {
-      if (bypass_pager)
-        {
-          std::cout.write (msg, len);
-          std::cout.flush ();
-        }
-      else
-        {
-          if (! external_pager)
-            {
-              std::string pgr = pager_command ();
-
-              if (! pgr.empty ())
-                {
-                  external_pager = new oprocstream (pgr.c_str ());
-
-                  if (external_pager)
-                    {
-                      octave::child_list& kids
-                        = octave::__get_child_list__ ("do_sync");
-
-                      kids.insert (external_pager->pid (),
-                                   pager_event_handler);
-                    }
-                }
-            }
-
-          if (external_pager)
-            {
-              if (external_pager->good ())
-                {
-                  external_pager->write (msg, len);
-
-                  external_pager->flush ();
-
-#if defined (EPIPE)
-                  if (errno == EPIPE)
-                    external_pager->setstate (std::ios::failbit);
-#endif
-                }
-              else
-                {
-                  // FIXME: omething is not right with the
-                  // pager.  If it died then we should receive a
-                  // signal for that.  If there is some other problem,
-                  // then what?
-                }
-            }
-          else
-            {
-              std::cout.write (msg, len);
-              std::cout.flush ();
-            }
-        }
-    }
-}
-
-// Assume our terminal wraps long lines.
-
-static bool
-more_than_a_screenful (const char *s, int len)
-{
-  if (s)
-    {
-      int available_rows = octave::command_editor::terminal_rows () - 2;
-
-      int cols = octave::command_editor::terminal_cols ();
-
-      int count = 0;
-
-      int chars_this_line = 0;
-
-      for (int i = 0; i < len; i++)
-        {
-          if (*s++ == '\n')
-            {
-              count += chars_this_line / cols + 1;
-              chars_this_line = 0;
-            }
-          else
-            chars_this_line++;
-        }
-
-      if (count > available_rows)
-        return true;
-    }
-
-  return false;
-}
-
 namespace octave
 {
+  static bool
+  pager_event_handler (pid_t pid, int status)
+  {
+    bool retval = false;
+
+    if (pid > 0)
+      {
+        if (octave::sys::wifexited (status) || octave::sys::wifsignaled (status))
+          {
+            // Avoid warning() since that will put us back in the pager,
+            // which would be bad news.
+
+            std::cerr << "warning: connection to external pager lost (pid = "
+                      << pid << ')' << std::endl;
+            std::cerr << "warning: flushing pending output (please wait)"
+                      << std::endl;
+
+            // Request removal of this PID from the list of child
+            // processes.
+
+            retval = true;
+          }
+      }
+
+    return retval;
+  }
+
+  // Assume our terminal wraps long lines.
+
+  static bool
+  more_than_a_screenful (const char *s, int len)
+  {
+    if (s)
+      {
+        int available_rows = octave::command_editor::terminal_rows () - 2;
+
+        int cols = octave::command_editor::terminal_cols ();
+
+        int count = 0;
+
+        int chars_this_line = 0;
+
+        for (int i = 0; i < len; i++)
+          {
+            if (*s++ == '\n')
+              {
+                count += chars_this_line / cols + 1;
+                chars_this_line = 0;
+              }
+            else
+              chars_this_line++;
+          }
+
+        if (count > available_rows)
+          return true;
+      }
+
+    return false;
+  }
+
+  static std::string default_pager (void)
+  {
+    std::string pager_binary = sys::env::getenv ("PAGER");
+
+    if (pager_binary.empty ())
+      pager_binary = config::default_pager ();
+
+    return pager_binary;
+  }
+
   int
   pager_buf::sync (void)
   {
-    if (! application::interactive ()
-        || application::forced_interactive ()
-        || really_flush_to_pager
-        || (Vpage_screen_output && Vpage_output_immediately)
-        || ! Vpage_screen_output)
-      {
-        char *buf = eback ();
+    octave::output_system& output_sys
+      = octave::__get_output_system__ ("pager_buf::sync");
 
-        int len = pptr () - buf;
+    char *buf = eback ();
 
-        bool bypass_pager = (! application::interactive ()
-                             || application::forced_interactive ()
-                             || ! Vpage_screen_output
-                             || (really_flush_to_pager
-                                 && Vpage_screen_output
-                                 && ! Vpage_output_immediately
-                                 && ! more_than_a_screenful (buf, len)));
+    int len = pptr () - buf;
 
-        if (len > 0)
-          {
-            do_sync (buf, len, bypass_pager);
+    if (output_sys.sync (buf, len))
+      {
+        flush_current_contents_to_diary ();
 
-            flush_current_contents_to_diary ();
-
-            seekoff (0, std::ios::beg);
-          }
+        seekoff (0, std::ios::beg);
       }
 
     return 0;
@@ -295,7 +162,11 @@
   int
   diary_buf::sync (void)
   {
-    if (write_to_diary_file && external_diary_file)
+    output_system& output_sys = __get_output_system__ ("__stdout__");
+
+    std::ofstream& external_diary_file = output_sys.external_diary_file ();
+
+    if (output_sys.write_to_diary_file () && external_diary_file)
       {
         char *buf = eback ();
 
@@ -310,8 +181,6 @@
     return 0;
   }
 
-  pager_stream *pager_stream::instance = nullptr;
-
   pager_stream::pager_stream (void) : std::ostream (nullptr), pb (nullptr)
   {
     pb = new pager_buf ();
@@ -325,24 +194,21 @@
     delete pb;
   }
 
-  std::ostream&
-  pager_stream::stream (void)
+  std::ostream& pager_stream::stream (void)
   {
-    return instance_ok () ? *instance : std::cout;
+    return *this;
   }
 
-  void
-  pager_stream::flush_current_contents_to_diary (void)
+  void pager_stream::flush_current_contents_to_diary (void)
   {
-    if (instance_ok ())
-      instance->do_flush_current_contents_to_diary ();
+    if (pb)
+      pb->flush_current_contents_to_diary ();
   }
 
-  void
-  pager_stream::set_diary_skip (void)
+  void pager_stream::set_diary_skip (void)
   {
-    if (instance_ok ())
-      instance->do_set_diary_skip ();
+    if (pb)
+      pb->set_diary_skip ();
   }
 
   // Reinitialize the pager buffer to avoid hanging on to large internal
@@ -350,29 +216,7 @@
   // called when the pager is not in use.  For example, just before
   // getting command-line input.
 
-  void
-  pager_stream::reset (void)
-  {
-    if (instance_ok ())
-      instance->do_reset ();
-  }
-
-  void
-  pager_stream::do_flush_current_contents_to_diary (void)
-  {
-    if (pb)
-      pb->flush_current_contents_to_diary ();
-  }
-
-  void
-  pager_stream::do_set_diary_skip (void)
-  {
-    if (pb)
-      pb->set_diary_skip ();
-  }
-
-  void
-  pager_stream::do_reset (void)
+  void pager_stream::reset (void)
   {
     delete pb;
     pb = new pager_buf ();
@@ -380,27 +224,6 @@
     setf (unitbuf);
   }
 
-  bool
-  pager_stream::instance_ok (void)
-  {
-    bool retval = true;
-
-    if (! instance)
-      {
-        instance = new pager_stream ();
-
-        if (instance)
-          singleton_cleanup_list::add (cleanup_instance);
-      }
-
-    if (! instance)
-      error ("unable to create pager_stream object!");
-
-    return retval;
-  }
-
-  diary_stream *diary_stream::instance = nullptr;
-
   diary_stream::diary_stream (void) : std::ostream (nullptr), db (nullptr)
   {
     db = new diary_buf ();
@@ -414,10 +237,9 @@
     delete db;
   }
 
-  std::ostream&
-  diary_stream::stream (void)
+  std::ostream& diary_stream::stream (void)
   {
-    return instance_ok () ? *instance : std::cout;
+    return *this;
   }
 
   // Reinitialize the diary buffer to avoid hanging on to large internal
@@ -425,15 +247,7 @@
   // called when the pager is not in use.  For example, just before
   // getting command-line input.
 
-  void
-  diary_stream::reset (void)
-  {
-    if (instance_ok ())
-      instance->do_reset ();
-  }
-
-  void
-  diary_stream::do_reset (void)
+  void diary_stream::reset (void)
   {
     delete db;
     db = new diary_buf ();
@@ -441,82 +255,243 @@
     setf (unitbuf);
   }
 
-  bool
-  diary_stream::instance_ok (void)
+  void flush_stdout (void)
   {
-    bool retval = true;
+    output_system& output_sys = __get_output_system__ ("flush_stdout");
 
-    if (! instance)
-      {
-        instance = new diary_stream ();
+    output_sys.flush_stdout ();
+  }
 
-        if (instance)
-          singleton_cleanup_list::add (cleanup_instance);
-      }
+  output_system::output_system (interpreter& interp)
+    : m_interpreter (interp), m_pager_stream (), m_diary_stream (),
+      m_external_pager (nullptr), m_external_diary_file (),
+      m_diary_file_name ("diary"), m_PAGER (default_pager ()),
+      m_PAGER_FLAGS (), m_page_output_immediately (false),
+      m_page_screen_output (false), m_write_to_diary_file (false),
+      m_really_flush_to_pager (false), m_flushing_output_to_pager (false)
+  { }
 
-    if (! instance)
-      error ("unable to create diary_stream object!");
+  octave_value output_system::PAGER (const octave_value_list& args,
+                                     int nargout)
+  {
+    return set_internal_variable (m_PAGER, args, nargout, "PAGER", false);
+  }
 
-    return retval;
+  octave_value output_system::PAGER_FLAGS (const octave_value_list& args,
+                                           int nargout)
+  {
+    return set_internal_variable (m_PAGER_FLAGS, args, nargout,
+                                  "PAGER_FLAGS", false);
   }
 
-  void
-  flush_stdout (void)
+  octave_value
+  output_system::page_output_immediately (const octave_value_list& args,
+                                          int nargout)
+  {
+    return set_internal_variable (m_page_output_immediately, args, nargout,
+                                  "page_output_immediately");
+  }
+
+  octave_value
+  output_system::page_screen_output (const octave_value_list& args,
+                                     int nargout)
+  {
+    return set_internal_variable (m_page_screen_output, args, nargout,
+                                  "page_screen_output");
+  }
+
+  std::string output_system::pager_command (void) const
   {
-    if (! flushing_output_to_pager)
+    std::string cmd = m_PAGER;
+
+    if (! (cmd.empty () || m_PAGER_FLAGS.empty ()))
+      cmd += ' ' + m_PAGER_FLAGS;
+
+    return cmd;
+  }
+
+  void output_system::reset (void)
+  {
+    flush_stdout ();
+
+    m_pager_stream.reset ();
+    m_diary_stream.reset ();
+  }
+
+  void output_system::flush_stdout (void)
+  {
+    if (! m_flushing_output_to_pager)
       {
         unwind_protect frame;
 
-        frame.protect_var (really_flush_to_pager);
-        frame.protect_var (flushing_output_to_pager);
+        frame.protect_var (m_really_flush_to_pager);
+        frame.protect_var (m_flushing_output_to_pager);
 
-        really_flush_to_pager = true;
-        flushing_output_to_pager = true;
+        m_really_flush_to_pager = true;
+        m_flushing_output_to_pager = true;
 
-        octave_stdout.flush ();
+        std::ostream& pager_ostream = m_pager_stream.stream ();
+
+        pager_ostream.flush ();
 
         clear_external_pager ();
       }
   }
-}
+
+  void output_system::close_diary (void)
+  {
+    // Try to flush the current buffer to the diary now, so that things
+    // like
+    //
+    // function foo ()
+    //   diary on;
+    //   ...
+    //   diary off;
+    // endfunction
+    //
+    // will do the right thing.
+
+    m_pager_stream.flush_current_contents_to_diary ();
+
+    if (m_external_diary_file.is_open ())
+      {
+        octave_diary.flush ();
+        m_external_diary_file.close ();
+      }
+  }
+
+  void output_system::open_diary (void)
+  {
+    close_diary ();
+
+    // If there is pending output in the pager buf, it should not go
+    // into the diary file.
+
+    m_pager_stream.set_diary_skip ();
+
+    m_external_diary_file.open (m_diary_file_name.c_str (), std::ios::app);
+
+    if (! m_external_diary_file)
+      error ("diary: can't open diary file '%s'", m_diary_file_name.c_str ());
+  }
 
-static void
-close_diary_file (void)
-{
-  // Try to flush the current buffer to the diary now, so that things
-  // like
-  //
-  // function foo ()
-  //   diary on;
-  //   ...
-  //   diary off;
-  // endfunction
-  //
-  // will do the right thing.
+  bool output_system::sync (const char *buf, int len)
+  {
+    if (! application::interactive ()
+        || application::forced_interactive ()
+        || m_really_flush_to_pager
+        || (m_page_screen_output && m_page_output_immediately)
+        || ! m_page_screen_output)
+      {
+        bool bypass_pager = (! application::interactive ()
+                             || application::forced_interactive ()
+                             || ! m_page_screen_output
+                             || (m_really_flush_to_pager
+                                 && m_page_screen_output
+                                 && ! m_page_output_immediately
+                                 && ! more_than_a_screenful (buf, len)));
+
+        if (len > 0)
+          {
+            do_sync (buf, len, bypass_pager);
 
-  octave::pager_stream::flush_current_contents_to_diary ();
+            return true;
+          }
+      }
+
+    return false;
+  }
+
+  void output_system::clear_external_pager (void)
+  {
+    if (m_external_pager)
+      {
+        child_list& kids = m_interpreter.get_child_list ();
+
+        kids.remove (m_external_pager->pid ());
+
+        delete m_external_pager;
+        m_external_pager = nullptr;
+      }
+  }
 
-  if (external_diary_file.is_open ())
-    {
-      octave_diary.flush ();
-      external_diary_file.close ();
-    }
-}
+  void output_system::start_external_pager (void)
+  {
+    if (m_external_pager)
+      return;
+
+    std::string pgr = pager_command ();
+
+    if (! pgr.empty ())
+      {
+        m_external_pager = new oprocstream (pgr.c_str ());
+
+        if (m_external_pager)
+          {
+            octave::child_list& kids = m_interpreter.get_child_list ();
+
+            kids.insert (m_external_pager->pid (),
+                         pager_event_handler);
+          }
+      }
+  }
+
+  void output_system::do_sync (const char *msg, int len, bool bypass_pager)
+  {
+    if (msg && len > 0)
+      {
+        if (bypass_pager)
+          {
+            std::cout.write (msg, len);
+            std::cout.flush ();
+          }
+        else
+          {
+            start_external_pager ();
 
-static void
-open_diary_file (void)
-{
-  close_diary_file ();
+            if (m_external_pager)
+              {
+                if (m_external_pager->good ())
+                  {
+                    m_external_pager->write (msg, len);
+
+                    m_external_pager->flush ();
 
-  // If there is pending output in the pager buf, it should not go
-  // into the diary file.
-
-  octave::pager_stream::set_diary_skip ();
+#if defined (EPIPE)
+                    if (errno == EPIPE)
+                      m_external_pager->setstate (std::ios::failbit);
+#endif
+                  }
+                else
+                  {
+                    // FIXME: something is not right with the
+                    // pager.  If it died then we should receive a
+                    // signal for that.  If there is some other problem,
+                    // then what?
+                  }
+              }
+            else
+              {
+                std::cout.write (msg, len);
+                std::cout.flush ();
+              }
+          }
+      }
+  }
 
-  external_diary_file.open (diary_file.c_str (), std::ios::app);
+  std::ostream& __stdout__ (void)
+  {
+    output_system& output_sys = __get_output_system__ ("__stdout__");
+
+    return output_sys.__stdout__ ();
+  }
 
-  if (! external_diary_file)
-    error ("diary: can't open diary file '%s'", diary_file.c_str ());
+  std::ostream& __diary__ (void)
+  {
+    output_system& output_sys = __get_output_system__ ("__diary__");
+
+    return output_sys.__diary__ ();
+  }
 }
 
 DEFUN (diary, args, nargout,
@@ -558,22 +533,22 @@
   if (nargin > 1)
     print_usage ();
 
-  if (diary_file.empty ())
-    diary_file = "diary";
+  octave::output_system& output_sys = octave::__get_output_system__ ("Fdiary");
 
   if (nargout > 0)
     {
       // Querying diary variables
       if (nargout == 1)
-        return ovl (write_to_diary_file);
+        return ovl (output_sys.write_to_diary_file ());
       else
-        return ovl (write_to_diary_file, diary_file);
+        return ovl (output_sys.write_to_diary_file (),
+                    output_sys.diary_file_name ());
     }
 
   if (nargin == 0)
     {
-      write_to_diary_file = ! write_to_diary_file;
-      open_diary_file ();
+      output_sys.write_to_diary_file (! output_sys.write_to_diary_file ());
+      output_sys.open_diary ();
     }
   else
     {
@@ -581,27 +556,27 @@
 
       if (arg == "on")
         {
-          write_to_diary_file = true;
-          open_diary_file ();
+          output_sys.write_to_diary_file (true);
+          output_sys.open_diary ();
         }
       else if (arg == "off")
         {
-          close_diary_file ();
-          write_to_diary_file = false;
+          output_sys.close_diary ();
+          output_sys.write_to_diary_file (false);
         }
       else
         {
-          diary_file = arg;
-          write_to_diary_file = true;
-          open_diary_file ();
+          output_sys.diary_file_name (arg);
+          output_sys.write_to_diary_file (true);
+          output_sys.open_diary ();
         }
     }
 
   return ovl ();
 }
 
-DEFUN (more, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (more, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn  {} {} more
 @deftypefnx {} {} more on
 @deftypefnx {} {} more off
@@ -618,19 +593,21 @@
   if (nargin > 1)
     print_usage ();
 
+  octave::output_system& output_sys = interp.get_output_system ();
+
   if (nargin > 0)
     {
       std::string arg = args(0).xstring_value (R"(more: argument must be string "on" or "off")");
 
       if (arg == "on")
-        Vpage_screen_output = true;
+        output_sys.page_screen_output (true);
       else if (arg == "off")
-        Vpage_screen_output = false;
+        output_sys.page_screen_output (false);
       else
         error (R"(more: argument must be "on" or "off")");
     }
   else
-    Vpage_screen_output = ! Vpage_screen_output;
+    output_sys.page_screen_output (! output_sys.page_screen_output ());
 
   return ovl ();
 }
@@ -651,8 +628,8 @@
   return ovl (size);
 }
 
-DEFUN (page_output_immediately, args, nargout,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (page_output_immediately, interp, args, nargout,
+           doc: /* -*- texinfo -*-
 @deftypefn  {} {@var{val} =} page_output_immediately ()
 @deftypefnx {} {@var{old_val} =} page_output_immediately (@var{new_val})
 @deftypefnx {} {} page_output_immediately (@var{new_val}, "local")
@@ -668,11 +645,13 @@
 @seealso{page_screen_output, more, PAGER, PAGER_FLAGS}
 @end deftypefn */)
 {
-  return SET_INTERNAL_VARIABLE (page_output_immediately);
+  octave::output_system& output_sys = interp.get_output_system ();
+
+  return output_sys.page_output_immediately (args, nargout);
 }
 
-DEFUN (page_screen_output, args, nargout,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (page_screen_output, interp, args, nargout,
+           doc: /* -*- texinfo -*-
 @deftypefn  {} {@var{val} =} page_screen_output ()
 @deftypefnx {} {@var{old_val} =} page_screen_output (@var{new_val})
 @deftypefnx {} {} page_screen_output (@var{new_val}, "local")
@@ -690,11 +669,13 @@
 @seealso{more, page_output_immediately, PAGER, PAGER_FLAGS}
 @end deftypefn */)
 {
-  return SET_INTERNAL_VARIABLE (page_screen_output);
+  octave::output_system& output_sys = interp.get_output_system ();
+
+  return output_sys.page_screen_output (args, nargout);
 }
 
-DEFUN (PAGER, args, nargout,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (PAGER, interp, args, nargout,
+           doc: /* -*- texinfo -*-
 @deftypefn  {} {@var{val} =} PAGER ()
 @deftypefnx {} {@var{old_val} =} PAGER (@var{new_val})
 @deftypefnx {} {} PAGER (@var{new_val}, "local")
@@ -711,11 +692,13 @@
 @seealso{PAGER_FLAGS, page_output_immediately, more, page_screen_output}
 @end deftypefn */)
 {
-  return SET_NONEMPTY_INTERNAL_STRING_VARIABLE (PAGER);
+  octave::output_system& output_sys = interp.get_output_system ();
+
+  return output_sys.PAGER (args, nargout);
 }
 
-DEFUN (PAGER_FLAGS, args, nargout,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (PAGER_FLAGS, interp, args, nargout,
+           doc: /* -*- texinfo -*-
 @deftypefn  {} {@var{val} =} PAGER_FLAGS ()
 @deftypefnx {} {@var{old_val} =} PAGER_FLAGS (@var{new_val})
 @deftypefnx {} {} PAGER_FLAGS (@var{new_val}, "local")
@@ -728,5 +711,7 @@
 @seealso{PAGER, more, page_screen_output, page_output_immediately}
 @end deftypefn */)
 {
-  return SET_NONEMPTY_INTERNAL_STRING_VARIABLE (PAGER_FLAGS);
+  octave::output_system& output_sys = interp.get_output_system ();
+
+  return output_sys.PAGER_FLAGS (args, nargout);
 }
--- a/libinterp/corefcn/pager.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/pager.h	Fri Aug 10 09:09:51 2018 +0200
@@ -25,14 +25,18 @@
 
 #include "octave-config.h"
 
+#include <fstream>
 #include <iosfwd>
 #include <sstream>
 #include <string>
 
-#include <sys/types.h>
+class octave_value;
+class oprocstream;
 
 namespace octave
 {
+  class interpreter;
+
   class
   OCTINTERP_API
   pager_buf : public std::stringbuf
@@ -58,12 +62,10 @@
   OCTINTERP_API
   pager_stream : public std::ostream
   {
-  protected:
+  public:
 
     pager_stream (void);
 
-  public:
-
     // No copying!
 
     pager_stream (const pager_stream&) = delete;
@@ -72,28 +74,16 @@
 
     ~pager_stream (void);
 
-    static void flush_current_contents_to_diary (void);
+    void flush_current_contents_to_diary (void);
 
-    static void set_diary_skip (void);
+    void set_diary_skip (void);
 
-    static std::ostream& stream (void);
+    std::ostream& stream (void);
 
-    static void reset (void);
+    void reset (void);
 
   private:
 
-    void do_flush_current_contents_to_diary (void);
-
-    void do_set_diary_skip (void);
-
-    void do_reset (void);
-
-    static pager_stream *instance;
-
-    static bool instance_ok (void);
-
-    static void cleanup_instance (void) { delete instance; instance = nullptr; }
-
     pager_buf *pb;
   };
 
@@ -114,12 +104,10 @@
   OCTINTERP_API
   diary_stream : public std::ostream
   {
-  protected:
+  public:
 
     diary_stream (void);
 
-  public:
-
     // No copying!
 
     diary_stream (const diary_stream&) = delete;
@@ -128,24 +116,194 @@
 
     ~diary_stream (void);
 
-    static std::ostream& stream (void);
+    std::ostream& stream (void);
 
-    static void reset (void);
+    void reset (void);
 
   private:
 
-    void do_reset (void);
-
-    static diary_stream *instance;
-
-    static bool instance_ok (void);
-
-    static void cleanup_instance (void) { delete instance; instance = nullptr; }
-
     diary_buf *db;
   };
 
   extern OCTAVE_API void flush_stdout (void);
+
+  class output_system
+  {
+  public:
+
+    output_system (interpreter& interp);
+
+    output_system (const output_system&) = delete;
+
+    output_system& operator = (const output_system&) = delete;
+
+    ~output_system (void) = default;
+
+    pager_stream& pager (void) { return m_pager_stream; }
+
+    diary_stream& diary (void) { return m_diary_stream; }
+
+    std::string diary_file_name (void) const { return m_diary_file_name; }
+
+    std::string diary_file_name (const std::string& nm)
+    {
+      std::string val = m_diary_file_name;
+      m_diary_file_name = nm.empty () ? "diary" : nm;
+      return val;
+    }
+
+    octave_value PAGER (const octave_value_list& args, int nargout);
+
+    std::string PAGER (void) const { return m_PAGER; }
+
+    std::string PAGER (const std::string& s)
+    {
+      std::string val = m_PAGER;
+      m_PAGER = s;
+      return val;
+    }
+
+    octave_value PAGER_FLAGS (const octave_value_list& args, int nargout);
+
+    std::string PAGER_FLAGS (void) const { return m_PAGER_FLAGS; }
+
+    std::string PAGER_FLAGS (const std::string& s)
+    {
+      std::string val = m_PAGER_FLAGS;
+      m_PAGER_FLAGS = s;
+      return val;
+    }
+
+    octave_value page_output_immediately (const octave_value_list& args,
+                                          int nargout);
+
+    bool page_output_immediately (void) const
+    {
+      return m_page_output_immediately;
+    }
+
+    bool page_output_immediately (bool flag)
+    {
+      bool val = m_page_output_immediately;
+      m_page_output_immediately = flag;
+      return val;
+    }
+
+    octave_value page_screen_output (const octave_value_list& args,
+                                     int nargout);
+
+    bool page_screen_output (void) const { return m_page_screen_output; }
+
+    bool page_screen_output (bool flag)
+    {
+      bool val = m_page_screen_output;
+      m_page_screen_output = flag;
+      return val;
+    }
+
+    bool write_to_diary_file (void) const
+    {
+      return m_write_to_diary_file;
+    }
+
+    bool write_to_diary_file (bool flag)
+    {
+      bool val = m_write_to_diary_file;
+      m_write_to_diary_file = flag;
+      return val;
+    }
+
+    bool really_flush_to_pager (void) const
+    {
+      return m_really_flush_to_pager;
+    }
+
+    bool really_flush_to_pager (bool flag)
+    {
+      bool val = m_really_flush_to_pager;
+      m_really_flush_to_pager = flag;
+      return val;
+    }
+
+    bool flushing_output_to_pager (void) const
+    {
+      return m_flushing_output_to_pager;
+    }
+
+    bool flushing_output_to_pager (bool flag)
+    {
+      bool val = m_flushing_output_to_pager;
+      m_flushing_output_to_pager = flag;
+      return val;
+    }
+
+    std::string pager_command (void) const;
+
+    std::ofstream& external_diary_file (void) { return m_external_diary_file; }
+
+    void reset (void);
+
+    void flush_stdout (void);
+
+    bool sync (const char *msg, int len);
+
+    void clear_external_pager (void);
+
+    void open_diary (void);
+
+    void close_diary (void);
+
+    std::ostream& __stdout__ (void) { return m_pager_stream.stream (); }
+
+    std::ostream& __diary__ (void) { return m_diary_stream.stream (); }
+
+  private:
+
+    interpreter& m_interpreter;
+
+    pager_stream m_pager_stream;
+
+    diary_stream m_diary_stream;
+
+    // Our actual connection to the external pager.
+    oprocstream *m_external_pager = nullptr;
+
+    // The diary file.
+    std::ofstream m_external_diary_file;
+
+    // The name of the current diary file.
+    std::string m_diary_file_name;
+
+    // The shell command to run as the pager.
+    std::string m_PAGER;
+
+    // The options to pass to the pager.
+    std::string m_PAGER_FLAGS;
+
+    // TRUE means that if output is going to the pager, it is sent as soon
+    // as it is available.  Otherwise, it is buffered and only sent to the
+    // pager when it is time to print another prompt.
+    bool m_page_output_immediately;
+
+    // TRUE means all output intended for the screen should be passed
+    // through the pager.
+    bool m_page_screen_output;
+
+    // TRUE means we write to the diary file.
+    bool m_write_to_diary_file;
+
+    bool m_really_flush_to_pager;
+
+    bool m_flushing_output_to_pager;
+
+    void start_external_pager (void);
+
+    void do_sync (const char *msg, int len, bool bypass_pager);
+  };
+
+  extern std::ostream& __stdout__ (void);
+
+  extern std::ostream& __diary__ (void);
 }
 
 #if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
@@ -171,8 +329,8 @@
 
 #endif
 
-#define octave_stdout (octave::pager_stream::stream ())
+#define octave_stdout (octave::__stdout__ ())
 
-#define octave_diary (octave::diary_stream::stream ())
+#define octave_diary (octave::__diary__ ())
 
 #endif
--- a/libinterp/corefcn/pr-output.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/pr-output.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -2664,7 +2664,7 @@
 
               if (pr_as_read_syntax)
                 {
-                  os << '"' << undo_string_escapes (row) << '"';
+                  os << '"' << octave::undo_string_escapes (row) << '"';
 
                   if (i < nstr - 1)
                     os << "; ";
@@ -3482,7 +3482,7 @@
   // disp is done.
 
   bool print_newlines = false;
-  if (valid_identifier (name))
+  if (octave::valid_identifier (name))
     print_newlines = value.print_name_tag (octave_stdout, name);
 
   // Use feval so that dispatch will also work for disp.
--- a/libinterp/corefcn/procstream.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/procstream.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -24,7 +24,7 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <iomanip>
 
 #include "procstream.h"
 
--- a/libinterp/corefcn/procstream.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/procstream.h	Fri Aug 10 09:09:51 2018 +0200
@@ -25,8 +25,7 @@
 
 #include "octave-config.h"
 
-#include <istream>
-#include <ostream>
+#include <iosfwd>
 #include <string>
 
 #include <sys/types.h>
--- a/libinterp/corefcn/quad.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/quad.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -26,9 +26,6 @@
 
 #include <string>
 
-#include <iomanip>
-#include <iostream>
-
 #include "Quad.h"
 #include "lo-mappers.h"
 
--- a/libinterp/corefcn/qz.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/qz.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -164,7 +164,7 @@
 (@pxref{XREFbalance,,balance}), which may be lead to less accurate results than
 @code{eig}.  The order of output arguments was selected for compatibility with
 @sc{matlab}.
-@seealso{eig, balance, lu, chol, hess, qr, qzhess, schur, svd}
+@seealso{eig, ordeig, balance, lu, chol, hess, qr, qzhess, schur, svd}
 @end deftypefn */)
 {
   int nargin = args.length ();
--- a/libinterp/corefcn/rand.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/rand.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -118,10 +118,10 @@
 
   octave::unwind_protect frame;
   // Restore current distribution on any exit.
-  frame.add_fcn (octave_rand::distribution,
-                 octave_rand::distribution ());
+  frame.add_fcn (octave::rand::distribution,
+                 octave::rand::distribution ());
 
-  octave_rand::distribution (distribution);
+  octave::rand::distribution (distribution);
 
   switch (nargin)
     {
@@ -150,21 +150,21 @@
             std::string s_arg = tmp.string_value ();
 
             if (s_arg == "dist")
-              retval = octave_rand::distribution ();
+              retval = octave::rand::distribution ();
             else if (s_arg == "seed")
-              retval = octave_rand::seed ();
+              retval = octave::rand::seed ();
             else if (s_arg == "state" || s_arg == "twister")
-              retval = octave_rand::state (fcn);
+              retval = octave::rand::state (fcn);
             else if (s_arg == "uniform")
-              octave_rand::uniform_distribution ();
+              octave::rand::uniform_distribution ();
             else if (s_arg == "normal")
-              octave_rand::normal_distribution ();
+              octave::rand::normal_distribution ();
             else if (s_arg == "exponential")
-              octave_rand::exponential_distribution ();
+              octave::rand::exponential_distribution ();
             else if (s_arg == "poisson")
-              octave_rand::poisson_distribution ();
+              octave::rand::poisson_distribution ();
             else if (s_arg == "gamma")
-              octave_rand::gamma_distribution ();
+              octave::rand::gamma_distribution ();
             else
               error ("%s: unrecognized string argument", fcn);
           }
@@ -250,11 +250,11 @@
                   {
                     double d = args(idx+1).double_value ();
 
-                    octave_rand::seed (d);
+                    octave::rand::seed (d);
                   }
                 else if (args(idx+1).is_string ()
                          && args(idx+1).string_value () == "reset")
-                  octave_rand::reset ();
+                  octave::rand::reset ();
                 else
                   error ("%s: seed must be a real scalar", fcn);
               }
@@ -262,7 +262,7 @@
               {
                 if (args(idx+1).is_string ()
                     && args(idx+1).string_value () == "reset")
-                  octave_rand::reset (fcn);
+                  octave::rand::reset (fcn);
                 else
                   {
                     ColumnVector s =
@@ -274,7 +274,7 @@
                       if (octave::math::isinf (s.xelem (i)))
                         s.xelem (i) = 0.0;
 
-                    octave_rand::state (s, fcn);
+                    octave::rand::state (s, fcn);
                   }
               }
             else
@@ -313,7 +313,7 @@
       if (additional_arg)
         {
           if (a.numel () == 1)
-            return octave_rand::float_nd_array (dims, a(0));
+            return octave::rand::float_nd_array (dims, a(0));
           else
             {
               if (a.dims () != dims)
@@ -324,20 +324,20 @@
               float *v = m.fortran_vec ();
 
               for (octave_idx_type i = 0; i < len; i++)
-                v[i] = octave_rand::float_scalar (a(i));
+                v[i] = octave::rand::float_scalar (a(i));
 
               return m;
             }
         }
       else
-        return octave_rand::float_nd_array (dims);
+        return octave::rand::float_nd_array (dims);
     }
   else
     {
       if (additional_arg)
         {
           if (a.numel () == 1)
-            return octave_rand::nd_array (dims, a(0));
+            return octave::rand::nd_array (dims, a(0));
           else
             {
               if (a.dims () != dims)
@@ -348,13 +348,13 @@
               double *v = m.fortran_vec ();
 
               for (octave_idx_type i = 0; i < len; i++)
-                v[i] = octave_rand::scalar (a(i));
+                v[i] = octave::rand::scalar (a(i));
 
               return m;
             }
         }
       else
-        return octave_rand::nd_array (dims);
+        return octave::rand::nd_array (dims);
     }
 }
 
@@ -538,7 +538,7 @@
 %!assert (__rand_sample__ (NaN), __rand_sample__ (0))
 */
 
-static std::string current_distribution = octave_rand::distribution ();
+static std::string current_distribution = octave::rand::distribution ();
 
 DEFUN (randn, args, ,
        doc: /* -*- texinfo -*-
@@ -1131,7 +1131,7 @@
   bool short_shuffle = m < n/5;
 
   // Generate random numbers.
-  NDArray r = octave_rand::nd_array (dim_vector (1, m));
+  NDArray r = octave::rand::nd_array (dim_vector (1, m));
   double *rvec = r.fortran_vec ();
 
   octave_idx_type idx_len = (short_shuffle ? m : n);
--- a/libinterp/corefcn/regexp.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/regexp.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -374,7 +374,7 @@
   bool extra_options = false;
   parse_options (options, args, who, 2, extra_options);
 
-  octave::regexp::match_data rx_lst
+  const octave::regexp::match_data rx_lst
     = octave::regexp::match (pattern, buffer, options, who);
 
   string_vector named_pats = rx_lst.named_patterns ();
@@ -408,7 +408,7 @@
 
   if (options.once ())
     {
-      octave::regexp::match_data::const_iterator p = rx_lst.begin ();
+      auto p = rx_lst.begin ();
 
       retval(4) = (sz ? p->tokens () : Cell ());
       retval(3) = (sz ? p->match_string () : "");
--- a/libinterp/corefcn/schur.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/schur.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -122,7 +122,7 @@
 The Schur@tie{}decomposition is used to compute eigenvalues of a square
 matrix, and has applications in the solution of algebraic @nospell{Riccati}
 equations in control (see @code{are} and @code{dare}).
-@seealso{rsf2csf, ordschur, lu, chol, hess, qr, qz, svd}
+@seealso{rsf2csf, ordschur, ordeig, lu, chol, hess, qr, qz, svd}
 @end deftypefn */)
 {
   int nargin = args.length ();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/corefcn/settings.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,93 @@
+/*
+
+Copyright (C) 2018 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
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include "defun.h"
+#include "interpreter.h"
+#include "ov.h"
+#include "ovl.h"
+#include "settings.h"
+#include "variables.h"
+
+namespace octave
+{
+  settings::settings (void)
+    : m_display_tokens (false), m_token_count (0),
+      m_lexer_debug_flag (false)
+  { }
+
+  octave_value settings::display_tokens (const octave_value_list& args,
+                                         int nargout)
+  {
+    return set_internal_variable (m_display_tokens, args, nargout,
+                                  "__display_tokens__");
+  }
+
+  octave_value settings::lexer_debug_flag (const octave_value_list& args,
+                                           int nargout)
+  {
+    return set_internal_variable (m_lexer_debug_flag, args, nargout,
+                                  "__lexer_debug_flag__");
+  }
+}
+
+DEFMETHOD (__display_tokens__, interp, args, nargout,
+           doc: /* -*- texinfo -*-
+@deftypefn {} {} __display_tokens__ ()
+Query or set the internal variable that determines whether Octave's
+lexer displays tokens as they are read.
+@seealso{__lexer_debug_flag__, __token_count__}
+@end deftypefn */)
+{
+  octave::settings& stgs = interp.get_settings ();
+
+  return stgs.display_tokens (args, nargout);
+}
+
+DEFMETHOD (__token_count__, interp, , ,
+           doc: /* -*- texinfo -*-
+@deftypefn {} {} __token_count__ ()
+Return the number of language tokens processed since Octave startup.
+@seealso{__lexer_debug_flag__, __display_tokens__}
+@end deftypefn */)
+{
+  octave::settings& stgs = interp.get_settings ();
+
+  return octave_value (stgs.token_count ());
+}
+
+DEFMETHOD (__lexer_debug_flag__, interp, args, nargout,
+           doc: /* -*- texinfo -*-
+@deftypefn  {} {@var{val} =} __lexer_debug_flag__ ()
+@deftypefnx {} {@var{old_val} =} __lexer_debug_flag__ (@var{new_val})
+Query or set the internal flag that determines whether Octave's lexer prints
+debug information as it processes an expression.
+@seealso{__display_tokens__, __token_count__, __parse_debug_flag__}
+@end deftypefn */)
+{
+  octave::settings& stgs = interp.get_settings ();
+
+  return stgs.lexer_debug_flag (args, nargout);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/corefcn/settings.h	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,90 @@
+/*
+
+Copyright (C) 2018 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
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if ! defined (octave_settings_h)
+#define octave_settings_h 1
+
+#include "octave-config.h"
+
+class octave_value_list;
+
+namespace octave
+{
+  // Most settings for the interpreter are stored in the classes which
+  // they affect (intput_system, output_system, load_path, etc.  Some
+  // don't really fit anywhere else.  For example, there is no single
+  // lexer or parser object, so we store settings for those things
+  // here.
+
+  class settings
+  {
+  public:
+
+    settings (void);
+
+    settings (const settings&) = delete;
+
+    settings& operator = (const settings&) = delete;
+
+    ~settings (void) = default;
+
+    octave_value display_tokens (const octave_value_list& args, int nargout);
+
+    bool display_tokens (void) const { return m_display_tokens; }
+
+    bool display_tokens (bool flag)
+    {
+      bool val = m_display_tokens;
+      m_display_tokens = flag;
+      return val;
+    }
+
+    // Read only.
+    size_t token_count (void) const { return m_token_count; }
+
+    void increment_token_count (void) { ++m_token_count; }
+
+    octave_value lexer_debug_flag (const octave_value_list& args, int nargout);
+
+    bool lexer_debug_flag (void) const { return m_lexer_debug_flag; }
+
+    bool lexer_debug_flag (bool flag)
+    {
+      bool val = m_lexer_debug_flag;
+      m_lexer_debug_flag = flag;
+      return val;
+    }
+
+  private:
+
+    // Display tokens as they are processed, for debugging.
+    bool m_display_tokens = false;
+
+    // Number of tokens processed since interpreter startup.
+    size_t m_token_count = 0;
+
+    // Internal variable for lexer debugging state.
+    bool m_lexer_debug_flag = false;
+  };
+}
+
+#endif
--- a/libinterp/corefcn/sighandlers.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/sighandlers.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -41,7 +41,6 @@
 #include "quit.h"
 #include "signal-wrappers.h"
 
-#include "bp-table.h"
 #include "defun.h"
 #include "error.h"
 #include "input.h"
@@ -51,8 +50,6 @@
 #include "octave.h"
 #include "oct-map.h"
 #include "pager.h"
-#include "pt-bp.h"
-#include "pt-eval.h"
 #include "sighandlers.h"
 #include "sysdep.h"
 #include "utils.h"
@@ -186,8 +183,7 @@
     static const bool have_sigusr2
       = octave_get_sig_number ("SIGUSR2", &sigusr2);
 
-    octave::child_list& kids
-      = octave::__get_child_list__ ("respond_to_pending_signals");
+    child_list& kids = __get_child_list__ ("respond_to_pending_signals");
 
     for (int sig = 0; sig < octave_num_signals (); sig++)
       {
--- a/libinterp/corefcn/sighandlers.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/sighandlers.h	Fri Aug 10 09:09:51 2018 +0200
@@ -80,60 +80,4 @@
   extern OCTINTERP_API bool Vdebug_on_interrupt;
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::interrupt_handler' instead")
-typedef octave::interrupt_handler octave_interrupt_handler;
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sig_handler' instead")
-typedef octave::sig_handler octave_sig_handler;
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::pipe_handler_error_count' instead")
-static auto& pipe_handler_error_count = octave::pipe_handler_error_count;
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::can_interrupt' instead")
-static auto& can_interrupt = octave::can_interrupt;
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::set_signal_handler' instead")
-inline octave::sig_handler *
-octave_set_signal_handler (int sig, octave::sig_handler *handler,
-                           bool restart_syscalls = true)
-{
-  return octave::set_signal_handler (sig, handler, restart_syscalls);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::set_signal_handler' instead")
-inline octave::sig_handler *
-octave_set_signal_handler (const char *signame, octave::sig_handler *handler,
-                           bool restart_syscalls = true)
-{
-  return octave::set_signal_handler (signame, handler, restart_syscalls);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::set_signal_handler' instead")
-const auto install_signal_handlers = octave::install_signal_handlers;
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::respond_to_pending_signals' instead")
-const auto octave_signal_handler = octave::respond_to_pending_signals;
-
-namespace octave
-{
-  OCTAVE_DEPRECATED (4.4, "use 'octave::respond_to_pending_signals' instead")
-  const auto signal_handler = respond_to_pending_signals;
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::interrupt_handler' instead")
-const auto octave_catch_interrupts = octave::catch_interrupts;
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::ignore_interrupts' instead")
-const auto octave_ignore_interrupts = octave::ignore_interrupts;
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::set_interrupt_handler' instead")
-const auto octave_set_interrupt_handler = octave::set_interrupt_handler;
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::Vdebug_on_interrupt' instead")
-static auto& Vdebug_on_interrupt = octave::Vdebug_on_interrupt;
-
 #endif
-
-#endif
--- a/libinterp/corefcn/sparse.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/sparse.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -151,7 +151,7 @@
       octave_idx_type m = 0;
       octave_idx_type n = 0;
 
-      get_dimensions (args(0), args(1), "sparse", m, n);
+      octave::get_dimensions (args(0), args(1), "sparse", m, n);
 
       if (m >= 0 && n >= 0)
         retval = SparseMatrix (m, n);
@@ -184,7 +184,7 @@
 
       if (nargin == 5)
         {
-          get_dimensions (args(3), args(4), "sparse", m, n);
+          octave::get_dimensions (args(3), args(4), "sparse", m, n);
 
           if (m < 0 || n < 0)
             error ("sparse: dimensions must be non-negative");
--- a/libinterp/corefcn/strfind.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/strfind.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -186,7 +186,7 @@
         @}
 @end group
 @end example
-@seealso{findstr, strmatch, regexp, regexpi, find}
+@seealso{regexp, regexpi, find}
 @end deftypefn */)
 {
   int nargin = args.length ();
@@ -255,7 +255,7 @@
         error ("strfind: first argument must be a string or cell array of strings");
     }
   else if (argpat.iscell ())
-    retval = do_simple_cellfun (Fstrfind, "strfind", args);
+    retval = octave::do_simple_cellfun (Fstrfind, "strfind", args);
   else
     error ("strfind: PATTERN must be a string or cell array of strings");
 
@@ -372,7 +372,7 @@
 @end group
 @end example
 
-@seealso{regexprep, strfind, findstr}
+@seealso{regexprep, strfind}
 @end deftypefn */)
 {
   int nargin = args.length ();
@@ -433,7 +433,7 @@
         error ("strrep: S must be a string or cell array of strings");
     }
   else if (argpat.iscell () || argrep.iscell ())
-    retval = do_simple_cellfun (Fstrrep, "strrep", args);
+    retval = octave::do_simple_cellfun (Fstrrep, "strrep", args);
   else
     error ("strrep: PTN and REP arguments must be strings or cell arrays of strings");
 
--- a/libinterp/corefcn/strfns.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/strfns.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -32,6 +32,7 @@
 #include "dMatrix.h"
 #include "localcharset-wrapper.h"
 #include "uniconv-wrappers.h"
+#include "unistr-wrappers.h"
 
 #include "Cell.h"
 #include "defun.h"
@@ -657,11 +658,13 @@
 %!assert (strncmp ("abce", "aBc", 3), false)
 %!assert (strncmp (100, 100, 1), false)
 %!assert (strncmp ("abce", {"abcd", "bca", "abc"}, 3), logical ([1, 0, 1]))
-%!assert (strncmp ("abc",  {"abcd", "bca", "abc"}, 4), logical ([0, 0, 0]))
+%!assert (strncmp ("abc",  {"abcd", "bca", "abc"}, 4), logical ([0, 0, 1]))
 %!assert (strncmp ({"abcd", "bca", "abc"},"abce", 3), logical ([1, 0, 1]))
 %!assert (strncmp ({"abcd", "bca", "abc"},{"abcd", "bca", "abe"}, 3), logical ([1, 1, 0]))
 %!assert (strncmp ("abc", {"abcd", 10}, 2), logical ([1, 0]))
 
+%!assert <*54373> (strncmp ("abc", "abc", 100))
+
 %!error strncmp ()
 %!error strncmp ("abc", "def")
 */
@@ -732,6 +735,8 @@
 
 /*
 %!assert (strncmpi ("abc123", "ABC456", 3), true)
+
+%!assert <*54373> (strncmpi ("abc", "abC", 100))
 */
 
 DEFUN (__native2unicode__, args, ,
@@ -840,6 +845,60 @@
   return ovl (retval);
 }
 
+DEFUN (unicode_idx, args, ,
+       doc: /* -*- texinfo -*-
+@deftypefn {} {@var{idx} =} unicode_idx (@var{str})
+Return an array with the indices for each UTF-8 encoded character in @var{str}.
+
+@example
+@group
+unicode_idx ("aäbc")
+     @result{} [1, 2, 2, 3, 4]
+@end group
+@end example
+
+@end deftypefn */)
+{
+  int nargin = args.length ();
+
+  if (nargin != 1)
+    print_usage ();
+
+  charNDArray str = args(0).xchar_array_value ("STR must be a string");
+  Array<octave_idx_type> p (dim_vector (str.ndims (), 1));
+  charNDArray str_p;
+  if (str.ndims () > 1)
+  {
+    for (octave_idx_type i=0; i < str.ndims (); i++)
+      p(i) = i;
+    p(0) = 1;
+    p(1) = 0;
+    str_p = str.permute (p);
+  }
+
+  const uint8_t *src = reinterpret_cast<const uint8_t *> (str_p.data ());
+  octave_idx_type srclen = str.numel ();
+
+  NDArray idx (str_p.dims ());
+
+  octave_idx_type u8_char_num = 1;
+  for (octave_idx_type i = 0; i < srclen; u8_char_num++)
+  {
+    int mblen = octave_u8_strmblen_wrapper (src + i);
+    if (mblen < 1)
+      mblen = 1;
+    for (octave_idx_type j = 0; j < mblen; j++)
+      idx (i+j) = u8_char_num;
+    i += mblen;
+  }
+
+  return ovl(str.ndims () > 1 ? idx.permute (p, true) : idx);
+}
+
+/*
+%!assert (unicode_idx (["aäou"; "Ä∞"]), [1 2 2 3 4; 5 5 6 6 6]);
+*/
+
 DEFUN (list_in_columns, args, ,
        doc: /* -*- texinfo -*-
 @deftypefn {} {} list_in_columns (@var{arg}, @var{width}, @var{prefix})
--- a/libinterp/corefcn/svd.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/svd.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -168,7 +168,7 @@
 {
   int nargin = args.length ();
 
-  if (nargin < 1 || nargin > 2 || nargout == 2 || nargout > 3)
+  if (nargin < 1 || nargin > 2 || nargout > 3)
     print_usage ();
 
   octave_value arg = args(0);
@@ -198,6 +198,9 @@
 
           if (nargout == 0 || nargout == 1)
             retval(0) = sigma.extract_diag ();
+          else if (nargout == 2)
+            retval = ovl (result.left_singular_matrix (),
+                          sigma);
           else
             retval = ovl (result.left_singular_matrix (),
                           sigma,
@@ -219,6 +222,9 @@
 
           if (nargout == 0 || nargout == 1)
             retval(0) = sigma.extract_diag ();
+          else if (nargout == 2)
+            retval = ovl (result.left_singular_matrix (),
+                          sigma);
           else
             retval = ovl (result.left_singular_matrix (),
                           sigma,
@@ -243,6 +249,9 @@
 
           if (nargout == 0 || nargout == 1)
             retval(0) = sigma.extract_diag ();
+          else if (nargout == 2)
+            retval = ovl (result.left_singular_matrix (),
+                          sigma);
           else
             retval = ovl (result.left_singular_matrix (),
                           sigma,
@@ -264,6 +273,9 @@
 
           if (nargout == 0 || nargout == 1)
             retval(0) = sigma.extract_diag ();
+          else if (nargout == 2)
+            retval = ovl (result.left_singular_matrix (),
+                          sigma);
           else
             retval = ovl (result.left_singular_matrix (),
                           sigma,
@@ -280,9 +292,9 @@
 %!assert (svd ([1, 2; 2, 1]), [3; 1], sqrt (eps))
 
 %!test
-a = [1, 2; 3, 4] + [5, 6; 7, 8]*i;
-[u,s,v] = svd (a);
-assert (a, u * s * v', 128 * eps);
+%! a = [1, 2; 3, 4] + [5, 6; 7, 8]*i;
+%! [u,s,v] = svd (a);
+%! assert (a, u * s * v', 128 * eps);
 
 %!test
 %! [u, s, v] = svd ([1, 2; 2, 1]);
@@ -362,7 +374,6 @@
 
 %!error svd ()
 %!error svd ([1, 2; 4, 5], 2, 3)
-%!error [u, v] = svd ([1, 2; 3, 4])
 */
 
 DEFUN (svd_driver, args, nargout,
--- a/libinterp/corefcn/symscope.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/symscope.h	Fri Aug 10 09:09:51 2018 +0200
@@ -27,7 +27,6 @@
 #include "octave-config.h"
 
 #include <deque>
-#include <limits>
 #include <list>
 #include <map>
 #include <memory>
@@ -121,7 +120,7 @@
 
     symbol_record find_symbol (const std::string& name)
     {
-      table_iterator p = m_symbols.find (name);
+      auto p = m_symbols.find (name);
 
       if (p == m_symbols.end ())
         return insert (name);
@@ -179,7 +178,7 @@
 
     void rename (const std::string& old_name, const std::string& new_name)
     {
-      table_iterator p = m_symbols.find (old_name);
+      auto p = m_symbols.find (old_name);
 
       if (p != m_symbols.end ())
         {
@@ -196,7 +195,7 @@
     void assign (const std::string& name, const octave_value& value,
                  bool force_add)
     {
-      table_iterator p = m_symbols.find (name);
+      auto p = m_symbols.find (name);
 
       if (p == m_symbols.end ())
         {
@@ -216,7 +215,7 @@
 
     void force_assign (const std::string& name, const octave_value& value)
     {
-      table_iterator p = m_symbols.find (name);
+      auto p = m_symbols.find (name);
 
       if (p == m_symbols.end ())
         {
@@ -260,7 +259,7 @@
 
     void pop_context (void)
     {
-      table_iterator tbl_it = m_symbols.begin ();
+      auto tbl_it = m_symbols.begin ();
 
       while (tbl_it != m_symbols.end ())
         {
@@ -303,7 +302,7 @@
 
     void clear_variable (const std::string& name)
     {
-      table_iterator p = m_symbols.find (name);
+      auto p = m_symbols.find (name);
 
       if (p != m_symbols.end ())
         p->second.clear (m_context);
--- a/libinterp/corefcn/symtab.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/symtab.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -97,7 +97,7 @@
     bool retval = false;
 
     octave_value ov_fcn
-      = octave::load_fcn_from_file (ff, dir_name, dispatch_type,
+      = load_fcn_from_file (ff, dir_name, dispatch_type,
                                     package_name);
 
     if (ov_fcn.is_defined ())
@@ -167,7 +167,8 @@
 
                             if (! dispatch_type.empty ())
                               {
-                                load_path& lp = __get_load_path__ ("out_of_date_check");
+                                load_path& lp
+                                  = __get_load_path__ ("out_of_date_check");
 
                                 file = lp.find_method (dispatch_type, nm,
                                                        dir_name, pack);
@@ -210,7 +211,8 @@
 
                             if (file.empty ())
                               {
-                                load_path& lp = __get_load_path__ ("out_of_date_check");
+                                load_path& lp
+                                  = __get_load_path__ ("out_of_date_check");
                                 file = lp.find_fcn (nm, dir_name, pack);
                               }
                           }
@@ -283,8 +285,8 @@
                     // breakpoints associated with it
                     if (clear_breakpoints)
                       {
-                        octave::bp_table& bptab
-                          = octave::__get_bp_table__ ("out_of_date_check");
+                        bp_table& bptab
+                          = __get_bp_table__ ("out_of_date_check");
 
                         bptab.remove_all_breakpoints_in_file (canonical_nm,
                                                               true);
--- a/libinterp/corefcn/symtab.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/symtab.h	Fri Aug 10 09:09:51 2018 +0200
@@ -27,7 +27,6 @@
 #include "octave-config.h"
 
 #include <deque>
-#include <limits>
 #include <list>
 #include <map>
 #include <set>
@@ -241,7 +240,7 @@
     octave_value
     find_autoload (const std::string& name)
     {
-      fcn_table_iterator p = m_fcn_table.find (name);
+      auto p = m_fcn_table.find (name);
 
       return (p != m_fcn_table.end ()
               ? p->second.find_autoload () : octave_value ());
@@ -261,7 +260,7 @@
 
     octave_value find_user_function (const std::string& name)
     {
-      fcn_table_iterator p = m_fcn_table.find (name);
+      auto p = m_fcn_table.find (name);
 
       return (p != m_fcn_table.end ()
               ? p->second.find_user_function () : octave_value ());
@@ -269,7 +268,7 @@
 
     octave_value find_cmdline_function (const std::string& name)
     {
-      fcn_table_iterator p = m_fcn_table.find (name);
+      auto p = m_fcn_table.find (name);
 
       return (p != m_fcn_table.end ()
               ? p->second.find_cmdline_function () : octave_value ());
@@ -278,7 +277,7 @@
     void install_cmdline_function (const std::string& name,
                                    const octave_value& fcn)
     {
-      fcn_table_iterator p = m_fcn_table.find (name);
+      auto p = m_fcn_table.find (name);
 
       if (p != m_fcn_table.end ())
         {
@@ -303,7 +302,7 @@
                                  const octave_value& fcn,
                                  const std::string& file_name)
     {
-      fcn_table_iterator p = m_fcn_table.find (name);
+      auto p = m_fcn_table.find (name);
 
       if (p != m_fcn_table.end ())
         {
@@ -324,7 +323,7 @@
     void install_user_function (const std::string& name,
                                 const octave_value& fcn)
     {
-      fcn_table_iterator p = m_fcn_table.find (name);
+      auto p = m_fcn_table.find (name);
 
       if (p != m_fcn_table.end ())
         {
@@ -347,7 +346,7 @@
     void install_built_in_function (const std::string& name,
                                     const octave_value& fcn)
     {
-      fcn_table_iterator p = m_fcn_table.find (name);
+      auto p = m_fcn_table.find (name);
 
       if (p != m_fcn_table.end ())
         {
@@ -383,7 +382,7 @@
 
     void clear_functions (bool force = false)
     {
-      fcn_table_iterator p = m_fcn_table.begin ();
+      auto p = m_fcn_table.begin ();
 
       while (p != m_fcn_table.end ())
         (p++)->second.clear (force);
@@ -408,7 +407,7 @@
     {
       glob_match pattern (pat);
 
-      fcn_table_iterator p = m_fcn_table.begin ();
+      auto p = m_fcn_table.begin ();
 
       while (p != m_fcn_table.end ())
         {
@@ -431,7 +430,7 @@
 
     void clear_user_function (const std::string& name)
     {
-      fcn_table_iterator p = m_fcn_table.find (name);
+      auto p = m_fcn_table.find (name);
 
       if (p != m_fcn_table.end ())
         {
@@ -447,7 +446,7 @@
     // This clears oct and mex files, including autoloads.
     void clear_dld_function (const std::string& name)
     {
-      fcn_table_iterator p = m_fcn_table.find (name);
+      auto p = m_fcn_table.find (name);
 
       if (p != m_fcn_table.end ())
         {
@@ -460,7 +459,7 @@
 
     void clear_mex_functions (void)
     {
-      fcn_table_iterator p = m_fcn_table.begin ();
+      auto p = m_fcn_table.begin ();
 
       while (p != m_fcn_table.end ())
         (p++)->second.clear_mex_function ();
@@ -491,7 +490,7 @@
     void install_built_in_dispatch (const std::string& name,
                                     const std::string& klass)
     {
-      fcn_table_iterator p = m_fcn_table.find (name);
+      auto p = m_fcn_table.find (name);
 
       if (p != m_fcn_table.end ())
         {
@@ -669,7 +668,7 @@
 
     fcn_info * get_fcn_info (const std::string& name)
     {
-      fcn_table_iterator p = m_fcn_table.find (name);
+      auto p = m_fcn_table.find (name);
       return p != m_fcn_table.end () ? &p->second : nullptr;
     }
 
--- a/libinterp/corefcn/syscalls.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/syscalls.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -42,7 +42,6 @@
 #include "oct-env.h"
 #include "oct-syscalls.h"
 #include "oct-uname.h"
-
 #include "defun.h"
 #include "error.h"
 #include "errwarn.h"
@@ -52,6 +51,7 @@
 #include "ovl.h"
 #include "oct-stdstrm.h"
 #include "oct-stream.h"
+#include "octave-link.h"
 #include "sysdep.h"
 #include "utils.h"
 #include "variables.h"
@@ -1088,8 +1088,12 @@
 
   std::string msg;
 
+  octave_link::file_remove (name, "");
+
   int status = octave::sys::unlink (name, msg);
 
+  octave_link::file_renamed (status == 0);
+
   return ovl (status, msg);
 }
 
--- a/libinterp/corefcn/sysdep.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/sysdep.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -64,6 +64,7 @@
 #include "lo-sysinfo.h"
 #include "mach-info.h"
 #include "oct-env.h"
+#include "uniconv-wrappers.h"
 #include "unistd-wrappers.h"
 #include "unsetenv-wrapper.h"
 
@@ -122,26 +123,26 @@
 
   if (h != INVALID_HANDLE_VALUE)
     {
-      MODULEENTRY32 mod_info;
+      MODULEENTRY32W mod_info;
 
       ZeroMemory (&mod_info, sizeof (mod_info));
       mod_info.dwSize = sizeof (mod_info);
 
-      if (Module32First (h, &mod_info))
+      if (Module32FirstW (h, &mod_info))
         {
           do
             {
-              std::string mod_name (mod_info.szModule);
+              std::string mod_name (octave::sys::u8_from_wstring (mod_info.szModule));
 
               if (mod_name.find ("octinterp") != std::string::npos)
                 {
-                  bin_dir = mod_info.szExePath;
+                  bin_dir = octave::sys::u8_from_wstring (mod_info.szExePath);
                   if (! bin_dir.empty () && bin_dir.back () != '\\')
                     bin_dir.push_back ('\\');
                   break;
                 }
             }
-          while (Module32Next (h, &mod_info));
+          while (Module32NextW (h, &mod_info));
         }
 
       CloseHandle (h);
@@ -166,33 +167,35 @@
 
 #endif
 
-// Set app id if we have the SetCurrentProcessExplicitAppUserModelID
-// available (>= Win7).  FIXME: Could we check for existence of this
-// function in the configure script instead of dynamically loading
-// shell32.dll?
+namespace octave
+{
+  // Set app id if we have the SetCurrentProcessExplicitAppUserModelID
+  // available (>= Win7).  FIXME: Could we check for existence of this
+  // function in the configure script instead of dynamically loading
+  // shell32.dll?
 
-void
-set_application_id (void)
-{
+  void set_application_id (void)
+  {
 #if defined (__MINGW32__) || defined (_MSC_VER)
 
-  typedef HRESULT (WINAPI *SETCURRENTAPPID)(PCWSTR AppID);
+    typedef HRESULT (WINAPI *SETCURRENTAPPID)(PCWSTR AppID);
 
-  HMODULE hShell = LoadLibrary ("shell32.dll");
+    HMODULE hShell = LoadLibrary ("shell32.dll");
 
-  if (hShell)
-    {
-      SETCURRENTAPPID pfnSetCurrentProcessExplicitAppUserModelID =
-        reinterpret_cast<SETCURRENTAPPID> (GetProcAddress (hShell,
-                                           "SetCurrentProcessExplicitAppUserModelID"));
+    if (hShell)
+      {
+        SETCURRENTAPPID pfnSetCurrentProcessExplicitAppUserModelID =
+          reinterpret_cast<SETCURRENTAPPID> (GetProcAddress (hShell,
+                                                             "SetCurrentProcessExplicitAppUserModelID"));
 
-      if (pfnSetCurrentProcessExplicitAppUserModelID)
-        pfnSetCurrentProcessExplicitAppUserModelID (L"gnu.octave." VERSION);
+        if (pfnSetCurrentProcessExplicitAppUserModelID)
+          pfnSetCurrentProcessExplicitAppUserModelID (L"gnu.octave." VERSION);
 
-      FreeLibrary (hShell);
-    }
+        FreeLibrary (hShell);
+      }
 
 #endif
+  }
 }
 
 DEFUN (__open_with_system_app__, args, ,
@@ -209,8 +212,9 @@
   octave_value retval;
 
 #if defined (OCTAVE_USE_WINDOWS_API)
-  HINSTANCE status = ShellExecute (0, 0, file.c_str (), 0, 0,
-                                   SW_SHOWNORMAL);
+  HINSTANCE status = ShellExecuteW (0, 0,
+                                    octave::sys::u8_to_wstring (file).c_str (),
+                                    0, 0, SW_SHOWNORMAL);
 
   // ShellExecute returns a value greater than 32 if successful.
   retval = (reinterpret_cast<ptrdiff_t> (status) > 32);
@@ -249,364 +253,368 @@
 }
 #endif
 
-// Return TRUE if FILE1 and FILE2 refer to the same (physical) file.
+namespace octave
+{
+  // Return TRUE if FILE1 and FILE2 refer to the same (physical) file.
 
-bool
-same_file_internal (const std::string& file1, const std::string& file2)
-{
+  bool same_file_internal (const std::string& file1, const std::string& file2)
+  {
 #if defined (OCTAVE_USE_WINDOWS_API)
 
-  bool retval = false;
+    bool retval = false;
 
-  const char *f1 = file1.c_str ();
-  const char *f2 = file2.c_str ();
-
-  bool f1_is_dir = GetFileAttributes (f1) & FILE_ATTRIBUTE_DIRECTORY;
-  bool f2_is_dir = GetFileAttributes (f2) & FILE_ATTRIBUTE_DIRECTORY;
+    std::wstring file1w = octave::sys::u8_to_wstring (file1);
+    std::wstring file2w = octave::sys::u8_to_wstring (file2);
+    const wchar_t *f1 = file1w.c_str ();
+    const wchar_t *f2 = file2w.c_str ();
 
-  // Windows native code
-  // Reference: http://msdn2.microsoft.com/en-us/library/aa363788.aspx
+    bool f1_is_dir = GetFileAttributesW (f1) & FILE_ATTRIBUTE_DIRECTORY;
+    bool f2_is_dir = GetFileAttributesW (f2) & FILE_ATTRIBUTE_DIRECTORY;
+
+    // Windows native code
+    // Reference: http://msdn2.microsoft.com/en-us/library/aa363788.aspx
 
-  DWORD share = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE;
+    DWORD share = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE;
 
-  HANDLE hfile1
-    = CreateFile (f1, 0, share, 0, OPEN_EXISTING,
-                  f1_is_dir ? FILE_FLAG_BACKUP_SEMANTICS : 0, 0);
+    HANDLE hfile1
+      = CreateFileW (f1, 0, share, 0, OPEN_EXISTING,
+                     f1_is_dir ? FILE_FLAG_BACKUP_SEMANTICS : 0, 0);
 
-  if (hfile1 != INVALID_HANDLE_VALUE)
-    {
-      HANDLE hfile2
-        = CreateFile (f2, 0, share, 0, OPEN_EXISTING,
-                      f2_is_dir ? FILE_FLAG_BACKUP_SEMANTICS : 0, 0);
+    if (hfile1 != INVALID_HANDLE_VALUE)
+      {
+        HANDLE hfile2
+          = CreateFileW (f2, 0, share, 0, OPEN_EXISTING,
+                         f2_is_dir ? FILE_FLAG_BACKUP_SEMANTICS : 0, 0);
 
-      if (hfile2 != INVALID_HANDLE_VALUE)
-        {
-          BY_HANDLE_FILE_INFORMATION hfi1;
-          BY_HANDLE_FILE_INFORMATION hfi2;
+        if (hfile2 != INVALID_HANDLE_VALUE)
+          {
+            BY_HANDLE_FILE_INFORMATION hfi1;
+            BY_HANDLE_FILE_INFORMATION hfi2;
 
-          if (GetFileInformationByHandle (hfile1, &hfi1)
-              && GetFileInformationByHandle (hfile2, &hfi2))
-            {
-              retval = (hfi1.dwVolumeSerialNumber == hfi2.dwVolumeSerialNumber
-                        && hfi1.nFileIndexHigh == hfi2.nFileIndexHigh
-                        && hfi1.nFileIndexLow == hfi2.nFileIndexLow);
-            }
+            if (GetFileInformationByHandle (hfile1, &hfi1)
+                && GetFileInformationByHandle (hfile2, &hfi2))
+              {
+                retval = (hfi1.dwVolumeSerialNumber == hfi2.dwVolumeSerialNumber
+                          && hfi1.nFileIndexHigh == hfi2.nFileIndexHigh
+                          && hfi1.nFileIndexLow == hfi2.nFileIndexLow);
+              }
 
-          CloseHandle (hfile2);
-        }
+            CloseHandle (hfile2);
+          }
 
-      CloseHandle (hfile1);
-    }
+        CloseHandle (hfile1);
+      }
 
-  return retval;
+    return retval;
 
 #else
 
-  // POSIX Code
+    // POSIX Code
 
-  octave::sys::file_stat fs_file1 (file1);
-  octave::sys::file_stat fs_file2 (file2);
+    octave::sys::file_stat fs_file1 (file1);
+    octave::sys::file_stat fs_file2 (file2);
 
-  return (fs_file1 && fs_file2
-          && fs_file1.ino () == fs_file2.ino ()
-          && fs_file1.dev () == fs_file2.dev ());
+    return (fs_file1 && fs_file2
+            && fs_file1.ino () == fs_file2.ino ()
+            && fs_file1.dev () == fs_file2.dev ());
 
 #endif
-}
+  }
 
-void
-sysdep_init (void)
-{
-  // Use a function from libgomp to force loading of OpenMP library.
-  // Otherwise, a dynamically loaded library making use of OpenMP such
-  // as GraphicsMagick will segfault on exit (bug #41699).
+  void sysdep_init (void)
+  {
+    // Use a function from libgomp to force loading of OpenMP library.
+    // Otherwise, a dynamically loaded library making use of OpenMP such
+    // as GraphicsMagick will segfault on exit (bug #41699).
 #if defined (HAVE_OMP_GET_NUM_THREADS)
-  omp_get_num_threads ();
+    omp_get_num_threads ();
 #endif
 
 #if defined (__386BSD__) || defined (__FreeBSD__) || defined (__NetBSD__)
-  BSD_init ();
+    BSD_init ();
 #elif defined (__MINGW32__)
-  MINGW_init ();
+    MINGW_init ();
 #elif defined (_MSC_VER)
-  MSVC_init ();
+    MSVC_init ();
 #endif
-}
+  }
 
-void
-sysdep_cleanup (void)
-{
+  void sysdep_cleanup (void)
+  {
 #if defined (OCTAVE_USE_WINDOWS_API)
-  // Let us fail immediately without displaying any dialog.
-  SetProcessShutdownParameters (0x280, SHUTDOWN_NORETRY);
+    // Let us fail immediately without displaying any dialog.
+    SetProcessShutdownParameters (0x280, SHUTDOWN_NORETRY);
 #endif
-}
+  }
 
-// Set terminal in raw mode.  From less-177.
-//
-// Change terminal to "raw mode", or restore to "normal" mode.
-// "Raw mode" means
-//      1. An outstanding read will complete on receipt of a single keystroke.
-//      2. Input is not echoed.
-//      3. On output, \n is mapped to \r\n.
-//      4. \t is NOT expanded into spaces.
-//      5. Signal-causing characters such as ctrl-C (interrupt),
-//         etc. are NOT disabled.
-// It doesn't matter whether an input \n is mapped to \r, or vice versa.
+  // Set terminal in raw mode.  From less-177.
+  //
+  // Change terminal to "raw mode", or restore to "normal" mode.
+  // "Raw mode" means
+  //      1. An outstanding read will complete on receipt of a single keystroke.
+  //      2. Input is not echoed.
+  //      3. On output, \n is mapped to \r\n.
+  //      4. \t is NOT expanded into spaces.
+  //      5. Signal-causing characters such as ctrl-C (interrupt),
+  //         etc. are NOT disabled.
+  // It doesn't matter whether an input \n is mapped to \r, or vice versa.
 
-void
-raw_mode (bool on, bool wait)
-{
-  static bool curr_on = false;
+  void raw_mode (bool on, bool wait)
+  {
+    static bool curr_on = false;
 
-  int tty_fd = STDIN_FILENO;
-  if (! octave_isatty_wrapper (tty_fd))
-    {
-      if (octave::application::interactive ()
-          && ! octave::application::forced_interactive ())
-        error ("stdin is not a tty!");
-    }
+    int tty_fd = STDIN_FILENO;
+    if (! octave_isatty_wrapper (tty_fd))
+      {
+        if (octave::application::interactive ()
+            && ! octave::application::forced_interactive ())
+          error ("stdin is not a tty!");
+      }
 
-  if (on == curr_on)
-    return;
+    if (on == curr_on)
+      return;
 
 #if defined (HAVE_TERMIOS_H)
-  {
-    struct termios s;
-    static struct termios save_term;
+    {
+      struct termios s;
+      static struct termios save_term;
 
-    if (on)
-      {
-        // Get terminal modes.
+      if (on)
+        {
+          // Get terminal modes.
 
-        tcgetattr (tty_fd, &s);
+          tcgetattr (tty_fd, &s);
 
-        // Save modes and set certain variables dependent on modes.
+          // Save modes and set certain variables dependent on modes.
 
-        save_term = s;
-//      ospeed = s.c_cflag & CBAUD;
-//      erase_char = s.c_cc[VERASE];
-//      kill_char = s.c_cc[VKILL];
+          save_term = s;
+          //      ospeed = s.c_cflag & CBAUD;
+          //      erase_char = s.c_cc[VERASE];
+          //      kill_char = s.c_cc[VKILL];
 
-        // Set the modes to the way we want them.
+          // Set the modes to the way we want them.
 
-        s.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL);
-        s.c_oflag |=  (OPOST | ONLCR);
+          s.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL);
+          s.c_oflag |=  (OPOST | ONLCR);
 #if defined (OCRNL)
-        s.c_oflag &= ~(OCRNL);
+          s.c_oflag &= ~(OCRNL);
 #endif
 #if defined (ONOCR)
-        s.c_oflag &= ~(ONOCR);
+          s.c_oflag &= ~(ONOCR);
 #endif
 #if defined (ONLRET)
-        s.c_oflag &= ~(ONLRET);
+          s.c_oflag &= ~(ONLRET);
 #endif
-        s.c_cc[VMIN] = (wait ? 1 : 0);
-        s.c_cc[VTIME] = 0;
-      }
-    else
-      {
-        // Restore saved modes.
+          s.c_cc[VMIN] = (wait ? 1 : 0);
+          s.c_cc[VTIME] = 0;
+        }
+      else
+        {
+          // Restore saved modes.
 
-        s = save_term;
-      }
+          s = save_term;
+        }
 
-    tcsetattr (tty_fd, wait ? TCSAFLUSH : TCSADRAIN, &s);
-  }
+      tcsetattr (tty_fd, wait ? TCSAFLUSH : TCSADRAIN, &s);
+    }
 #elif defined (HAVE_TERMIO_H)
-  {
-    struct termio s;
-    static struct termio save_term;
+    {
+      struct termio s;
+      static struct termio save_term;
 
-    if (on)
-      {
-        // Get terminal modes.
+      if (on)
+        {
+          // Get terminal modes.
 
-        ioctl (tty_fd, TCGETA, &s);
+          ioctl (tty_fd, TCGETA, &s);
 
-        // Save modes and set certain variables dependent on modes.
+          // Save modes and set certain variables dependent on modes.
 
-        save_term = s;
-//      ospeed = s.c_cflag & CBAUD;
-//      erase_char = s.c_cc[VERASE];
-//      kill_char = s.c_cc[VKILL];
+          save_term = s;
+          //      ospeed = s.c_cflag & CBAUD;
+          //      erase_char = s.c_cc[VERASE];
+          //      kill_char = s.c_cc[VKILL];
 
-        // Set the modes to the way we want them.
+          // Set the modes to the way we want them.
 
-        s.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL);
-        s.c_oflag |=  (OPOST | ONLCR);
+          s.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL);
+          s.c_oflag |=  (OPOST | ONLCR);
 #if defined (OCRNL)
-        s.c_oflag &= ~(OCRNL);
+          s.c_oflag &= ~(OCRNL);
 #endif
 #if defined (ONOCR)
-        s.c_oflag &= ~(ONOCR);
+          s.c_oflag &= ~(ONOCR);
 #endif
 #if defined (ONLRET)
-        s.c_oflag &= ~(ONLRET);
+          s.c_oflag &= ~(ONLRET);
 #endif
-        s.c_cc[VMIN] = (wait ? 1 : 0);
-      }
-    else
-      {
-        // Restore saved modes.
+          s.c_cc[VMIN] = (wait ? 1 : 0);
+        }
+      else
+        {
+          // Restore saved modes.
+
+          s = save_term;
+        }
+
+      ioctl (tty_fd, TCSETAW, &s);
+    }
+#elif defined (HAVE_SGTTY_H)
+    {
+      octave_unused_parameter (wait);
+
+      struct sgttyb s;
+      static struct sgttyb save_term;
+
+      if (on)
+        {
+          // Get terminal modes.
 
-        s = save_term;
-      }
+          ioctl (tty_fd, TIOCGETP, &s);
+
+          // Save modes and set certain variables dependent on modes.
+
+          save_term = s;
+          //      ospeed = s.sg_ospeed;
+          //      erase_char = s.sg_erase;
+          //      kill_char = s.sg_kill;
+
+          // Set the modes to the way we want them.
 
-    ioctl (tty_fd, TCSETAW, &s);
-  }
-#elif defined (HAVE_SGTTY_H)
-  {
+          s.sg_flags |= CBREAK;
+          s.sg_flags &= ~(ECHO);
+        }
+      else
+        {
+          // Restore saved modes.
+
+          s = save_term;
+        }
+
+      ioctl (tty_fd, TIOCSETN, &s);
+    }
+#else
+
     octave_unused_parameter (wait);
 
-    struct sgttyb s;
-    static struct sgttyb save_term;
-
-    if (on)
-      {
-        // Get terminal modes.
-
-        ioctl (tty_fd, TIOCGETP, &s);
-
-        // Save modes and set certain variables dependent on modes.
-
-        save_term = s;
-//      ospeed = s.sg_ospeed;
-//      erase_char = s.sg_erase;
-//      kill_char = s.sg_kill;
-
-        // Set the modes to the way we want them.
+    warn_disabled_feature ("", "raw mode console I/O");
 
-        s.sg_flags |= CBREAK;
-        s.sg_flags &= ~(ECHO);
-      }
-    else
-      {
-        // Restore saved modes.
-
-        s = save_term;
-      }
-
-    ioctl (tty_fd, TIOCSETN, &s);
-  }
-#else
-
-  octave_unused_parameter (wait);
-
-  warn_disabled_feature ("", "raw mode console I/O");
-
-  // Make sure the current mode doesn't toggle.
-  on = curr_on;
+    // Make sure the current mode doesn't toggle.
+    on = curr_on;
 #endif
 
-  curr_on = on;
-}
+    curr_on = on;
+  }
 
-FILE *
-octave_popen (const char *command, const char *mode)
-{
+  FILE * popen (const char *command, const char *mode)
+  {
 #if defined (__MINGW32__) || defined (_MSC_VER)
-  if (mode && mode[0] && ! mode[1])
-    {
-      // Use binary mode on Windows if unspecified
-      char tmode[3] = {mode[0], 'b', '\0'};
+    wchar_t *wcommand = u8_to_wchar (command);
+    wchar_t *wmode = u8_to_wchar (mode);
 
-      return _popen (command, tmode);
-    }
-  else
-    return _popen (command, mode);
-#else
-  return popen (command, mode);
-#endif
-}
+    octave::unwind_protect frame;
+    frame.add_fcn (::free, static_cast<void *> (wcommand));
+    frame.add_fcn (::free, static_cast<void *> (wmode));
+
+    if (wmode && wmode[0] && ! wmode[1])
+      {
+        // Use binary mode on Windows if unspecified
+        wchar_t tmode[3] = {wmode[0], L'b', L'\0'};
 
-int
-octave_pclose (FILE *f)
-{
-#if defined (__MINGW32__) || defined (_MSC_VER)
-  return _pclose (f);
+        return _wpopen (wcommand, tmode);
+      }
+    else
+      return _wpopen (wcommand, wmode);
 #else
-  return pclose (f);
+    return ::popen (command, mode);
 #endif
-}
-
-// Read one character from the terminal.
+  }
 
-int
-octave_kbhit (bool wait)
-{
+  int pclose (FILE *f)
+  {
+#if defined (__MINGW32__) || defined (_MSC_VER)
+    return ::_pclose (f);
+#else
+    return ::pclose (f);
+#endif
+  }
+
+  // Read one character from the terminal.
+
+  int kbhit (bool wait)
+  {
 #if defined (HAVE__KBHIT) && defined (HAVE__GETCH)
-  // This essentially means we are on a Windows system.
-  int c;
+    // This essentially means we are on a Windows system.
+    int c;
 
-  if (wait)
-    c = _getch ();
-  else
-    c = (! _kbhit ()) ? 0 : _getch ();
+    if (wait)
+      c = _getch ();
+    else
+      c = (! _kbhit ()) ? 0 : _getch ();
 
 #else
-  raw_mode (true, wait);
+    raw_mode (true, wait);
 
-  // Get current handler.
-  octave::interrupt_handler saved_interrupt_handler
-    = octave::ignore_interrupts ();
+    // Get current handler.
+    octave::interrupt_handler saved_interrupt_handler
+      = octave::ignore_interrupts ();
 
-  // Restore it, disabling system call restarts (if possible) so the
-  // read can be interrupted.
+    // Restore it, disabling system call restarts (if possible) so the
+    // read can be interrupted.
 
-  octave::set_interrupt_handler (saved_interrupt_handler, false);
+    octave::set_interrupt_handler (saved_interrupt_handler, false);
 
-  int c = std::cin.get ();
+    int c = std::cin.get ();
 
-  if (std::cin.fail () || std::cin.eof ())
-    std::cin.clear ();
+    if (std::cin.fail () || std::cin.eof ())
+      std::cin.clear ();
 
-  // Restore it, enabling system call restarts (if possible).
-  octave::set_interrupt_handler (saved_interrupt_handler, true);
+    // Restore it, enabling system call restarts (if possible).
+    octave::set_interrupt_handler (saved_interrupt_handler, true);
 
-  raw_mode (false, true);
+    raw_mode (false, true);
 #endif
 
-  return c;
-}
+    return c;
+  }
 
-std::string
-get_P_tmpdir (void)
-{
+  std::string get_P_tmpdir (void)
+  {
 #if defined (OCTAVE_USE_WINDOWS_API)
 
-  std::string retval;
+    std::string retval;
 
 #if defined (P_tmpdir)
-  retval = P_tmpdir;
+    retval = P_tmpdir;
 #endif
 
-  // Apparently some versions of MinGW and MSVC either don't define
-  // P_tmpdir, or they define it to a single backslash, neither of which
-  // is particularly helpful.
+    // Apparently some versions of MinGW and MSVC either don't define
+    // P_tmpdir, or they define it to a single backslash, neither of which
+    // is particularly helpful.
 
-  if (retval.empty () || retval == R"(\)")
-    {
-      retval = octave::sys::env::getenv ("TEMP");
+    if (retval.empty () || retval == R"(\)")
+      {
+        retval = octave::sys::env::getenv ("TEMP");
 
-      if (retval.empty ())
-        retval = octave::sys::env::getenv ("TMP");
+        if (retval.empty ())
+          retval = octave::sys::env::getenv ("TMP");
 
-      if (retval.empty ())
-        retval = R"(c:\temp)";
-    }
+        if (retval.empty ())
+          retval = R"(c:\temp)";
+      }
 
-  return retval;
+    return retval;
 
 #elif defined (P_tmpdir)
 
-  return P_tmpdir;
+    return P_tmpdir;
 
 #else
 
-  return "/tmp";
+    return "/tmp";
 
 #endif
+  }
 }
 
 DEFUN (clc, , ,
@@ -728,7 +736,9 @@
   LONG result;
   HKEY h_subkey;
 
-  result = RegOpenKeyExA (h_rootkey, subkey.c_str (), 0, KEY_READ, &h_subkey);
+  result = RegOpenKeyExW (h_rootkey,
+                          octave::sys::u8_to_wstring (subkey).c_str (), 0,
+                          KEY_READ, &h_subkey);
   if (result != ERROR_SUCCESS)
     return result;
 
@@ -737,27 +747,30 @@
   frame.add_fcn (reg_close_key_wrapper, h_subkey);
 
   DWORD length = 0;
-  result = RegQueryValueExA (h_subkey, name.c_str (), nullptr, nullptr, nullptr,
-                             &length);
+  result = RegQueryValueExW (h_subkey,
+                             octave::sys::u8_to_wstring (name).c_str (),
+                             nullptr, nullptr, nullptr, &length);
   if (result != ERROR_SUCCESS)
     return result;
 
   DWORD type = 0;
   OCTAVE_LOCAL_BUFFER (BYTE, data, length);
-  result = RegQueryValueExA (h_subkey, name.c_str (), nullptr, &type, data,
-                             &length);
+  result = RegQueryValueExW (h_subkey,
+                             octave::sys::u8_to_wstring (name).c_str (),
+                             nullptr, &type, data, &length);
   if (result != ERROR_SUCCESS)
     return result;
 
   if (type == REG_DWORD)
     value = octave_int32 (*data);
   else if (type == REG_SZ || type == REG_EXPAND_SZ)
-    value = string_vector (reinterpret_cast<char *> (data));
+    value = string_vector (octave::sys::u8_from_wstring (
+                                        reinterpret_cast<wchar_t *> (data)));
 
   return result;
 }
 
-LONG
+static LONG
 get_regkey_names (HKEY h_rootkey, const std::string subkey,
                   std::list<std::string> &fields)
 {
@@ -766,22 +779,24 @@
 
   fields.clear ();
 
-  retval = RegOpenKeyEx (h_rootkey, subkey.c_str (), 0, KEY_READ, &h_subkey);
+  retval = RegOpenKeyExW (h_rootkey,
+                          octave::sys::u8_to_wstring (subkey).c_str (), 0,
+                          KEY_READ, &h_subkey);
   if (retval != ERROR_SUCCESS)
     return retval;
 
   DWORD idx = 0;
   const int MAX_VALUE_NAME_SIZE = 32766;
-  char value_name[MAX_VALUE_NAME_SIZE+1];
+  wchar_t value_name[MAX_VALUE_NAME_SIZE+1];
   DWORD value_name_size = MAX_VALUE_NAME_SIZE;
 
   while (true)
     {
-      retval = RegEnumValue (h_subkey, idx, value_name, &value_name_size,
-                             nullptr, nullptr, nullptr, nullptr);
+      retval = RegEnumValueW (h_subkey, idx, value_name, &value_name_size,
+                              nullptr, nullptr, nullptr, nullptr);
       if (retval != ERROR_SUCCESS)
         break;
-      fields.push_back (value_name);
+      fields.push_back (octave::sys::u8_from_wstring (value_name));
       value_name_size = MAX_VALUE_NAME_SIZE;
       idx++;
     }
@@ -1030,7 +1045,7 @@
 
   Fdrawnow ();
 
-  int c = octave_kbhit (args.length () == 0);
+  int c = octave::kbhit (args.length () == 0);
 
   if (c == -1)
     c = 0;
@@ -1091,17 +1106,17 @@
           if (octave::math::isinf (dval))
             {
               octave::flush_stdout ();
-              octave_kbhit ();
+              octave::kbhit ();
             }
           else
-            octave_sleep (dval);
+            octave::sleep (dval);
         }
     }
   else
     {
       Fdrawnow ();
       octave::flush_stdout ();
-      octave_kbhit ();
+      octave::kbhit ();
     }
 
   return ovl ();
--- a/libinterp/corefcn/sysdep.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/sysdep.h	Fri Aug 10 09:09:51 2018 +0200
@@ -32,24 +32,93 @@
 #include "lo-ieee.h"
 #include "lo-sysdep.h"
 
-extern OCTINTERP_API void sysdep_init (void);
+namespace octave
+{
+  extern OCTINTERP_API void sysdep_init (void);
+
+  extern OCTINTERP_API void set_application_id (void);
+
+  extern OCTINTERP_API void sysdep_cleanup (void);
 
-extern OCTINTERP_API void set_application_id (void);
+  extern OCTINTERP_API void raw_mode (bool, bool wait = true);
+
+  extern OCTINTERP_API FILE * popen (const char *command, const char *mode);
+
+  extern OCTINTERP_API int pclose (FILE *f);
+
+  extern OCTINTERP_API int kbhit (bool wait = true);
+
+  extern OCTINTERP_API std::string get_P_tmpdir (void);
 
-extern OCTINTERP_API void sysdep_cleanup (void);
+  extern OCTINTERP_API bool same_file_internal (const std::string&,
+                                                const std::string&);
+}
+
+#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
 
-extern OCTINTERP_API void raw_mode (bool, bool wait = true);
+OCTAVE_DEPRECATED (5, "use 'octave::sysdep_init' instead")
+inline void
+sysdep_init (void)
+{
+  octave::sysdep_init ();
+}
+
+OCTAVE_DEPRECATED (5, "use 'octave::set_application_id' instead")
+inline void
+set_application_id (void)
+{
+  octave::set_application_id ();
+}
 
-extern OCTINTERP_API FILE * octave_popen (const char *command,
-                                          const char *mode);
+OCTAVE_DEPRECATED (5, "use 'octave::sysdep_cleanup' instead")
+inline void
+sysdep_cleanup (void)
+{
+  octave::sysdep_cleanup ();
+}
 
-extern OCTINTERP_API int octave_pclose (FILE *f);
+OCTAVE_DEPRECATED (5, "use 'octave::raw_mode' instead")
+inline void
+raw_mode (bool on, bool wait = true)
+{
+  octave::raw_mode (on, wait);
+}
+
+OCTAVE_DEPRECATED (5, "use 'octave::popen' instead")
+inline FILE *
+octave_popen (const char *command, const char *mode)
+{
+  return octave::popen (command, mode);
+}
 
-extern OCTINTERP_API int octave_kbhit (bool wait = true);
+OCTAVE_DEPRECATED (5, "use 'octave::pclose' instead")
+inline int
+octave_pclose (FILE *f)
+{
+  return octave::pclose (f);
+}
+
+OCTAVE_DEPRECATED (5, "use 'octave::kbhit' instead")
+inline int
+octave_kbhit (bool wait = true)
+{
+  return octave::kbhit (wait);
+}
 
-extern OCTINTERP_API std::string get_P_tmpdir (void);
+OCTAVE_DEPRECATED (5, "use 'octave::get_P_tmpdir' instead")
+inline std::string
+get_P_tmpdir (void)
+{
+  return octave::get_P_tmpdir ();
+}
 
-extern OCTINTERP_API bool same_file_internal (const std::string&,
-                                              const std::string&);
+OCTAVE_DEPRECATED (5, "use 'octave::same_file_internal' instead")
+inline bool
+same_file_internal (const std::string& a, const std::string& b)
+{
+  return octave::same_file_internal (a, b);
+}
 
 #endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/corefcn/text-engine.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,42 @@
+/*
+
+Copyright (C) 2013-2018 Michael Goffioul
+
+This file is part of Octave.
+
+Octave is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Octave is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include "text-engine.h"
+#include "oct-tex-symbols.cc"
+
+namespace octave
+{
+  uint32_t
+  text_element_symbol::get_symbol_code (void) const
+  {
+    uint32_t code = invalid_code;
+
+    if (0 <= symbol && symbol < num_symbol_codes)
+      code = symbol_codes[symbol][0];
+
+    return code;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/corefcn/text-engine.h	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,508 @@
+/*
+
+Copyright (C) 2009-2018 Michael Goffioul
+
+This file is part of Octave.
+
+Octave is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Octave is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if ! defined (octave_text_engine_h)
+#define octave_text_engine_h 1
+
+#include "octave-config.h"
+
+#include <memory>
+#include <string>
+
+#include "base-list.h"
+#include "caseless-str.h"
+#include "dMatrix.h"
+
+namespace octave
+{
+  class text_element;
+  class text_element_string;
+  class text_element_symbol;
+  class text_element_list;
+  class text_element_subscript;
+  class text_element_superscript;
+  class text_element_combined;
+  class text_element_fontname;
+  class text_element_fontsize;
+  class text_element_fontstyle;
+  class text_element_color;
+
+  class text_processor;
+
+  class
+  OCTINTERP_API
+  text_element
+  {
+  public:
+    text_element (void) { }
+
+    virtual ~text_element (void) = default;
+
+    virtual void accept (text_processor& p) = 0;
+
+  private:
+    text_element (const text_element&);
+  };
+
+  class
+  OCTINTERP_API
+  text_element_string : public text_element
+  {
+  public:
+    text_element_string (const std::string& s = "")
+      : text_element (), str (s) { }
+
+    ~text_element_string (void) = default;
+
+    std::string string_value (void) const { return str; }
+
+    void accept (text_processor& p);
+
+  private:
+    std::string str;
+
+  private:
+    text_element_string (const text_element_string &);
+  };
+
+  class
+  OCTINTERP_API
+  text_element_symbol : public text_element
+  {
+  public:
+    enum { invalid_code = 0xFFFFFFFFU };
+
+  public:
+    text_element_symbol (int sym)
+      : text_element (), symbol (sym) { }
+
+    ~text_element_symbol (void) = default;
+
+    int get_symbol (void) const { return symbol; }
+
+    uint32_t get_symbol_code (void) const;
+
+    void accept (text_processor& p);
+
+  private:
+    int symbol;
+  };
+
+  class
+  OCTINTERP_API
+  text_element_list
+    : public text_element, public base_list<text_element *>
+  {
+  public:
+    text_element_list (void)
+      : text_element (), base_list<text_element*> () { }
+
+    text_element_list (text_element *e)
+      : text_element (), base_list<text_element*> ()
+    {
+      push_back (e);
+    }
+
+    ~text_element_list (void)
+      {
+        while (! empty ())
+          {
+            auto it = begin ();
+            delete (*it);
+            erase (it);
+          }
+      }
+
+    void accept (text_processor& p);
+  };
+
+  class
+  OCTINTERP_API
+  text_element_subscript : public text_element
+  {
+  public:
+    text_element_subscript (text_element *e)
+      : text_element (), elem (e) { }
+
+    text_element_subscript (char c)
+      : text_element ()
+      { elem = new text_element_string (std::string (1, c)); }
+
+    ~text_element_subscript (void)
+      { delete elem; }
+
+    void accept (text_processor& p);
+
+    text_element * get_element (void) { return elem; }
+
+  private:
+    text_element *elem;
+
+  private:
+    text_element_subscript (void);
+  };
+
+  class
+  OCTINTERP_API
+  text_element_superscript : public text_element
+  {
+  public:
+    text_element_superscript (text_element *e)
+      : text_element (), elem (e) { }
+
+    text_element_superscript (char c)
+      : text_element ()
+      { elem = new text_element_string (std::string (1, c)); }
+
+    ~text_element_superscript (void)
+      { delete elem; }
+
+    void accept (text_processor& p);
+
+    text_element * get_element (void) { return elem; }
+
+  private:
+    text_element *elem;
+
+  private:
+    text_element_superscript (void);
+  };
+
+  class
+  OCTINTERP_API
+  text_element_combined : public text_element_list
+  {
+  public:
+    text_element_combined (text_element *e)
+      : text_element_list (e) { }
+
+    text_element_combined (text_element *e1, text_element *e2)
+      : text_element_list(e1)
+      { push_back (e2); }
+
+    void accept (text_processor& p);
+  };
+
+  class
+  OCTINTERP_API
+  text_element_fontstyle : public text_element
+  {
+  public:
+    enum fontstyle
+    {
+      normal,
+      bold,
+      italic,
+      oblique
+    };
+
+    text_element_fontstyle (fontstyle st)
+      : text_element (), style (st) { }
+
+    ~text_element_fontstyle (void) = default;
+
+    fontstyle get_fontstyle (void) const { return style; }
+
+    void accept (text_processor& p);
+
+  private:
+    fontstyle style;
+
+  private:
+    text_element_fontstyle (void);
+  };
+
+  class
+  OCTINTERP_API
+  text_element_fontname : public text_element
+  {
+  public:
+    text_element_fontname (const std::string& fname)
+      : text_element (), name (fname) { }
+
+    ~text_element_fontname (void) = default;
+
+    const std::string& get_fontname (void) const { return name; }
+
+    void accept (text_processor& p);
+
+  private:
+    std::string name;
+
+  private:
+    text_element_fontname (void);
+  };
+
+  class
+  OCTINTERP_API
+  text_element_fontsize : public text_element
+  {
+  public:
+    text_element_fontsize (double fsize)
+      : text_element (), size (fsize) { }
+
+    ~text_element_fontsize (void) = default;
+
+    double get_fontsize (void) const { return size; }
+
+    void accept (text_processor& p);
+
+  private:
+    double size;
+
+  private:
+    text_element_fontsize (void);
+  };
+
+  class
+  OCTINTERP_API
+  text_element_color : public text_element
+  {
+  public:
+    text_element_color (double r, double g, double b)
+      : text_element (), rgb (1, 3, 0.0)
+      {
+        rgb(0) = r;
+        rgb(1) = g;
+        rgb(2) = b;
+      }
+
+    text_element_color (const std::string& cname)
+      : text_element (), rgb (1, 3, 0.0)
+      {
+#define ASSIGN_COLOR(r,g,b) { rgb(0) = r; rgb(1) = g; rgb(2) = b; }
+        if (cname == "red") ASSIGN_COLOR(1, 0, 0)
+        else if (cname == "green") ASSIGN_COLOR(0, 1, 0)
+        else if (cname == "yellow") ASSIGN_COLOR(1, 1, 0)
+        else if (cname == "magenta") ASSIGN_COLOR(1, 0, 1)
+        else if (cname == "blue") ASSIGN_COLOR(0, 0, 1)
+        else if (cname == "black") ASSIGN_COLOR(0, 0, 0)
+        else if (cname == "white") ASSIGN_COLOR(1, 1, 1)
+        else if (cname == "gray") ASSIGN_COLOR(.5, .5, .5)
+        else if (cname == "darkGreen") ASSIGN_COLOR(0, .5, 0)
+        else if (cname == "orange") ASSIGN_COLOR(1, .65, 0)
+        else if (cname == "lightBlue") ASSIGN_COLOR(0.68, .85, .9)
+#undef ASSIGN_COLOR
+      }
+
+    ~text_element_color (void) = default;
+
+    Matrix get_color (void) { return rgb; }
+
+    void accept (text_processor& p);
+
+  private:
+    Matrix rgb;
+  };
+
+  class
+  OCTINTERP_API
+  text_processor
+  {
+  public:
+    virtual void visit (text_element_string& e) = 0;
+
+    virtual void visit (text_element_symbol&) { }
+
+    virtual void visit (text_element_list& e)
+    {
+      for (auto& el_p : e)
+        {
+          el_p->accept (*this);
+        }
+    }
+
+    virtual void visit (text_element_subscript& e)
+    { e.get_element ()->accept (*this); }
+
+    virtual void visit (text_element_superscript& e)
+    { e.get_element ()->accept (*this); }
+
+    virtual void visit (text_element_combined&) { }
+
+    virtual void visit (text_element_fontstyle&) { }
+
+    virtual void visit (text_element_fontname&) { }
+
+    virtual void visit (text_element_fontsize&) { }
+
+    virtual void visit (text_element_color&) { }
+
+    virtual void reset (void) { }
+
+  protected:
+    text_processor (void) { }
+
+    virtual ~text_processor (void) = default;
+  };
+
+#define TEXT_ELEMENT_ACCEPT(cls)                \
+  inline void                                   \
+  cls::accept (text_processor& p)               \
+  {                                             \
+    p.visit (*this);                            \
+  }
+
+  TEXT_ELEMENT_ACCEPT(text_element_string)
+  TEXT_ELEMENT_ACCEPT(text_element_symbol)
+  TEXT_ELEMENT_ACCEPT(text_element_list)
+  TEXT_ELEMENT_ACCEPT(text_element_subscript)
+  TEXT_ELEMENT_ACCEPT(text_element_superscript)
+  TEXT_ELEMENT_ACCEPT(text_element_combined)
+  TEXT_ELEMENT_ACCEPT(text_element_fontstyle)
+  TEXT_ELEMENT_ACCEPT(text_element_fontname)
+  TEXT_ELEMENT_ACCEPT(text_element_fontsize)
+  TEXT_ELEMENT_ACCEPT(text_element_color)
+
+  class
+  OCTINTERP_API
+  text_parser
+  {
+  public:
+    text_parser (void) { }
+
+    virtual ~text_parser (void) = default;
+
+    virtual text_element * parse (const std::string& s) = 0;
+
+  public:
+    static text_element * parse (const std::string& s,
+                                 const caseless_str& interpreter);
+  };
+
+  class
+  OCTINTERP_API
+  text_parser_none : public text_parser
+  {
+  public:
+    text_parser_none (void) : text_parser () { }
+
+    ~text_parser_none (void) = default;
+
+    // FIXME: is it possible to use reference counting to manage the
+    // memory for the object returned by the text parser?  That would be
+    // preferable to having to know when and where to delete the object it
+    // creates...
+
+    text_element * parse (const std::string& s)
+    {
+      return new text_element_string (s);
+    }
+  };
+
+  class
+  OCTINTERP_API
+  text_parser_tex : public text_parser
+  {
+  public:
+    text_parser_tex (void)
+      : text_parser (), scanner (nullptr), buffer_state (nullptr), result (nullptr)
+      { }
+
+    ~text_parser_tex (void)
+      { destroy_lexer (); }
+
+    text_element * parse (const std::string& s);
+
+    void * get_scanner (void) { return scanner; }
+
+    void set_parse_result (text_element *e) { result = e; }
+
+    text_element * get_parse_result (void) { return result; }
+
+  private:
+    bool init_lexer (const std::string& s);
+
+    void destroy_lexer (void);
+
+  private:
+    void *scanner;
+
+    void *buffer_state;
+
+    text_element *result;
+  };
+
+  inline text_element*
+  text_parser::parse (const std::string& s, const caseless_str& interpreter)
+  {
+    std::unique_ptr<text_parser> parser;
+
+    if (interpreter.compare ("tex"))
+      parser.reset (new text_parser_tex ());
+    else
+      parser.reset (new text_parser_none ());
+
+    return parser->parse (s);
+  }
+}
+
+#if defined (OCAVE_USE_DEPRECATED_FUNCTIONS)
+
+OCTAVE_DEPRECATED (5, "use 'octave::text_element' instead")
+typedef octave::text_element text_element;
+
+OCTAVE_DEPRECATED (5, "use 'octave::text_element_string' instead")
+typedef octave::text_element_string text_element_string;
+
+OCTAVE_DEPRECATED (5, "use 'octave::text_element_symbol' instead")
+typedef octave::text_element_symbol text_element_symbol;
+
+OCTAVE_DEPRECATED (5, "use 'octave::text_element_list' instead")
+typedef octave::text_element_list text_element_list;
+
+OCTAVE_DEPRECATED (5, "use 'octave::text_element_subscript' instead")
+typedef octave::text_element_subscript text_element_subscript;
+
+OCTAVE_DEPRECATED (5, "use 'octave::text_element_superscript' instead")
+typedef octave::text_element_superscript text_element_superscript;
+
+OCTAVE_DEPRECATED (5, "use 'octave::text_element_combined' instead")
+typedef octave::text_element_combined text_element_combined;
+
+OCTAVE_DEPRECATED (5, "use 'octave::text_element_fontstyle' instead")
+typedef octave::text_element_fontstyle text_element_fontstyle;
+
+OCTAVE_DEPRECATED (5, "use 'octave::text_element_fontname' instead")
+typedef octave::text_element_fontname text_element_fontname;
+
+OCTAVE_DEPRECATED (5, "use 'octave::text_element_fontsize' instead")
+typedef octave::text_element_fontsize text_element_fontsize;
+
+OCTAVE_DEPRECATED (5, "use 'octave::text_element_color' instead")
+typedef octave::text_element_color text_element_color;
+
+OCTAVE_DEPRECATED (5, "use 'octave::text_processor' instead")
+typedef octave::text_processor text_processor;
+
+OCTAVE_DEPRECATED (5, "use 'octave::text_parser' instead")
+typedef octave::text_parser text_parser;
+
+OCTAVE_DEPRECATED (5, "use 'octave::text_parser_none' instead")
+typedef octave::text_parser_none text_parser_none;
+
+OCTAVE_DEPRECATED (5, "use 'octave::text_parser_tex' instead")
+typedef octave::text_parser_tex text_parser_tex;
+
+#endif
+
+#endif
--- a/libinterp/corefcn/text-renderer.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/text-renderer.h	Fri Aug 10 09:09:51 2018 +0200
@@ -34,11 +34,10 @@
 #include "dMatrix.h"
 #include "uint8NDArray.h"
 
-#include "txt-eng.h"
-
 namespace octave
 {
   class base_text_renderer;
+  class text_element;
 
   class
   OCTINTERP_API
--- a/libinterp/corefcn/toplev.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/toplev.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -26,8 +26,8 @@
 
 #include <cerrno>
 #include <cstdlib>
+
 #include <new>
-
 #include <sstream>
 #include <string>
 
--- a/libinterp/corefcn/tsearch.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/tsearch.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -50,7 +50,7 @@
     return (a > c ? c : a);
 }
 
-#define REF(x,k,i) x(static_cast<octave_idx_type>(elem((k), (i))) - 1)
+#define REF(x,k,i) x(static_cast<octave_idx_type> (elem((k), (i))) - 1)
 
 // for large data set the algorithm is very slow
 // one should presort (how?) either the elements of the points of evaluation
--- a/libinterp/corefcn/txt-eng.cc	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-/*
-
-Copyright (C) 2013-2018 Michael Goffioul
-
-This file is part of Octave.
-
-Octave is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-Octave is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<https://www.gnu.org/licenses/>.
-
-*/
-
-#if defined (HAVE_CONFIG_H)
-#  include "config.h"
-#endif
-
-#include "txt-eng.h"
-#include "oct-tex-symbols.cc"
-
-uint32_t
-text_element_symbol::get_symbol_code (void) const
-{
-  uint32_t code = invalid_code;
-
-  if (0 <= symbol && symbol < num_symbol_codes)
-    code = symbol_codes[symbol][0];
-
-  return code;
-}
--- a/libinterp/corefcn/txt-eng.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/txt-eng.h	Fri Aug 10 09:09:51 2018 +0200
@@ -1,6 +1,6 @@
 /*
 
-Copyright (C) 2009-2018 Michael Goffioul
+Copyright (C) 2018 John W. Eaton
 
 This file is part of Octave.
 
@@ -25,430 +25,8 @@
 
 #include "octave-config.h"
 
-#include <memory>
-#include <string>
-
-#include "base-list.h"
-#include "caseless-str.h"
-#include "dMatrix.h"
-
-class text_element;
-class text_element_string;
-class text_element_symbol;
-class text_element_list;
-class text_element_subscript;
-class text_element_superscript;
-class text_element_combined;
-class text_element_fontname;
-class text_element_fontsize;
-class text_element_fontstyle;
-class text_element_color;
-
-class text_processor;
-
-class
-OCTINTERP_API
-text_element
-{
-public:
-  text_element (void) { }
-
-  virtual ~text_element (void) = default;
-
-  virtual void accept (text_processor& p) = 0;
-
-private:
-  text_element (const text_element&);
-};
-
-class
-OCTINTERP_API
-text_element_string : public text_element
-{
-public:
-  text_element_string (const std::string& s = "")
-    : text_element (), str (s) { }
-
-  ~text_element_string (void) = default;
-
-  std::string string_value (void) const { return str; }
-
-  void accept (text_processor& p);
-
-private:
-  std::string str;
-
-private:
-  text_element_string (const text_element_string &);
-};
-
-class
-OCTINTERP_API
-text_element_symbol : public text_element
-{
-public:
-  enum { invalid_code = 0xFFFFFFFFU };
-
-public:
-  text_element_symbol (int sym)
-    : text_element (), symbol (sym) { }
-
-  ~text_element_symbol (void) = default;
-
-  int get_symbol (void) const { return symbol; }
-
-  uint32_t get_symbol_code (void) const;
-
-  void accept (text_processor& p);
-
-private:
-  int symbol;
-};
-
-class
-OCTINTERP_API
-text_element_list
-  : public text_element, public octave::base_list<text_element *>
-{
-public:
-  text_element_list (void)
-    : text_element (), octave::base_list<text_element*> () { }
-
-  text_element_list (text_element *e)
-    : text_element (), octave::base_list<text_element*> ()
-  { push_back (e); }
-
-  ~text_element_list (void)
-  {
-    while (! empty ())
-      {
-        iterator it = begin ();
-        delete (*it);
-        erase (it);
-      }
-  }
-
-  void accept (text_processor& p);
-};
-
-class
-OCTINTERP_API
-text_element_subscript : public text_element
-{
-public:
-  text_element_subscript (text_element *e)
-    : text_element (), elem (e) { }
-
-  text_element_subscript (char c)
-    : text_element ()
-  { elem = new text_element_string (std::string (1, c)); }
-
-  ~text_element_subscript (void)
-  { delete elem; }
-
-  void accept (text_processor& p);
-
-  text_element * get_element (void) { return elem; }
-
-private:
-  text_element *elem;
-
-private:
-  text_element_subscript (void);
-};
-
-class
-OCTINTERP_API
-text_element_superscript : public text_element
-{
-public:
-  text_element_superscript (text_element *e)
-    : text_element (), elem (e) { }
-
-  text_element_superscript (char c)
-    : text_element ()
-  { elem = new text_element_string (std::string (1, c)); }
-
-  ~text_element_superscript (void)
-  { delete elem; }
-
-  void accept (text_processor& p);
-
-  text_element * get_element (void) { return elem; }
-
-private:
-  text_element *elem;
-
-private:
-  text_element_superscript (void);
-};
-
-class
-OCTINTERP_API
-text_element_combined : public text_element_list
-{
-public:
-  text_element_combined (text_element *e)
-    : text_element_list (e) { }
-
-  text_element_combined (text_element *e1, text_element *e2)
-    : text_element_list(e1)
-  { push_back (e2); }
-
-  void accept (text_processor& p);
-};
-
-class
-OCTINTERP_API
-text_element_fontstyle : public text_element
-{
-public:
-  enum fontstyle
-  {
-    normal,
-    bold,
-    italic,
-    oblique
-  };
-
-  text_element_fontstyle (fontstyle st)
-    : text_element (), style (st) { }
-
-  ~text_element_fontstyle (void) = default;
-
-  fontstyle get_fontstyle (void) const { return style; }
-
-  void accept (text_processor& p);
-
-private:
-  fontstyle style;
-
-private:
-  text_element_fontstyle (void);
-};
-
-class
-OCTINTERP_API
-text_element_fontname : public text_element
-{
-public:
-  text_element_fontname (const std::string& fname)
-    : text_element (), name (fname) { }
-
-  ~text_element_fontname (void) = default;
+#warning "txt-eng.h has been deprecated; use text-engine instead"
 
-  const std::string& get_fontname (void) const { return name; }
-
-  void accept (text_processor& p);
-
-private:
-  std::string name;
-
-private:
-  text_element_fontname (void);
-};
-
-class
-OCTINTERP_API
-text_element_fontsize : public text_element
-{
-public:
-  text_element_fontsize (double fsize)
-    : text_element (), size (fsize) { }
-
-  ~text_element_fontsize (void) = default;
-
-  double get_fontsize (void) const { return size; }
-
-  void accept (text_processor& p);
-
-private:
-  double size;
-
-private:
-  text_element_fontsize (void);
-};
-
-class
-OCTINTERP_API
-text_element_color : public text_element
-{
-public:
-  text_element_color (double r, double g, double b)
-    : text_element (), rgb (1, 3, 0.0)
-  {
-    rgb(0) = r;
-    rgb(1) = g;
-    rgb(2) = b;
-  }
-
-  text_element_color (const std::string& cname)
-    : text_element (), rgb (1, 3, 0.0)
-  {
-#define ASSIGN_COLOR(r,g,b) { rgb(0) = r; rgb(1) = g; rgb(2) = b; }
-    if (cname == "red") ASSIGN_COLOR(1, 0, 0)
-      else if (cname == "green") ASSIGN_COLOR(0, 1, 0)
-        else if (cname == "yellow") ASSIGN_COLOR(1, 1, 0)
-          else if (cname == "magenta") ASSIGN_COLOR(1, 0, 1)
-            else if (cname == "blue") ASSIGN_COLOR(0, 0, 1)
-              else if (cname == "black") ASSIGN_COLOR(0, 0, 0)
-                else if (cname == "white") ASSIGN_COLOR(1, 1, 1)
-                  else if (cname == "gray") ASSIGN_COLOR(.5, .5, .5)
-                    else if (cname == "darkGreen") ASSIGN_COLOR(0, .5, 0)
-                      else if (cname == "orange") ASSIGN_COLOR(1, .65, 0)
-                        else if (cname == "lightBlue") ASSIGN_COLOR(0.68, .85, .9)
-#undef ASSIGN_COLOR
-  }
-
-  ~text_element_color (void) = default;
-
-  Matrix get_color (void) { return rgb; }
-
-  void accept (text_processor& p);
-
-private:
-  Matrix rgb;
-};
-
-class
-OCTINTERP_API
-text_processor
-{
-public:
-  virtual void visit (text_element_string& e) = 0;
-
-  virtual void visit (text_element_symbol&) { }
-
-  virtual void visit (text_element_list& e)
-  {
-    for (auto& el_p : e)
-      {
-        el_p->accept (*this);
-      }
-  }
-
-  virtual void visit (text_element_subscript& e)
-  { e.get_element ()->accept (*this); }
-
-  virtual void visit (text_element_superscript& e)
-  { e.get_element ()->accept (*this); }
-
-  virtual void visit (text_element_combined&) { }
-
-  virtual void visit (text_element_fontstyle&) { }
-
-  virtual void visit (text_element_fontname&) { }
-
-  virtual void visit (text_element_fontsize&) { }
-
-  virtual void visit (text_element_color&) { }
-
-  virtual void reset (void) { }
-
-protected:
-  text_processor (void) { }
-
-  virtual ~text_processor (void) = default;
-};
-
-#define TEXT_ELEMENT_ACCEPT(cls)                \
-  inline void                                   \
-  cls::accept (text_processor& p)               \
-  {                                             \
-    p.visit (*this);                            \
-  }
-
-TEXT_ELEMENT_ACCEPT(text_element_string)
-TEXT_ELEMENT_ACCEPT(text_element_symbol)
-TEXT_ELEMENT_ACCEPT(text_element_list)
-TEXT_ELEMENT_ACCEPT(text_element_subscript)
-TEXT_ELEMENT_ACCEPT(text_element_superscript)
-TEXT_ELEMENT_ACCEPT(text_element_combined)
-TEXT_ELEMENT_ACCEPT(text_element_fontstyle)
-TEXT_ELEMENT_ACCEPT(text_element_fontname)
-TEXT_ELEMENT_ACCEPT(text_element_fontsize)
-TEXT_ELEMENT_ACCEPT(text_element_color)
-
-class
-OCTINTERP_API
-text_parser
-{
-public:
-  text_parser (void) { }
-
-  virtual ~text_parser (void) = default;
-
-  virtual text_element * parse (const std::string& s) = 0;
-
-public:
-  static text_element * parse (const std::string& s,
-                               const caseless_str& interpreter);
-};
-
-class
-OCTINTERP_API
-text_parser_none : public text_parser
-{
-public:
-  text_parser_none (void) : text_parser () { }
-
-  ~text_parser_none (void) = default;
-
-  // FIXME: is it possible to use reference counting to manage the
-  // memory for the object returned by the text parser?  That would be
-  // preferable to having to know when and where to delete the object it
-  // creates...
-
-  text_element * parse (const std::string& s)
-  {
-    return new text_element_string (s);
-  }
-};
-
-class
-OCTINTERP_API
-text_parser_tex : public text_parser
-{
-public:
-  text_parser_tex (void)
-    : text_parser (), scanner (nullptr), buffer_state (nullptr), result (nullptr)
-  { }
-
-  ~text_parser_tex (void)
-  { destroy_lexer (); }
-
-  text_element * parse (const std::string& s);
-
-  void * get_scanner (void) { return scanner; }
-
-  void set_parse_result (text_element *e) { result = e; }
-
-  text_element * get_parse_result (void) { return result; }
-
-private:
-  bool init_lexer (const std::string& s);
-
-  void destroy_lexer (void);
-
-private:
-  void *scanner;
-
-  void *buffer_state;
-
-  text_element *result;
-};
-
-inline text_element*
-text_parser::parse (const std::string& s, const caseless_str& interpreter)
-{
-  std::unique_ptr<text_parser> parser;
-
-  if (interpreter.compare ("tex"))
-    parser.reset (new text_parser_tex ());
-  else
-    parser.reset (new text_parser_none ());
-
-  return parser->parse (s);
-}
+#include "text-engine.h"
 
 #endif
--- a/libinterp/corefcn/typecast.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/typecast.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -25,6 +25,7 @@
 #  include "config.h"
 #endif
 
+#include <algorithm>
 #include <limits>
 
 #include "mx-base.h"
@@ -227,6 +228,8 @@
            array.class_name ().c_str ());
 
   std::string numclass = args(1).string_value ();
+  std::transform (numclass.begin (), numclass.end (), numclass.begin (),
+                  tolower);
 
   if (numclass.size () == 0)
     ;
--- a/libinterp/corefcn/url-handle-manager.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/url-handle-manager.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -48,7 +48,7 @@
     // part.  To avoid running out of integers, we recycle the integer
     // part but tack on a new random part each time.
 
-    free_list_iterator p = handle_free_list.begin ();
+    auto p = handle_free_list.begin ();
 
     if (p != handle_free_list.end ())
       {
@@ -69,7 +69,7 @@
   {
     if (h.ok ())
       {
-        iterator p = handle_map.find (h);
+        auto p = handle_map.find (h);
 
         if (p == handle_map.end ())
           error ("url_handle_manager::free: invalid object %g", h.value ());
--- a/libinterp/corefcn/urlwrite.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/urlwrite.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -31,11 +31,11 @@
 #include <string>
 #include <fstream>
 #include <iomanip>
-#include <iostream>
 
 #include "dir-ops.h"
 #include "file-ops.h"
 #include "file-stat.h"
+#include "lo-sysdep.h"
 #include "oct-env.h"
 #include "oct-handle.h"
 #include "glob-match.h"
@@ -637,8 +637,11 @@
         }
       else
         {
+          std::string ascii_fname = octave::sys::get_ASCII_filename (file);
+
           // FIXME: Does ascii mode need to be flagged here?
-          std::ifstream ifile (file.c_str (), std::ios::in | std::ios::binary);
+          std::ifstream ifile (ascii_fname.c_str (),
+                               std::ios::in | std::ios::binary);
 
           if (! ifile.is_open ())
             error ("__ftp_mput__: unable to open file");
--- a/libinterp/corefcn/utils.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/utils.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -29,8 +29,8 @@
 #include <cstring>
 
 #include <fstream>
-#include <iostream>
 #include <limits>
+#include <ostream>
 #include <string>
 
 #include "dir-ops.h"
@@ -48,7 +48,6 @@
 #include "vasprintf-wrapper.h"
 
 #include "Cell.h"
-#include "defaults.h"
 #include "defun.h"
 #include "dirfns.h"
 #include "error.h"
@@ -68,25 +67,26 @@
 #include "utils.h"
 #include "variables.h"
 
-// Return TRUE if S is a valid identifier.
-
-bool
-valid_identifier (const char *s)
+namespace octave
 {
-  if (! s || ! (isalpha (*s) || *s == '_' || *s == '$'))
-    return false;
+  // Return TRUE if S is a valid identifier.
 
-  while (*++s != '\0')
-    if (! (isalnum (*s) || *s == '_' || *s == '$'))
+  bool valid_identifier (const char *s)
+  {
+    if (! s || ! (isalpha (*s) || *s == '_' || *s == '$'))
       return false;
 
-  return true;
-}
+    while (*++s != '\0')
+      if (! (isalnum (*s) || *s == '_' || *s == '$'))
+        return false;
 
-bool
-valid_identifier (const std::string& s)
-{
-  return valid_identifier (s.c_str ());
+    return true;
+  }
+
+  bool valid_identifier (const std::string& s)
+  {
+    return valid_identifier (s.c_str ());
+  }
 }
 
 DEFUN (isvarname, args, ,
@@ -105,7 +105,8 @@
     {
       std::string varname = args(0).string_value ();
 
-      retval = valid_identifier (varname) && ! octave::is_keyword (varname);
+      retval = (octave::valid_identifier (varname)
+                && ! octave::is_keyword (varname));
     }
 
   return retval;
@@ -124,161 +125,154 @@
 %!error isvarname ("foo", "bar")
 */
 
-// Return TRUE if F and G are both names for the same file.
-
-bool
-same_file (const std::string& f, const std::string& g)
+namespace octave
 {
-  return same_file_internal (f, g);
-}
+  // Return TRUE if F and G are both names for the same file.
 
-int
-almost_match (const std::string& std, const std::string& s, int min_match_len,
-              int case_sens)
-{
-  int stdlen = std.length ();
-  int slen = s.length ();
+  bool same_file (const std::string& f, const std::string& g)
+  {
+    return same_file_internal (f, g);
+  }
+
+  int almost_match (const std::string& std, const std::string& s,
+                    int min_match_len, int case_sens)
+  {
+    int stdlen = std.length ();
+    int slen = s.length ();
 
-  return (slen <= stdlen
-          && slen >= min_match_len
-          && (case_sens
-              ? (strncmp (std.c_str (), s.c_str (), slen) == 0)
-              : (octave_strncasecmp (std.c_str (), s.c_str (), slen) == 0)));
-}
+    return (slen <= stdlen
+            && slen >= min_match_len
+            && (case_sens
+                ? (strncmp (std.c_str (), s.c_str (), slen) == 0)
+                : (octave_strncasecmp (std.c_str (), s.c_str (), slen) == 0)));
+  }
 
-// Ugh.
+  // Ugh.
 
-int
-keyword_almost_match (const char * const *std, int *min_len,
-                      const std::string& s,
-                      int min_toks_to_match, int max_toks)
-{
-  int status = 0;
-  int tok_count = 0;
-  int toks_matched = 0;
+  int keyword_almost_match (const char * const *std, int *min_len,
+                            const std::string& s,
+                            int min_toks_to_match, int max_toks)
+  {
+    int status = 0;
+    int tok_count = 0;
+    int toks_matched = 0;
 
-  if (s.empty () || max_toks < 1)
-    return status;
-
-  char *kw = strsave (s.c_str ());
+    if (s.empty () || max_toks < 1)
+      return status;
 
-  char *t = kw;
-  while (*t != '\0')
-    {
-      if (*t == '\t')
-        *t = ' ';
-      t++;
-    }
+    char *kw = strsave (s.c_str ());
 
-  char *beg = kw;
-  while (*beg == ' ')
-    beg++;
+    char *t = kw;
+    while (*t != '\0')
+      {
+        if (*t == '\t')
+          *t = ' ';
+        t++;
+      }
 
-  if (*beg == '\0')
-    return status;
+    char *beg = kw;
+    while (*beg == ' ')
+      beg++;
 
-  const char **to_match = new const char * [max_toks + 1];
-  const char * const *s1 = std;
-  const char **s2 = to_match;
+    if (*beg == '\0')
+      return status;
 
-  if (! s1 || ! s2)
-    goto done;
+    const char **to_match = new const char * [max_toks + 1];
+    const char * const *s1 = std;
+    const char **s2 = to_match;
 
-  s2[tok_count] = beg;
-  char *end;
-  while ((end = strchr (beg, ' ')) != nullptr)
-    {
-      *end = '\0';
-      beg = end + 1;
+    if (! s1 || ! s2)
+      goto done;
 
-      while (*beg == ' ')
-        beg++;
+    s2[tok_count] = beg;
+    char *end;
+    while ((end = strchr (beg, ' ')) != nullptr)
+      {
+        *end = '\0';
+        beg = end + 1;
 
-      if (*beg == '\0')
-        break;
+        while (*beg == ' ')
+          beg++;
 
-      tok_count++;
-      if (tok_count >= max_toks)
-        goto done;
+        if (*beg == '\0')
+          break;
 
-      s2[tok_count] = beg;
-    }
-  s2[tok_count+1] = nullptr;
+        tok_count++;
+        if (tok_count >= max_toks)
+          goto done;
 
-  s2 = to_match;
+        s2[tok_count] = beg;
+      }
+    s2[tok_count+1] = nullptr;
 
-  for (;;)
-    {
-      if (! almost_match (*s1, *s2, min_len[toks_matched], 0))
-        goto done;
+    s2 = to_match;
 
-      toks_matched++;
+    for (;;)
+      {
+        if (! almost_match (*s1, *s2, min_len[toks_matched], 0))
+          goto done;
 
-      s1++;
-      s2++;
+        toks_matched++;
 
-      if (! *s2)
-        {
-          status = (toks_matched >= min_toks_to_match);
-          goto done;
-        }
+        s1++;
+        s2++;
+
+        if (! *s2)
+          {
+            status = (toks_matched >= min_toks_to_match);
+            goto done;
+          }
 
-      if (! *s1)
-        goto done;
-    }
+        if (! *s1)
+          goto done;
+      }
 
-done:
+  done:
 
-  delete [] kw;
-  delete [] to_match;
+    delete [] kw;
+    delete [] to_match;
 
-  return status;
-}
+    return status;
+  }
 
-int
-empty_arg (const char * /* name */, octave_idx_type nr, octave_idx_type nc)
-{
-  return (nr == 0 || nc == 0);
-}
+  // See if the given file is in the path.
 
-// See if the given file is in the path.
+  std::string search_path_for_file (const std::string& path,
+                                    const string_vector& names)
+  {
+    directory_path p (path);
 
-std::string
-search_path_for_file (const std::string& path, const string_vector& names)
-{
-  octave::directory_path p (path);
+    return sys::env::make_absolute (p.find_first_of (names.std_list ()));
+  }
+
+  // Find all locations of the given file in the path.
 
-  return octave::sys::env::make_absolute (p.find_first_of (names.std_list ()));
-}
+  string_vector search_path_for_all_files (const std::string& path,
+                                           const string_vector& names)
+  {
+    directory_path p (path);
 
-// Find all locations of the given file in the path.
+    string_vector sv = p.find_all_first_of (names.std_list ());
 
-string_vector
-search_path_for_all_files (const std::string& path, const string_vector& names)
-{
-  octave::directory_path p (path);
+    octave_idx_type len = sv.numel ();
 
-  string_vector sv = p.find_all_first_of (names.std_list ());
+    for (octave_idx_type i = 0; i < len; i++)
+      sv[i] = sys::env::make_absolute (sv[i]);
 
-  octave_idx_type len = sv.numel ();
-
-  for (octave_idx_type i = 0; i < len; i++)
-    sv[i] = octave::sys::env::make_absolute (sv[i]);
+    return sv;
+  }
 
-  return sv;
-}
+  static string_vector make_absolute (const string_vector& sv)
+  {
+    octave_idx_type len = sv.numel ();
+
+    string_vector retval (len);
 
-static string_vector
-make_absolute (const string_vector& sv)
-{
-  octave_idx_type len = sv.numel ();
+    for (octave_idx_type i = 0; i < len; i++)
+      retval[i] = sys::env::make_absolute (sv[i]);
 
-  string_vector retval (len);
-
-  for (octave_idx_type i = 0; i < len; i++)
-    retval[i] = octave::sys::env::make_absolute (sv[i]);
-
-  return retval;
+    return retval;
+  }
 }
 
 DEFMETHOD (file_in_loadpath, interp, args, ,
@@ -325,7 +319,7 @@
       if (opt != "all")
         error (R"(file_in_loadpath: "all" is only valid second argument)");
 
-      return ovl (Cell (make_absolute (lp.find_all_first_of (names))));
+      return ovl (Cell (octave::make_absolute (lp.find_all_first_of (names))));
     }
 }
 
@@ -388,7 +382,7 @@
     error ("file_in_path: FILE argument must not be empty");
 
   if (nargin == 2)
-    return ovl (search_path_for_file (path, names));
+    return ovl (octave::search_path_for_file (path, names));
   else
     {
       std::string opt = args(2).xstring_value ("file_in_path: optional third argument must be a string");
@@ -396,7 +390,7 @@
       if (opt != "all")
         error (R"(file_in_path: "all" is only valid third argument)");
 
-      return ovl (Cell (make_absolute (search_path_for_all_files (path, names))));
+      return ovl (Cell (octave::make_absolute (octave::search_path_for_all_files (path, names))));
     }
 }
 
@@ -422,323 +416,247 @@
 %!error file_in_path (path (), "plot.m", "bar")
 */
 
-std::string
-file_in_path (const std::string& name, const std::string& suffix)
+namespace octave
 {
-  std::string nm = name;
+  std::string file_in_path (const std::string& name, const std::string& suffix)
+  {
+    std::string nm = name;
 
-  if (! suffix.empty ())
-    nm.append (suffix);
-
-  octave::load_path& lp = octave::__get_load_path__ ("file_in_path");
-
-  return octave::sys::env::make_absolute (lp.find_file (nm));
-}
+    if (! suffix.empty ())
+      nm.append (suffix);
 
-std::string
-find_data_file_in_load_path  (const std::string& fcn,
-                              const std::string& file,
-                              bool require_regular_file)
-{
-  std::string fname = file;
+    load_path& lp = __get_load_path__ ("file_in_path");
+
+    return sys::env::make_absolute (lp.find_file (nm));
+  }
 
-  if (! (octave::sys::env::absolute_pathname (fname)
-         || octave::sys::env::rooted_relative_pathname (fname)))
-    {
-      // Load path will also search "." first, but we don't want to
-      // issue a warning if the file is found in the current directory,
-      // so do an explicit check for that.
-      octave::sys::file_stat fs (fname);
-
-      bool local_file_ok
-        = fs.exists () && (fs.is_reg () || ! require_regular_file);
+  std::string find_data_file_in_load_path  (const std::string& fcn,
+                                            const std::string& file,
+                                            bool require_regular_file)
+  {
+    std::string fname = file;
 
-      if (! local_file_ok)
-        {
-          octave::load_path& lp =
-            octave::__get_load_path__ ("find_data_file_in_load_path");
-
-          // Not directly found; search load path.
-          std::string tmp
-            = octave::sys::env::make_absolute (lp.find_file (fname));
+    if (! (sys::env::absolute_pathname (fname)
+           || sys::env::rooted_relative_pathname (fname)))
+      {
+        // Load path will also search "." first, but we don't want to
+        // issue a warning if the file is found in the current directory,
+        // so do an explicit check for that.
+        sys::file_stat fs (fname);
 
-          if (! tmp.empty ())
-            {
-              warn_data_file_in_path (fcn, tmp);
-
-              fname = tmp;
-            }
-        }
-    }
+        bool local_file_ok
+          = fs.exists () && (fs.is_reg () || ! require_regular_file);
 
-  return fname;
-}
-
-// See if there is an function file in the path.
-// If so, return the full path to the file.
+        if (! local_file_ok)
+          {
+            load_path& lp =
+              __get_load_path__ ("find_data_file_in_load_path");
 
-std::string
-fcn_file_in_path (const std::string& name)
-{
-  std::string retval;
+            // Not directly found; search load path.
+            std::string tmp
+              = sys::env::make_absolute (lp.find_file (fname));
 
-  int len = name.length ();
-
-  if (len > 0)
-    {
-      if (octave::sys::env::absolute_pathname (name))
-        {
-          octave::sys::file_stat fs (name);
+            if (! tmp.empty ())
+              {
+                warn_data_file_in_path (fcn, tmp);
 
-          if (fs.exists () && ! fs.is_dir ())
-            retval = name;
-        }
-      else if (len > 2 && name[len - 2] == '.' && name[len - 1] == 'm')
-        {
-          octave::load_path& lp = octave::__get_load_path__ ("fcn_file_in_path");
+                fname = tmp;
+              }
+          }
+      }
 
-          retval = lp.find_fcn_file (name.substr (0, len-2));
-        }
-      else
-        {
-          std::string fname = name;
-          size_t pos = name.find_first_of ('>');
-          if (pos != std::string::npos)
-            fname = name.substr (0, pos);
+    return fname;
+  }
+
+  // See if there is an function file in the path.
+  // If so, return the full path to the file.
 
-          octave::load_path& lp = octave::__get_load_path__ ("fcn_file_in_path");
+  std::string fcn_file_in_path (const std::string& name)
+  {
+    std::string retval;
 
-          retval = lp.find_fcn_file (fname);
-        }
-    }
+    int len = name.length ();
 
-  return retval;
-}
-
-// See if there is a directory called "name" in the path and if it
-// contains a Contents.m file.  If so, return the full path to this file.
-
-std::string
-contents_file_in_path (const std::string& dir)
-{
-  std::string retval;
+    if (len > 0)
+      {
+        if (sys::env::absolute_pathname (name))
+          {
+            sys::file_stat fs (name);
 
-  if (! dir.empty ())
-    {
-      octave::load_path& lp = octave::__get_load_path__ ("contents_in_file_path");
-
-      std::string tcontents
-        = octave::sys::file_ops::concat (lp.find_dir (dir), "Contents.m");
-
-      octave::sys::file_stat fs (tcontents);
-
-      if (fs.exists ())
-        retval = octave::sys::env::make_absolute (tcontents);
-    }
-
-  return retval;
-}
-
-// Deprecated in 4.2, remove in version 5.
-// See if there is a .oct file in the path.
-// If so, return the full path to the file.
+            if (fs.exists () && ! fs.is_dir ())
+              retval = name;
+          }
+        else if (len > 2 && name[len - 2] == '.' && name[len - 1] == 'm')
+          {
+            load_path& lp = __get_load_path__ ("fcn_file_in_path");
 
-std::string
-oct_file_in_path (const std::string& name)
-{
-  std::string retval;
-
-  int len = name.length ();
+            retval = lp.find_fcn_file (name.substr (0, len-2));
+          }
+        else
+          {
+            std::string fname = name;
+            size_t pos = name.find_first_of ('>');
+            if (pos != std::string::npos)
+              fname = name.substr (0, pos);
 
-  if (len > 0)
-    {
-      if (octave::sys::env::absolute_pathname (name))
-        {
-          octave::sys::file_stat fs (name);
+            load_path& lp = __get_load_path__ ("fcn_file_in_path");
+
+            retval = lp.find_fcn_file (fname);
+          }
+      }
 
-          if (fs.exists ())
-            retval = name;
-        }
-      else if (len > 4 && name.find (".oct", len-5))
-        {
-          octave::load_path& lp = octave::__get_load_path__ ("oct_file_in_path");
+    return retval;
+  }
+
+  // See if there is a directory called "name" in the path and if it
+  // contains a Contents.m file.  If so, return the full path to this file.
 
-          retval = lp.find_oct_file (name.substr (0, len-4));
-        }
-      else
-        {
-          octave::load_path& lp = octave::__get_load_path__ ("oct_file_in_path");
+  std::string contents_file_in_path (const std::string& dir)
+  {
+    std::string retval;
 
-          retval = lp.find_oct_file (name);
-        }
-    }
+    if (! dir.empty ())
+      {
+        load_path& lp = __get_load_path__ ("contents_in_file_path");
 
-  return retval;
-}
+        std::string tcontents
+          = sys::file_ops::concat (lp.find_dir (dir), "Contents.m");
 
-// Deprecated in 4.2, remove in version 5.
-// See if there is a .mex file in the path.
-// If so, return the full path to the file.
+        sys::file_stat fs (tcontents);
 
-std::string
-mex_file_in_path (const std::string& name)
-{
-  std::string retval;
+        if (fs.exists ())
+          retval = sys::env::make_absolute (tcontents);
+      }
 
-  int len = name.length ();
+    return retval;
+  }
 
-  if (len > 0)
-    {
-      if (octave::sys::env::absolute_pathname (name))
-        {
-          octave::sys::file_stat fs (name);
+  // Replace backslash escapes in a string with the real values.
 
-          if (fs.exists ())
-            retval = name;
-        }
-      else if (len > 4 && name.find (".mex", len-5))
-        {
-          octave::load_path& lp = octave::__get_load_path__ ("mex_file_in_path");
+  std::string do_string_escapes (const std::string& s)
+  {
+    std::string retval;
 
-          retval = lp.find_mex_file (name.substr (0, len-4));
-        }
-      else
-        {
-          octave::load_path& lp = octave::__get_load_path__ ("mex_file_in_path");
+    size_t i = 0;
+    size_t j = 0;
+    size_t len = s.length ();
 
-          retval = lp.find_mex_file (name);
-        }
-    }
-
-  return retval;
-}
+    retval.resize (len);
 
-// Replace backslash escapes in a string with the real values.
-
-std::string
-do_string_escapes (const std::string& s)
-{
-  std::string retval;
-
-  size_t i = 0;
-  size_t j = 0;
-  size_t len = s.length ();
+    while (j < len)
+      {
+        if (s[j] == '\\' && j+1 < len)
+          {
+            switch (s[++j])
+              {
+              case 'a': // alarm
+                retval[i] = '\a';
+                break;
 
-  retval.resize (len);
+              case 'b': // backspace
+                retval[i] = '\b';
+                break;
 
-  while (j < len)
-    {
-      if (s[j] == '\\' && j+1 < len)
-        {
-          switch (s[++j])
-            {
-            case 'a': // alarm
-              retval[i] = '\a';
-              break;
+              case 'f': // formfeed
+                retval[i] = '\f';
+                break;
 
-            case 'b': // backspace
-              retval[i] = '\b';
-              break;
-
-            case 'f': // formfeed
-              retval[i] = '\f';
-              break;
+              case 'n': // newline
+                retval[i] = '\n';
+                break;
 
-            case 'n': // newline
-              retval[i] = '\n';
-              break;
+              case 'r': // carriage return
+                retval[i] = '\r';
+                break;
 
-            case 'r': // carriage return
-              retval[i] = '\r';
-              break;
+              case 't': // horizontal tab
+                retval[i] = '\t';
+                break;
 
-            case 't': // horizontal tab
-              retval[i] = '\t';
-              break;
-
-            case 'v': // vertical tab
-              retval[i] = '\v';
-              break;
+              case 'v': // vertical tab
+                retval[i] = '\v';
+                break;
 
-            case '\\': // backslash
-              retval[i] = '\\';
-              break;
+              case '\\': // backslash
+                retval[i] = '\\';
+                break;
 
-            case '\'': // quote
-              retval[i] = '\'';
-              break;
-
-            case '"': // double quote
-              retval[i] = '"';
-              break;
+              case '\'': // quote
+                retval[i] = '\'';
+                break;
 
-            case '0':
-            case '1':
-            case '2':
-            case '3':
-            case '4':
-            case '5':
-            case '6':
-            case '7': // octal input
-            {
-              size_t k;
-              int tmpi = s[j] - '0';
-              for (k = j+1; k < std::min (j+3, len); k++)
+              case '"': // double quote
+                retval[i] = '"';
+                break;
+
+              case '0':
+              case '1':
+              case '2':
+              case '3':
+              case '4':
+              case '5':
+              case '6':
+              case '7': // octal input
                 {
-                  int digit = s[k] - '0';
-                  if (digit < 0 || digit > 7)
-                    break;
-                  tmpi <<= 3;
-                  tmpi += digit;
-                }
-              retval[i] = tmpi;
-              j = k - 1;
-              break;
-            }
-
-            case 'x': // hex input
-            {
-              size_t k;
-              int tmpi = 0;
-              for (k = j+1; k < std::min (j+3, len); k++)
-                {
-                  if (! isxdigit (s[k]))
-                    break;
-
-                  tmpi <<= 4;
-                  int digit = s[k];
-                  if (digit >= 'a')
-                    tmpi += digit - 'a' + 10;
-                  else if (digit >= 'A')
-                    tmpi += digit - 'A' + 10;
-                  else
-                    tmpi += digit - '0';
+                  size_t k;
+                  int tmpi = s[j] - '0';
+                  for (k = j+1; k < std::min (j+3, len); k++)
+                    {
+                      int digit = s[k] - '0';
+                      if (digit < 0 || digit > 7)
+                        break;
+                      tmpi <<= 3;
+                      tmpi += digit;
+                    }
+                  retval[i] = tmpi;
+                  j = k - 1;
+                  break;
                 }
 
-              if (k == j+1)
-                warning (R"(malformed hex escape sequence '\x' -- converting to '\0')");
+              case 'x': // hex input
+                {
+                  size_t k;
+                  int tmpi = 0;
+                  for (k = j+1; k < std::min (j+3, len); k++)
+                    {
+                      if (! isxdigit (s[k]))
+                        break;
 
-              retval[i] = tmpi;
-              j = k - 1;
-              break;
-            }
+                      tmpi <<= 4;
+                      int digit = s[k];
+                      if (digit >= 'a')
+                        tmpi += digit - 'a' + 10;
+                      else if (digit >= 'A')
+                        tmpi += digit - 'A' + 10;
+                      else
+                        tmpi += digit - '0';
+                    }
+
+                  if (k == j+1)
+                    warning (R"(malformed hex escape sequence '\x' -- converting to '\0')");
 
-            default:
-              warning (R"(unrecognized escape sequence '\%c' -- converting to '%c')", s[j], s[j]);
-              retval[i] = s[j];
-              break;
-            }
-        }
-      else
-        retval[i] = s[j];
+                  retval[i] = tmpi;
+                  j = k - 1;
+                  break;
+                }
 
-      i++;
-      j++;
-    }
+              default:
+                warning (R"(unrecognized escape sequence '\%c' -- converting to '%c')", s[j], s[j]);
+                retval[i] = s[j];
+                break;
+              }
+          }
+        else
+          retval[i] = s[j];
 
-  retval.resize (i);
+        i++;
+        j++;
+      }
 
-  return retval;
+    retval.resize (i);
+
+    return retval;
+  }
 }
 
 DEFUN (do_string_escapes, args, ,
@@ -757,7 +675,7 @@
 
   std::string str = args(0).xstring_value ("do_string_escapes: STRING argument must be of type string");
 
-  return ovl (do_string_escapes (str));
+  return ovl (octave::do_string_escapes (str));
 }
 
 /*
@@ -797,63 +715,64 @@
 %!warning <unrecognized escape sequence> do_string_escapes ('\G');
 */
 
-const char *
-undo_string_escape (char c)
+namespace octave
 {
-  if (! c)
-    return "";
+  const char * undo_string_escape (char c)
+  {
+    if (! c)
+      return "";
 
-  switch (c)
-    {
-    case '\0':
-      return R"(\0)";
-
-    case '\a':
-      return R"(\a)";
+    switch (c)
+      {
+      case '\0':
+        return R"(\0)";
 
-    case '\b': // backspace
-      return R"(\b)";
+      case '\a':
+        return R"(\a)";
 
-    case '\f': // formfeed
-      return R"(\f)";
+      case '\b': // backspace
+        return R"(\b)";
 
-    case '\n': // newline
-      return R"(\n)";
+      case '\f': // formfeed
+        return R"(\f)";
 
-    case '\r': // carriage return
-      return R"(\r)";
+      case '\n': // newline
+        return R"(\n)";
 
-    case '\t': // horizontal tab
-      return R"(\t)";
+      case '\r': // carriage return
+        return R"(\r)";
 
-    case '\v': // vertical tab
-      return R"(\v)";
+      case '\t': // horizontal tab
+        return R"(\t)";
 
-    case '\\': // backslash
-      return R"(\\)";
+      case '\v': // vertical tab
+        return R"(\v)";
 
-    case '"': // double quote
-      return R"(\")";
+      case '\\': // backslash
+        return R"(\\)";
 
-    default:
-      {
-        static char retval[2] {'\0', '\0'};
+      case '"': // double quote
+        return R"(\")";
+
+      default:
+        {
+          static char retval[2] {'\0', '\0'};
 
-        retval[0] = c;
-        return retval;
+          retval[0] = c;
+          return retval;
+        }
       }
-    }
-}
+  }
 
-std::string
-undo_string_escapes (const std::string& s)
-{
-  std::string retval;
+  std::string undo_string_escapes (const std::string& s)
+  {
+    std::string retval;
 
-  for (size_t i = 0; i < s.length (); i++)
-    retval.append (undo_string_escape (s[i]));
+    for (size_t i = 0; i < s.length (); i++)
+      retval.append (undo_string_escape (s[i]));
 
-  return retval;
+    return retval;
+  }
 }
 
 DEFUN (undo_string_escapes, args, ,
@@ -892,7 +811,7 @@
 
   std::string str = args(0).xstring_value ("undo_string_escapes: S argument must be a string");
 
-  return ovl (undo_string_escapes (str));
+  return ovl (octave::undo_string_escapes (str));
 }
 
 /*
@@ -1123,295 +1042,288 @@
 %!error errno_list ("foo")
 */
 
-static void
-check_dimensions (octave_idx_type& nr, octave_idx_type& nc, const char *warnfor)
+namespace octave
 {
-  if (nr < 0 || nc < 0)
-    {
+  static void check_dimensions (octave_idx_type& nr, octave_idx_type& nc,
+                                const char *warnfor)
+  {
+    if (nr < 0 || nc < 0)
+      {
+        warning_with_id ("Octave:neg-dim-as-zero",
+                         "%s: converting negative dimension to zero", warnfor);
+
+        nr = (nr < 0) ? 0 : nr;
+        nc = (nc < 0) ? 0 : nc;
+      }
+  }
+
+  void check_dimensions (dim_vector& dim, const char *warnfor)
+  {
+    bool neg = false;
+
+    for (int i = 0; i < dim.ndims (); i++)
+      {
+        if (dim(i) < 0)
+          {
+            dim(i) = 0;
+            neg = true;
+          }
+      }
+
+    if (neg)
       warning_with_id ("Octave:neg-dim-as-zero",
                        "%s: converting negative dimension to zero", warnfor);
-
-      nr = (nr < 0) ? 0 : nr;
-      nc = (nc < 0) ? 0 : nc;
-    }
-}
-
-void
-check_dimensions (dim_vector& dim, const char *warnfor)
-{
-  bool neg = false;
+  }
 
-  for (int i = 0; i < dim.ndims (); i++)
-    {
-      if (dim(i) < 0)
-        {
-          dim(i) = 0;
-          neg = true;
-        }
-    }
+  void get_dimensions (const octave_value& a, const char *warn_for,
+                       dim_vector& dim)
+  {
+    // We support dimensions to be specified by any vector, even if it's a
+    // vector of dimensions 0x1, 1x0, 1x1x0, or 1x1x6.  If the vector ends
+    // up being empty, the final dimensions end up being 0x0.
+    if (! a.dims ().isvector ())
+      error ("%s (A): use %s (size (A)) instead", warn_for, warn_for);
 
-  if (neg)
-    warning_with_id ("Octave:neg-dim-as-zero",
-                     "%s: converting negative dimension to zero", warnfor);
-}
+    const Array<octave_idx_type> v = a.octave_idx_type_vector_value ();
+    const octave_idx_type n = v.numel ();
 
-void
-get_dimensions (const octave_value& a, const char *warn_for,
-                dim_vector& dim)
-{
-  // We support dimensions to be specified by any vector, even if it's a
-  // vector of dimensions 0x1, 1x0, 1x1x0, or 1x1x6.  If the vector ends
-  // up being empty, the final dimensions end up being 0x0.
-  if (! a.dims ().isvector ())
-    error ("%s (A): use %s (size (A)) instead", warn_for, warn_for);
+    dim.resize (n); // even if n < 2, resize sets it back to 2
+    if (n == 0)
+      {
+        dim(0) = 0;
+        dim(1) = 0;
+      }
+    else if (n == 1)
+      {
+        dim(0) = v(0);
+        dim(1) = v(0);
+      }
+    else
+      for (octave_idx_type i = 0; i < n; i++)
+        dim(i) = v(i);
 
-  const Array<octave_idx_type> v = a.octave_idx_type_vector_value ();
-  const octave_idx_type n = v.numel ();
+    octave::check_dimensions (dim, warn_for);
+  }
 
-  dim.resize (n); // even if n < 2, resize sets it back to 2
-  if (n == 0)
-    {
-      dim(0) = 0;
-      dim(1) = 0;
-    }
-  else if (n == 1)
-    {
-      dim(0) = v(0);
-      dim(1) = v(0);
-    }
-  else
-    for (octave_idx_type i = 0; i < n; i++)
-      dim(i) = v(i);
+  void get_dimensions (const octave_value& a, const char *warn_for,
+                       octave_idx_type& nr, octave_idx_type& nc)
+  {
+    if (a.is_scalar_type ())
+      {
+        nr = nc = a.idx_type_value ();
+      }
+    else
+      {
+        nr = a.rows ();
+        nc = a.columns ();
 
-  check_dimensions (dim, warn_for);
-}
+        if ((nr != 1 || nc != 2) && (nr != 2 || nc != 1))
+          error ("%s (A): use %s (size (A)) instead", warn_for, warn_for);
 
-void
-get_dimensions (const octave_value& a, const char *warn_for,
-                octave_idx_type& nr, octave_idx_type& nc)
-{
-  if (a.is_scalar_type ())
-    {
-      nr = nc = a.idx_type_value ();
-    }
-  else
-    {
-      nr = a.rows ();
-      nc = a.columns ();
+        Array<double> v = a.vector_value ();
+        nr = static_cast<octave_idx_type> (math::fix (v(0)));
+        nc = static_cast<octave_idx_type> (math::fix (v(1)));
+      }
+
+    octave::check_dimensions (nr, nc, warn_for);
+  }
 
-      if ((nr != 1 || nc != 2) && (nr != 2 || nc != 1))
-        error ("%s (A): use %s (size (A)) instead", warn_for, warn_for);
-
-      Array<double> v = a.vector_value ();
-      nr = static_cast<octave_idx_type> (octave::math::fix (v(0)));
-      nc = static_cast<octave_idx_type> (octave::math::fix (v(1)));
-    }
-
-  check_dimensions (nr, nc, warn_for);
-}
+  void get_dimensions (const octave_value& a, const octave_value& b,
+                       const char *warn_for, octave_idx_type& nr,
+                       octave_idx_type& nc)
+  {
+    nr = a.isempty ()
+      ? 0 : a.idx_type_value ("%s: row dimension must be a scalar", warn_for);
+    nc = b.isempty ()
+      ? 0 : b.idx_type_value ("%s: column dimension must be a scalar", warn_for);
 
-void
-get_dimensions (const octave_value& a, const octave_value& b,
-                const char *warn_for, octave_idx_type& nr, octave_idx_type& nc)
-{
-  nr = a.isempty ()
-       ? 0 : a.idx_type_value ("%s: row dimension must be a scalar", warn_for);
-  nc = b.isempty ()
-       ? 0 : b.idx_type_value ("%s: column dimension must be a scalar", warn_for);
+    octave::check_dimensions (nr, nc, warn_for);
+  }
 
-  check_dimensions (nr, nc, warn_for);
-}
+  octave_idx_type dims_to_numel (const dim_vector& dims,
+                                 const octave_value_list& idx_arg)
+  {
+    octave_idx_type retval;
 
-octave_idx_type
-dims_to_numel (const dim_vector& dims, const octave_value_list& idx_arg)
-{
-  octave_idx_type retval;
-
-  octave_idx_type len = idx_arg.length ();
+    octave_idx_type len = idx_arg.length ();
 
-  if (len == 0)
-    retval = dims.numel ();
-  else
-    {
-      const dim_vector dv = dims.redim (len);
-      retval = 1;
-      for (octave_idx_type i = 0; i < len; i++)
-        {
-          octave_value idxi = idx_arg(i);
-          if (idxi.is_magic_colon ())
-            retval *= dv(i);
-          else if (idxi.isnumeric ())
-            retval *= idxi.numel ();
-          else
-            {
-              try
-                {
-                  idx_vector jdx = idxi.index_vector ();
+    if (len == 0)
+      retval = dims.numel ();
+    else
+      {
+        const dim_vector dv = dims.redim (len);
+        retval = 1;
+        for (octave_idx_type i = 0; i < len; i++)
+          {
+            octave_value idxi = idx_arg(i);
+            if (idxi.is_magic_colon ())
+              retval *= dv(i);
+            else if (idxi.isnumeric ())
+              retval *= idxi.numel ();
+            else
+              {
+                try
+                  {
+                    idx_vector jdx = idxi.index_vector ();
 
-                  retval *= jdx.length (dv(i));
-                }
-              catch (const octave::index_exception& e)
-                {
-                  std::string idx = e.idx ();
-                  std::string msg = e.details ();
+                    retval *= jdx.length (dv(i));
+                  }
+                catch (const index_exception& e)
+                  {
+                    std::string idx = e.idx ();
+                    std::string msg = e.details ();
+
+                    error ("dims_to_numel: Invalid IDX %s. %s",
+                           idx.c_str (), msg.c_str ());
+                  }
+              }
+          }
+      }
 
-                  error ("dims_to_numel: Invalid IDX %s. %s",
-                         idx.c_str (), msg.c_str ());
-                }
-            }
-        }
-    }
+    return retval;
+  }
+
+  Matrix identity_matrix (octave_idx_type nr, octave_idx_type nc)
+  {
+    Matrix m (nr, nc, 0.0);
 
-  return retval;
-}
+    if (nr > 0 && nc > 0)
+      {
+        octave_idx_type n = std::min (nr, nc);
 
-Matrix
-identity_matrix (octave_idx_type nr, octave_idx_type nc)
-{
-  Matrix m (nr, nc, 0.0);
+        for (octave_idx_type i = 0; i < n; i++)
+          m (i, i) = 1.0;
+      }
+
+    return m;
+  }
 
-  if (nr > 0 && nc > 0)
-    {
-      octave_idx_type n = std::min (nr, nc);
-
-      for (octave_idx_type i = 0; i < n; i++)
-        m (i, i) = 1.0;
-    }
+  FloatMatrix float_identity_matrix (octave_idx_type nr, octave_idx_type nc)
+  {
+    FloatMatrix m (nr, nc, 0.0);
 
-  return m;
-}
+    if (nr > 0 && nc > 0)
+      {
+        octave_idx_type n = std::min (nr, nc);
 
-FloatMatrix
-float_identity_matrix (octave_idx_type nr, octave_idx_type nc)
-{
-  FloatMatrix m (nr, nc, 0.0);
+        for (octave_idx_type i = 0; i < n; i++)
+          m (i, i) = 1.0;
+      }
 
-  if (nr > 0 && nc > 0)
-    {
-      octave_idx_type n = std::min (nr, nc);
+    return m;
+  }
 
-      for (octave_idx_type i = 0; i < n; i++)
-        m (i, i) = 1.0;
-    }
+  size_t format (std::ostream& os, const char *fmt, ...)
+  {
+    size_t retval;
 
-  return m;
-}
+    va_list args;
+    va_start (args, fmt);
+
+    retval = vformat (os, fmt, args);
 
-size_t
-octave_format (std::ostream& os, const char *fmt, ...)
-{
-  size_t retval;
+    va_end (args);
 
-  va_list args;
-  va_start (args, fmt);
+    return retval;
+  }
 
-  retval = octave_vformat (os, fmt, args);
+  size_t vformat (std::ostream& os, const char *fmt, va_list args)
+  {
+    std::string s = vasprintf (fmt, args);
 
-  va_end (args);
-
-  return retval;
-}
+    os << s;
 
-size_t
-octave_vformat (std::ostream& os, const char *fmt, va_list args)
-{
-  std::string s = octave_vasprintf (fmt, args);
+    return s.length ();
+  }
 
-  os << s;
+  std::string vasprintf (const char *fmt, va_list args)
+  {
+    std::string retval;
 
-  return s.length ();
-}
+    char *result;
 
-std::string
-octave_vasprintf (const char *fmt, va_list args)
-{
-  std::string retval;
+    int status = octave_vasprintf_wrapper (&result, fmt, args);
 
-  char *result;
-
-  int status = octave_vasprintf_wrapper (&result, fmt, args);
+    if (status >= 0)
+      {
+        retval = result;
+        ::free (result);
+      }
 
-  if (status >= 0)
-    {
-      retval = result;
-      ::free (result);
-    }
+    return retval;
+  }
 
-  return retval;
-}
+  std::string asprintf (const char *fmt, ...)
+  {
+    std::string retval;
+
+    va_list args;
+    va_start (args, fmt);
 
-std::string
-octave_asprintf (const char *fmt, ...)
-{
-  std::string retval;
+    retval = vasprintf (fmt, args);
+
+    va_end (args);
 
-  va_list args;
-  va_start (args, fmt);
-
-  retval = octave_vasprintf (fmt, args);
+    return retval;
+  }
 
-  va_end (args);
-
-  return retval;
-}
+  // FIXME: sleep is complicated because we want it to be interruptible.
+  // With the way this program handles signals, the sleep system call
+  // won't respond to SIGINT.  Maybe there is a better way than
+  // breaking this up into multiple shorter intervals?
 
-// FIXME: sleep is complicated because we want it to be interruptible.
-// With the way this program handles signals, the sleep system call
-// won't respond to SIGINT.  Maybe there is a better way than
-// breaking this up into multiple shorter intervals?
+  void sleep (double seconds)
+  {
+    if (seconds <= 0)
+      return;
+
+    // Split delay into whole seconds and the remainder as a decimal
+    // fraction.
 
-void
-octave_sleep (double seconds)
-{
-  if (seconds <= 0)
-    return;
+    double fraction = std::modf (seconds, &seconds);
+
+    // Further split the fractional seconds into whole tenths and the
+    // nearest number of nanoseconds remaining.
 
-  // Split delay into whole seconds and the remainder as a decimal
-  // fraction.
+    double tenths = 0;
+    fraction = std::modf (fraction * 10, &tenths) / 10;
+    fraction = std::round (fraction * 1000000000);
 
-  double fraction = std::modf (seconds, &seconds);
-
-  // Further split the fractional seconds into whole tenths and the
-  // nearest number of nanoseconds remaining.
+    // Sleep for the hundredths portion.
 
-  double tenths = 0;
-  fraction = std::modf (fraction * 10, &tenths) / 10;
-  fraction = std::round (fraction * 1000000000);
+    struct timespec hundredths_delay = { 0, static_cast<long> (fraction) };
 
-  // Sleep for the hundredths portion.
+    octave_nanosleep_wrapper (&hundredths_delay, nullptr);
 
-  struct timespec hundredths_delay = { 0, static_cast<long> (fraction) };
+    // Sleep for the whole tenths portion, allowing interrupts every
+    // tenth.
 
-  octave_nanosleep_wrapper (&hundredths_delay, nullptr);
-
-  // Sleep for the whole tenths portion, allowing interrupts every
-  // tenth.
+    struct timespec one_tenth = { 0, 100000000 };
 
-  struct timespec one_tenth = { 0, 100000000 };
+    for (int i = 0; i < static_cast<int> (tenths); i++)
+      {
+        octave_nanosleep_wrapper (&one_tenth, nullptr);
 
-  for (int i = 0; i < static_cast<int> (tenths); i++)
-    {
-      octave_nanosleep_wrapper (&one_tenth, nullptr);
+        octave_quit ();
+      }
 
-      octave_quit ();
-    }
+    // Sleep for the whole seconds portion, allowing interrupts every
+    // tenth.
 
-  // Sleep for the whole seconds portion, allowing interrupts every
-  // tenth.
-
-  time_t sec = ((seconds > std::numeric_limits<time_t>::max ())
-                ? std::numeric_limits<time_t>::max ()
-                : static_cast<time_t> (seconds));
+    time_t sec = ((seconds > std::numeric_limits<time_t>::max ())
+                  ? std::numeric_limits<time_t>::max ()
+                  : static_cast<time_t> (seconds));
 
-  for (time_t s = 0; s < sec; s++)
-    {
-      for (int i = 0; i < 10; i++)
-        {
-          octave_nanosleep_wrapper (&one_tenth, nullptr);
+    for (time_t s = 0; s < sec; s++)
+      {
+        for (int i = 0; i < 10; i++)
+          {
+            octave_nanosleep_wrapper (&one_tenth, nullptr);
 
-          octave_quit ();
-        }
-    }
+            octave_quit ();
+          }
+      }
+  }
 }
 
 DEFUN (isindex, args, ,
@@ -1477,86 +1389,89 @@
 %!error isindex (1:3, 2, 3)
 */
 
-octave_value_list
-do_simple_cellfun (octave_value_list (*fun) (const octave_value_list&, int),
-                   const char *fun_name, const octave_value_list& args,
-                   int nargout)
+namespace octave
 {
-  octave_value_list new_args = args;
-  octave_value_list retval;
-  int nargin = args.length ();
-  OCTAVE_LOCAL_BUFFER (bool, iscell, nargin);
-  OCTAVE_LOCAL_BUFFER (Cell, cells, nargin);
-  OCTAVE_LOCAL_BUFFER (Cell, rcells, nargout);
+  octave_value_list
+  do_simple_cellfun (octave_value_list (*fun) (const octave_value_list&, int),
+                     const char *fun_name, const octave_value_list& args,
+                     int nargout)
+  {
+    octave_value_list new_args = args;
+    octave_value_list retval;
+    int nargin = args.length ();
+    OCTAVE_LOCAL_BUFFER (bool, iscell, nargin);
+    OCTAVE_LOCAL_BUFFER (Cell, cells, nargin);
+    OCTAVE_LOCAL_BUFFER (Cell, rcells, nargout);
 
-  const Cell *ccells = cells;
+    const Cell *ccells = cells;
 
-  octave_idx_type numel = 1;
-  dim_vector dims (1, 1);
+    octave_idx_type numel = 1;
+    dim_vector dims (1, 1);
 
-  for (int i = 0; i < nargin; i++)
-    {
-      octave_value arg = new_args(i);
-      iscell[i] = arg.iscell ();
-      if (iscell[i])
-        {
-          cells[i] = arg.cell_value ();
-          octave_idx_type n = ccells[i].numel ();
-          if (n == 1)
-            {
-              iscell[i] = false;
-              new_args(i) = ccells[i](0);
-            }
-          else if (numel == 1)
-            {
-              numel = n;
-              dims = ccells[i].dims ();
-            }
-          else if (dims != ccells[i].dims ())
-            error ("%s: cell arguments must have matching sizes", fun_name);
-        }
-    }
+    for (int i = 0; i < nargin; i++)
+      {
+        octave_value arg = new_args(i);
+        iscell[i] = arg.iscell ();
+        if (iscell[i])
+          {
+            cells[i] = arg.cell_value ();
+            octave_idx_type n = ccells[i].numel ();
+            if (n == 1)
+              {
+                iscell[i] = false;
+                new_args(i) = ccells[i](0);
+              }
+            else if (numel == 1)
+              {
+                numel = n;
+                dims = ccells[i].dims ();
+              }
+            else if (dims != ccells[i].dims ())
+              error ("%s: cell arguments must have matching sizes", fun_name);
+          }
+      }
 
-  for (int i = 0; i < nargout; i++)
-    rcells[i].clear (dims);
+    for (int i = 0; i < nargout; i++)
+      rcells[i].clear (dims);
 
-  for (octave_idx_type j = 0; j < numel; j++)
-    {
-      for (int i = 0; i < nargin; i++)
-        if (iscell[i])
-          new_args(i) = ccells[i](j);
+    for (octave_idx_type j = 0; j < numel; j++)
+      {
+        for (int i = 0; i < nargin; i++)
+          if (iscell[i])
+            new_args(i) = ccells[i](j);
 
-      octave_quit ();
+        octave_quit ();
 
-      const octave_value_list tmp = fun (new_args, nargout);
+        const octave_value_list tmp = fun (new_args, nargout);
 
-      if (tmp.length () < nargout)
-        error ("%s: do_simple_cellfun: internal error", fun_name);
+        if (tmp.length () < nargout)
+          error ("%s: do_simple_cellfun: internal error", fun_name);
 
-      for (int i = 0; i < nargout; i++)
-        rcells[i](j) = tmp(i);
-    }
+        for (int i = 0; i < nargout; i++)
+          rcells[i](j) = tmp(i);
+      }
 
-  retval.resize (nargout);
+    retval.resize (nargout);
 
-  for (int i = 0; i < nargout; i++)
-    retval(i) = rcells[i];
+    for (int i = 0; i < nargout; i++)
+      retval(i) = rcells[i];
 
-  return retval;
-}
+    return retval;
+  }
 
-octave_value
-do_simple_cellfun (octave_value_list (*fun) (const octave_value_list&, int),
-                   const char *fun_name, const octave_value_list& args)
-{
-  octave_value retval;
+  octave_value
+  do_simple_cellfun (octave_value_list (*fun) (const octave_value_list&, int),
+                     const char *fun_name, const octave_value_list& args)
+  {
+    octave_value retval;
 
-  const octave_value_list tmp = do_simple_cellfun (fun, fun_name, args, 1);
+    const octave_value_list tmp = octave::do_simple_cellfun (fun, fun_name, args, 1);
 
-  if (tmp.length () > 0)
-    retval = tmp(0);
+    if (tmp.length () > 0)
+      retval = tmp(0);
 
-  return retval;
+    return retval;
+  }
 }
 
 DEFUN (isstudent, args, ,
@@ -1579,3 +1494,183 @@
 
 %!error isstudent (1)
 */
+
+// Always define these functions.  The macro is intended to allow the
+// declarations to be hidden, not so that Octave will not provide the
+// functions if they are requested.
+
+// #if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
+
+#include "ov.h"
+#include "ovl.h"
+#include "str-vec.h"
+
+bool
+valid_identifier (const char *s)
+{
+  return octave::valid_identifier (s);
+}
+
+bool
+valid_identifier (const std::string& s)
+{
+  return octave::valid_identifier (s);
+}
+
+bool
+same_file (const std::string& f, const std::string& g)
+{
+  return octave::same_file (f, g);
+}
+
+int
+almost_match (const std::string& std, const std::string& s,
+              int min_match_len, int case_sens)
+{
+  return octave::almost_match (std, s, min_match_len, case_sens);
+}
+
+int
+keyword_almost_match (const char * const *std, int *min_len,
+                      const std::string& s, int min_toks_to_match,
+                      int max_toks)
+{
+  return octave::keyword_almost_match (std, min_len, s, min_toks_to_match,
+                                       max_toks);
+}
+
+std::string
+search_path_for_file (const std::string& path, const string_vector& names)
+{
+  return octave::search_path_for_file (path, names);
+}
+
+string_vector
+search_path_for_all_files (const std::string& path, const string_vector& names)
+{
+  return octave::search_path_for_all_files (path, names);
+}
+
+std::string
+file_in_path (const std::string& name, const std::string& suffix)
+{
+  return octave::file_in_path (name, suffix);
+}
+
+std::string
+find_data_file_in_load_path  (const std::string& fcn, const std::string& file,
+                              bool require_regular_file)
+{
+  return octave::find_data_file_in_load_path  (fcn, file, require_regular_file);
+}
+
+std::string
+contents_file_in_path (const std::string& s)
+{
+  return octave::contents_file_in_path (s);
+}
+
+std::string
+fcn_file_in_path (const std::string& s)
+{
+  return octave::fcn_file_in_path (s);
+}
+
+std::string
+do_string_escapes (const std::string& s)
+{
+  return octave::do_string_escapes (s);
+}
+
+const char *
+undo_string_escape (char c)
+{
+  return octave::undo_string_escape (c);
+}
+
+std::string
+undo_string_escapes (const std::string& s)
+{
+  return octave::undo_string_escapes (s);
+}
+
+void
+check_dimensions (dim_vector& dim, const char *warnfor)
+{
+  return octave::check_dimensions (dim, warnfor);
+}
+
+void
+get_dimensions (const octave_value& a, const char *warn_for,
+                dim_vector& dim)
+{
+  return octave::get_dimensions (a, warn_for, dim);
+}
+
+void
+get_dimensions (const octave_value& a, const octave_value& b,
+                const char *warn_for, octave_idx_type& nr,
+                octave_idx_type& nc)
+{
+  return octave::get_dimensions (a, b, warn_for, nr, nc);
+}
+
+void
+get_dimensions (const octave_value& a, const char *warn_for,
+                octave_idx_type& nr, octave_idx_type& nc)
+{
+  return octave::get_dimensions (a, warn_for, nr, nc);
+}
+
+octave_idx_type
+dims_to_numel (const dim_vector& dims, const octave_value_list& idx)
+{
+  return octave::dims_to_numel (dims, idx);
+}
+
+Matrix
+identity_matrix (octave_idx_type nr, octave_idx_type nc)
+{
+  return octave::identity_matrix (nr, nc);
+}
+
+FloatMatrix
+float_identity_matrix (octave_idx_type nr, octave_idx_type nc)
+{
+  return octave::float_identity_matrix (nr, nc);
+}
+
+size_t
+octave_vformat (std::ostream& os, const char *fmt, va_list args)
+{
+  return octave::vformat (os, fmt, args);
+}
+
+std::string
+octave_vasprintf (const char *fmt, va_list args)
+{
+  return octave::vasprintf (fmt, args);
+}
+
+void
+octave_sleep (double seconds)
+{
+  octave::sleep (seconds);
+}
+
+octave_value_list
+do_simple_cellfun (octave_value_list (*fun) (const octave_value_list&, int),
+                   const char *fun_name, const octave_value_list& args,
+                   int nargout)
+{
+  return octave::do_simple_cellfun (fun, fun_name, args, nargout);
+}
+
+octave_value
+do_simple_cellfun (octave_value_list (*fun) (const octave_value_list&, int),
+                   const char *fun_name, const octave_value_list& args)
+{
+  return octave::do_simple_cellfun (fun, fun_name, args);
+}
+
+// #endif
--- a/libinterp/corefcn/utils.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/utils.h	Fri Aug 10 09:09:51 2018 +0200
@@ -38,103 +38,231 @@
 class octave_value_list;
 class string_vector;
 
-extern OCTINTERP_API bool valid_identifier (const char *s);
-extern OCTINTERP_API bool valid_identifier (const std::string& s);
+namespace octave
+{
+  extern OCTINTERP_API bool valid_identifier (const char *s);
+  extern OCTINTERP_API bool valid_identifier (const std::string& s);
+
+  extern OCTINTERP_API bool
+  same_file (const std::string& f, const std::string& g);
+
+  extern OCTINTERP_API int almost_match (const std::string& std,
+                                         const std::string& s,
+                                         int min_match_len = 1,
+                                         int case_sens = 1);
+
+  extern OCTINTERP_API int
+  keyword_almost_match (const char * const *std, int *min_len,
+                        const std::string& s, int min_toks_to_match,
+                        int max_toks);
+
+  extern OCTINTERP_API std::string
+  search_path_for_file (const std::string&, const string_vector&);
+
+  extern OCTINTERP_API string_vector
+  search_path_for_all_files (const std::string&, const string_vector&);
+
+  extern OCTINTERP_API std::string
+  file_in_path (const std::string&, const std::string&);
+
+  extern OCTINTERP_API std::string
+  find_data_file_in_load_path  (const std::string& fcn,
+                                const std::string& file,
+                                bool require_regular_file = false);
+
+  extern OCTINTERP_API std::string contents_file_in_path (const std::string&);
+
+  extern OCTINTERP_API std::string fcn_file_in_path (const std::string&);
+
+  extern OCTINTERP_API std::string do_string_escapes (const std::string& s);
+
+  extern OCTINTERP_API const char * undo_string_escape (char c);
+
+  extern OCTINTERP_API std::string undo_string_escapes (const std::string& s);
+
+  extern OCTINTERP_API void
+  check_dimensions (dim_vector& dim, const char *warnfor);
+
+  extern OCTINTERP_API void
+  get_dimensions (const octave_value& a, const char *warn_for,
+                  dim_vector& dim);
 
+  extern OCTINTERP_API void
+  get_dimensions (const octave_value& a, const octave_value& b,
+                  const char *warn_for, octave_idx_type& nr,
+                  octave_idx_type& nc);
+
+  extern OCTINTERP_API void
+  get_dimensions (const octave_value& a, const char *warn_for,
+                  octave_idx_type& nr, octave_idx_type& nc);
+
+  extern OCTINTERP_API octave_idx_type
+  dims_to_numel (const dim_vector& dims, const octave_value_list& idx);
+
+  extern OCTINTERP_API Matrix
+  identity_matrix (octave_idx_type nr, octave_idx_type nc);
+
+  extern OCTINTERP_API FloatMatrix
+  float_identity_matrix (octave_idx_type nr, octave_idx_type nc);
+
+  extern OCTINTERP_API size_t
+  format (std::ostream& os, const char *fmt, ...);
+
+  extern OCTINTERP_API size_t
+  vformat (std::ostream& os, const char *fmt, va_list args);
+
+  extern OCTINTERP_API std::string
+  vasprintf (const char *fmt, va_list args);
+
+  extern OCTINTERP_API std::string asprintf (const char *fmt, ...);
+
+  extern OCTINTERP_API void sleep (double seconds);
+
+  extern OCTINTERP_API
+  octave_value_list
+  do_simple_cellfun (octave_value_list (*fun) (const octave_value_list&, int),
+                     const char *fun_name, const octave_value_list& args,
+                     int nargout);
+
+  extern OCTINTERP_API
+  octave_value
+  do_simple_cellfun (octave_value_list (*fun) (const octave_value_list&, int),
+                     const char *fun_name, const octave_value_list& args);
+}
+
+#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
+
+OCTAVE_DEPRECATED (5, "use 'octave::valid_identifier' instead")
+extern OCTINTERP_API bool
+valid_identifier (const char *s);
+
+OCTAVE_DEPRECATED (5, "use 'octave::valid_identifier' instead")
+extern OCTINTERP_API bool
+valid_identifier (const std::string& s);
+
+OCTAVE_DEPRECATED (5, "use 'octave::same_file' instead")
 extern OCTINTERP_API bool
 same_file (const std::string& f, const std::string& g);
 
-extern OCTINTERP_API int almost_match (const std::string& std,
-                                       const std::string& s,
-                                       int min_match_len = 1,
-                                       int case_sens = 1);
+OCTAVE_DEPRECATED (5, "use 'octave::almost_match' instead")
+extern OCTINTERP_API int
+almost_match (const std::string& std, const std::string& s,
+              int min_match_len = 1, int case_sens = 1);
 
+OCTAVE_DEPRECATED (5, "use 'octave::keyword_almost_match' instead")
 extern OCTINTERP_API int
 keyword_almost_match (const char * const *std, int *min_len,
                       const std::string& s, int min_toks_to_match,
                       int max_toks);
 
-OCTAVE_DEPRECATED (4.2, "use 'octave_value::isempty' instead")
-extern OCTINTERP_API int empty_arg (const char *name, octave_idx_type nr,
-                                    octave_idx_type nc);
+OCTAVE_DEPRECATED (5, "use 'octave::search_path_for_file' instead")
+extern OCTINTERP_API std::string
+search_path_for_file (const std::string& path, const string_vector& names);
 
-extern OCTINTERP_API std::string
-search_path_for_file (const std::string&, const string_vector&);
-
+OCTAVE_DEPRECATED (5, "use 'octave::search_path_for_all_files' instead")
 extern OCTINTERP_API string_vector
-search_path_for_all_files (const std::string&, const string_vector&);
+search_path_for_all_files (const std::string& path, const string_vector& names);
 
+OCTAVE_DEPRECATED (5, "use 'octave::file_in_path' instead")
 extern OCTINTERP_API std::string
-file_in_path (const std::string&, const std::string&);
+file_in_path (const std::string& name, const std::string& suffix);
 
+OCTAVE_DEPRECATED (5, "use 'octave::find_data_file_in_load_path ' instead")
 extern OCTINTERP_API std::string
-find_data_file_in_load_path  (const std::string& fcn,
-                              const std::string& file,
+find_data_file_in_load_path  (const std::string& fcn, const std::string& file,
                               bool require_regular_file = false);
 
-extern OCTINTERP_API std::string contents_file_in_path (const std::string&);
+OCTAVE_DEPRECATED (5, "use 'octave::contents_file_in_path' instead")
+extern OCTINTERP_API std::string
+contents_file_in_path (const std::string& s);
 
-extern OCTINTERP_API std::string fcn_file_in_path (const std::string&);
-
-OCTAVE_DEPRECATED (4.2, "use 'load_path::find_oct_file' instead")
-extern OCTINTERP_API std::string oct_file_in_path (const std::string&);
+OCTAVE_DEPRECATED (5, "use 'octave::fcn_file_in_path' instead")
+extern OCTINTERP_API std::string
+fcn_file_in_path (const std::string& s);
 
-OCTAVE_DEPRECATED (4.2, "use 'load_path::find_mex_file' instead")
-extern OCTINTERP_API std::string mex_file_in_path (const std::string&);
-
-extern OCTINTERP_API std::string do_string_escapes (const std::string& s);
+OCTAVE_DEPRECATED (5, "use 'octave::do_string_escapes' instead")
+extern OCTINTERP_API std::string
+do_string_escapes (const std::string& s);
 
-extern OCTINTERP_API const char * undo_string_escape (char c);
+OCTAVE_DEPRECATED (5, "use 'octave::undo_string_escape' instead")
+extern OCTINTERP_API const char *
+undo_string_escape (char c);
 
-extern OCTINTERP_API std::string undo_string_escapes (const std::string& s);
+OCTAVE_DEPRECATED (5, "use 'octave::undo_string_escapes' instead")
+extern OCTINTERP_API std::string
+undo_string_escapes (const std::string& s);
 
+OCTAVE_DEPRECATED (5, "use 'octave::check_dimensions' instead")
 extern OCTINTERP_API void
 check_dimensions (dim_vector& dim, const char *warnfor);
 
+OCTAVE_DEPRECATED (5, "use 'octave::get_dimensions' instead")
 extern OCTINTERP_API void
 get_dimensions (const octave_value& a, const char *warn_for,
                 dim_vector& dim);
 
+OCTAVE_DEPRECATED (5, "use 'octave::get_dimensions' instead")
 extern OCTINTERP_API void
 get_dimensions (const octave_value& a, const octave_value& b,
                 const char *warn_for, octave_idx_type& nr,
                 octave_idx_type& nc);
 
+OCTAVE_DEPRECATED (5, "use 'octave::get_dimensions' instead")
 extern OCTINTERP_API void
-get_dimensions (const octave_value& a,const char *warn_for,
+get_dimensions (const octave_value& a, const char *warn_for,
                 octave_idx_type& nr, octave_idx_type& nc);
 
+OCTAVE_DEPRECATED (5, "use 'octave::dims_to_numel' instead")
 extern OCTINTERP_API octave_idx_type
 dims_to_numel (const dim_vector& dims, const octave_value_list& idx);
 
+OCTAVE_DEPRECATED (5, "use 'octave::identity_matrix' instead")
 extern OCTINTERP_API Matrix
 identity_matrix (octave_idx_type nr, octave_idx_type nc);
 
+OCTAVE_DEPRECATED (5, "use 'octave::float_identity_matrix' instead")
 extern OCTINTERP_API FloatMatrix
 float_identity_matrix (octave_idx_type nr, octave_idx_type nc);
 
-extern OCTINTERP_API size_t
-octave_format (std::ostream& os, const char *fmt, ...);
+template <typename ... Args>
+OCTAVE_DEPRECATED (5, "use 'octave::format' instead")
+size_t
+octave_format (std::ostream& os, const char *fmt, Args&& ... args)
+{
+  return octave::format (os, fmt, std::forward<Args> (args) ...);
+}
 
+OCTAVE_DEPRECATED (5, "use 'octave::vformat' instead")
 extern OCTINTERP_API size_t
 octave_vformat (std::ostream& os, const char *fmt, va_list args);
 
+OCTAVE_DEPRECATED (5, "use 'octave::vasprintf' instead")
 extern OCTINTERP_API std::string
 octave_vasprintf (const char *fmt, va_list args);
 
-extern OCTINTERP_API std::string octave_asprintf (const char *fmt, ...);
+template <typename ... Args>
+OCTAVE_DEPRECATED (5, "use 'octave::asprintf' instead")
+std::string
+octave_asprintf (const char *fmt, Args&& ... args)
+{
+  return octave::asprintf (fmt, std::forward<Args> (args) ...);
+}
 
-extern OCTINTERP_API void octave_sleep (double seconds);
+OCTAVE_DEPRECATED (5, "use 'octave::sleep' instead")
+extern OCTINTERP_API void
+octave_sleep (double seconds);
 
-extern OCTINTERP_API
-octave_value_list
+OCTAVE_DEPRECATED (5, "use 'octave::do_simple_cellfun' instead")
+extern OCTINTERP_API octave_value_list
 do_simple_cellfun (octave_value_list (*fun) (const octave_value_list&, int),
                    const char *fun_name, const octave_value_list& args,
                    int nargout);
 
-extern OCTINTERP_API
-octave_value
+OCTAVE_DEPRECATED (5, "use 'octave::do_simple_cellfun' instead")
+extern OCTINTERP_API octave_value
 do_simple_cellfun (octave_value_list (*fun) (const octave_value_list&, int),
                    const char *fun_name, const octave_value_list& args);
 
 #endif
+
+#endif
--- a/libinterp/corefcn/variables.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/variables.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -40,7 +40,6 @@
 #include "str-vec.h"
 
 #include "call-stack.h"
-#include "defaults.h"
 #include "Cell.h"
 #include "defun.h"
 #include "dirfns.h"
@@ -160,165 +159,6 @@
   return retval;
 }
 
-string_vector
-get_struct_elts (const std::string& text)
-{
-  int n = 1;
-
-  size_t pos = 0;
-
-  size_t len = text.length ();
-
-  while ((pos = text.find ('.', pos)) != std::string::npos)
-    {
-      if (++pos == len)
-        break;
-
-      n++;
-    }
-
-  string_vector retval (n);
-
-  pos = 0;
-
-  for (int i = 0; i < n; i++)
-    {
-      len = text.find ('.', pos);
-
-      if (len != std::string::npos)
-        len -= pos;
-
-      retval[i] = text.substr (pos, len);
-
-      if (len != std::string::npos)
-        pos += len + 1;
-    }
-
-  return retval;
-}
-
-static inline bool
-is_variable (octave::symbol_table& symtab, const std::string& name)
-{
-  bool retval = false;
-
-  if (! name.empty ())
-    {
-      octave::symbol_scope scope = symtab.current_scope ();
-
-      octave_value val = scope ? scope.varval (name) : octave_value ();
-
-      retval = val.is_defined ();
-    }
-
-  return retval;
-}
-
-string_vector
-generate_struct_completions (const std::string& text,
-                             std::string& prefix, std::string& hint)
-{
-  string_vector names;
-
-  size_t pos = text.rfind ('.');
-  bool array = false;
-
-  if (pos != std::string::npos)
-    {
-      if (pos == text.length ())
-        hint = "";
-      else
-        hint = text.substr (pos+1);
-
-      prefix = text.substr (0, pos);
-
-      if (prefix == "")
-        {
-          array = true;
-          prefix = find_indexed_expression (text);
-        }
-
-      std::string base_name = prefix;
-
-      pos = base_name.find_first_of ("{(. ");
-
-      if (pos != std::string::npos)
-        base_name = base_name.substr (0, pos);
-
-      octave::symbol_table& symtab
-        = octave::__get_symbol_table__ ("generate_struct_completions");
-
-      if (is_variable (symtab, base_name))
-        {
-          int parse_status;
-
-          octave::unwind_protect frame;
-
-          frame.protect_var (discard_error_messages);
-          frame.protect_var (discard_warning_messages);
-
-          discard_error_messages = true;
-          discard_warning_messages = true;
-
-          try
-            {
-              octave_value tmp = octave::eval_string (prefix, true, parse_status);
-
-              frame.run ();
-
-              if (tmp.is_defined ()
-                  && (tmp.isstruct () || tmp.isjava () || tmp.is_classdef_object ()))
-                names = tmp.map_keys ();
-            }
-          catch (const octave::execution_exception&)
-            {
-              octave::interpreter::recover_from_exception ();
-            }
-        }
-    }
-
-  // Undo look-back that found the array expression,
-  // but insert an extra "." to distinguish from the non-struct case.
-  if (array)
-    prefix = ".";
-
-  return names;
-}
-
-// FIXME: this will have to be much smarter to work "correctly".
-bool
-looks_like_struct (const std::string& text, char prev_char)
-{
-  bool retval = (! text.empty ()
-                 && (text != "." || prev_char == ')' || prev_char == '}')
-                 && text.find_first_of (octave::sys::file_ops::dir_sep_chars ()) == std::string::npos
-                 && text.find ("..") == std::string::npos
-                 && text.rfind ('.') != std::string::npos);
-
-#if 0
-  symbol_record *sr = curr_sym_tab->lookup (text);
-
-  if (sr && ! sr->is_function ())
-    {
-      int parse_status;
-
-      octave::unwind_protect frame;
-
-      frame.protect_var (discard_error_messages);
-
-      discard_error_messages = true;
-
-      octave_value tmp = eval_string (text, true, parse_status);
-
-      frame.run ();
-
-      retval = (tmp.is_defined () && tmp.isstruct ());
-    }
-#endif
-
-  return retval;
-}
-
 static octave_value
 do_isglobal (octave::symbol_table& symtab, const octave_value_list& args)
 {
@@ -361,6 +201,7 @@
 %!test
 %! global x;
 %! assert (isglobal ("x"), true);
+%! clear -global x;  # cleanup after test
 
 %!error isglobal ()
 %!error isglobal ("a", "b")
@@ -440,7 +281,7 @@
             }
         }
 
-      file_name = file_in_path (name, "");
+      file_name = octave::file_in_path (name, "");
 
       if (file_name.empty ())
         file_name = name;
@@ -707,13 +548,7 @@
   octave::call_stack& cs
     = octave::__get_call_stack__ ("curr_fcn_unwind_protect_frame");
 
-  octave_user_code *curr_usr_code = cs.caller_user_code ();
-
-  octave_user_function *curr_usr_fcn
-    = (curr_usr_code && curr_usr_code->is_user_function ()
-       ? dynamic_cast<octave_user_function *> (curr_usr_code) : nullptr);
-
-  return curr_usr_fcn ? curr_usr_fcn->unwind_protect_frame () : nullptr;
+  return cs.curr_fcn_unwind_protect_frame ();
 }
 
 template <typename T>
@@ -1013,7 +848,7 @@
 print_descriptor (std::ostream& os, std::list<whos_parameter> params)
 {
   // This method prints a line of information on a given symbol
-  std::list<whos_parameter>::iterator i = params.begin ();
+  auto i = params.begin ();
   std::ostringstream param_buf;
 
   octave::preserve_stream_state stream_state (os);
@@ -1154,7 +989,7 @@
     {
       std::string dims_str = get_dims_str (varval);
 
-      std::list<whos_parameter>::const_iterator i = params.begin ();
+      auto i = params.begin ();
 
       octave::preserve_stream_state stream_state (os);
 
@@ -1330,7 +1165,7 @@
     Cell nesting_info (len, 1);
     Cell persistent_info (len, 1);
 
-    std::list<symbol_info>::const_iterator p = lst.begin ();
+    auto p = lst.cbegin ();
 
     for (size_t j = 0; j < len; j++)
       {
@@ -2814,3 +2649,40 @@
 
   symtab.top_level_assign (nm, val);
 }
+
+string_vector
+get_struct_elts (const std::string& text)
+{
+  int n = 1;
+
+  size_t pos = 0;
+
+  size_t len = text.length ();
+
+  while ((pos = text.find ('.', pos)) != std::string::npos)
+    {
+      if (++pos == len)
+        break;
+
+      n++;
+    }
+
+  string_vector retval (n);
+
+  pos = 0;
+
+  for (int i = 0; i < n; i++)
+    {
+      len = text.find ('.', pos);
+
+      if (len != std::string::npos)
+        len -= pos;
+
+      retval[i] = text.substr (pos, len);
+
+      if (len != std::string::npos)
+        pos += len + 1;
+    }
+
+  return retval;
+}
--- a/libinterp/corefcn/variables.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/variables.h	Fri Aug 10 09:09:51 2018 +0200
@@ -58,16 +58,6 @@
                   const std::string& fname, const std::string& header,
                   const std::string& trailer);
 
-extern OCTINTERP_API string_vector
-get_struct_elts (const std::string& text);
-
-extern OCTINTERP_API string_vector
-generate_struct_completions (const std::string& text, std::string& prefix,
-                             std::string& hint);
-
-extern OCTINTERP_API bool
-looks_like_struct (const std::string& text, char prev_char);
-
 extern OCTINTERP_API int
 symbol_exist (const std::string& name, const std::string& type = "any");
 
@@ -165,4 +155,8 @@
 extern OCTINTERP_API void
 set_top_level_value (const std::string& nm, const octave_value& val);
 
+OCTAVE_DEPRECATED (5, "this function will be removed in a future version of Octave")
+extern OCTINTERP_API string_vector
+get_struct_elts (const std::string& text);
+
 #endif
--- a/libinterp/corefcn/zfstream.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/corefcn/zfstream.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -34,7 +34,9 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <iomanip>
+#include <istream>
+#include <ostream>
 
 #include "zfstream.h"
 
--- a/libinterp/dldfcn/__eigs__.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/dldfcn/__eigs__.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -182,6 +182,7 @@
   bool sym_tested = false;
   bool cholB = false;
   bool a_is_sparse = false;
+  bool b_is_sparse = false;
   ColumnVector permB;
   int arg_offset = 0;
   double tol = std::numeric_limits<double>::epsilon ();
@@ -265,6 +266,13 @@
       if (args(1+arg_offset).iscomplex ())
         {
           b_arg = 1+arg_offset;
+          if (args(b_arg).issparse ())
+            {
+              bscm = (args(b_arg).sparse_complex_matrix_value ());
+              b_is_sparse = true;
+            }
+          else
+            bcm = (args(b_arg).complex_matrix_value ());
           have_b = true;
           b_is_complex = true;
           arg_offset++;
@@ -272,6 +280,13 @@
       else
         {
           b_arg = 1+arg_offset;
+          if (args(b_arg).issparse ())
+            {
+              bsmm = (args(b_arg).sparse_matrix_value ());
+              b_is_sparse = true;
+            }
+          else
+            bmm = (args(b_arg).matrix_value ());
           have_b = true;
           arg_offset++;
         }
@@ -374,14 +389,14 @@
     {
       if (a_is_complex || b_is_complex)
         {
-          if (a_is_sparse)
+          if (b_is_sparse)
             bscm = args(b_arg).sparse_complex_matrix_value ();
           else
             bcm = args(b_arg).complex_matrix_value ();
         }
       else
         {
-          if (a_is_sparse)
+          if (b_is_sparse)
             bsmm = args(b_arg).sparse_matrix_value ();
           else
             bmm = args(b_arg).matrix_value ();
@@ -400,10 +415,18 @@
       ComplexColumnVector eig_val;
 
       if (have_a_fun)
-        nconv = EigsComplexNonSymmetricFunc
-                (eigs_complex_func, n, typ, sigma, k, p, info, eig_vec,
-                 eig_val, cresid, octave_stdout, tol, (nargout > 1), cholB,
-                 disp, maxit);
+        {
+          if (b_is_sparse)
+            nconv = EigsComplexNonSymmetricFunc
+              (eigs_complex_func, n, typ, sigma, k, p, info, eig_vec,
+               eig_val, bscm, permB, cresid, octave_stdout, tol,
+               (nargout > 1), cholB, disp, maxit);
+          else
+            nconv = EigsComplexNonSymmetricFunc
+              (eigs_complex_func, n, typ, sigma, k, p, info, eig_vec,
+               eig_val, bcm, permB, cresid, octave_stdout, tol,
+               (nargout > 1), cholB, disp, maxit);
+        }
       else if (have_sigma)
         {
           if (a_is_sparse)
@@ -443,10 +466,18 @@
       ComplexColumnVector eig_val;
 
       if (have_a_fun)
-        nconv = EigsComplexNonSymmetricFunc
-                (eigs_complex_func, n, typ,  sigma, k, p, info, eig_vec,
-                 eig_val, cresid, octave_stdout, tol, (nargout > 1), cholB,
-                 disp, maxit);
+        {
+          if (b_is_sparse)
+            nconv = EigsComplexNonSymmetricFunc
+              (eigs_complex_func, n, typ, sigma, k, p, info, eig_vec,
+               eig_val, bscm, permB, cresid, octave_stdout, tol,
+               (nargout > 1), cholB, disp, maxit);
+          else
+            nconv = EigsComplexNonSymmetricFunc
+              (eigs_complex_func, n, typ, sigma, k, p, info, eig_vec,
+               eig_val, bcm, permB, cresid, octave_stdout, tol,
+               (nargout > 1), cholB, disp, maxit);
+        }
       else
         {
           if (a_is_sparse)
@@ -474,10 +505,18 @@
           ColumnVector eig_val;
 
           if (have_a_fun)
-            nconv = EigsRealSymmetricFunc
-                    (eigs_func, n, typ, sigmar, k, p, info, eig_vec,
-                     eig_val, resid, octave_stdout, tol, (nargout > 1),
-                     cholB, disp, maxit);
+            {
+              if (b_is_sparse)
+                nconv = EigsRealSymmetricFunc
+                       (eigs_func, n, typ, sigmar, k, p, info, eig_vec,
+                        eig_val, bsmm, permB, resid, octave_stdout, tol,
+                        (nargout > 1), cholB, disp, maxit);
+              else
+                nconv = EigsRealSymmetricFunc
+                       (eigs_func, n, typ, sigmar, k, p, info, eig_vec,
+                        eig_val, bmm, permB, resid, octave_stdout, tol,
+                        (nargout > 1), cholB, disp, maxit);
+            }
           else if (have_sigma)
             {
               if (a_is_sparse)
@@ -516,10 +555,18 @@
           ComplexColumnVector eig_val;
 
           if (have_a_fun)
-            nconv = EigsRealNonSymmetricFunc
-                    (eigs_func, n, typ, sigmar, k, p, info, eig_vec,
-                     eig_val, resid, octave_stdout, tol, (nargout > 1),
-                     cholB, disp, maxit);
+            {
+              if (b_is_sparse)
+                nconv = EigsRealNonSymmetricFunc
+                        (eigs_func, n, typ, sigmar, k, p, info, eig_vec,
+                         eig_val, bsmm, permB, resid, octave_stdout, tol,
+                         (nargout > 1), cholB, disp, maxit);
+              else
+                nconv = EigsRealNonSymmetricFunc
+                        (eigs_func, n, typ, sigmar, k, p, info, eig_vec,
+                         eig_val, bmm, permB, resid, octave_stdout, tol,
+                         (nargout > 1), cholB, disp, maxit);
+            }
           else if (have_sigma)
             {
               if (a_is_sparse)
--- a/libinterp/dldfcn/__init_fltk__.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/dldfcn/__init_fltk__.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -2441,7 +2441,7 @@
 
         octave_value_list args = input_event_hook_fcn_id;
         args.append (false);
-        Fremove_input_event_hook (args, 0);
+        Fremove_input_event_hook (m_interpreter, args, 0);
         input_event_hook_fcn_id = octave_value_list ();
 
         figure_manager::close_all ();
@@ -2504,7 +2504,7 @@
 
       octave_value fcn (new octave_builtin (F__fltk_check__));
       octave_value fcn_handle (new octave_fcn_handle (fcn, "@__fltk_check__"));
-      octave_value_list id = Fadd_input_event_hook (fcn_handle, 1);
+      octave_value_list id = Fadd_input_event_hook (interp, fcn_handle, 1);
 
       fltk->set_input_event_hook_id (id);
     }
--- a/libinterp/dldfcn/__init_gnuplot__.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/dldfcn/__init_gnuplot__.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -189,7 +189,7 @@
           std::string gnuplot_binary = tmp(0).string_value ();
 
           string_vector args (gnuplot_binary);
-          std::string gnuplot_path = search_path_for_file (path, args);
+          std::string gnuplot_path = octave::search_path_for_file (path, args);
 
           octave::sys::file_stat fs (gnuplot_path);
 
@@ -197,7 +197,7 @@
             {
               args[0] += exeext;
 
-              gnuplot_path = search_path_for_file (path, args);
+              gnuplot_path = octave::search_path_for_file (path, args);
 
               fs = octave::sys::file_stat (gnuplot_path);
             }
--- a/libinterp/dldfcn/__ode15__.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/dldfcn/__ode15__.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -24,6 +24,8 @@
 #  include "config.h"
 #endif
 
+#include <iostream>
+
 #include "dColVector.h"
 #include "dMatrix.h"
 #include "dSparse.h"
--- a/libinterp/dldfcn/__osmesa_print__.cc	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,257 +0,0 @@
-/*
-
-Copyright (C) 2016-2018 Andreas Weber <andy.weber.aw@gmail.com>
-
-This file is part of Octave.
-
-Octave is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-Octave is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<https://www.gnu.org/licenses/>.
-
-This code is based on Brian Pauls' src/osdemos/osdemo.c
-from git://anongit.freedesktop.org/mesa/demos
-
-*/
-
-#if defined (HAVE_CONFIG_H)
-#  include "config.h"
-#endif
-
-#if defined (HAVE_OSMESA_H)
-#  include <osmesa.h>
-#elif defined (HAVE_GL_OSMESA_H)
-#  include <GL/osmesa.h>
-#endif
-
-#include <string>
-
-#include "Array.h"
-#include "dMatrix.h"
-#include "oct-locbuf.h"
-#include "uint8NDArray.h"
-#include "unwind-prot.h"
-
-#include "defun-dld.h"
-#include "error.h"
-#include "errwarn.h"
-#include "gl-render.h"
-#include "gl2ps-print.h"
-#include "graphics.h"
-#include "oct-opengl.h"
-#include "ov.h"
-#include "ovl.h"
-
-#if defined (HAVE_OSMESA)
-
-static void
-reset_visibility (figure::properties *fp)
-{
-  fp->set_visible ("on");
-}
-
-#endif
-
-DEFUN_DLD(__osmesa_print__, args, ,
-          doc: /* -*- texinfo -*-
-@deftypefn  {} {} __osmesa_print__ (@var{h}, @var{file}, @var{term})
-@deftypefnx {} {@var{img} =} __osmesa_print__ (@var{h})
-Print figure @var{h} using OSMesa and gl2ps for vector formats.
-
-This is a private internal function.
-
-The first method calls gl2ps with the appropriate @var{term} and writes
-the output of gl2ps to @var{file}.  If the first character of @var{file}
-is @code{|}, then a process is started and the output of gl2ps is piped
-to it.
-
-Valid options for @var{term}, which can be concatenated in one string, are:
-
-@table @asis
-@item @qcode{eps}, @qcode{pdf}, @qcode{ps}, @qcode{svg}, @qcode{pgf}, @qcode{tex}
-Select output format.
-
-@item @code{is2D}
-Use GL2PS_SIMPLE_SORT instead of GL2PS_BSP_SORT as Z-depth sorting
-algorithm.
-
-@item @code{notext}
-Don't render text.
-@end table
-
-The second method doesn't use gl2ps and returns a RGB image in @var{img}
-instead.
-
-@end deftypefn */)
-{
-#if defined (HAVE_OSMESA)
-
-  int nargin = args.length ();
-
-  if (nargin != 1 && nargin != 3)
-    print_usage ();
-
-  if (nargin == 3)
-    {
-      if (! (args(1).is_string () && args(2).is_string ()))
-        error ("__osmesa_print__: FILE and TERM must be strings");
-    }
-
-  octave_value_list retval;
-
-  int h = args(0).double_value ();
-  graphics_object fobj = gh_manager::get_object (h);
-  if (! (fobj && fobj.isa ("figure")))
-    error ("__osmesa_print__: H must be a valid figure handle");
-
-  figure::properties& fp =
-    dynamic_cast<figure::properties&> (fobj.get_properties ());
-
-  bool internal = true;
-  Matrix bb = fp.get_boundingbox (internal);
-
-  GLsizei Width = static_cast<GLsizei> (bb(2));
-  GLsizei Height = static_cast<GLsizei> (bb(3));
-
-  // Create an RGBA-mode context, specify Z=16, stencil=0, accum=0 sizes
-  OSMesaContext ctx = OSMesaCreateContextExt (OSMESA_RGBA, 16, 0, 0, nullptr);
-  if (! ctx)
-    error ("__osmesa_print__: OSMesaCreateContext failed!\n");
-
-  // Allocate the image buffer
-  OCTAVE_LOCAL_BUFFER (GLubyte, buffer, 4 * Width * Height);
-
-  // Bind the buffer to the context and make it current
-  if (! OSMesaMakeCurrent (ctx, buffer, GL_UNSIGNED_BYTE, Width, Height))
-    error ("__osmesa_print__: OSMesaMakeCurrent failed!\n");
-
-  // Test for a bug in OSMesa with version < 9.0
-  //
-  // Unfortunately the macros OSMESA_MAJOR_VERSION and OSMESA_MINOR_VERSION
-  // weren't updated between many releases and can't be used for detection.
-  // (Version 8.0 until 9.1.4 all return MAJOR 6, MINOR 5)
-  GLint z, s;
-  glGetIntegerv (GL_DEPTH_BITS, &z);
-  glGetIntegerv (GL_STENCIL_BITS, &s);
-  if (z != 16 || s != 0)
-    error ("__osmesa_print__: Depth and stencil doesn't match,"
-           " are you sure you are using OSMesa >= 9.0?");
-
-  octave::unwind_protect outer_frame;
-
-  bool v = fp.is_visible ();
-
-  if (v)
-    {
-      outer_frame.add_fcn (reset_visibility, &fp);
-
-      fp.set_visible ("off");
-    }
-
-  if (nargin == 3)
-    {
-      std::string file = args(1).string_value ();
-      std::string term = args(2).string_value ();
-
-      octave::gl2ps_print (fobj, file, term);
-    }
-  else
-    {
-      // return RGB image
-      octave::opengl_renderer rend;
-
-      // Draw and finish () or there may primitives missing in the
-      // output.
-      rend.draw (fobj);
-      rend.finish ();
-
-      dim_vector dv (4, Width, Height);
-
-      // FIXME: We expect that GLubyte is 1 Byte long.
-      // Adapt code if this isn't always true
-      assert (sizeof (GLubyte) == 1);
-      uint8NDArray img (dv);
-      unsigned char *p = reinterpret_cast<unsigned char *>(img.fortran_vec ());
-      memcpy (p, buffer, (4 * Width * Height));
-
-      Array<octave_idx_type> perm (dim_vector (3, 1));
-      perm(0) = 2;
-      perm(1) = 1;
-      perm(2) = 0;
-
-      Array<idx_vector> idx (dim_vector (3, 1));
-
-      // Flip Y
-      idx(0) = idx_vector::make_range (Height - 1, -1, Height);
-      idx(1) = idx_vector::colon;
-
-      // Remove alpha channel
-      idx(2) = idx_vector (0, 3);
-      retval(0) = octave_value (img.permute (perm).index(idx));
-    }
-
-  OSMesaDestroyContext (ctx);
-
-  return retval;
-
-#else
-
-  octave_unused_parameter (args);
-
-  err_disabled_feature ("__osmesa_print__", "offscreen rendering with OSMesa");
-
-#endif
-}
-
-/*
-## FIXME: osmesa does not work correctly on Windows platforms.
-##        This is not critical, since this facility will mostly be used in
-##        the future for generating the images in Octave's own documentation.
-##        For the moment, disable these tests on PC's and Macs.
-%!testif HAVE_OPENGL, HAVE_OSMESA, HAVE_GL2PS_H
-%! if (isunix ())
-%!   hf = figure ("visible", "off");
-%!   fn = tempname ();
-%!   unwind_protect
-%!     sombrero ();
-%!     __osmesa_print__ (hf, fn, "svg");
-%!     assert (stat (fn).size > 2e6);
-%!     img = __osmesa_print__ (hf);
-%!     assert (size (img), [get(hf, "position")([4, 3]), 3]);
-%!     ## Use pixel sum per RGB channel as fingerprint
-%!     img_fp = squeeze (sum (sum (img), 2));
-%!     assert (img_fp, [52942515; 54167797; 56158178], -0.05);
-%!   unwind_protect_cleanup
-%!     close (hf);
-%!     unlink (fn);
-%!   end_unwind_protect
-%! endif
-
-%!testif HAVE_OPENGL, HAVE_OSMESA, HAVE_GL2PS_H
-%! if (isunix ())
-%!   hf = figure ("visible", "off");
-%!   fn = tempname ();
-%!   unwind_protect
-%!     plot (sin (0:0.1:2*pi));
-%!     __osmesa_print__ (hf, fn, "svgis2d");
-%!     assert (stat (fn).size, 9022, -0.20);
-%!     img = __osmesa_print__ (hf);
-%!     assert (size (img), [get(hf, "position")([4, 3]), 3]);
-%!     ## Use pixel sum per RGB channel as fingerprint
-%!     img_fp = squeeze (sum (sum (img), 2));
-%!     assert (img_fp, [59281711; 59281711; 59482179], -0.05);
-%!   unwind_protect_cleanup
-%!     close (hf);
-%!     unlink (fn);
-%!   end_unwind_protect
-%! endif
-*/
--- a/libinterp/dldfcn/audioread.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/dldfcn/audioread.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -167,6 +167,9 @@
             case SF_FORMAT_PCM_32:
               ret_audio = int32NDArray (audio * 2147483648);
               break;
+            case SF_FORMAT_FLOAT:
+              ret_audio = FloatNDArray (audio);
+              break;
             default:
               ret_audio = audio;
               break;
@@ -374,7 +377,12 @@
           else if (bits == 16)
             info.format |= SF_FORMAT_PCM_16;
           else if (bits == 24)
-            info.format |= SF_FORMAT_PCM_32;
+            {
+              if ((info.format & SF_FORMAT_TYPEMASK) == SF_FORMAT_WAV)
+                info.format |= SF_FORMAT_PCM_32;
+              else
+                info.format |= SF_FORMAT_PCM_24;
+            }
           else if (bits == 32)
             {
               if ((info.format & SF_FORMAT_TYPEMASK) == SF_FORMAT_WAV
@@ -584,6 +592,12 @@
     case SF_FORMAT_PCM_32:
       bits = 32;
       break;
+    case SF_FORMAT_FLOAT:
+      bits = 32;
+      break;
+    case SF_FORMAT_DOUBLE:
+      bits = 64;
+      break;
     default:
       bits = -1;
       break;
--- a/libinterp/dldfcn/ccolamd.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/dldfcn/ccolamd.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -509,7 +509,7 @@
       OCTAVE_LOCAL_BUFFER (octave::suitesparse_integer, cmember, cslen);
       for (octave_idx_type i = 0; i < cslen; i++)
         // convert cmember from 1-based to 0-based
-        cmember[i] = static_cast<octave_idx_type>(in_cmember(i) - 1);
+        cmember[i] = static_cast<octave_idx_type> (in_cmember(i) - 1);
 
       if (cslen != n_col)
         error ("csymamd: CMEMBER must be of length equal to #cols of A");
--- a/libinterp/dldfcn/config-module.awk	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/dldfcn/config-module.awk	Fri Aug 10 09:09:51 2018 +0200
@@ -76,14 +76,12 @@
         printf ("%%canon_reldir%%_%s_la_CPPFLAGS = $(libinterp_liboctinterp_la_CPPFLAGS) %s\n",
                 basename, cppflags[i]);
       }
-    printf ("%%canon_reldir%%_%s_la_CFLAGS = $(libinterp_liboctinterp_la_CFLAGS) %s\n",
-            basename, cppflags[i]);
-    printf ("%%canon_reldir%%_%s_la_CXXFLAGS = $(libinterp_liboctinterp_la_CXXFLAGS) %s\n",
-            basename, cppflags[i]);
     printf ("%%canon_reldir%%_%s_la_LDFLAGS = -avoid-version -module $(NO_UNDEFINED_LDFLAG) %s $(OCT_LINK_OPTS) $(WARN_LDFLAGS)\n",
             basename, ldflags[i]);
-    printf ("%%canon_reldir%%_%s_la_LIBADD = $(DLD_LIBOCTINTERP_LIBADD) liboctave/liboctave.la %s $(OCT_LINK_DEPS)\n",
+    printf ("%%canon_reldir%%_%s_la_LIBADD = $(DLD_LIBOCTINTERP_LIBADD) %s\n",
             basename, libraries[i]);
+    printf ("%%canon_reldir%%_%s_la_DEPENDENCIES = $(OCT_LINK_DEPS)\n",
+            basename);
   }
 
   print "";
--- a/libinterp/dldfcn/convhulln.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/dldfcn/convhulln.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -33,7 +33,6 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
 #include <limits>
 #include <string>
 
--- a/libinterp/dldfcn/dmperm.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/dldfcn/dmperm.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -91,7 +91,7 @@
           for (octave_idx_type i = 0; i < nc; i++)
             if (jmatch[nr+i] >= 0)
               r++;
-          retval(0) = static_cast<double>(r);
+          retval(0) = static_cast<double> (r);
         }
       else
         retval(0) = put_int (jmatch + nr, nc);
--- a/libinterp/dldfcn/gzip.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/dldfcn/gzip.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -61,6 +61,7 @@
 #include "file-ops.h"
 #include "file-stat.h"
 #include "glob-match.h"
+#include "lo-sysdep.h"
 #include "oct-env.h"
 #include "str-vec.h"
 
@@ -97,7 +98,7 @@
     CFile (void) = delete;
 
     CFile (const std::string& path, const std::string& mode)
-      : m_fp (std::fopen (path.c_str (), mode.c_str ()))
+      : m_fp (octave::sys::fopen (path, mode))
     {
       if (! m_fp)
         throw std::runtime_error ("unable to open file");
@@ -483,13 +484,14 @@
       // is_dir and is_reg will return false if failed to stat.
       if (fs.is_dir ())
         {
-          sys::dir_entry dir (path);
-          if (dir)
+          string_vector dirlist;
+          std::string msg;
+
+          // Collect the whole list of filenames first, before recursion
+          // to avoid issues with infinite loop if the action generates
+          // files in the same directory (highly likely).
+          if (sys::get_dirlist (path, dirlist, msg))
             {
-              // Collect the whole list of filenames first, before recursion
-              // to avoid issues with infinite loop if the action generates
-              // files in the same directory (highly likely).
-              string_vector dirlist = dir.read ();
               for (octave_idx_type i = 0; i < dirlist.numel (); i++)
                 if (dirlist(i) != "." && dirlist(i) != "..")
                   walk (sys::file_ops::concat (path, dirlist(i)));
--- a/libinterp/dldfcn/module-files	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/dldfcn/module-files	Fri Aug 10 09:09:51 2018 +0200
@@ -6,7 +6,6 @@
 __init_fltk__.cc|$(FLTK_CPPFLAGS) $(FT2_CPPFLAGS) $(FONTCONFIG_CPPFLAGS)|$(FLTK_LDFLAGS) $(FT2_LDFLAGS)|$(FLTK_LIBS) $(FT2_LIBS) $(OPENGL_LIBS)
 __init_gnuplot__.cc|$(FT2_CPPFLAGS) $(FONTCONFIG_CPPFLAGS)||
 __ode15__.cc|$(SUNDIALS_XCPPFLAGS)|$(SUNDIALS_XLDFLAGS)|$(SUNDIALS_XLIBS)
-__osmesa_print__.cc|$(OSMESA_CPPFLAGS) $(FT2_CPPFLAGS)|$(OSMESA_LDFLAGS)|$(OSMESA_LIBS)
 __voronoi__.cc|$(QHULL_CPPFLAGS)|$(QHULL_LDFLAGS)|$(QHULL_LIBS)
 amd.cc|$(SPARSE_XCPPFLAGS)|$(SPARSE_XLDFLAGS)|$(SPARSE_XLIBS)
 audiodevinfo.cc|$(PORTAUDIO_CPPFLAGS)|$(PORTAUDIO_LDFLAGS)|$(PORTAUDIO_LIBS)
--- a/libinterp/mk-builtins.pl	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/mk-builtins.pl	Fri Aug 10 09:09:51 2018 +0200
@@ -169,7 +169,7 @@
     }
 
     ($fcn = $arg) =~ s,.*/,,;
-    $fcn =~ s/\.(cc|cpp|in\.cc|in\.yy|ll)$//;
+    $fcn =~ s/\.(cc|cpp|in\.cc|yy|ll)$//;
     $fcn =~ s/-/_/g;
     $fcn = "install_${fcn}_fcns";
 
--- a/libinterp/mk-version-h.in.sh	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-#! /bin/sh
-#
-# Copyright (C) 2016-2018 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
-# <https://www.gnu.org/licenses/>.
-
-: ${SED=@SED@}
-
-OCTAVE_API_VERSION="@OCTAVE_API_VERSION@"
-OCTAVE_COPYRIGHT="@OCTAVE_COPYRIGHT@"
-OCTAVE_MAJOR_VERSION="@OCTAVE_MAJOR_VERSION@"
-OCTAVE_MINOR_VERSION="@OCTAVE_MINOR_VERSION@"
-OCTAVE_PATCH_VERSION="@OCTAVE_PATCH_VERSION@"
-OCTAVE_RELEASE_DATE="@OCTAVE_RELEASE_DATE@"
-OCTAVE_VERSION="@OCTAVE_VERSION@"
-
-$SED \
-  -e "s|%NO_EDIT_WARNING%|DO NOT EDIT!  Generated automatically by mk-version-h.|" \
-  -e "s|%OCTAVE_API_VERSION%|\"${OCTAVE_API_VERSION}\"|" \
-  -e "s|%OCTAVE_COPYRIGHT%|\"${OCTAVE_COPYRIGHT}\"|" \
-  -e "s|%OCTAVE_MAJOR_VERSION%|${OCTAVE_MAJOR_VERSION}|" \
-  -e "s|%OCTAVE_MINOR_VERSION%|${OCTAVE_MINOR_VERSION}|" \
-  -e "s|%OCTAVE_PATCH_VERSION%|${OCTAVE_PATCH_VERSION}|" \
-  -e "s|%OCTAVE_RELEASE_DATE%|\"${OCTAVE_RELEASE_DATE}\"|" \
-  -e "s|%OCTAVE_VERSION%|\"${OCTAVE_VERSION}\"|"
--- a/libinterp/module.mk	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/module.mk	Fri Aug 10 09:09:51 2018 +0200
@@ -22,11 +22,9 @@
   $(HDF5_CPPFLAGS) \
   $(MAGICK_CPPFLAGS)
 
-%canon_reldir%_liboctinterp_la_CFLAGS = $(AM_CFLAGS) $(WARN_CFLAGS)
+octlib_LTLIBRARIES += %reldir%/liboctinterp.la
 
-%canon_reldir%_liboctinterp_la_CXXFLAGS = $(AM_CXXFLAGS) $(WARN_CXXFLAGS)
-
-octlib_LTLIBRARIES += %reldir%/liboctinterp.la
+%canon_reldir%_pkgconfig_DATA = %reldir%/octinterp.pc
 
 BUILT_SOURCES += \
   %reldir%/builtin-defun-decls.h \
@@ -37,19 +35,15 @@
   %reldir%/corefcn/oct-tex-parser.h \
   %reldir%/corefcn/oct-tex-symbols.cc \
   %reldir%/parse-tree/oct-gperf.h \
-  %reldir%/parse-tree/oct-parse.h \
-  %reldir%/version.h
+  %reldir%/parse-tree/oct-parse.h
 
 ULT_PARSER_SRC := \
-  %reldir%/corefcn/oct-tex-lexer.in.ll \
-  %reldir%/corefcn/oct-tex-parser.in.yy \
-  %reldir%/parse-tree/oct-parse.in.yy
+  %reldir%/corefcn/oct-tex-lexer.in.ll
 
 GENERATED_PARSER_FILES := \
   %reldir%/corefcn/oct-tex-lexer.ll \
   %reldir%/corefcn/oct-tex-parser.h \
-  %reldir%/corefcn/oct-tex-parser.yy \
-  %reldir%/parse-tree/oct-parse.yy
+  %reldir%/parse-tree/oct-parse.h
 
 ## These generated files are included in the source distribution to
 ## avoid needing certain tools to build from a distribution tarball.
@@ -57,10 +51,8 @@
 LIBINTERP_BUILT_DISTFILES = \
   $(GENERATED_PARSER_FILES) \
   $(OPT_HANDLERS) \
-  %reldir%/corefcn/oct-tex-parser.h \
   %reldir%/corefcn/oct-tex-symbols.cc \
-  %reldir%/parse-tree/oct-gperf.h \
-  %reldir%/parse-tree/oct-parse.h
+  %reldir%/parse-tree/oct-gperf.h
 
 ## Files that are created during build process and installed,
 ## BUT not distributed in tarball.
@@ -75,8 +67,7 @@
   %reldir%/corefcn/mxarray.h \
   %reldir%/corefcn/oct-errno.cc \
   %reldir%/liboctinterp-build-info.cc \
-  %reldir%/operators/ops.cc \
-  %reldir%/version.h
+  %reldir%/operators/ops.cc
 
 %canon_reldir%_EXTRA_DIST += \
   %reldir%/DOCSTRINGS \
@@ -86,14 +77,9 @@
   %reldir%/mk-builtins.pl \
   %reldir%/mk-doc.pl \
   %reldir%/mk-pkg-add.sh \
-  %reldir%/mk-version-h.in.sh \
   %reldir%/op-kw-docs \
-  %reldir%/version.in.h \
   $(LIBINTERP_BUILT_DISTFILES)
 
-GEN_CONFIG_SHELL += \
-  %reldir%/mk-version-h.sh
-
 octinclude_HEADERS += \
   %reldir%/build-env.h \
   %reldir%/liboctinterp-build-info.h \
@@ -112,12 +98,10 @@
   %reldir%/builtin-defun-decls.h \
   %reldir%/corefcn/graphics-props.cc \
   %reldir%/corefcn/graphics.h \
-  %reldir%/corefcn/mxarray.h \
-  %reldir%/version.h
+  %reldir%/corefcn/mxarray.h
 
 DIST_SRC += \
   %reldir%/octave.cc \
-  %reldir%/version.cc \
   $(OCTAVE_VALUE_SRC) \
   $(PARSE_TREE_SRC) \
   $(COREFCN_SRC)
@@ -131,7 +115,7 @@
 
 if AMCOND_ENABLE_DYNAMIC_LINKING
   OCT_FILES = $(DLDFCN_LIBS:.la=.oct)
-  DLD_LIBOCTINTERP_LIBADD = %reldir%/liboctinterp.la
+  DLD_LIBOCTINTERP_LIBADD = $(OCT_LINK_DEPS)
   LIBINTERP_DLDFCN_LIBADD =
 else
   OCT_FILES =
@@ -141,7 +125,6 @@
 
 %canon_reldir%_liboctinterp_la_SOURCES = \
   %reldir%/octave.cc \
-  %reldir%/version.cc \
   $(LIBINTERP_OPERATORS_SRC) \
   $(TEMPLATE_INST_SRC)
 
@@ -155,8 +138,7 @@
   %reldir%/corefcn/mxarray.h \
   %reldir%/corefcn/oct-errno.cc \
   %reldir%/liboctinterp-build-info.cc \
-  %reldir%/operators/ops.cc \
-  %reldir%/version.h
+  %reldir%/operators/ops.cc
 
 %canon_reldir%_liboctinterp_la_LIBADD = \
   %reldir%/octave-value/liboctave-value.la \
@@ -171,7 +153,9 @@
     liboctave/external/blas-xtra/libxerbla.la
 endif
 
-# Increment these as needed and according to the rules in the libtool manual:
+## Increment the following version numbers as needed and according
+## to the rules in the etc/HACKING.md file:
+
 %canon_reldir%_liboctinterp_current = 5
 %canon_reldir%_liboctinterp_revision = 0
 %canon_reldir%_liboctinterp_age = 0
@@ -243,9 +227,6 @@
 	$(SHELL) $(srcdir)/%reldir%/mk-build-env-features.sh $< > $@-t && \
 	mv $@-t $@
 
-%reldir%/version.h: %reldir%/version.in.h %reldir%/mk-version-h.sh | %reldir%/$(octave_dirstamp)
-	$(AM_V_GEN)$(call simple-filter-rule,%reldir%/mk-version-h.sh)
-
 %reldir%/liboctinterp-build-info.cc: %reldir%/liboctinterp-build-info.in.cc HG-ID | %reldir%/$(octave_dirstamp)
 	$(AM_V_GEN)$(build-info-commands)
 
@@ -331,6 +312,8 @@
 	rm -f $(DESTDIR)$(octetcdir)/built-in-docstrings
 .PHONY: uninstall-built-in-docstrings
 
+pkgconfig_DATA += $(%canon_reldir%_pkgconfig_DATA)
+
 EXTRA_DIST += $(%canon_reldir%_EXTRA_DIST)
 
 %canon_reldir%_CLEANFILES += \
@@ -341,6 +324,9 @@
   %reldir%/corefcn/oct-tex-parser.output \
   %reldir%/parse-tree/oct-parse.output
 
+%canon_reldir%_DISTCLEANFILES += \
+  $(%canon_reldir%_pkgconfig_DATA)
+
 %canon_reldir%_MAINTAINERCLEANFILES += \
   %reldir%/DOCSTRINGS \
   $(LIBINTERP_BUILT_DISTFILES)
--- a/libinterp/octave-value/module.mk	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/module.mk	Fri Aug 10 09:09:51 2018 +0200
@@ -146,8 +146,4 @@
   $(HDF5_CPPFLAGS) \
   $(JAVA_CPPFLAGS)
 
-%canon_reldir%_liboctave_value_la_CFLAGS = $(AM_CFLAGS) $(WARN_CFLAGS)
-
-%canon_reldir%_liboctave_value_la_CXXFLAGS = $(AM_CXXFLAGS) $(WARN_CXXFLAGS)
-
 %canon_reldir%_liboctave_value_la_LIBADD = $(JAVA_LIBS)
--- a/libinterp/octave-value/ov-base-diag.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-base-diag.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -24,7 +24,9 @@
 // C++ source files that should have included config.h before including
 // this file.
 
-#include <iostream>
+#include <istream>
+#include <ostream>
+#include <sstream>
 
 #include "mach-info.h"
 #include "lo-ieee.h"
--- a/libinterp/octave-value/ov-base-diag.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-base-diag.h	Fri Aug 10 09:09:51 2018 +0200
@@ -80,7 +80,7 @@
 
   dim_vector dims (void) const { return matrix.dims (); }
 
-  octave_idx_type nnz (void) const { return to_dense ().nnz (); }
+  octave_idx_type nnz (void) const { return diag ().nnz (); }
 
   octave_value reshape (const dim_vector& new_dims) const
   { return to_dense ().reshape (new_dims); }
--- a/libinterp/octave-value/ov-base-int.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-base-int.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -24,8 +24,10 @@
 // C++ source files that should have included config.h before including
 // this file.
 
-#include <iostream>
+#include <istream>
 #include <limits>
+#include <ostream>
+#include <sstream>
 #include <vector>
 
 #include "dNDArray.h"
--- a/libinterp/octave-value/ov-base-mat.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-base-mat.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -25,7 +25,8 @@
 // C++ source files that should have included config.h before including
 // this file.
 
-#include <iostream>
+#include <ostream>
+#include <sstream>
 
 #include "Array-util.h"
 
--- a/libinterp/octave-value/ov-base-scalar.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-base-scalar.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -24,7 +24,8 @@
 // C++ source files that should have included config.h before including
 // this file.
 
-#include <iostream>
+#include <ostream>
+#include <sstream>
 
 #include "oct-inttypes.h"
 
--- a/libinterp/octave-value/ov-base-sparse.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-base-sparse.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -27,7 +27,9 @@
 // this file.
 
 #include <iomanip>
-#include <iostream>
+#include <istream>
+#include <ostream>
+#include <sstream>
 
 #include "ovl.h"
 #include "ov-base.h"
--- a/libinterp/octave-value/ov-base.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-base.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -25,8 +25,9 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <istream>
 #include <limits>
+#include <ostream>
 
 #include "lo-ieee.h"
 #include "lo-mappers.h"
@@ -192,7 +193,7 @@
 octave_idx_type
 octave_base_value::numel (const octave_value_list& idx)
 {
-  return dims_to_numel (dims (), idx);
+  return octave::dims_to_numel (dims (), idx);
 }
 
 octave_value
@@ -1410,7 +1411,7 @@
   Cell type_field (1, len);
   Cell subs_field (1, len);
 
-  std::list<octave_value_list>::const_iterator p = idx.begin ();
+  auto p = idx.begin ();
 
   for (size_t i = 0; i < len; i++)
     {
--- a/libinterp/octave-value/ov-bool-mat.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-bool-mat.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -25,7 +25,8 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <istream>
+#include <ostream>
 #include <vector>
 
 #include "dNDArray.h"
--- a/libinterp/octave-value/ov-bool-mat.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-bool-mat.h	Fri Aug 10 09:09:51 2018 +0200
@@ -169,7 +169,7 @@
     octave_idx_type nel = numel ();
 
     for (octave_idx_type i = 0; i < nel; i++)
-      retval(i) = static_cast<char>(matrix(i));
+      retval(i) = static_cast<char> (matrix(i));
 
     return retval;
   }
--- a/libinterp/octave-value/ov-bool-sparse.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-bool-sparse.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -25,8 +25,8 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
-#include <limits>
+#include <istream>
+#include <ostream>
 #include <vector>
 
 #include "dim-vector.h"
@@ -166,7 +166,7 @@
 
   for (octave_idx_type j = 0; j < nc; j++)
     for (octave_idx_type i = matrix.cidx (j); i < matrix.cidx (j+1); i++)
-      retval(matrix.ridx (i) + nr * j) = static_cast<char>(matrix.data (i));
+      retval(matrix.ridx (i) + nr * j) = static_cast<char> (matrix.data (i));
 
   return retval;
 }
--- a/libinterp/octave-value/ov-bool.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-bool.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -24,7 +24,8 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <istream>
+#include <ostream>
 
 #include "oct-inttypes.h"
 
--- a/libinterp/octave-value/ov-cell.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-cell.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -25,8 +25,8 @@
 #  include "config.h"
 #endif
 
-#include <iomanip>
-#include <iostream>
+#include <istream>
+#include <ostream>
 #include <sstream>
 #include <vector>
 #include <queue>
@@ -1251,7 +1251,7 @@
       break;
 
     case 1:
-      get_dimensions (args(0), "cell", dims);
+      octave::get_dimensions (args(0), "cell", dims);
       break;
 
     default:
@@ -1267,7 +1267,7 @@
 
   dims.chop_trailing_singletons ();
 
-  check_dimensions (dims, "cell");
+  octave::check_dimensions (dims, "cell");
 
   return ovl (Cell (dims));
 }
--- a/libinterp/octave-value/ov-ch-mat.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-ch-mat.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -26,7 +26,7 @@
 #endif
 
 #include <cctype>
-#include <iostream>
+#include <ostream>
 
 #include "dNDArray.h"
 #include "fNDArray.h"
@@ -41,6 +41,9 @@
 
 #include "lo-ieee.h"
 #include "mx-base.h"
+#include "unicase-wrappers.h"
+#include "unictype-wrappers.h"
+#include "unistr-wrappers.h"
 
 #include "mxarray.h"
 #include "ov-base.h"
@@ -258,20 +261,80 @@
     case umap_ ## UMAP:                                               \
       return octave_value (matrix.map<TYPE, int (&) (int)> (FCN))
 
-    STRING_MAPPER (xisalnum, std::isalnum, bool);
-    STRING_MAPPER (xisalpha, std::isalpha, bool);
     STRING_MAPPER (xisascii, xisascii, bool);
-    STRING_MAPPER (xiscntrl, std::iscntrl, bool);
-    STRING_MAPPER (xisdigit, std::isdigit, bool);
-    STRING_MAPPER (xisgraph, std::isgraph, bool);
-    STRING_MAPPER (xislower, std::islower, bool);
-    STRING_MAPPER (xisprint, std::isprint, bool);
-    STRING_MAPPER (xispunct, std::ispunct, bool);
-    STRING_MAPPER (xisspace, std::isspace, bool);
-    STRING_MAPPER (xisupper, std::isupper, bool);
-    STRING_MAPPER (xisxdigit, std::isxdigit, bool);
-    STRING_MAPPER (xtolower, std::tolower, char);
-    STRING_MAPPER (xtoupper, std::toupper, char);
+
+#define STRING_U8_MAPPER(UMAP,FCN)                                             \
+    case umap_ ## UMAP:                                                        \
+      {                                                                        \
+        charNDArray in_m = matrix;                                             \
+        Array<octave_idx_type> p (dim_vector (matrix.ndims (), 1));            \
+        if (matrix.ndims () > 1)                                               \
+          {                                                                    \
+            for (octave_idx_type i=0; i < matrix.ndims (); i++)                \
+              p(i) = i;                                                        \
+            p(0) = 1;                                                          \
+            p(1) = 0;                                                          \
+            in_m = matrix.permute (p);                                         \
+          }                                                                    \
+        boolNDArray b_array = boolNDArray (in_m.dims ());                      \
+        const uint8_t *in = reinterpret_cast<const uint8_t *> (in_m.data ());  \
+        uint32_t uc;                                                           \
+        for (octave_idx_type i = 0; i < in_m.numel (); )                       \
+        {                                                                      \
+          int mblen = octave_u8_strmbtouc_wrapper (&uc, in + i);               \
+          if (mblen < 1)                                                       \
+            mblen = 1;                                                         \
+          bool is_upper = FCN (uc);                                            \
+          for (int j = 0; j < mblen; j++)                                      \
+            b_array(i+j) = is_upper;                                           \
+          i += mblen;                                                          \
+        }                                                                      \
+        return octave_value ((matrix.ndims () > 1) ? b_array.permute (p, true) \
+                                                   : b_array);                 \
+      }
+
+    STRING_U8_MAPPER (xisalnum, octave_uc_is_alnum_wrapper);
+    STRING_U8_MAPPER (xisalpha, octave_uc_is_alpha_wrapper);
+    STRING_U8_MAPPER (xiscntrl, octave_uc_is_cntrl_wrapper);
+    STRING_U8_MAPPER (xisdigit, octave_uc_is_digit_wrapper);
+    STRING_U8_MAPPER (xisgraph, octave_uc_is_graph_wrapper);
+    STRING_U8_MAPPER (xislower, octave_uc_is_lower_wrapper);
+    STRING_U8_MAPPER (xisprint, octave_uc_is_print_wrapper);
+    STRING_U8_MAPPER (xispunct, octave_uc_is_punct_wrapper);
+    STRING_U8_MAPPER (xisspace, octave_uc_is_space_wrapper);
+    STRING_U8_MAPPER (xisupper, octave_uc_is_upper_wrapper);
+    STRING_U8_MAPPER (xisxdigit, octave_uc_is_xdigit_wrapper);
+
+#define STRING_U8_FCN(UMAP,U8_FCN,STD_FCN)                                     \
+    case umap_ ## UMAP:                                                        \
+      {                                                                        \
+        charNDArray in_m = matrix;                                             \
+        Array<octave_idx_type> p (dim_vector (matrix.ndims (), 1));            \
+        if (matrix.ndims () > 1)                                               \
+          {                                                                    \
+            for (octave_idx_type i=0; i < matrix.ndims (); i++)                \
+              p(i) = i;                                                        \
+            p(0) = 1;                                                          \
+            p(1) = 0;                                                          \
+            in_m = matrix.permute (p);                                         \
+          }                                                                    \
+        size_t output_length = in_m.numel ();                                  \
+        charNDArray ch_array = charNDArray (in_m.dims ());                     \
+        const uint8_t *in = reinterpret_cast<const uint8_t *> (in_m.data ());  \
+        uint8_t *buf = reinterpret_cast<uint8_t *> (ch_array.fortran_vec ());  \
+        U8_FCN (in, matrix.numel (), nullptr, buf, &output_length);            \
+        if (output_length != static_cast<size_t> (matrix.numel ()))            \
+          {                                                                    \
+            warning_with_id ("octave:multi_byte_char_length",                  \
+                             "UMAP: Possible multi-byte error.");              \
+            return octave_value (matrix.map<char, int (&) (int)> (STD_FCN));   \
+          }                                                                    \
+        return octave_value ((matrix.ndims () > 1) ? ch_array.permute (p, true)\
+                                                   : ch_array);                \
+      }
+
+    STRING_U8_FCN (xtolower, octave_u8_tolower_wrapper, std::tolower);
+    STRING_U8_FCN (xtoupper, octave_u8_toupper_wrapper, std::toupper);
 
     // For Matlab compatibility, these should work on ASCII values
     // without error or warning.
--- a/libinterp/octave-value/ov-class.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-class.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -25,7 +25,8 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <istream>
+#include <ostream>
 
 #include "Array-util.h"
 #include "byte-swap.h"
@@ -387,7 +388,7 @@
           {
             if (type.length () > 1 && type[1] == '.')
               {
-                std::list<octave_value_list>::const_iterator p = idx.begin ();
+                auto p = idx.begin ();
                 octave_value_list key_idx = *++p;
 
                 Cell tmp = dotref (key_idx);
@@ -635,7 +636,7 @@
           {
             if (type.length () > 1 && type[1] == '.')
               {
-                std::list<octave_value_list>::const_iterator p = idx.begin ();
+                auto p = idx.begin ();
                 octave_value_list t_idx = *p;
 
                 octave_value_list key_idx = *++p;
@@ -689,7 +690,7 @@
             std::string next_type = type.substr (1);
 
             Cell tmpc (1, 1);
-            octave_map::iterator pkey = map.seek (key);
+            auto pkey = map.seek (key);
             if (pkey != map.end ())
               {
                 map.contents (pkey).make_unique ();
@@ -730,7 +731,7 @@
       {
         if (n > 1 && type[1] == '.')
           {
-            std::list<octave_value_list>::const_iterator p = idx.begin ();
+            auto p = idx.begin ();
             octave_value_list key_idx = *++p;
 
             assert (key_idx.length () == 1);
@@ -846,7 +847,7 @@
 
   size_t retval = 0;
 
-  for (octave_map::const_iterator it = map.begin (); it != map.end (); it++)
+  for (auto it = map.cbegin (); it != map.cend (); it++)
     {
       std::string key = map.key (it);
 
@@ -925,7 +926,7 @@
     {
       for (auto& par : parent_list)
         {
-          octave_map::iterator smap = map.seek (par);
+          auto smap = map.seek (par);
 
           Cell& tmp = map.contents (smap);
 
@@ -1124,7 +1125,7 @@
   std::string dbgstr = "dork";
 
   // First, check to see if there might be an issue with inheritance.
-  for (octave_map::const_iterator it = map.begin (); it != map.end (); it++)
+  for (auto it = map.cbegin (); it != map.cend (); it++)
     {
       std::string key = map.key (it);
       Cell        val = map.contents (it);
@@ -1187,7 +1188,7 @@
 
   os << "# length: " << m.nfields () << "\n";
 
-  octave_map::iterator i = m.begin ();
+  auto i = m.begin ();
   while (i != m.end ())
     {
       octave_value val = map.contents (i);
@@ -1293,7 +1294,7 @@
   int32_t len = m.nfields ();
   os.write (reinterpret_cast<char *> (&len), 4);
 
-  octave_map::iterator i = m.begin ();
+  auto i = m.begin ();
   while (i != m.end ())
     {
       octave_value val = map.contents (i);
@@ -1705,12 +1706,12 @@
   if (nparents () != obj.nparents ())
     error ("mismatch in number of parent classes");
 
-  std::list<std::string> obj_parents
+  const std::list<std::string> obj_parents
     = obj.parent_class_name_list ();
-  std::list<std::string> pnames = parents ();
+  const std::list<std::string> pnames = parents ();
 
-  std::list<std::string>::const_iterator p = obj_parents.begin ();
-  std::list<std::string>::const_iterator q = pnames.begin ();
+  auto p = obj_parents.begin ();
+  auto q = pnames.begin ();
 
   while (p != obj_parents.end ())
     {
--- a/libinterp/octave-value/ov-classdef.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-classdef.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -364,6 +364,22 @@
             panic_impossible ();
         }
     }
+  else if (acc.isobject ())
+    {
+      cdef_class ctx = get_class_context ();
+
+      // At this point, a class context is always required.
+      if (ctx.ok ())
+        {
+          if (ctx == cls)
+            return true;
+
+          cdef_class acc_cls (to_cdef (acc));
+
+          if (is_superclass (acc_cls, ctx))
+            return true;
+        }
+    }
   else if (acc.iscell ())
     {
       Cell acc_c = acc.cell_value ();
@@ -1042,6 +1058,10 @@
   octave_classdef_meta (const cdef_meta_object& obj)
     : object (obj) { }
 
+  octave_classdef_meta (const octave_classdef_meta&) = delete;
+
+  octave_classdef_meta& operator = (const octave_classdef_meta&) = delete;
+
   ~octave_classdef_meta (void)
   { object.meta_release (); }
 
@@ -1103,9 +1123,15 @@
 class octave_classdef_superclass_ref : public octave_function
 {
 public:
+  octave_classdef_superclass_ref (void) = delete;
+
   octave_classdef_superclass_ref (const octave_value_list& a)
     : octave_function (), args (a) { }
 
+  octave_classdef_superclass_ref (const octave_classdef_superclass_ref&) = delete;
+
+  octave_classdef_superclass_ref& operator = (const octave_classdef_superclass_ref&) = delete;
+
   ~octave_classdef_superclass_ref (void) = default;
 
   bool is_classdef_superclass_ref (void) const { return true; }
@@ -1113,7 +1139,7 @@
   octave_function * function_value (bool = false) { return this; }
 
   octave_value_list
-  call (octave::tree_evaluator&, int nargout, const octave_value_list& idx)
+  call (octave::tree_evaluator& tw, int nargout, const octave_value_list& idx)
   {
     octave_value_list retval;
 
@@ -1137,12 +1163,11 @@
           error ("`%s' is not a direct superclass of `%s'",
                  cname.c_str (), ctx.get_name ().c_str ());
 
-        if (! is_constructed_object (mname))
+        if (! is_constructed_object (tw, mname))
           error ("cannot call superclass constructor with variable `%s'",
                  mname.c_str ());
 
-        octave::symbol_scope scope
-          = octave::__require_current_scope__ ("octave_classdef_superclass_ref::call");
+        octave::symbol_scope scope = tw.get_current_scope ();
 
         octave_value sym = scope.varval (mname);
 
@@ -1185,10 +1210,10 @@
   }
 
 private:
-  bool is_constructed_object (const std::string nm)
+  bool is_constructed_object (octave::tree_evaluator& tw,
+                              const std::string& nm)
   {
-    octave::call_stack& cs
-      = octave::__get_call_stack__ ("octave_classdef_superclass_ref::is_constructed_object");
+    octave::call_stack& cs = tw.get_call_stack ();
 
     octave_function *of = cs.current ();
 
@@ -1370,7 +1395,7 @@
 
             if (type.length () > 1 && type[1] == '(')
               {
-                std::list<octave_value_list>::const_iterator it = idx.begin ();
+                auto it = idx.begin ();
 
                 args = *++it;
 
@@ -1879,7 +1904,7 @@
 cdef_method
 cdef_class::cdef_class_rep::find_method (const std::string& nm, bool local)
 {
-  method_iterator it = method_map.find (nm);
+  auto it = method_map.find (nm);
 
   if (it == method_map.end ())
     {
@@ -1918,9 +1943,17 @@
 class ctor_analyzer : public octave::tree_walker
 {
 public:
+  ctor_analyzer (void) = delete;
+
   ctor_analyzer (const std::string& ctor, const std::string& obj)
     : octave::tree_walker (), who (ctor), obj_name (obj) { }
 
+  ctor_analyzer (const ctor_analyzer&) = delete;
+
+  ctor_analyzer& operator = (const ctor_analyzer&) = delete;
+
+  ~ctor_analyzer (void) = default;
+
   void visit_statement_list (octave::tree_statement_list& t)
   {
     for (const auto& stmt_p : t)
@@ -2145,7 +2178,7 @@
 cdef_property
 cdef_class::cdef_class_rep::find_property (const std::string& nm)
 {
-  property_iterator it = property_map.find (nm);
+  auto it = property_map.find (nm);
 
   if (it != property_map.end ())
     {
@@ -2885,8 +2918,7 @@
                   // detect which ones are invalid and do not correspond to a
                   // defined property.
 
-                  std::map<std::string, octave_value>::iterator git =
-                    get_methods.find (prop_name);
+                  auto git = get_methods.find (prop_name);
 
                   if (git != get_methods.end ())
                     {
@@ -2895,8 +2927,7 @@
                       get_methods.erase (git);
                     }
 
-                  std::map<std::string, octave_value>::iterator sit =
-                    set_methods.find (prop_name);
+                  auto sit = set_methods.find (prop_name);
 
                   if (sit != set_methods.end ())
                     {
@@ -3324,11 +3355,8 @@
   Cell retval (1, m.size ());
   int i = 0;
 
-  for (typename std::map<T1, T2>::const_iterator it = m.begin ();
-       it != m.end (); ++it, ++i)
-    {
-      retval(i) = to_ov (it->second);
-    }
+  for (auto it = m.begin (); it != m.end (); ++it, ++i)
+    retval(i) = to_ov (it->second);
 
   return retval;
 }
@@ -3750,7 +3778,7 @@
 cdef_manager::find_class (const std::string& name, bool error_if_not_found,
                           bool load_if_not_found)
 {
-  std::map<std::string, cdef_class>::iterator it = m_all_classes.find (name);
+  auto it = m_all_classes.find (name);
 
   if (it == m_all_classes.end ())
     {
@@ -3762,8 +3790,7 @@
 
           if (pos == std::string::npos)
             {
-              octave::symbol_table& symtab
-                = octave::__get_symbol_table__ ("cdef_manager::find_class");
+              octave::symbol_table& symtab = m_interpreter.get_symbol_table ();
 
               ov_cls = symtab.find (name);
             }
@@ -3840,8 +3867,7 @@
     }
   else
     {
-      octave::load_path& lp
-        = octave::__get_load_path__ ("cdef_manager::find_package");
+      octave::load_path& lp = m_interpreter.get_load_path ();
 
       if (load_if_not_found && lp.find_package (name))
         {
--- a/libinterp/octave-value/ov-classdef.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-classdef.h	Fri Aug 10 09:09:51 2018 +0200
@@ -340,6 +340,8 @@
     register_object ();
   }
 
+  cdef_object_base& operator = (const cdef_object_base&) = delete;
+
   ~cdef_object_base (void) { unregister_object (); }
 
   cdef_class get_class (void) const;
@@ -366,9 +368,6 @@
 
   // The class of the object
   cdef_object klass;
-
-  // No assignment!
-  cdef_object_base& operator = (const cdef_object_base&);
 };
 
 class
@@ -380,6 +379,10 @@
   cdef_object_array (const Array<cdef_object>& a)
     : cdef_object_base (), array (a) { }
 
+  cdef_object_array& operator = (const cdef_object_array&) = delete;
+
+  ~cdef_object_array (void) = default;
+
   cdef_object_rep * clone (void) const
   { return new cdef_object_array (*this); }
 
@@ -426,9 +429,6 @@
   // Private copying!
   cdef_object_array (const cdef_object_array& obj)
     : cdef_object_base (obj), array (obj.array) { }
-
-  // No assignment!
-  cdef_object_array& operator = (const cdef_object_array&);
 };
 
 class
@@ -437,6 +437,8 @@
 public:
   cdef_object_scalar (void) : cdef_object_base () { }
 
+  cdef_object_scalar& operator = (const cdef_object_scalar&) = delete;
+
   ~cdef_object_scalar (void) = default;
 
   dim_vector dims (void) const { return dim_vector (1, 1); }
@@ -504,10 +506,6 @@
   // Restricted object copying!
   cdef_object_scalar (const cdef_object_scalar& obj)
     : cdef_object_base (obj), map (obj.map), ctor_list (obj.ctor_list) { }
-
-private:
-  // No assignment!
-  cdef_object_scalar& operator = (const cdef_object_scalar&);
 };
 
 class
@@ -517,6 +515,8 @@
   handle_cdef_object (void)
     : cdef_object_scalar () { }
 
+  handle_cdef_object& operator = (const handle_cdef_object&) = delete;
+
   ~handle_cdef_object (void);
 
   cdef_object_rep * clone (void) const
@@ -537,10 +537,6 @@
   // Restricted copying!
   handle_cdef_object (const handle_cdef_object& obj)
     : cdef_object_scalar (obj) { }
-
-private:
-  // No assignment
-  handle_cdef_object& operator = (const handle_cdef_object&);
 };
 
 class
@@ -550,6 +546,8 @@
   value_cdef_object (void)
     : cdef_object_scalar () { }
 
+  value_cdef_object& operator = (const value_cdef_object&) = delete;
+
   ~value_cdef_object (void);
 
   cdef_object_rep * clone (void) const
@@ -565,9 +563,6 @@
   // Private copying!
   value_cdef_object (const value_cdef_object& obj)
     : cdef_object_scalar (obj) { }
-
-  // No assignment!
-  value_cdef_object& operator = (const value_cdef_object&);
 };
 
 class
@@ -577,6 +572,8 @@
   cdef_meta_object_rep (void)
     : handle_cdef_object () { }
 
+  cdef_meta_object_rep& operator = (const cdef_meta_object_rep&) = delete;
+
   ~cdef_meta_object_rep (void) = default;
 
   cdef_object_rep * copy (void) const
@@ -609,10 +606,6 @@
   // Restricted copying!
   cdef_meta_object_rep (const cdef_meta_object_rep& obj)
     : handle_cdef_object (obj) { }
-
-private:
-  // No assignment!
-  cdef_meta_object_rep& operator = (const cdef_meta_object_rep&);
 };
 
 class
@@ -632,6 +625,8 @@
   cdef_meta_object (const cdef_object& obj)
     : cdef_object (obj) { }
 
+  cdef_meta_object& operator = (const cdef_object&) = delete;
+
   ~cdef_meta_object (void) = default;
 
   bool is_class (void) const { return get_rep ()->is_class (); }
@@ -676,6 +671,10 @@
 
     cdef_class_rep (const std::list<cdef_class>& superclasses);
 
+    cdef_class_rep& operator = (const cdef_class_rep&) = delete;
+
+    ~cdef_class_rep (void) = default;
+
     cdef_object_rep * copy (void) const { return new cdef_class_rep (*this); }
 
     bool is_class (void) const { return true; }
@@ -845,6 +844,8 @@
     return *this;
   }
 
+  ~cdef_class (void) = default;
+
   cdef_method find_method (const std::string& nm, bool local = false);
 
   void install_method (const cdef_method& meth)
@@ -990,6 +991,10 @@
     cdef_property_rep (void)
       : cdef_meta_object_rep () { }
 
+    cdef_property_rep& operator = (const cdef_property_rep& p) = delete;
+
+    ~cdef_property_rep (void) = default;
+
     cdef_object_rep * copy (void) const { return new cdef_property_rep (*this); }
 
     bool is_property (void) const { return true; }
@@ -1054,6 +1059,8 @@
     return *this;
   }
 
+  ~cdef_property (void) = default;
+
   octave_value get_value (const cdef_object& obj, bool do_check_access = true,
                           const std::string& who = "")
   { return get_rep ()->get_value (obj, do_check_access, who); }
@@ -1100,6 +1107,10 @@
       : cdef_meta_object_rep (), function (), dispatch_type ()
     { }
 
+    cdef_method_rep& operator = (const cdef_method_rep& m) = delete;
+
+    ~cdef_method_rep (void) = default;
+
     cdef_object_rep * copy (void) const { return new cdef_method_rep(*this); }
 
     bool is_method (void) const { return true; }
@@ -1186,6 +1197,8 @@
     return *this;
   }
 
+  ~cdef_method (void) = default;
+
   // normal invocation
   octave_value_list execute (const octave_value_list& args, int nargout,
                              bool do_check_access = true,
@@ -1314,6 +1327,8 @@
     cdef_package_rep (void)
       : cdef_meta_object_rep (), member_count (0) { }
 
+    cdef_package_rep& operator = (const cdef_package_rep&) = delete;
+
     ~cdef_package_rep (void) = default;
 
     cdef_object_rep * copy (void) const { return new cdef_package_rep (*this); }
@@ -1420,6 +1435,8 @@
     return *this;
   }
 
+  ~cdef_package (void) = default;
+
   void install_class (const cdef_class& cls, const std::string& nm)
   { get_rep ()->install_class (cls, nm); }
 
@@ -1462,8 +1479,11 @@
   octave_classdef (const cdef_object& obj)
     : octave_base_value (), object (obj) { }
 
-  octave_classdef (const octave_classdef& obj)
-    : octave_base_value (obj), object (obj.object) { }
+  octave_classdef (const octave_classdef&) = delete;
+
+  octave_classdef& operator = (const octave_classdef&) = delete;
+
+  ~octave_classdef (void) = default;
 
   octave_base_value * clone (void) const
   { return new octave_classdef (object.clone ()); }
--- a/libinterp/octave-value/ov-colon.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-colon.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -24,7 +24,7 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <ostream>
 
 #include "error.h"
 #include "pr-output.h"
--- a/libinterp/octave-value/ov-complex.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-complex.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -24,7 +24,8 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <istream>
+#include <ostream>
 #include <sstream>
 
 #include "lo-ieee.h"
--- a/libinterp/octave-value/ov-cs-list.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-cs-list.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -24,9 +24,6 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
-#include <sstream>
-
 #include "lo-utils.h"
 
 #include "defun.h"
--- a/libinterp/octave-value/ov-cx-mat.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-cx-mat.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -25,7 +25,8 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <istream>
+#include <ostream>
 #include <vector>
 
 #include "dNDArray.h"
@@ -244,7 +245,7 @@
       octave_idx_type nel = numel ();
 
       for (octave_idx_type i = 0; i < nel; i++)
-        retval.elem (i) = static_cast<char>(std::real (matrix.elem (i)));
+        retval.elem (i) = static_cast<char> (std::real (matrix.elem (i)));
     }
 
   return retval;
--- a/libinterp/octave-value/ov-cx-sparse.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-cx-sparse.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -25,8 +25,8 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
-#include <limits>
+#include <istream>
+#include <ostream>
 #include <vector>
 
 #include "lo-specfun.h"
@@ -178,7 +178,7 @@
       for (octave_idx_type j = 0; j < nc; j++)
         for (octave_idx_type i = matrix.cidx (j); i < matrix.cidx (j+1); i++)
           retval(matrix.ridx (i) + nr * j) =
-            static_cast<char>(std::real (matrix.data (i)));
+            static_cast<char> (std::real (matrix.data (i)));
     }
 
   return retval;
--- a/libinterp/octave-value/ov-fcn-handle.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-fcn-handle.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -26,8 +26,9 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <istream>
 #include <list>
+#include <ostream>
 #include <sstream>
 #include <vector>
 
@@ -160,7 +161,7 @@
         }
       else
         {
-          str_ov_map::iterator it = overloads.find (dispatch_type);
+          auto it = overloads.find (dispatch_type);
 
           if (it == overloads.end ())
             {
@@ -169,10 +170,10 @@
               octave::symbol_table& symtab
                 = octave::__get_symbol_table__ ("octave_fcn_handle::call");
 
-              std::list<std::string> plist
+              const std::list<std::string> plist
                 = symtab.parent_classes (dispatch_type);
 
-              std::list<std::string>::const_iterator pit = plist.begin ();
+              auto pit = plist.begin ();
 
               while (pit != plist.end ())
                 {
@@ -240,9 +241,9 @@
       for (int i = 0; i < btyp_num_types && retval; i++)
         retval = builtin_overloads[i].is_copy_of (h.builtin_overloads[i]);
 
-      str_ov_map::const_iterator iter = overloads.begin ();
-      str_ov_map::const_iterator hiter = h.overloads.begin ();
-      for (; iter != overloads.end () && retval; iter++, hiter++)
+      auto iter = overloads.cbegin ();
+      auto hiter = h.overloads.cbegin ();
+      for (; iter != overloads.cend () && retval; iter++, hiter++)
         retval = (iter->first == hiter->first)
                  && (iter->second.is_copy_of (hiter->second));
     }
@@ -1171,7 +1172,7 @@
           H5Gget_num_objs (data_hid, &num_obj);
           H5Gclose (data_hid);
 
-          if (num_obj != static_cast<hsize_t>(len))
+          if (num_obj != static_cast<hsize_t> (len))
             error ("load: failed to load anonymous function handle");
 
           hdf5_callback_data dsub;
@@ -1939,7 +1940,7 @@
 
 octave_fcn_handle *
 octave_fcn_binder::maybe_binder (const octave_value& f,
-                                 octave::tree_evaluator *tw)
+                                 octave::tree_evaluator& tw)
 {
   octave_fcn_handle *retval = nullptr;
 
@@ -1998,7 +1999,7 @@
 
           if (arg_list && arg_list->length () > 0)
             {
-              octave::symbol_scope scope = tw->get_current_scope ();
+              octave::symbol_scope scope = tw.get_current_scope ();
 
               octave::symbol_record::context_id context
                 = scope.current_context ();
@@ -2011,13 +2012,13 @@
               // Verify that each argument is either a named param, a constant,
               // or a defined identifier.
               int iarg = 0;
-              for (octave::tree_argument_list::iterator it = arg_list->begin ();
+              for (auto it = arg_list->begin ();
                    it != arg_list->end (); ++it, ++iarg)
                 {
                   octave::tree_expression *elt = *it;
                   if (elt && elt->is_constant ())
                     {
-                      arg_template(iarg) = tw->evaluate (elt);
+                      arg_template(iarg) = tw.evaluate (elt);
                       arg_mask[iarg] = -1;
                     }
                   else if (elt && elt->is_identifier ())
@@ -2030,7 +2031,7 @@
                         }
                       else if (elt_id->is_defined (context))
                         {
-                          arg_template(iarg) = tw->evaluate (elt_id);
+                          arg_template(iarg) = tw.evaluate (elt_id);
                           arg_mask[iarg] = -1;
                         }
                       else
@@ -2052,7 +2053,7 @@
                 {
                   // If the head is a value, use it as root.
                   if (head_id->is_defined (context))
-                    root_val = tw->evaluate (head_id);
+                    root_val = tw.evaluate (head_id);
                   else
                     {
                       // It's a name.
--- a/libinterp/octave-value/ov-fcn-handle.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-fcn-handle.h	Fri Aug 10 09:09:51 2018 +0200
@@ -198,7 +198,7 @@
 
   // Factory method.
   static octave_fcn_handle * maybe_binder (const octave_value& f,
-                                           octave::tree_evaluator *tw);
+                                           octave::tree_evaluator& tw);
 
 protected:
 
--- a/libinterp/octave-value/ov-fcn-inline.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-fcn-inline.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -29,7 +29,7 @@
 #endif
 
 #include <istream>
-#include <iostream>
+#include <ostream>
 #include <sstream>
 #include <vector>
 
--- a/libinterp/octave-value/ov-float.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-float.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -24,7 +24,8 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <istream>
+#include <ostream>
 
 #include "oct-inttypes.h"
 
--- a/libinterp/octave-value/ov-flt-complex.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-flt-complex.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -24,7 +24,8 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <istream>
+#include <ostream>
 
 #include "lo-ieee.h"
 #include "lo-specfun.h"
--- a/libinterp/octave-value/ov-flt-cx-mat.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-flt-cx-mat.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -25,7 +25,8 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <istream>
+#include <ostream>
 #include <vector>
 
 #include "dNDArray.h"
@@ -218,7 +219,7 @@
       octave_idx_type nel = numel ();
 
       for (octave_idx_type i = 0; i < nel; i++)
-        retval.elem (i) = static_cast<char>(std::real (matrix.elem (i)));
+        retval.elem (i) = static_cast<char> (std::real (matrix.elem (i)));
     }
 
   return retval;
--- a/libinterp/octave-value/ov-flt-re-mat.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-flt-re-mat.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -25,8 +25,9 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <istream>
 #include <limits>
+#include <ostream>
 #include <vector>
 
 #include "dNDArray.h"
@@ -215,7 +216,7 @@
   octave_idx_type nel = numel ();
 
   for (octave_idx_type i = 0; i < nel; i++)
-    retval.elem (i) = static_cast<char>(matrix.elem (i));
+    retval.elem (i) = static_cast<char> (matrix.elem (i));
 
   return retval;
 }
--- a/libinterp/octave-value/ov-int16.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-int16.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -24,9 +24,6 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
-#include <limits>
-
 #include "lo-ieee.h"
 #include "lo-utils.h"
 #include "mx-base.h"
--- a/libinterp/octave-value/ov-int32.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-int32.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -24,9 +24,6 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
-#include <limits>
-
 #include "lo-ieee.h"
 #include "lo-utils.h"
 #include "mx-base.h"
--- a/libinterp/octave-value/ov-int64.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-int64.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -24,9 +24,6 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
-#include <limits>
-
 #include "lo-ieee.h"
 #include "lo-utils.h"
 #include "mx-base.h"
--- a/libinterp/octave-value/ov-int8.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-int8.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -24,9 +24,6 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
-#include <limits>
-
 #include "lo-ieee.h"
 #include "lo-utils.h"
 #include "mx-base.h"
--- a/libinterp/octave-value/ov-java.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-java.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -34,9 +34,9 @@
 #endif
 
 #include <algorithm>
-#include <map>
+#include <fstream>
 #include <iostream>
-#include <fstream>
+#include <map>
 #include <string>
 #include <vector>
 
@@ -53,6 +53,7 @@
 #include "file-stat.h"
 #include "fpucw-wrappers.h"
 #include "load-path.h"
+#include "lo-sysdep.h"
 #include "oct-env.h"
 #include "oct-shlib.h"
 #include "ov-java.h"
@@ -237,7 +238,9 @@
 
     void read_java_opts (const std::string& filename)
     {
-      std::ifstream js (filename.c_str ());
+      std::string ascii_fname = octave::sys::get_ASCII_filename (filename);
+
+      std::ifstream js (ascii_fname.c_str ());
 
       if (! js.bad () && ! js.fail ())
         {
@@ -358,7 +361,9 @@
 {
   std::string classpath;
 
-  std::ifstream fs (filepath.c_str ());
+  std::string ascii_fname = octave::sys::get_ASCII_filename (filepath);
+
+  std::ifstream fs (ascii_fname.c_str ());
 
   if (! fs.bad () && ! fs.fail ())
     {
@@ -491,11 +496,99 @@
   return retval;
 }
 
+static std::string
+get_jvm_lib_path_in_subdir (std::string java_home_path)
+{
+  // This assumes that whatever architectures are installed are appropriate for
+  // this machine
+#if defined (OCTAVE_USE_WINDOWS_API)
+  std::string subdirs[] = {"bin/client", "bin/server"};
+  std::string libjvm = "jvm.dll";
+#else
+  std::string subdirs[] = {"jre/lib/server", "jre/lib", "lib/client",
+    "lib/server", "jre/lib/amd64/client", "jre/lib/amd64/server",
+    "jre/lib/i386/client", "jre/lib/i386/server"};
+#  if defined (__APPLE__)
+  std::string libjvm = "libjvm.dylib";
+#  else
+  std::string libjvm = "libjvm.so";
+#  endif
+#endif
+
+  for (size_t i = 0; i < sizeof (subdirs) / sizeof (subdirs[0]); i++)
+    {
+      std::string candidate = java_home_path + "/" + subdirs[i] + "/" + libjvm;
+      if (octave::sys::file_stat (candidate))
+        return candidate;
+    }
+  return "";
+}
+
 #if defined (OCTAVE_USE_WINDOWS_API)
 // Declare function defined in sysdep.cc
 extern LONG
 get_regkey_value (HKEY h_rootkey, const std::string subkey,
                   const std::string name, octave_value& value);
+
+static std::string
+get_jvm_lib_path_from_registry ()
+{
+  // In Windows, find the location of the JRE from the registry
+  // and load the symbol from the dll.
+  std::string key, jversion, value;
+
+  // First search for JRE >= 9
+  key = R"(software\javasoft\jre)";
+
+  jversion = octave::sys::env::getenv ("JAVA_VERSION");
+  octave_value regval;
+  LONG retval;
+  if (jversion.empty ())
+    {
+      value = "CurrentVersion";
+      retval = get_regkey_value (HKEY_LOCAL_MACHINE, key, value, regval);
+
+      if (retval != ERROR_SUCCESS)
+        {
+          // Search for JRE < 9
+          key = R"(software\javasoft\java runtime environment)";
+          retval = get_regkey_value (HKEY_LOCAL_MACHINE, key, value,
+                                     regval);
+        }
+
+      if (retval != ERROR_SUCCESS)
+        error ("unable to find Java Runtime Environment: %s::%s",
+               key.c_str (), value.c_str ());
+
+      jversion = regval.xstring_value (
+        "initialize_jvm: registry value \"%s\" at \"%s\" must be a string",
+        value.c_str (), key.c_str ());
+    }
+
+  key = key + '\\' + jversion;
+  value = "RuntimeLib";
+  retval = get_regkey_value (HKEY_LOCAL_MACHINE, key, value, regval);
+  if (retval != ERROR_SUCCESS)
+    {
+      // Search for JRE < 9
+      key = R"(software\javasoft\java runtime environment\)" + jversion;
+      retval = get_regkey_value (HKEY_LOCAL_MACHINE, key, value, regval);
+    }
+
+  if (retval != ERROR_SUCCESS)
+    error ("unable to find Java Runtime Environment: %s::%s",
+           key.c_str (), value.c_str ());
+
+  std::string jvm_lib_path = regval.xstring_value (
+        "initialize_jvm: registry value \"%s\" at \"%s\" must be a string",
+        value.c_str (), key.c_str ());
+
+  if (jvm_lib_path.empty ())
+    error ("unable to find Java Runtime Environment: %s::%s",
+           key.c_str (), value.c_str ());
+
+  return jvm_lib_path;
+}
 #endif
 
 //! Initialize the java virtual machine (jvm) and field #jvm if necessary.
@@ -546,68 +639,22 @@
 
   if (! create_vm || ! get_vm)
     {
-#if defined (OCTAVE_USE_WINDOWS_API)
-      // In Windows, find the location of the JRE from the registry
-      // and load the symbol from the dll.
-      std::string key, jversion, value;
-
-      // First search for JRE >= 9
-      key = R"(software\javasoft\jre)";
-
-      jversion = octave::sys::env::getenv ("JAVA_VERSION");
-      octave_value regval;
-      LONG retval;
-      if (jversion.empty ())
-        {
-          value = "CurrentVersion";
-          retval = get_regkey_value (HKEY_LOCAL_MACHINE, key, value, regval);
-
-          if (retval != ERROR_SUCCESS)
-            {
-              // Search for JRE < 9
-              key = R"(software\javasoft\java runtime environment)";
-              retval = get_regkey_value (HKEY_LOCAL_MACHINE, key, value,
-                                         regval);
-            }
-
-          if (retval != ERROR_SUCCESS)
-            error ("unable to find Java Runtime Environment: %s::%s",
-                   key.c_str (), value.c_str ());
-
-          jversion = regval.xstring_value (
-            "initialize_jvm: registry value \"%s\" at \"%s\" must be a string",
-            value.c_str (), key.c_str ());
-        }
-
-      key = key + '\\' + jversion;
-      value = "RuntimeLib";
-      retval = get_regkey_value (HKEY_LOCAL_MACHINE, key, value, regval);
-      if (retval != ERROR_SUCCESS)
-        {
-          // Search for JRE < 9
-          key = R"(software\javasoft\java runtime environment\)" + jversion;
-          retval = get_regkey_value (HKEY_LOCAL_MACHINE, key, value, regval);
-        }
-
-      if (retval != ERROR_SUCCESS)
-        error ("unable to find Java Runtime Environment: %s::%s",
-               key.c_str (), value.c_str ());
-
-      jvm_lib_path = regval.xstring_value (
-            "initialize_jvm: registry value \"%s\" at \"%s\" must be a string",
-            value.c_str (), key.c_str ());
+      // JAVA_HOME environment variable takes precedence
+      std::string java_home_env = octave::sys::env::getenv ("JAVA_HOME");
+      if (! java_home_env.empty ())
+        jvm_lib_path = get_jvm_lib_path_in_subdir (java_home_env);
 
       if (jvm_lib_path.empty ())
-        error ("unable to find Java Runtime Environment: %s::%s",
-               key.c_str (), value.c_str ());
+#if defined (OCTAVE_USE_WINDOWS_API)
+        jvm_lib_path = get_jvm_lib_path_from_registry ();
+#elif defined (__APPLE__)
+        // Fall back to JAVA_LDPATH determined by configure and set in config.h
+        jvm_lib_path = std::string (JAVA_LDPATH) + "/libjvm.dylib";
 #else
-      // JAVA_LDPATH determined by configure and set in config.h
-#  if defined (__APPLE__)
-      jvm_lib_path = JAVA_LDPATH + std::string ("/libjvm.dylib");
-#  else
-      jvm_lib_path = JAVA_LDPATH + std::string ("/libjvm.so");
-#  endif
+        // Fall back to JAVA_LDPATH determined by configure and set in config.h
+        jvm_lib_path = std::string (JAVA_LDPATH) + "/libjvm.so";
 #endif
+
       lib = octave::dynamic_library (jvm_lib_path);
 
       if (! lib)
@@ -1431,7 +1478,7 @@
         {
           jmethodID mID = jni_env->GetMethodID (cls, "getID", "()I");
           int ID = jni_env->CallIntMethod (jobj, mID);
-          std::map<int,octave_value>::iterator it = octave_ref_map.find (ID);
+          auto it = octave_ref_map.find (ID);
 
           if (it != octave_ref_map.end ())
             retval = it->second;
@@ -1921,7 +1968,7 @@
 Java_org_octave_Octave_doInvoke (JNIEnv *env, jclass, jint ID,
                                  jobjectArray args)
 {
-  std::map<int,octave_value>::iterator it = octave_ref_map.find (ID);
+  auto it = octave_ref_map.find (ID);
 
   if (it != octave_ref_map.end ())
     {
@@ -2067,7 +2114,7 @@
           count++;
           ovl(1) = octave_value (this);
           ovl(0) = (idx.front ())(0);
-          std::list<octave_value_list>::const_iterator it = idx.begin ();
+          auto it = idx.begin ();
           ovl.append (*++it);
           retval = FjavaMethod (ovl, 1);
           skip++;
@@ -2142,7 +2189,7 @@
       else if (type.length () > 2 && type[1] == '(')
         {
           std::list<octave_value_list> new_idx;
-          std::list<octave_value_list>::const_iterator it = idx.begin ();
+          auto it = idx.begin ();
           new_idx.push_back (*it++);
           new_idx.push_back (*it++);
           octave_value_list u = subsref (type.substr (0, 2), new_idx, 1);
--- a/libinterp/octave-value/ov-range.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-range.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -24,7 +24,9 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <istream>
+#include <ostream>
+#include <sstream>
 
 #include "dNDArray.h"
 #include "fNDArray.h"
@@ -220,7 +222,7 @@
   octave_idx_type nel = numel ();
 
   for (octave_idx_type i = 0; i < nel; i++)
-    retval.elem (i) = static_cast<char>(matrix.elem (i));
+    retval.elem (i) = static_cast<char> (matrix.elem (i));
 
   return retval;
 }
--- a/libinterp/octave-value/ov-re-mat.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-re-mat.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -25,8 +25,9 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <istream>
 #include <limits>
+#include <ostream>
 #include <vector>
 
 #include "dNDArray.h"
@@ -225,7 +226,7 @@
   octave_idx_type nel = numel ();
 
   for (octave_idx_type i = 0; i < nel; i++)
-    retval.elem (i) = static_cast<char>(matrix.elem (i));
+    retval.elem (i) = static_cast<char> (matrix.elem (i));
 
   return retval;
 }
--- a/libinterp/octave-value/ov-re-sparse.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-re-sparse.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -25,8 +25,9 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <istream>
 #include <limits>
+#include <ostream>
 #include <vector>
 
 #include "lo-specfun.h"
@@ -147,7 +148,7 @@
 
   for (octave_idx_type j = 0; j < nc; j++)
     for (octave_idx_type i = matrix.cidx (j); i < matrix.cidx (j+1); i++)
-      retval(matrix.ridx (i) + nr * j) = static_cast<char>(matrix.data (i));
+      retval(matrix.ridx (i) + nr * j) = static_cast<char> (matrix.data (i));
 
   return retval;
 }
--- a/libinterp/octave-value/ov-scalar.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-scalar.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -24,7 +24,8 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <istream>
+#include <ostream>
 
 #include "oct-inttypes.h"
 
--- a/libinterp/octave-value/ov-str-mat.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-str-mat.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -27,7 +27,8 @@
 
 #include <cctype>
 
-#include <iostream>
+#include <istream>
+#include <ostream>
 #include <vector>
 
 #include "data-conv.h"
@@ -51,7 +52,6 @@
 #include "ov-re-mat.h"
 #include "ov-str-mat.h"
 #include "pr-output.h"
-#include "pt-mat.h"
 #include "utils.h"
 
 
@@ -289,7 +289,7 @@
           std::string retval = string_value ();
 
           if (! is_sq_string ())
-            retval = undo_string_escapes (retval);
+            retval = octave::undo_string_escapes (retval);
 
           return retval;
         }
--- a/libinterp/octave-value/ov-struct.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-struct.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -24,7 +24,8 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <istream>
+#include <ostream>
 
 #include "Cell.h"
 #include "builtin-defun-decls.h"
@@ -107,7 +108,7 @@
 static void
 maybe_warn_invalid_field_name (const std::string& key, const char *who)
 {
-  if (! valid_identifier (key))
+  if (! octave::valid_identifier (key))
     {
       if (who)
         warning_with_id ("Octave:language-extension",
@@ -135,7 +136,7 @@
       {
         if (type.length () > 1 && type[1] == '.')
           {
-            std::list<octave_value_list>::const_iterator p = idx.begin ();
+            auto p = idx.begin ();
             octave_value_list key_idx = *++p;
 
             const Cell tmp = dotref (key_idx);
@@ -198,7 +199,7 @@
       {
         if (type.length () > 1 && type[1] == '.')
           {
-            std::list<octave_value_list>::const_iterator p = idx.begin ();
+            auto p = idx.begin ();
             octave_value_list key_idx = *++p;
 
             const Cell tmp = dotref (key_idx, auto_add);
@@ -291,7 +292,7 @@
           {
             if (type.length () > 1 && type[1] == '.')
               {
-                std::list<octave_value_list>::const_iterator p = idx.begin ();
+                auto p = idx.begin ();
                 octave_value_list t_idx = *p;
 
                 octave_value_list key_idx = *++p;
@@ -313,7 +314,7 @@
                 std::string next_type = type.substr (2);
 
                 Cell tmpc (1, 1);
-                octave_map::iterator pkey = map.seek (key);
+                auto pkey = map.seek (key);
                 if (pkey != map.end ())
                   {
                     map.contents (pkey).make_unique ();
@@ -365,7 +366,7 @@
             std::string next_type = type.substr (1);
 
             Cell tmpc (1, 1);
-            octave_map::iterator pkey = map.seek (key);
+            auto pkey = map.seek (key);
             if (pkey != map.end ())
               {
                 map.contents (pkey).make_unique ();
@@ -414,7 +415,7 @@
       {
         if (n > 1 && type[1] == '.')
           {
-            std::list<octave_value_list>::const_iterator p = idx.begin ();
+            auto p = idx.begin ();
             octave_value_list key_idx = *++p;
             octave_value_list idxf = idx.front ();
 
@@ -550,7 +551,7 @@
 
   size_t retval = 0;
 
-  for (octave_map::const_iterator p = map.begin (); p != map.end (); p++)
+  for (auto p = map.cbegin (); p != map.cend (); p++)
     {
       std::string key = map.key (p);
 
@@ -1212,7 +1213,7 @@
           std::string next_type = type.substr (1);
 
           octave_value tmp;
-          octave_map::iterator pkey = map.seek (key);
+          auto pkey = map.seek (key);
           if (pkey != map.end ())
             {
               map.contents (pkey).make_unique ();
@@ -1264,7 +1265,7 @@
 
   size_t retval = 0;
 
-  for (octave_map::const_iterator p = map.begin (); p != map.end (); p++)
+  for (auto p = map.cbegin (); p != map.cend (); p++)
     {
       std::string key = map.key (p);
 
--- a/libinterp/octave-value/ov-typeinfo.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-typeinfo.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -24,6 +24,8 @@
 #  include "config.h"
 #endif
 
+#include <iostream>
+
 #include "Array.h"
 
 #include "defun.h"
--- a/libinterp/octave-value/ov-uint16.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-uint16.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -24,9 +24,6 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
-#include <limits>
-
 #include "lo-ieee.h"
 #include "lo-utils.h"
 #include "mx-base.h"
--- a/libinterp/octave-value/ov-uint32.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-uint32.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -24,9 +24,6 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
-#include <limits>
-
 #include "lo-ieee.h"
 #include "lo-utils.h"
 #include "mx-base.h"
--- a/libinterp/octave-value/ov-uint64.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-uint64.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -24,9 +24,6 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
-#include <limits>
-
 #include "lo-ieee.h"
 #include "lo-utils.h"
 #include "mx-base.h"
--- a/libinterp/octave-value/ov-uint8.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-uint8.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -24,9 +24,6 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
-#include <limits>
-
 #include "lo-ieee.h"
 #include "lo-utils.h"
 #include "mx-base.h"
--- a/libinterp/octave-value/ov-usr-fcn.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-usr-fcn.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -64,14 +64,17 @@
 
 octave_user_code::~octave_user_code (void)
 {
+  // FIXME: shouldn't this happen automatically when deleting cmd_list?
+  if (cmd_list)
+    cmd_list->remove_all_breakpoints (file_name);
+
+  delete cmd_list;
   delete m_file_info;
 }
 
 void
 octave_user_code::get_file_info (void)
 {
-  std::string file_name = fcn_file_name ();
-
   m_file_info = new octave::file_info (file_name);
 
   octave::sys::file_stat fs (file_name);
@@ -118,6 +121,20 @@
   return std::map<std::string, octave_value> ();
 }
 
+octave_value
+octave_user_code::dump (void) const
+{
+  std::map<std::string, octave_value> m
+    = {{ "scope_info", m_scope ? m_scope.dump () : "0x0" },
+       { "file_name", file_name },
+       { "time_parsed", t_parsed },
+       { "time_checked", t_checked },
+       { "call_depth", m_call_depth }};
+
+  return octave_value (m);
+}
+
+
 // User defined scripts.
 
 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_user_script,
@@ -125,20 +142,14 @@
                                      "user-defined script");
 
 octave_user_script::octave_user_script (void)
-  : octave_user_code (), cmd_list (nullptr), file_name (),
-    t_parsed (static_cast<time_t> (0)),
-    t_checked (static_cast<time_t> (0)),
-    call_depth (-1)
+  : octave_user_code ()
 { }
 
 octave_user_script::octave_user_script
   (const std::string& fnm, const std::string& nm,
    const octave::symbol_scope& scope, octave::tree_statement_list *cmds,
    const std::string& ds)
-  : octave_user_code (nm, scope, ds), cmd_list (cmds), file_name (fnm),
-    t_parsed (static_cast<time_t> (0)),
-    t_checked (static_cast<time_t> (0)),
-    call_depth (-1)
+  : octave_user_code (fnm, nm, scope, cmds, ds)
 {
   if (cmd_list)
     cmd_list->mark_as_script_body ();
@@ -147,81 +158,14 @@
 octave_user_script::octave_user_script
   (const std::string& fnm, const std::string& nm,
    const octave::symbol_scope& scope, const std::string& ds)
-  : octave_user_code (nm, scope, ds), cmd_list (nullptr), file_name (fnm),
-    t_parsed (static_cast<time_t> (0)),
-    t_checked (static_cast<time_t> (0)),
-    call_depth (-1)
+    : octave_user_code (fnm, nm, scope, nullptr, ds)
 { }
 
-octave_user_script::~octave_user_script (void)
-{
-  if (cmd_list)
-    cmd_list->remove_all_breakpoints (file_name);
-
-  delete cmd_list;
-}
-
 octave_value_list
 octave_user_script::call (octave::tree_evaluator& tw, int nargout,
                           const octave_value_list& args)
 {
-  octave_value_list retval;
-
-  octave::unwind_protect frame;
-
-  if (args.length () != 0 || nargout != 0)
-    error ("invalid call to script %s", file_name.c_str ());
-
-  if (cmd_list)
-    {
-      frame.protect_var (call_depth);
-      call_depth++;
-
-      if (call_depth >= tw.max_recursion_depth ())
-        error ("max_recursion_depth exceeded");
-
-      octave::call_stack& cs
-        = octave::__get_call_stack__ ("octave_user_script::call");
-
-      cs.push (this);
-
-      // Set pointer to the current unwind_protect frame to allow
-      // certain builtins register simple cleanup in a very optimized manner.
-      // This is *not* intended as a general-purpose on-cleanup mechanism,
-      frame.protect_var (curr_unwind_protect_frame);
-      curr_unwind_protect_frame = &frame;
-
-      frame.add_method (cs, &octave::call_stack::pop);
-
-      // Update line number even if debugging.
-      frame.protect_var (Vtrack_line_num);
-      Vtrack_line_num = true;
-
-      frame.protect_var (octave::tree_evaluator::statement_context);
-      octave::tree_evaluator::statement_context = octave::tree_evaluator::script;
-
-      octave::profiler& profiler = tw.get_profiler ();
-
-      octave::profiler::enter<octave_user_script> block (profiler, *this);
-
-      frame.add_method (m_scope,
-                        &octave::symbol_scope::unbind_script_symbols);
-      m_scope.bind_script_symbols (tw.get_current_scope ());
-
-      if (tw.echo ())
-        tw.push_echo_state (frame, octave::tree_evaluator::ECHO_SCRIPTS,
-                            file_name);
-
-      cmd_list->accept (tw);
-
-      if (octave::tree_return_command::returning)
-        octave::tree_return_command::returning = 0;
-
-      if (octave::tree_break_command::breaking)
-        octave::tree_break_command::breaking--;
-    }
-
-  return retval;
+  return tw.execute_user_script (*this, nargout, args);
 }
 
 void
@@ -242,13 +186,11 @@
 octave_user_function::octave_user_function
   (const octave::symbol_scope& scope, octave::tree_parameter_list *pl,
    octave::tree_parameter_list *rl, octave::tree_statement_list *cl)
-  : octave_user_code ("", scope, ""),
-    param_list (pl), ret_list (rl), cmd_list (cl),
-    lead_comm (), trail_comm (), file_name (),
+  : octave_user_code ("", "", scope, cl, ""),
+    param_list (pl), ret_list (rl),
+    lead_comm (), trail_comm (),
     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),
+    parent_name (), system_fcn_file (false),
     num_named_args (param_list ? param_list->length () : 0),
     subfunction (false), inline_function (false),
     anonymous_function (false), nested_function (false),
@@ -266,13 +208,8 @@
 
 octave_user_function::~octave_user_function (void)
 {
-  // FIXME: shouldn't this happen automatically when deleting cmd_list?
-  if (cmd_list)
-    cmd_list->remove_all_breakpoints (file_name);
-
   delete param_list;
   delete ret_list;
-  delete cmd_list;
   delete lead_comm;
   delete trail_comm;
 
@@ -289,12 +226,6 @@
   return this;
 }
 
-void
-octave_user_function::stash_fcn_file_name (const std::string& nm)
-{
-  file_name = nm;
-}
-
 // If there is no explicit end statement at the end of the function,
 // relocate the no_op that was generated for the end of file condition
 // to appear on the next line after the last statement in the file, or
@@ -401,7 +332,7 @@
       // function file is parsed, it probably doesn't matter that
       // much.
 
-      std::string ff_name = fcn_file_in_path (file_name);
+      std::string ff_name = octave::fcn_file_in_path (file_name);
 
       std::string fcn_file_dir = octave::config::fcn_file_dir ();
       if (fcn_file_dir == ff_name.substr (0, fcn_file_dir.length ()))
@@ -488,194 +419,9 @@
 
 octave_value_list
 octave_user_function::call (octave::tree_evaluator& tw, int nargout,
-                            const octave_value_list& _args)
+                            const octave_value_list& args)
 {
-  octave_value_list retval;
-
-  if (! cmd_list)
-    return retval;
-
-  // If this function is a classdef constructor, extract the first input
-  // argument, which must be the partially constructed object instance.
-
-  octave_value_list args (_args);
-  octave_value_list ret_args;
-
-  if (is_classdef_constructor ())
-    {
-      if (args.length () > 0)
-        {
-          ret_args = args.slice (0, 1, true);
-          args = args.slice (1, args.length () - 1, true);
-        }
-      else
-        panic_impossible ();
-    }
-
-#if defined (HAVE_LLVM)
-  if (is_special_expr ()
-      && octave::tree_jit::execute (*this, args, retval))
-    return retval;
-#endif
-
-  octave::unwind_protect frame;
-
-  frame.protect_var (call_depth);
-  call_depth++;
-
-  if (call_depth >= tw.max_recursion_depth ())
-    error ("max_recursion_depth exceeded");
-
-  // Save old and set current symbol table context, for
-  // eval_undefined_error().
-
-  octave::call_stack& cs
-    = octave::__get_call_stack__ ("octave_user_function::call");
-
-  octave::symbol_record::context_id context
-    = anonymous_function ? 0 : call_depth;
-
-  cs.push (this, m_scope, context);
-
-  // Set pointer to the current unwind_protect frame to allow
-  // certain builtins register simple cleanup in a very optimized manner.
-  // This is *not* intended as a general-purpose on-cleanup mechanism,
-  frame.protect_var (curr_unwind_protect_frame);
-  curr_unwind_protect_frame = &frame;
-
-  frame.protect_var (Vtrack_line_num);
-  Vtrack_line_num = true;    // update source line numbers, even if debugging
-  frame.add_method (cs, &octave::call_stack::pop);
-
-  if (call_depth > 0 && ! is_anonymous_function ())
-    {
-      m_scope.push_context ();
-
-#if 0
-      std::cerr << name () << " scope: " << m_scope
-                << " call depth: " << call_depth
-                << " context: " << m_scope.current_context () << std::endl;
-#endif
-
-      frame.add_method (m_scope, &octave::symbol_scope::pop_context);
-    }
-
-  string_vector arg_names = _args.name_tags ();
-
-  if (param_list && ! param_list->varargs_only ())
-    {
-#if 0
-      std::cerr << "defining param list, scope: " << m_scope
-                << ", context: " << m_scope.current_context () << std::endl;
-#endif
-      tw.define_parameter_list_from_arg_vector (param_list, args);
-    }
-
-  // For classdef constructor, pre-populate the output arguments
-  // with the pre-initialized object instance, extracted above.
-
-  if (is_classdef_constructor ())
-    {
-      if (! ret_list)
-        error ("%s: invalid classdef constructor, no output argument defined",
-               dispatch_class ().c_str ());
-
-      tw.define_parameter_list_from_arg_vector (ret_list, ret_args);
-    }
-
-  // Force parameter list to be undefined when this function exits.
-  // Doing so decrements the reference counts on the values of local
-  // variables that are also named function parameters.
-
-  if (param_list)
-    frame.add_method (&tw, &octave::tree_evaluator::undefine_parameter_list,
-                      param_list);
-
-  // Force return list to be undefined when this function exits.
-  // Doing so decrements the reference counts on the values of local
-  // variables that are also named values returned by this function.
-
-  if (ret_list)
-    frame.add_method (&tw, &octave::tree_evaluator::undefine_parameter_list,
-                      ret_list);
-
-  if (call_depth == 0)
-    {
-      // Force symbols to be undefined again when this function
-      // exits.
-      //
-      // This cleanup function is added to the unwind_protect stack
-      // after the calls to clear the parameter lists so that local
-      // variables will be cleared before the parameter lists are
-      // cleared.  That way, any function parameters that have been
-      // declared global will be unmarked as global before they are
-      // undefined by the clear_param_list cleanup function.
-
-      frame.add_method (m_scope, &octave::symbol_scope::refresh);
-    }
-
-  bind_automatic_vars (tw, arg_names, args.length (), nargout,
-                       all_va_args (args));
-
-  frame.add_method (this, &octave_user_function::restore_warning_states);
-
-  // Evaluate the commands that make up the function.
-
-  frame.protect_var (octave::tree_evaluator::statement_context);
-  octave::tree_evaluator::statement_context = octave::tree_evaluator::function;
-
-  {
-    octave::profiler& profiler = tw.get_profiler ();
-
-    octave::profiler::enter<octave_user_function> block (profiler, *this);
-
-    if (tw.echo ())
-      tw.push_echo_state (frame, octave::tree_evaluator::ECHO_FUNCTIONS,
-                          file_name);
-
-    if (is_special_expr ())
-      {
-        assert (cmd_list->length () == 1);
-
-        octave::tree_statement *stmt = cmd_list->front ();
-
-        octave::tree_expression *expr = stmt->expression ();
-
-        if (expr)
-          {
-            cs.set_location (stmt->line (), stmt->column ());
-
-            retval = tw.evaluate_n (expr, nargout);
-          }
-      }
-    else
-      cmd_list->accept (tw);
-  }
-
-  if (octave::tree_return_command::returning)
-    octave::tree_return_command::returning = 0;
-
-  if (octave::tree_break_command::breaking)
-    octave::tree_break_command::breaking--;
-
-  // Copy return values out.
-
-  if (ret_list && ! is_special_expr ())
-    {
-      Cell varargout;
-
-      if (ret_list->takes_varargs ())
-        {
-          octave_value varargout_varval = m_scope.varval ("varargout");
-
-          if (varargout_varval.is_defined ())
-            varargout = varargout_varval.xcell_value ("varargout must be a cell array object");
-        }
-
-      retval = tw.convert_return_list_to_const_vector (ret_list, nargout, varargout);
-    }
-
-  return retval;
+  return tw.execute_user_function (*this, nargout, args);
 }
 
 void
@@ -742,24 +488,20 @@
 octave_user_function::dump (void) const
 {
   std::map<std::string, octave_value> m
-    = {{ "file_name", file_name },
+    = {{ "user_code", octave_user_code::dump () },
        { "line", location_line },
        { "col", location_column },
        { "end_line", end_location_line },
        { "end_col", end_location_column },
-       { "time_parsed", t_parsed },
-       { "time_checked", t_checked },
        { "parent_name", parent_name },
        { "system_fcn_file", system_fcn_file },
-       { "call_depth", call_depth },
        { "num_named_args", num_named_args },
        { "subfunction", subfunction },
        { "inline_function", inline_function },
        { "anonymous_function", anonymous_function },
        { "nested_function", nested_function },
        { "ctor_type", ctor_type_str () },
-       { "class_method", class_method },
-       { "scope_info", m_scope ? m_scope.dump () : "0x0" }};
+       { "class_method", class_method }};
 
   return octave_value (m);
 }
--- a/libinterp/octave-value/ov-usr-fcn.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave-value/ov-usr-fcn.h	Fri Aug 10 09:09:51 2018 +0200
@@ -60,20 +60,19 @@
 {
 protected:
 
-  octave_user_code (const std::string& nm,
+  octave_user_code (const std::string& fnm = "", const std::string& nm = "",
                     const octave::symbol_scope& scope = octave::symbol_scope (),
+                    octave::tree_statement_list *cmds = nullptr,
                     const std::string& ds = "")
-    : octave_function (nm, ds), m_scope (scope), m_file_info (nullptr),
-      curr_unwind_protect_frame (nullptr)
+    : octave_function (nm, ds), m_scope (scope), file_name (fnm),
+      t_parsed (static_cast<time_t> (0)),
+      t_checked (static_cast<time_t> (0)),
+      m_call_depth (-1), m_file_info (nullptr),
+      cmd_list (cmds)
   { }
 
 public:
 
-  octave_user_code (void)
-    : octave_function (), m_scope (), m_file_info (nullptr),
-      curr_unwind_protect_frame (nullptr)
-  { }
-
   // No copying!
 
   octave_user_code (const octave_user_code& f) = delete;
@@ -84,12 +83,6 @@
 
   bool is_user_code (void) const { return true; }
 
-  octave::unwind_protect *
-  unwind_protect_frame (void)
-  {
-    return curr_unwind_protect_frame;
-  }
-
   std::string get_code_line (size_t line);
 
   std::deque<std::string> get_code_lines (size_t line, size_t num_lines);
@@ -99,9 +92,34 @@
 
   octave::symbol_scope scope (void) { return m_scope; }
 
+  void stash_fcn_file_name (const std::string& nm) { file_name = nm; }
+
+  void mark_fcn_file_up_to_date (const octave::sys::time& t) { t_checked = t; }
+
+  void stash_fcn_file_time (const octave::sys::time& t)
+  {
+    t_parsed = t;
+    mark_fcn_file_up_to_date (t);
+  }
+
+  std::string fcn_file_name (void) const { return file_name; }
+
+  octave::sys::time time_parsed (void) const { return t_parsed; }
+
+  octave::sys::time time_checked (void) const { return t_checked; }
+
+  // XXX FIXME
+  int call_depth (void) const { return m_call_depth; }
+
+  void set_call_depth (int val) { m_call_depth = val; }
+
+  void increment_call_depth (void) { ++m_call_depth; }
+
   virtual std::map<std::string, octave_value> subfunctions (void) const;
 
-  virtual octave::tree_statement_list * body (void) = 0;
+  octave::tree_statement_list * body (void) { return cmd_list; }
+
+  octave_value dump (void) const;
 
 protected:
 
@@ -110,12 +128,25 @@
   // Our symbol table scope.
   octave::symbol_scope m_scope;
 
+  // The name of the file we parsed.
+  std::string file_name;
+
+  // The time the file was parsed.
+  octave::sys::time t_parsed;
+
+  // The time the file was last checked to see if it needs to be
+  // parsed again.
+  octave::sys::time t_checked;
+
+  // Used to keep track of recursion depth.
+  int m_call_depth;
+
   // Cached text of function or script code with line offsets
   // calculated.
   octave::file_info *m_file_info;
 
-  // pointer to the current unwind_protect frame of this function.
-  octave::unwind_protect *curr_unwind_protect_frame;
+  // The list of commands that make up the body of this function.
+  octave::tree_statement_list *cmd_list;
 };
 
 // Scripts.
@@ -142,7 +173,7 @@
 
   octave_user_script& operator = (const octave_user_script& f) = delete;
 
-  ~octave_user_script (void);
+  ~octave_user_script (void) = default;
 
   octave_function * function_value (bool = false) { return this; }
 
@@ -155,48 +186,17 @@
 
   bool is_user_script (void) const { return true; }
 
-  void stash_fcn_file_name (const std::string& nm) { file_name = nm; }
-
-  void mark_fcn_file_up_to_date (const octave::sys::time& t) { t_checked = t; }
-
-  void stash_fcn_file_time (const octave::sys::time& t)
-  {
-    t_parsed = t;
-    mark_fcn_file_up_to_date (t);
-  }
-
-  std::string fcn_file_name (void) const { return file_name; }
-
-  octave::sys::time time_parsed (void) const { return t_parsed; }
-
-  octave::sys::time time_checked (void) const { return t_checked; }
-
   octave_value_list
   call (octave::tree_evaluator& tw, int nargout = 0,
         const octave_value_list& args = octave_value_list ());
 
-  octave::tree_statement_list * body (void) { return cmd_list; }
+  void accept (octave::tree_walker& tw);
 
-  void accept (octave::tree_walker& tw);
+  // XXX FIXME
+  void set_call_depth (int val) { octave_user_code::set_call_depth (val); }
 
 private:
 
-  // The list of commands that make up the body of this function.
-  octave::tree_statement_list *cmd_list;
-
-  // The name of the file we parsed.
-  std::string file_name;
-
-  // The time the file was parsed.
-  octave::sys::time t_parsed;
-
-  // The time the file was last checked to see if it needs to be
-  // parsed again.
-  octave::sys::time t_checked;
-
-  // Used to keep track of recursion depth.
-  int call_depth;
-
   DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
 };
 
@@ -223,7 +223,7 @@
   octave::symbol_record::context_id active_context () const
   {
     return is_anonymous_function ()
-      ? 0 : static_cast<octave::symbol_record::context_id>(call_depth);
+      ? 0 : static_cast<octave::symbol_record::context_id>(m_call_depth);
   }
 
   octave_function * function_value (bool = false) { return this; }
@@ -236,8 +236,6 @@
 
   octave_user_function * define_ret_list (octave::tree_parameter_list *t);
 
-  void stash_fcn_file_name (const std::string& nm);
-
   void stash_fcn_location (int line, int col)
   {
     location_line = line;
@@ -266,16 +264,6 @@
 
   void stash_trailing_comment (octave::comment_list *tc) { trail_comm = tc; }
 
-  void mark_fcn_file_up_to_date (const octave::sys::time& t) { t_checked = t; }
-
-  void stash_fcn_file_time (const octave::sys::time& t)
-  {
-    t_parsed = t;
-    mark_fcn_file_up_to_date (t);
-  }
-
-  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; }
@@ -285,10 +273,6 @@
     return m_scope.parent_scope ();
   }
 
-  octave::sys::time time_parsed (void) const { return t_parsed; }
-
-  octave::sys::time time_checked (void) const { return t_checked; }
-
   void mark_as_system_fcn_file (void);
 
   bool is_system_fcn_file (void) const { return system_fcn_file; }
@@ -385,8 +369,6 @@
 
   octave::tree_parameter_list * return_list (void) { return ret_list; }
 
-  octave::tree_statement_list * body (void) { return cmd_list; }
-
   octave::comment_list * leading_comment (void) { return lead_comm; }
 
   octave::comment_list * trailing_comment (void) { return trail_comm; }
@@ -407,6 +389,9 @@
 
   octave_value dump (void) const;
 
+  // XXX FIXME
+  void set_call_depth (int val) { octave_user_code::set_call_depth (val); }
+
 private:
 
   enum class_ctor_type
@@ -425,18 +410,12 @@
   // this function.
   octave::tree_parameter_list *ret_list;
 
-  // The list of commands that make up the body of this function.
-  octave::tree_statement_list *cmd_list;
-
   // The comments preceding the FUNCTION token.
   octave::comment_list *lead_comm;
 
   // The comments preceding the ENDFUNCTION token.
   octave::comment_list *trail_comm;
 
-  // The name of the file we parsed.
-  std::string file_name;
-
   // Location where this function was defined.
   int location_line;
   int location_column;
@@ -446,21 +425,11 @@
   // The name of the parent function, if any.
   std::string parent_name;
 
-  // The time the file was parsed.
-  octave::sys::time t_parsed;
-
-  // The time the file was last checked to see if it needs to be
-  // parsed again.
-  octave::sys::time t_checked;
-
   // True if this function came from a file that is considered to be a
   // system function.  This affects whether we check the time stamp
   // on the file to see if it has changed.
   bool system_fcn_file;
 
-  // Used to keep track of recursion depth.
-  int call_depth;
-
   // The number of arguments that have names.
   int num_named_args;
 
@@ -492,6 +461,9 @@
 
   void print_code_function_trailer (const std::string& prefix);
 
+  // XXX FIXME (public)
+public:
+
   void bind_automatic_vars (octave::tree_evaluator& tw,
                             const string_vector& arg_names,
                             int nargin, int nargout,
--- a/libinterp/octave.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/octave.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -26,6 +26,7 @@
 #  include "config.h"
 #endif
 
+#include <iostream>
 #include <string>
 
 #include "file-ops.h"
@@ -35,7 +36,6 @@
 #include "str-vec.h"
 
 #include "Cell.h"
-#include "defaults.h"
 #include "defun.h"
 #include "display.h"
 #include "error.h"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/octinterp.in.pc	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,9 @@
+Name: @PACKAGE_NAME@
+Description: C++ interface to GNU Octave interpreter.
+URL: https://www.octave.org
+Version: @PACKAGE_VERSION@
+Requires: octave = @PACKAGE_VERSION@
+Requires.private:
+Libs: -L@octlibdir@ @LIBOCTINTERP@
+Libs.private:
+Cflags: -I@octincludedir@/..
--- a/libinterp/op-kw-docs	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/op-kw-docs	Fri Aug 10 09:09:51 2018 +0200
@@ -17,14 +17,14 @@
 ## <https://www.gnu.org/licenses/>.
 
 !
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} !
 Logical 'not' operator.
 @seealso{~, not}
 @end deftypefn
 ~
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} ~
 Logical 'not' operator.
@@ -38,21 +38,21 @@
 @seealso{!, not}
 @end deftypefn
 !=
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} !=
 Logical 'not equals' operator.
 @seealso{~=, ne}
 @end deftypefn
 ~=
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} ~=
 Logical 'not equals' operator.
 @seealso{!=, ne}
 @end deftypefn
 "
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} "
 String delimiter.
@@ -63,21 +63,21 @@
 @seealso{'}
 @end deftypefn
 #
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} #
 Begin comment character.
 @seealso{%, #@\{}
 @end deftypefn
 %
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} %
 Begin comment character.
 @seealso{#, %@\{}
 @end deftypefn
 #{
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} #@{
 Begin block comment.
@@ -87,7 +87,7 @@
 @seealso{%@\{, #@\}, #}
 @end deftypefn
 %{
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} %@{
 Begin block comment.
@@ -97,7 +97,7 @@
 @seealso{#@\{, %@\}, %}
 @end deftypefn
 #}
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} #@}
 Close block comment.
@@ -107,7 +107,7 @@
 @seealso{%@\}, #@\{, #}
 @end deftypefn
 %}
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} %@}
 Close block comment.
@@ -117,7 +117,7 @@
 @seealso{#@\}, %@\{, %}
 @end deftypefn
 ...
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} ...
 Continuation marker.
@@ -125,21 +125,21 @@
 Joins current line with following line before parsing.
 @end deftypefn
 &
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} &
 Element by element logical 'and' operator.
 @seealso{&&, and}
 @end deftypefn
 &&
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} &&
 Logical 'and' operator (with short-circuit evaluation).
 @seealso{&, and}
 @end deftypefn
 '
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} '
 Matrix transpose operator or string delimiter.
@@ -153,26 +153,26 @@
 @seealso{.', transpose, "}
 @end deftypefn
 (
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} (
 Array index or function argument delimiter.
 @end deftypefn
 )
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {})
 Array index or function argument delimiter.
 @end deftypefn
 *
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} *
 Multiplication operator.
 @seealso{.*, times}
 @end deftypefn
 **
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} **
 Power operator.
@@ -183,7 +183,7 @@
 @seealso{power, ^, .**, .^, realpow, realsqrt, cbrt, nthroot}
 @end deftypefn
 ^
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} ^
 Power operator.
@@ -194,14 +194,14 @@
 @seealso{power, **, .^, .**, realpow, realsqrt, cbrt, nthroot}
 @end deftypefn
 +
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} +
 Addition operator.
 @seealso{plus}
 @end deftypefn
 ++
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} ++
 Increment operator.
@@ -210,20 +210,20 @@
 @seealso{--}
 @end deftypefn
 ,
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} ,
 Array index, function argument, or command separator.
 @end deftypefn
 -
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} -
 Subtraction or unary negation operator.
 @seealso{minus}
 @end deftypefn
 --
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} --
 Decrement operator.
@@ -232,7 +232,7 @@
 @seealso{++}
 @end deftypefn
 .'
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} .'
 Matrix transpose operator.
@@ -242,14 +242,14 @@
 @seealso{', transpose}
 @end deftypefn
 .*
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} .*
 Element by element multiplication operator.
 @seealso{*, times}
 @end deftypefn
 .**
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} .**
 Element by element power operator.
@@ -260,7 +260,7 @@
 @seealso{**, ^, .^, power, realpow, realsqrt, cbrt, nthroot}
 @end deftypefn
 .^
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} .^
 Element by element power operator.
@@ -271,28 +271,28 @@
 @seealso{.**, ^, **, power, realpow, realsqrt, cbrt, nthroot}
 @end deftypefn
 ./
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} ./
 Element by element right division operator.
 @seealso{/, .\\, rdivide, mrdivide}
 @end deftypefn
 /
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} /
 Right division operator.
 @seealso{./, \\, rdivide, mrdivide}
 @end deftypefn
 .\
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} .\
 Element by element left division operator.
 @seealso{\\, ./, rdivide, mrdivide}
 @end deftypefn
 \
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} \
 Left division operator.
@@ -302,89 +302,89 @@
 @seealso{.\\, /, ldivide, mldivide}
 @end deftypefn
 :
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} :
 Select entire rows or columns of matrices.
 @end deftypefn
 ;
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} ;
 Array row or command separator.
 @seealso{,}
 @end deftypefn
 <
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} <
 'Less than' operator.
 @seealso{lt}
 @end deftypefn
 <=
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} <=
 'Less than' or 'equals' operator.
 @seealso{le}
 @end deftypefn
 =
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} =
 Assignment operator.
 @end deftypefn
 ==
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} ==
 Equality test operator.
 @seealso{eq}
 @end deftypefn
 >
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} >
 'Greater than' operator.
 @seealso{gt}
 @end deftypefn
 >=
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} >=
 'Greater than' or 'equals' operator.
 @seealso{ge}
 @end deftypefn
 [
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} [
 Return list delimiter.
 @seealso{]}
 @end deftypefn
 ]
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} ]
 Return list delimiter.
 @seealso{[}
 @end deftypefn
 |
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} |
 Element by element logical 'or' operator.
 @seealso{||, or}
 @end deftypefn
 ||
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} ||
 Logical 'or' (with short-circuit evaluation) operator.
 @seealso{|, or}
 @end deftypefn
 @
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} @@
 Return handle to a function.
@@ -404,14 +404,14 @@
 @seealso{function, functions, func2str, str2func}
 @end deftypefn
 break
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} break
 Exit the innermost enclosing do, while, or for loop.
 @seealso{do, while, for, parfor, continue}
 @end deftypefn
 case
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn  {} {} case @var{value}
 @deftypefnx {} {} case @{@var{value}, @dots{}@}
@@ -423,7 +423,7 @@
 @seealso{switch}
 @end deftypefn
 catch
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn  {} {} catch
 @deftypefnx {} {} catch @var{value}
@@ -431,21 +431,21 @@
 @seealso{try}
 @end deftypefn
 classdef
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} classdef
 Begin a classdef block.
 @seealso{properties, methods, events, enumeration}
 @end deftypefn
 continue
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} continue
 Jump to the end of the innermost enclosing do, while, or for loop.
 @seealso{break, do, while, for, parfor}
 @end deftypefn
 do
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} do
 Begin a do-until loop.
@@ -464,124 +464,124 @@
 @seealso{for, until, while}
 @end deftypefn
 else
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} else
 Alternate action for an if block.  See @code{if} for  an example.
 @seealso{if}
 @end deftypefn
 elseif
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} elseif (@var{condition})
 Alternate conditional test for an if block.  See @code{if} for an example.
 @seealso{if}
 @end deftypefn
 end_try_catch
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} end_try_catch
 Mark the end of a @code{try-catch} block.
 @seealso{try, catch}
 @end deftypefn
 end_unwind_protect
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} end_unwind_protect
 Mark the end of an unwind_protect block.
 @seealso{unwind_protect}
 @end deftypefn
 endclassdef
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} endclassdef
 Mark the end of a classdef definition.
 @seealso{classdef}
 @end deftypefn
 endenumeration
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} endenumeration
 Mark the end of an enumeration block in a classdef definition.
 @seealso{enumeration}
 @end deftypefn
 endevents
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} endevents
 Mark the end of an events block in a classdef definition.
 @seealso{events}
 @end deftypefn
 endfor
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} endfor
 Mark the end of a for loop.  See @code{for} for an example.
 @seealso{for}
 @end deftypefn
 endfunction
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} endfunction
 Mark the end of a function.
 @seealso{function}
 @end deftypefn
 endif
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} endif
 Mark the end of an if block.  See @code{if} for an example.
 @seealso{if}
 @end deftypefn
 endmethods
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} endmethods
 Mark the end of a methods block in a classdef definition.
 @seealso{methods}
 @end deftypefn
 endparfor
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} endparfor
 Mark the end of a parfor loop.  See @code{parfor} for an example.
 @seealso{parfor}
 @end deftypefn
 endproperties
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} endproperties
 Mark the end of a properties block in a classdef definition.
 @seealso{properties}
 @end deftypefn
 endswitch
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} endswitch
 Mark the end of a switch block.  See @code{switch} for an example.
 @seealso{switch}
 @end deftypefn
 endwhile
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} endwhile
 Mark the end of a while loop.  See @code{while} for an example.
 @seealso{do, while}
 @end deftypefn
 enumeration
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} enumeration
 Begin an enumeration block in a classdef definition.
 @end deftypefn
 events
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} events
 Begin an events block in a classdef definition.
 @end deftypefn
 for
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} for @var{i} = @var{range}
 Begin a for loop.
@@ -596,7 +596,7 @@
 @seealso{parfor, do, while}
 @end deftypefn
 function
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn  {} {} function @var{outputs} = function_name (@var{input}, @dots{})
 @deftypefnx {} {} function {} function_name (@var{input}, @dots{})
@@ -612,7 +612,7 @@
 @seealso{return}
 @end deftypefn
 global
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} global @var{var}
 Declare variables to have global scope.
@@ -628,7 +628,7 @@
 @seealso{persistent}
 @end deftypefn
 if
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn  {} {} if (@var{cond}) @dots{} endif
 @deftypefnx {} {} if (@var{cond}) @dots{} else @dots{} endif
@@ -653,13 +653,13 @@
 @c ## FIXME: Can't have duplicate DOCSTRING entries.  The function methods
 @c ##        already has a docstring which overrides this keyword definition.
 @c #methods
-@c #@c libinterp/parse-tree/oct-parse.in.yy
+@c #@c libinterp/parse-tree/oct-parse.yy
 @c #-*- texinfo -*-
 @c #@deftypefn {} {} methods
 @c #Begin a methods block in a classdef definition.
 @c #@end deftypefn
 otherwise
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} otherwise
 The default statement in a switch block which is executed when no other
@@ -667,7 +667,7 @@
 @seealso{switch, case}
 @end deftypefn
 parfor
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn  {} {} parfor @var{i} = @var{range}
 @deftypefnx {} {} parfor (@var{i} = @var{range}, @var{maxproc})
@@ -683,7 +683,7 @@
 @seealso{for, do, while}
 @end deftypefn
 persistent
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} persistent @var{var}
 Declare variables as persistent.
@@ -696,27 +696,27 @@
 @seealso{global}
 @end deftypefn
 properties
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} properties
 Begin a properties block in a classdef definition.
 @end deftypefn
 return
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} return
 Return from a function.
 @seealso{function}
 @end deftypefn
 static
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} static
 This statement has been deprecated in favor of @code{persistent}.
 @seealso{persistent}
 @end deftypefn
 switch
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} switch @var{statement}
 Begin a switch block.
@@ -738,7 +738,7 @@
 @seealso{if, case, otherwise}
 @end deftypefn
 try
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} try
 Begin a try-catch block.
@@ -749,14 +749,14 @@
 @seealso{catch, unwind_protect}
 @end deftypefn
 until
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} until (@var{cond})
 End a do-until loop.  See @code{do} for an example.
 @seealso{do}
 @end deftypefn
 unwind_protect
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} unwind_protect
 Begin an unwind_protect block.
@@ -769,28 +769,28 @@
 @seealso{unwind_protect_cleanup, try}
 @end deftypefn
 unwind_protect_cleanup
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} unwind_protect_cleanup
 Begin the cleanup section of an unwind_protect block.
 @seealso{unwind_protect}
 @end deftypefn
 varargin
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} varargin
 Pass an arbitrary number of arguments into a function.
 @seealso{varargout, nargin, isargout, nargout, nthargout}
 @end deftypefn
 varargout
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} varargout
 Pass an arbitrary number of arguments out of a function.
 @seealso{varargin, nargin, isargout, nargout, nthargout}
 @end deftypefn
 while
-@c libinterp/parse-tree/oct-parse.in.yy
+@c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} while
 Begin a while loop.
--- a/libinterp/operators/module.mk	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/operators/module.mk	Fri Aug 10 09:09:51 2018 +0200
@@ -142,3 +142,4 @@
 	$(AM_V_GEN)rm -f $@-t $@ && \
 	$(SHELL) $(srcdir)/%reldir%/mk-ops.sh $(LIBINTERP_OPERATORS_SRC) > $@-t && \
 	mv $@-t $@
+
--- a/libinterp/parse-tree/bp-table.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/parse-tree/bp-table.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -26,14 +26,11 @@
 #endif
 
 #include <algorithm>
-#include <fstream>
 #include <limits>
 #include <list>
 #include <map>
 #include <set>
 #include <string>
-#include <sstream>
-#include <iostream>
 
 #include "file-ops.h"
 
@@ -41,6 +38,7 @@
 #include "defun-int.h"
 #include "call-stack.h"
 #include "error.h"
+#include "interpreter.h"
 #include "interpreter-private.h"
 #include "oct-map.h"
 #include "octave-link.h"
@@ -70,7 +68,7 @@
     Vdebug_on_warning = false;
     bp_table::m_warnings_that_stop.clear ();
 
-    octave::Vdebug_on_interrupt = false;
+    Vdebug_on_interrupt = false;
   }
 
   // Process the "warn", "errs", "caught" and "intr" fields for a call of
@@ -101,6 +99,7 @@
               }
           }
       }
+
     if (fail)
       error ("dbstop: invalid 'errs' field");
 
@@ -127,6 +126,7 @@
               }
           }
       }
+
     if (fail)
       error ("dbstop: invalid 'caught' field");
 
@@ -153,12 +153,13 @@
               }
           }
       }
+
     if (fail)
       error ("dbstop: invalid 'warn' field");
 
     // process interrupt
     if (mv.isfield ("intr"))
-      octave::Vdebug_on_interrupt = 1;
+      Vdebug_on_interrupt = 1;
   }
 
   // Insert a breakpoint in function fcn at line within file fname,
@@ -173,7 +174,7 @@
   {
     bool found = false;
 
-    octave::tree_statement_list *cmds = fcn->body ();
+    tree_statement_list *cmds = fcn->body ();
 
     std::string file = fcn->fcn_file_name ();
 
@@ -212,14 +213,15 @@
   {
     if (cond.length () > 0)
       {
-        octave::parser parser (cond + " ;"); // ; to reject partial expr like "y=="
+        // ; to reject partial expr like "y=="
+        parser parser (cond + " ;", m_evaluator.get_interpreter ());
         parser.reset ();
         int parse_status = parser.run ();
         if (parse_status)
           error ("dbstop: Cannot parse condition '%s'", cond.c_str ());
         else
           {
-            octave::tree_statement *stmt = nullptr;
+            tree_statement *stmt = nullptr;
             if (! parser.m_stmt_list)
               error ("dbstop: "
                      "condition is not empty, but has nothing to evaluate");
@@ -229,7 +231,7 @@
                     && (stmt = parser.m_stmt_list->front ())
                     && stmt->is_expression ())
                   {
-                    octave::tree_expression *expr = stmt->expression ();
+                    tree_expression *expr = stmt->expression ();
                     if (expr->is_assignment_expression ())
                       error ("dbstop: condition cannot be an assignment.  "
                              "Did you mean '=='?");
@@ -239,6 +241,7 @@
               }
           }
       }
+
     return true;
   }
 
@@ -336,7 +339,7 @@
               {
                 // It was a line number.  Get function name from debugger.
                 if (Vdebugging)
-                  symbol_name = get_user_code ()->profiler_name ();
+                  symbol_name = m_evaluator.get_user_code ()->profiler_name ();
                 else
                   error ("%s: function name must come before line number "
                          "and 'if'", who);
@@ -412,7 +415,7 @@
                   }
                 else if (condition == "interrupt")
                   {
-                    octave::Vdebug_on_interrupt = on_off;
+                    Vdebug_on_interrupt = on_off;
                   }
                 else if (condition == "naninf")
                   {
@@ -455,7 +458,7 @@
                         if (stop_flag == &Vdebug_on_error)
                           {
                             // Matlab stops on both.
-                            octave::Vdebug_on_interrupt = on_off;
+                            Vdebug_on_interrupt = on_off;
                           }
                       }
                   }
@@ -555,7 +558,7 @@
                                              const bp_table::intmap& line,
                                              const std::string& condition)
   {
-    octave_user_code *main_fcn = get_user_code (fname);
+    octave_user_code *main_fcn = m_evaluator.get_user_code (fname);
 
     if (! main_fcn)
       error ("add_breakpoint: unable to find function '%s'\n", fname.c_str ());
@@ -586,8 +589,7 @@
           }
       }
 
-    octave::tree_evaluator::debug_mode = bp_table::have_breakpoints ()
-                                         || Vdebugging;
+    m_evaluator.debug_mode (bp_table::have_breakpoints () || Vdebugging);
 
     return retval;
   }
@@ -600,7 +602,7 @@
 
     std::string file = fcn->fcn_file_name ();
 
-    octave::tree_statement_list *cmds = fcn->body ();
+    tree_statement_list *cmds = fcn->body ();
 
     // FIXME: move the operation on cmds to the tree_statement_list class?
 
@@ -629,7 +631,7 @@
 
             results = cmds->list_breakpoints ();
 
-            bp_set_iterator it = m_bp_set.find (fname);
+            auto it = m_bp_set.find (fname);
             if (results.empty () && it != m_bp_set.end ())
               m_bp_set.erase (it);
           }
@@ -654,7 +656,7 @@
       }
     else
       {
-        octave_user_code *dbg_fcn = get_user_code (fname);
+        octave_user_code *dbg_fcn = m_evaluator.get_user_code (fname);
 
         if (! dbg_fcn)
           error ("remove_breakpoint: unable to find function %s\n",
@@ -683,8 +685,7 @@
           }
       }
 
-    octave::tree_evaluator::debug_mode = bp_table::have_breakpoints ()
-                                         || Vdebugging;
+    m_evaluator.debug_mode (bp_table::have_breakpoints () || Vdebugging);
 
     return retval;
   }
@@ -697,19 +698,19 @@
   {
     intmap retval;
 
-    octave_user_code *dbg_fcn = get_user_code (fname);
+    octave_user_code *dbg_fcn = m_evaluator.get_user_code (fname);
 
     if (dbg_fcn)
       {
         std::string file = dbg_fcn->fcn_file_name ();
 
-        octave::tree_statement_list *cmds = dbg_fcn->body ();
+        tree_statement_list *cmds = dbg_fcn->body ();
 
         if (cmds)
           {
             retval = cmds->remove_all_breakpoints (file);
 
-            bp_set_iterator it = m_bp_set.find (fname);
+            auto it = m_bp_set.find (fname);
             if (it != m_bp_set.end ())
               m_bp_set.erase (it);
           }
@@ -718,25 +719,24 @@
       error ("remove_all_breakpoint_in_file: "
              "unable to find function %s\n", fname.c_str ());
 
-    octave::tree_evaluator::debug_mode = bp_table::have_breakpoints ()
-                                         || Vdebugging;
+    m_evaluator.debug_mode (bp_table::have_breakpoints () || Vdebugging);
 
     return retval;
   }
 
   void bp_table::remove_all_breakpoints (void)
   {
-    // Odd loop structure required because delete will invalidate m_bp_set iterators
-    for (const_bp_set_iterator it = m_bp_set.begin (), it_next = it;
-         it != m_bp_set.end ();
+    // Odd loop structure required because delete will invalidate
+    // m_bp_set iterators.
+    for (auto it = m_bp_set.cbegin (), it_next = it;
+         it != m_bp_set.cend ();
          it = it_next)
       {
         ++it_next;
         remove_all_breakpoints_in_file (*it);
       }
 
-    octave::tree_evaluator::debug_mode = bp_table::have_breakpoints ()
-                                         || Vdebugging;
+    m_evaluator.debug_mode (bp_table::have_breakpoints () || Vdebugging);
   }
 
   std::string find_bkpt_list (octave_value_list slist, std::string match)
@@ -768,11 +768,11 @@
         if (fname_list.empty ()
             || find_bkpt_list (fname_list, bp_fname) != "")
           {
-            octave_user_code *dbg_fcn = get_user_code (bp_fname);
+            octave_user_code *dbg_fcn = m_evaluator.get_user_code (bp_fname);
 
             if (dbg_fcn)
               {
-                octave::tree_statement_list *cmds = dbg_fcn->body ();
+                tree_statement_list *cmds = dbg_fcn->body ();
 
                 // FIXME: move the operation on cmds to the
                 //        tree_statement_list class?
@@ -917,7 +917,7 @@
       }
 
     // print dbstop if interrupt information
-    if (octave::Vdebug_on_interrupt)
+    if (Vdebug_on_interrupt)
       {
         if (to_screen)
           octave_stdout << "stop if interrupt\n";
@@ -928,46 +928,11 @@
     return retval;
   }
 
-  // Return a pointer to the user-defined function FNAME.  If FNAME is empty,
-  // search backward for the first user-defined function in the
-  // current call stack.
-
   octave_user_code *
   get_user_code (const std::string& fname)
   {
-    octave_user_code *dbg_fcn = nullptr;
-
-    if (fname.empty ())
-      {
-        octave::call_stack& cs = octave::__get_call_stack__ ("get_user_code");
-
-        dbg_fcn = cs.debug_user_code ();
-      }
-    else
-      {
-        std::string name = fname;
+    tree_evaluator& tw = __get_evaluator__ ("get_user_code");
 
-        if (octave::sys::file_ops::dir_sep_char () != '/' && name[0] == '@')
-          {
-            auto beg = name.begin () + 2;  // never have @/method
-            auto end = name.end () - 1;    // never have trailing '/'
-            std::replace (beg, end, '/', octave::sys::file_ops::dir_sep_char ());
-          }
-
-        size_t name_len = name.length ();
-
-        if (name_len > 2 && name.substr (name_len-2) == ".m")
-          name = name.substr (0, name_len-2);
-
-        octave::symbol_table& symtab =
-          octave::__get_symbol_table__ ("get_user_code");
-
-        octave_value fcn = symtab.find_function (name);
-
-        if (fcn.is_defined () && fcn.is_user_code ())
-          dbg_fcn = fcn.user_code_value ();
-      }
-
-    return dbg_fcn;
+    return tw.get_user_code (fname);
   }
 }
--- a/libinterp/parse-tree/bp-table.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/parse-tree/bp-table.h	Fri Aug 10 09:09:51 2018 +0200
@@ -36,6 +36,8 @@
 
 namespace octave
 {
+  class tree_evaluator;
+
   struct bp_type
   {
     int line;
@@ -49,9 +51,9 @@
   {
   public:
 
-    bp_table (void)
-      : m_bp_set (), m_errors_that_stop (), m_caught_that_stop (),
-        m_warnings_that_stop ()
+    bp_table (tree_evaluator& tw)
+      : m_evaluator (tw), m_bp_set (), m_errors_that_stop (),
+        m_caught_that_stop (), m_warnings_that_stop ()
     { }
 
     ~bp_table (void) = default;
@@ -128,6 +130,8 @@
     typedef std::set<std::string>::const_iterator const_bp_set_iterator;
     typedef std::set<std::string>::iterator bp_set_iterator;
 
+    tree_evaluator& m_evaluator;
+
     // Set of function (.m file) names containing at least one breakpoint.
     std::set<std::string> m_bp_set;
 
@@ -149,6 +153,7 @@
                                              const std::string& fname);
   };
 
+  OCTAVE_DEPRECATED (5, "use 'octave::get_user_code' instead")
   extern octave_user_code * get_user_code (const std::string& fname = "");
 }
 
--- a/libinterp/parse-tree/comment-list.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/parse-tree/comment-list.h	Fri Aug 10 09:09:51 2018 +0200
@@ -85,14 +85,14 @@
   };
 
   class
-  comment_list : public octave::base_list<comment_elt>
+  comment_list : public base_list<comment_elt>
   {
   public:
 
     comment_list (void) { }
 
     void append (const comment_elt& elt)
-    { octave::base_list<comment_elt>::append (elt); }
+    { base_list<comment_elt>::append (elt); }
 
     void append (const std::string& s,
                  comment_elt::comment_type t = comment_elt::unknown)
--- a/libinterp/parse-tree/jit-ir.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/parse-tree/jit-ir.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -50,7 +50,7 @@
   // -------------------- jit_factory --------------------
   jit_factory::~jit_factory (void)
   {
-    for (value_list::iterator iter = m_all_values.begin ();
+    for (auto iter = m_all_values.begin ();
          iter != m_all_values.end (); ++iter)
       delete *iter;
   }
@@ -111,7 +111,7 @@
   jit_block_list::print_dom (std::ostream& os) const
   {
     os << "-------------------- dom info --------------------\n";
-    for (const_iterator iter = begin (); iter != end (); ++iter)
+    for (auto iter = begin (); iter != end (); ++iter)
       {
         assert (*iter);
         (*iter)->print_dom (os);
@@ -125,15 +125,14 @@
   jit_block_list::push_back (jit_block *b)
   {
     m_list.push_back (b);
-    iterator iter = m_list.end ();
+    auto iter = m_list.end ();
     b->stash_location (--iter);
   }
 
   std::ostream&
   operator<<(std::ostream& os, const jit_block_list& blocks)
   {
-    for (jit_block_list::const_iterator iter = blocks.begin ();
-         iter != blocks.end (); ++iter)
+    for (auto iter = blocks.begin (); iter != blocks.end (); ++iter)
       {
         assert (*iter);
         (*iter)->print (os, 0);
@@ -290,7 +289,7 @@
       old_term->remove ();
 
     bool was_empty = end () == begin ();
-    iterator merge_begin = end ();
+    auto merge_begin = end ();
     if (! was_empty)
       --merge_begin;
 
@@ -302,7 +301,7 @@
 
     // now merge_begin points to the start of the new instructions, we must
     // update their parent information
-    for (iterator iter = merge_begin; iter != end (); ++iter)
+    for (auto iter = merge_begin; iter != end (); ++iter)
       {
         jit_instruction *instr = *iter;
         instr->stash_parent (this, iter);
@@ -323,7 +322,7 @@
   jit_block::prepend_after_phi (jit_instruction *instr)
   {
     // FIXME: Make this O(1)
-    for (iterator iter = begin (); iter != end (); ++iter)
+    for (auto iter = begin (); iter != end (); ++iter)
       {
         jit_instruction *temp = *iter;
         if (! isa<jit_phi> (temp))
@@ -346,7 +345,7 @@
   jit_instruction *
   jit_block::insert_before (iterator loc, jit_instruction *instr)
   {
-    iterator iloc = m_instructions.insert (loc, instr);
+    auto iloc = m_instructions.insert (loc, instr);
     instr->stash_parent (this, iloc);
     return instr;
   }
@@ -355,7 +354,7 @@
   jit_block::insert_after (iterator loc, jit_instruction *instr)
   {
     ++loc;
-    iterator iloc = m_instructions.insert (loc, instr);
+    auto iloc = m_instructions.insert (loc, instr);
     instr->stash_parent (this, iloc);
     return instr;
   }
@@ -419,7 +418,7 @@
       os << "NULL";
     os << std::endl;
     os << "  df: ";
-    for (df_iterator iter = df_begin (); iter != df_end (); ++iter)
+    for (auto iter = df_begin (); iter != df_end (); ++iter)
       os << **iter << ' ';
     os << std::endl;
 
@@ -505,7 +504,7 @@
   void
   jit_block::pop_all (void)
   {
-    for (iterator iter = begin (); iter != end (); ++iter)
+    for (auto iter = begin (); iter != end (); ++iter)
       {
         jit_instruction *instr = *iter;
         instr->pop_variable ();
@@ -526,7 +525,7 @@
       }
     os << std::endl;
 
-    for (const_iterator iter = begin (); iter != end (); ++iter)
+    for (auto iter = begin (); iter != end (); ++iter)
       {
         jit_instruction *instr = *iter;
         instr->print (os, indent + 1) << std::endl;
--- a/libinterp/parse-tree/jit-typeinfo.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/parse-tree/jit-typeinfo.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -216,7 +216,7 @@
   extern "C" void
   octave_jit_err_nan_to_logical_conversion (void)
   {
-    octave::err_nan_to_logical_conversion ();
+    err_nan_to_logical_conversion ();
   }
 
   extern "C" void
@@ -225,14 +225,14 @@
     // FIXME: 0-argument form of octave::err_invalid_index removed in
     //        cset dd6345fd8a97.  Report -1 as the bad index for all
     //        occurrences.
-    octave::err_invalid_index (static_cast<octave_idx_type> (-1));
+    err_invalid_index (static_cast<octave_idx_type> (-1));
   }
 
   extern "C" void
   octave_jit_gindex_range (int nd, int dim, octave_idx_type iext,
                            octave_idx_type ext)
   {
-    octave::err_index_out_of_range (nd, dim, iext, ext);
+    err_index_out_of_range (nd, dim, iext, ext);
   }
 
   extern "C" jit_matrix
@@ -397,7 +397,7 @@
   static inline int
   xisint (double x)
   {
-    return (octave::math::x_nint (x) == x
+    return (math::x_nint (x) == x
             && ((x >= 0 && x < std::numeric_limits<int>::max ())
                 || (x <= 0 && x > std::numeric_limits<int>::min ())));
   }
@@ -586,8 +586,7 @@
           }
       }
 
-    for (std::vector<jit_type *>::const_iterator iter = m_args.begin ();
-         iter != m_args.end (); ++iter)
+    for (auto iter = m_args.cbegin (); iter != m_args.cend (); ++iter)
       {
         jit_type *ty = *iter;
         assert (ty);
@@ -751,7 +750,7 @@
     // FIXME: We should be treating arguments like a list, not a vector.
     // Shouldn't matter much for now, as the number of arguments shouldn't
     // be much bigger than 4
-    llvm::Function::arg_iterator iter = m_llvm_function->arg_begin ();
+    auto iter = m_llvm_function->arg_begin ();
     if (sret ())
       ++iter;
 
@@ -804,8 +803,7 @@
   // -------------------- jit_operation --------------------
   jit_operation::~jit_operation (void)
   {
-    for (generated_map::iterator iter = m_generated.begin ();
-         iter != m_generated.end (); ++iter)
+    for (auto iter = m_generated.begin (); iter != m_generated.end (); ++iter)
       {
         delete iter->first;
         delete iter->second;
@@ -878,7 +876,7 @@
   jit_operation::to_idx (const std::vector<jit_type*>& types) const
   {
     octave_idx_type numel = types.size ();
-    numel = std::max (numel, static_cast<octave_idx_type>(2));
+    numel = std::max (numel, static_cast<octave_idx_type> (2));
 
     Array<octave_idx_type> idx (dim_vector (1, numel));
     for (octave_idx_type i = 0;
@@ -1975,7 +1973,7 @@
     std::vector<jit_type *> args;
     args.resize (1);
 
-    for (std::map<std::string, jit_type *>::iterator iter = m_builtins.begin ();
+    for (auto iter = m_builtins.begin ();
          iter != m_builtins.end (); ++iter)
       {
         jit_type *btype = iter->second;
--- a/libinterp/parse-tree/jit-typeinfo.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/parse-tree/jit-typeinfo.h	Fri Aug 10 09:09:51 2018 +0200
@@ -754,7 +754,7 @@
 
     const jit_operation& do_binary_op (int op) const
     {
-      assert (static_cast<size_t>(op) < m_binary_ops.size ());
+      assert (static_cast<size_t> (op) < m_binary_ops.size ());
       return m_binary_ops[op];
     }
 
--- a/libinterp/parse-tree/lex.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/parse-tree/lex.h	Fri Aug 10 09:09:51 2018 +0200
@@ -26,7 +26,6 @@
 #include "octave-config.h"
 
 #include <deque>
-#include <limits>
 #include <list>
 #include <set>
 #include <stack>
@@ -581,7 +580,7 @@
       comment_list *m_comment_list;
     };
 
-    base_lexer (interpreter *interp = nullptr)
+    base_lexer (interpreter& interp)
       : lexical_feedback (), m_scanner (nullptr), m_input_buf (),
         m_comment_buf (), m_interpreter (interp)
     {
@@ -676,6 +675,12 @@
 
     void fatal_error (const char *msg);
 
+    bool debug_flag (void) const;
+
+    bool display_tokens (void) const;
+
+    void increment_token_count (void);
+
     void lexer_debug (const char *pattern);
 
     // Internal state of the flex-generated lexer.
@@ -688,7 +693,7 @@
     comment_buffer m_comment_buf;
 
     // Interpreter that contains us, if any.
-    interpreter *m_interpreter;
+    interpreter& m_interpreter;
 
     virtual void increment_promptflag (void) = 0;
 
@@ -755,15 +760,15 @@
   {
   public:
 
-    lexer (interpreter *interp = nullptr)
+    lexer (interpreter& interp)
       : base_lexer (interp), m_reader (this)
     { }
 
-    lexer (FILE *file, interpreter *interp = nullptr)
+    lexer (FILE *file, interpreter& interp)
       : base_lexer (interp), m_reader (file, this)
     { }
 
-    lexer (const std::string& eval_string, interpreter *interp = nullptr)
+    lexer (const std::string& eval_string, interpreter& interp)
       : base_lexer (interp), m_reader (eval_string, this)
     { }
 
@@ -818,26 +823,25 @@
   {
   public:
 
-    push_lexer (interpreter *interp = nullptr)
+    push_lexer (interpreter& interp)
       : base_lexer (interp), m_pflag (1)
     {
       append_input ("", false);
     }
 
-    push_lexer (const std::string& input, interpreter *interp = nullptr)
+    push_lexer (const std::string& input, interpreter& interp)
       : base_lexer (interp), m_pflag (1)
     {
       append_input (input, false);
     }
 
-    push_lexer (bool eof, interpreter *interp = nullptr)
+    push_lexer (bool eof, interpreter& interp)
       : base_lexer (interp), m_pflag (1)
     {
       append_input ("", eof);
     }
 
-    push_lexer (const std::string& input, bool eof,
-                interpreter *interp = nullptr)
+    push_lexer (const std::string& input, bool eof, interpreter& interp)
       : base_lexer (interp), m_pflag (1)
     {
       append_input (input, eof);
--- a/libinterp/parse-tree/lex.ll	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/parse-tree/lex.ll	Fri Aug 10 09:09:51 2018 +0200
@@ -323,13 +323,6 @@
      }                                                                  \
    while (0)
 
-static bool Vdisplay_tokens = false;
-
-static unsigned int Vtoken_count = 0;
-
-// Internal variable for lexer debugging state.
-static bool lexer_debug_flag = false;
-
 %}
 
 D       [0-9]
@@ -514,6 +507,8 @@
 <MATRIX_START>{S}* {
     curr_lexer->lexer_debug ("<MATRIX_START>{S}*");
 
+    curr_lexer->m_current_input_column += yyleng;
+
     curr_lexer->mark_previous_token_trailing_space ();
   }
 
@@ -555,14 +550,7 @@
 <MATRIX_START>\] {
     curr_lexer->lexer_debug ("<MATRIX_START>\\]");
 
-    curr_lexer->m_looking_at_object_index.pop_front ();
-
-    curr_lexer->m_looking_for_object_index = true;
-    curr_lexer->m_at_beginning_of_statement = false;
-
-    curr_lexer->handle_close_bracket (']');
-
-    return curr_lexer->count_token (']');
+    return curr_lexer->handle_close_bracket (']');
   }
 
 %{
@@ -572,14 +560,7 @@
 <MATRIX_START>\} {
     curr_lexer->lexer_debug ("<MATRIX_START>\\}*");
 
-    curr_lexer->m_looking_at_object_index.pop_front ();
-
-    curr_lexer->m_looking_for_object_index = true;
-    curr_lexer->m_at_beginning_of_statement = false;
-
-    curr_lexer->handle_close_bracket ('}');
-
-    return curr_lexer->count_token ('}');
+    return curr_lexer->handle_close_bracket ('}');
   }
 
 \[ {
@@ -1149,6 +1130,8 @@
           {
             yyless (0);
             unput (',');
+            // Adjust for comma that was not really in the input stream.
+            curr_lexer->m_current_input_column--;
           }
         else
           {
@@ -1184,6 +1167,8 @@
           {
             yyless (0);
             unput (',');
+            // Adjust for comma that was not really in the input stream.
+            curr_lexer->m_current_input_column--;
           }
         else
           {
@@ -1330,6 +1315,8 @@
           {
             yyless (0);
             unput (',');
+            // Adjust for comma that was not really in the input stream.
+            curr_lexer->m_current_input_column--;
           }
         else
           {
@@ -1441,7 +1428,10 @@
                     curr_lexer->begin_string (SQ_STRING_START);
                   }
                 else
-                  return curr_lexer->count_token (HERMITIAN);
+                  {
+                    curr_lexer->m_current_input_column++;
+                    return curr_lexer->count_token (HERMITIAN);
+                  }
               }
           }
         else
@@ -1454,7 +1444,10 @@
                 curr_lexer->begin_string (SQ_STRING_START);
               }
             else
-              return curr_lexer->count_token (HERMITIAN);
+              {
+                curr_lexer->m_current_input_column++;
+                return curr_lexer->count_token (HERMITIAN);
+              }
           }
       }
   }
@@ -1761,7 +1754,7 @@
         std::ostringstream buf;
 
         buf << "invalid character '"
-            << undo_string_escape (static_cast<char> (c))
+            << octave::undo_string_escape (static_cast<char> (c))
             << "' (ASCII " << c << ")";
 
         octave::token *tok
@@ -2036,44 +2029,6 @@
 
 */
 
-DEFUN (__display_tokens__, args, nargout,
-       doc: /* -*- texinfo -*-
-@deftypefn {} {} __display_tokens__ ()
-Query or set the internal variable that determines whether Octave's
-lexer displays tokens as they are read.
-@seealso{__lexer_debug_flag__, __token_count__}
-@end deftypefn */)
-{
-  return SET_INTERNAL_VARIABLE (display_tokens);
-}
-
-DEFUN (__token_count__, , ,
-       doc: /* -*- texinfo -*-
-@deftypefn {} {} __token_count__ ()
-Return the number of language tokens processed since Octave startup.
-@seealso{__lexer_debug_flag__, __display_tokens__}
-@end deftypefn */)
-{
-  return octave_value (Vtoken_count);
-}
-
-DEFUN (__lexer_debug_flag__, args, nargout,
-       doc: /* -*- texinfo -*-
-@deftypefn  {} {@var{val} =} __lexer_debug_flag__ ()
-@deftypefnx {} {@var{old_val} =} __lexer_debug_flag__ (@var{new_val})
-Query or set the internal flag that determines whether Octave's lexer prints
-debug information as it processes an expression.
-@seealso{__display_tokens__, __token_count__, __parse_debug_flag__}
-@end deftypefn */)
-{
-  octave_value retval;
-
-  retval = set_internal_variable (lexer_debug_flag, args, nargout,
-                                  "__lexer_debug_flag__");
-
-  return retval;
-}
-
 namespace octave
 {
   void
@@ -2438,7 +2393,7 @@
   {
     int c = yyinput (m_scanner);
 
-    if (lexer_debug_flag)
+    if (debug_flag ())
       {
         std::cerr << "I: ";
         display_character (c);
@@ -2451,7 +2406,7 @@
       {
         c = yyinput (m_scanner);
 
-        if (lexer_debug_flag)
+        if (debug_flag ())
           {
             std::cerr << "I: ";
             display_character (c);
@@ -2473,7 +2428,7 @@
   {
     if (c != EOF)
       {
-        if (lexer_debug_flag)
+        if (debug_flag ())
           {
             std::cerr << "U: ";
             display_character (c);
@@ -2968,7 +2923,12 @@
   int
   base_lexer::handle_close_bracket (int bracket_type)
   {
-    int retval = bracket_type;
+    m_looking_at_object_index.pop_front ();
+
+    m_looking_for_object_index = true;
+    m_at_beginning_of_statement = false;
+
+    m_current_input_column++;
 
     if (! m_nesting_level.none ())
       {
@@ -2984,7 +2944,7 @@
 
     pop_start_state ();
 
-    return retval;
+    return count_token (bracket_type);
   }
 
   bool
@@ -3407,10 +3367,33 @@
     error ("fatal lexer error: %s", msg);
   }
 
+  bool
+  base_lexer::debug_flag (void) const
+  {
+    settings& stgs = m_interpreter.get_settings ();
+    return stgs.lexer_debug_flag ();
+  }
+
+  bool
+  base_lexer::display_tokens (void) const
+  {
+    settings& stgs = m_interpreter.get_settings ();
+    return stgs.display_tokens ();
+  }
+
+  void
+  base_lexer::increment_token_count (void)
+  {
+    settings& stgs = m_interpreter.get_settings ();
+    stgs.increment_token_count ();
+
+    m_token_count++;
+  }
+
   void
   base_lexer::lexer_debug (const char *pattern)
   {
-    if (lexer_debug_flag)
+    if (debug_flag ())
       {
         std::cerr << std::endl;
 
@@ -3600,10 +3583,7 @@
   base_lexer::count_token_internal (int tok)
   {
     if (tok != '\n')
-      {
-        Vtoken_count++;
-        m_token_count++;
-      }
+      increment_token_count ();
 
     return show_token (tok);
   }
@@ -3611,10 +3591,11 @@
   int
   base_lexer::show_token (int tok)
   {
-    if (Vdisplay_tokens)
+
+    if (display_tokens ())
       display_token (tok);
 
-    if (lexer_debug_flag)
+    if (debug_flag ())
       {
         std::cerr << "R: ";
         display_token (tok);
--- a/libinterp/parse-tree/module.mk	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/parse-tree/module.mk	Fri Aug 10 09:09:51 2018 +0200
@@ -79,7 +79,6 @@
   %reldir%/pt-id.cc \
   %reldir%/pt-idx.cc \
   %reldir%/pt-jit.cc \
-  %reldir%/pt-jump.cc \
   %reldir%/pt-loop.cc \
   %reldir%/pt-mat.cc \
   %reldir%/pt-misc.cc \
@@ -105,9 +104,6 @@
 	mv $@-t $@ && \
 	rm -f $@-t1
 
-%reldir%/oct-parse.yy: %reldir%/oct-parse.in.yy
-	$(AM_V_GEN)$(call subst-bison-api-decls,octave_)
-
 noinst_LTLIBRARIES += \
   %reldir%/libparse-tree.la
 
@@ -117,15 +113,5 @@
   $(libinterp_liboctinterp_la_CPPFLAGS) \
   $(LLVM_CPPFLAGS)
 
-%canon_reldir%_libparse_tree_la_CFLAGS = \
-  $(AM_CFLAGS) \
-  $(WARN_CFLAGS)
-
-%canon_reldir%_libparse_tree_la_CXXFLAGS = \
-  $(AM_CXXFLAGS) \
-  $(WARN_CXXFLAGS) \
-  $(LLVM_CXXFLAGS)
-
 libinterp_EXTRA_DIST += \
-  %reldir%/oct-parse.in.yy \
   %reldir%/octave.gperf
--- a/libinterp/parse-tree/oct-parse.in.yy	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,5982 +0,0 @@
-/*
-
-Copyright (C) 1993-2018 John W. Eaton
-Copyright (C) 2009 David Grundberg
-Copyright (C) 2009-2010 VZLU Prague
-Copyright (C) 2016-2018 Oliver Heimlich
-
-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
-<https://www.gnu.org/licenses/>.
-
-*/
-
-// Parser for Octave.
-
-// C decarations.
-
-%{
-
-#define YYDEBUG 1
-
-#if defined (HAVE_CONFIG_H)
-#  include "config.h"
-#endif
-
-#include <cassert>
-#include <cstdio>
-#include <cstdlib>
-
-#include <iostream>
-#include <map>
-#include <sstream>
-
-#include "Matrix.h"
-#include "cmd-edit.h"
-#include "cmd-hist.h"
-#include "file-ops.h"
-#include "file-stat.h"
-#include "oct-env.h"
-#include "oct-time.h"
-#include "quit.h"
-
-#include "Cell.h"
-#include "builtin-defun-decls.h"
-#include "call-stack.h"
-#include "defaults.h"
-#include "defun.h"
-#include "dirfns.h"
-#include "dynamic-ld.h"
-#include "error.h"
-#include "input.h"
-#include "interpreter-private.h"
-#include "interpreter.h"
-#include "lex.h"
-#include "load-path.h"
-#include "oct-hist.h"
-#include "oct-map.h"
-#include "ov-classdef.h"
-#include "ov-fcn-handle.h"
-#include "ov-usr-fcn.h"
-#include "ov-null-mat.h"
-#include "pager.h"
-#include "parse.h"
-#include "pt-all.h"
-#include "pt-eval.h"
-#include "pt-funcall.h"
-#include "symtab.h"
-#include "token.h"
-#include "unwind-prot.h"
-#include "utils.h"
-#include "variables.h"
-
-// oct-parse.h must be included after pt-all.h
-#include "oct-parse.h"
-
-extern int octave_lex (YYSTYPE *, void *);
-
-// List of autoloads (function -> file mapping).
-static std::map<std::string, std::string> autoload_map;
-
-// Forward declarations for some functions defined at the bottom of
-// the file.
-
-static void yyerror (octave::base_parser& parser, const char *s);
-
-#define lexer parser.m_lexer
-#define scanner lexer.m_scanner
-
-#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
-   // Disable this warning for code that is generated by Bison,
-   // including grammar rules.  Push the current state so we can
-   // restore the warning state prior to functions we define at
-   // the bottom of the file.
-#  pragma GCC diagnostic push
-#  pragma GCC diagnostic ignored "-Wold-style-cast"
-#endif
-
-%}
-
-// Bison declarations.
-
-// The grammar currently has 9 shift/reduce conflicts.  Ensure that
-// we notice if that number changes.
-
-%expect 9
-
-%API_PREFIX_DECL%
-
-// We are using the pure parser interface and the reentrant lexer
-// interface but the Octave parser and lexer are NOT properly
-// reentrant because both still use many global variables.  It should be
-// safe to create a parser object and call it while another parser
-// object is active (to parse a callback function while the main
-// interactive parser is waiting for input, for example) if you take
-// care to properly save and restore (typically with an unwind_protect
-// object) relevant global values before and after the nested call.
-
-%define api.pure
-%PUSH_PULL_DECL%
-%parse-param { octave::base_parser& parser }
-%lex-param { void *lexer.scanner }
-
-%union
-{
-  int dummy_type;
-
-  // The type of the basic tokens returned by the lexer.
-  octave::token *tok_val;
-
-  // Comment strings that we need to deal with mid-rule.
-  octave::comment_list *comment_type;
-
-  // Types for the nonterminals we generate.
-  char punct_type;
-  octave::tree *tree_type;
-  octave::tree_matrix *tree_matrix_type;
-  octave::tree_cell *tree_cell_type;
-  octave::tree_expression *tree_expression_type;
-  octave::tree_constant *tree_constant_type;
-  octave::tree_fcn_handle *tree_fcn_handle_type;
-  octave::tree_funcall *tree_funcall_type;
-  octave::tree_function_def *tree_function_def_type;
-  octave::tree_anon_fcn_handle *tree_anon_fcn_handle_type;
-  octave::tree_identifier *tree_identifier_type;
-  octave::tree_index_expression *tree_index_expression_type;
-  octave::tree_colon_expression *tree_colon_expression_type;
-  octave::tree_argument_list *tree_argument_list_type;
-  octave::tree_parameter_list *tree_parameter_list_type;
-  octave::tree_command *tree_command_type;
-  octave::tree_if_command *tree_if_command_type;
-  octave::tree_if_clause *tree_if_clause_type;
-  octave::tree_if_command_list *tree_if_command_list_type;
-  octave::tree_switch_command *tree_switch_command_type;
-  octave::tree_switch_case *tree_switch_case_type;
-  octave::tree_switch_case_list *tree_switch_case_list_type;
-  octave::tree_decl_elt *tree_decl_elt_type;
-  octave::tree_decl_init_list *tree_decl_init_list_type;
-  octave::tree_decl_command *tree_decl_command_type;
-  octave::tree_statement *tree_statement_type;
-  octave::tree_statement_list *tree_statement_list_type;
-  octave_user_function *octave_user_function_type;
-
-  octave::tree_classdef *tree_classdef_type;
-  octave::tree_classdef_attribute* tree_classdef_attribute_type;
-  octave::tree_classdef_attribute_list* tree_classdef_attribute_list_type;
-  octave::tree_classdef_superclass* tree_classdef_superclass_type;
-  octave::tree_classdef_superclass_list* tree_classdef_superclass_list_type;
-  octave::tree_classdef_body* tree_classdef_body_type;
-  octave::tree_classdef_property* tree_classdef_property_type;
-  octave::tree_classdef_property_list* tree_classdef_property_list_type;
-  octave::tree_classdef_properties_block* tree_classdef_properties_block_type;
-  octave::tree_classdef_methods_list* tree_classdef_methods_list_type;
-  octave::tree_classdef_methods_block* tree_classdef_methods_block_type;
-  octave::tree_classdef_event* tree_classdef_event_type;
-  octave::tree_classdef_events_list* tree_classdef_events_list_type;
-  octave::tree_classdef_events_block* tree_classdef_events_block_type;
-  octave::tree_classdef_enum* tree_classdef_enum_type;
-  octave::tree_classdef_enum_list* tree_classdef_enum_list_type;
-  octave::tree_classdef_enum_block* tree_classdef_enum_block_type;
-}
-
-// Tokens with line and column information.
-%token <tok_val> '=' ':' '-' '+' '*' '/'
-%token <tok_val> ADD_EQ SUB_EQ MUL_EQ DIV_EQ LEFTDIV_EQ POW_EQ
-%token <tok_val> EMUL_EQ EDIV_EQ ELEFTDIV_EQ EPOW_EQ AND_EQ OR_EQ
-%token <tok_val> EXPR_AND_AND EXPR_OR_OR
-%token <tok_val> EXPR_AND EXPR_OR EXPR_NOT
-%token <tok_val> EXPR_LT EXPR_LE EXPR_EQ EXPR_NE EXPR_GE EXPR_GT
-%token <tok_val> LEFTDIV EMUL EDIV ELEFTDIV EPLUS EMINUS
-%token <tok_val> HERMITIAN TRANSPOSE
-%token <tok_val> PLUS_PLUS MINUS_MINUS POW EPOW
-%token <tok_val> NUM IMAG_NUM
-%token <tok_val> STRUCT_ELT
-%token <tok_val> NAME
-%token <tok_val> END
-%token <tok_val> DQ_STRING SQ_STRING
-%token <tok_val> FOR PARFOR WHILE DO UNTIL
-%token <tok_val> IF ELSEIF ELSE
-%token <tok_val> SWITCH CASE OTHERWISE
-%token <tok_val> BREAK CONTINUE FUNC_RET
-%token <tok_val> UNWIND CLEANUP
-%token <tok_val> TRY CATCH
-%token <tok_val> GLOBAL PERSISTENT
-%token <tok_val> FCN_HANDLE
-%token <tok_val> CLASSDEF
-%token <tok_val> PROPERTIES METHODS EVENTS ENUMERATION
-%token <tok_val> METAQUERY
-%token <tok_val> SUPERCLASSREF
-%token <tok_val> FQ_IDENT
-%token <tok_val> GET SET
-%token <tok_val> FCN
-%token <tok_val> LEXICAL_ERROR
-
-// Other tokens.
-%token<dummy_type> END_OF_INPUT
-%token<dummy_type> INPUT_FILE
-// %token VARARGIN VARARGOUT
-
-%token<dummy_type> '(' ')' '[' ']' '{' '}' '.' ',' ';' '@' '\n'
-
-// Nonterminals we construct.
-%type <dummy_type> indirect_ref_op decl_param_init
-%type <dummy_type> push_fcn_symtab push_script_symtab begin_file
-%type <dummy_type> param_list_beg param_list_end stmt_begin parse_error
-%type <dummy_type> parsing_local_fcns
-%type <comment_type> stash_comment
-%type <tok_val> function_beg classdef_beg
-%type <punct_type> sep_no_nl opt_sep_no_nl nl opt_nl sep opt_sep
-%type <tree_type> input
-%type <tree_constant_type> string constant magic_colon
-%type <tree_anon_fcn_handle_type> anon_fcn_handle
-%type <tree_fcn_handle_type> fcn_handle
-%type <tree_matrix_type> matrix_rows
-%type <tree_cell_type> cell_rows
-%type <tree_expression_type> matrix cell
-%type <tree_expression_type> primary_expr oper_expr power_expr expr_no_assign
-%type <tree_expression_type> simple_expr colon_expr assign_expr expression
-%type <tree_identifier_type> identifier fcn_name magic_tilde
-%type <tree_funcall_type> superclass_identifier meta_identifier
-%type <tree_index_expression_type> word_list_cmd
-%type <tree_argument_list_type> arg_list word_list assign_lhs
-%type <tree_argument_list_type> cell_or_matrix_row
-%type <tree_parameter_list_type> opt_param_list param_list
-%type <tree_parameter_list_type> param_list1 param_list2
-%type <tree_parameter_list_type> return_list return_list1
-%type <tree_command_type> command select_command loop_command
-%type <tree_command_type> jump_command except_command
-%type <tree_function_def_type> function
-%type <tree_classdef_type> classdef
-%type <tree_command_type> file
-%type <tree_if_command_type> if_command
-%type <tree_if_clause_type> elseif_clause else_clause
-%type <tree_if_command_list_type> if_cmd_list1 if_cmd_list
-%type <tree_switch_command_type> switch_command
-%type <tree_switch_case_type> switch_case default_case
-%type <tree_switch_case_list_type> case_list1 case_list
-%type <tree_decl_elt_type> decl2 param_list_elt
-%type <tree_decl_init_list_type> decl1
-%type <tree_decl_command_type> declaration
-%type <tree_statement_type> statement function_end
-%type <tree_statement_list_type> simple_list simple_list1 list list1
-%type <tree_statement_list_type> opt_list
-%type <tree_statement_list_type> opt_fcn_list fcn_list fcn_list1
-%type <tree_classdef_attribute_type> attr
-%type <tree_classdef_attribute_list_type> attr_list opt_attr_list
-%type <tree_classdef_superclass_type> superclass
-%type <tree_classdef_superclass_list_type> superclass_list opt_superclass_list
-%type <tree_classdef_body_type> class_body
-%type <tree_classdef_property_type> class_property
-%type <tree_classdef_property_list_type> property_list
-%type <tree_classdef_properties_block_type> properties_block
-%type <tree_classdef_methods_list_type> methods_list
-%type <tree_classdef_methods_block_type> methods_block
-%type <tree_classdef_event_type> class_event
-%type <tree_classdef_events_list_type> events_list
-%type <tree_classdef_events_block_type> events_block
-%type <tree_classdef_enum_type> class_enum
-%type <tree_classdef_enum_list_type> enum_list
-%type <tree_classdef_enum_block_type> enum_block
-%type <tree_function_def_type> method_decl method
-%type <octave_user_function_type> method_decl1
-
-// Precedence and associativity.
-%right '=' ADD_EQ SUB_EQ MUL_EQ DIV_EQ LEFTDIV_EQ POW_EQ EMUL_EQ EDIV_EQ ELEFTDIV_EQ EPOW_EQ OR_EQ AND_EQ
-%left EXPR_OR_OR
-%left EXPR_AND_AND
-%left EXPR_OR
-%left EXPR_AND
-%left EXPR_LT EXPR_LE EXPR_EQ EXPR_NE EXPR_GE EXPR_GT
-%left ':'
-%left '-' '+' EPLUS EMINUS
-%left '*' '/' LEFTDIV EMUL EDIV ELEFTDIV
-%right UNARY EXPR_NOT
-%left POW EPOW HERMITIAN TRANSPOSE
-%right PLUS_PLUS MINUS_MINUS
-%left '(' '.' '{'
-
-// How to clean up if there is a parse error.  We handle deleting tokens
-// and comments seperately and separators are just characters.  The
-// remaining items are dynamically allocated parse tree objects that
-// must be deleted.  Use the wildcard case (<*>) to detect unhandled
-// cases (for example, a new semantic type is added but not handled
-// here).
-
-%destructor { } <tok_val>
-%destructor { } <punct_type>
-%destructor { } <comment_type>
-%destructor { } <>
-
-%destructor { delete $$; } <tree_type>
-%destructor { delete $$; } <tree_matrix_type>
-%destructor { delete $$; } <tree_cell_type>
-%destructor { delete $$; } <tree_expression_type>
-%destructor { delete $$; } <tree_constant_type>
-%destructor { delete $$; } <tree_fcn_handle_type>
-%destructor { delete $$; } <tree_funcall_type>
-%destructor { delete $$; } <tree_function_def_type>
-%destructor { delete $$; } <tree_anon_fcn_handle_type>
-%destructor { delete $$; } <tree_identifier_type>
-%destructor { delete $$; } <tree_index_expression_type>
-%destructor { delete $$; } <tree_argument_list_type>
-%destructor { delete $$; } <tree_parameter_list_type>
-%destructor { delete $$; } <tree_command_type>
-%destructor { delete $$; } <tree_if_command_type>
-%destructor { delete $$; } <tree_if_clause_type>
-%destructor { delete $$; } <tree_if_command_list_type>
-%destructor { delete $$; } <tree_switch_command_type>
-%destructor { delete $$; } <tree_switch_case_type>
-%destructor { delete $$; } <tree_switch_case_list_type>
-%destructor { delete $$; } <tree_decl_elt_type>
-%destructor { delete $$; } <tree_decl_init_list_type>
-%destructor { delete $$; } <tree_decl_command_type>
-%destructor { delete $$; } <tree_statement_type>
-%destructor { delete $$; } <tree_statement_list_type>
-%destructor { delete $$; } <octave_user_function_type>
-
-%destructor { delete $$; } <tree_classdef_type>
-%destructor { delete $$; } <tree_classdef_attribute_type>
-%destructor { delete $$; } <tree_classdef_attribute_list_type>
-%destructor { delete $$; } <tree_classdef_superclass_type>
-%destructor { delete $$; } <tree_classdef_superclass_list_type>
-%destructor { delete $$; } <tree_classdef_body_type>
-%destructor { delete $$; } <tree_classdef_property_type>
-%destructor { delete $$; } <tree_classdef_property_list_type>
-%destructor { delete $$; } <tree_classdef_properties_block_type>
-%destructor { delete $$; } <tree_classdef_methods_list_type>
-%destructor { delete $$; } <tree_classdef_methods_block_type>
-%destructor { delete $$; } <tree_classdef_event_type>
-%destructor { delete $$; } <tree_classdef_events_list_type>
-%destructor { delete $$; } <tree_classdef_events_block_type>
-%destructor { delete $$; } <tree_classdef_enum_type>
-%destructor { delete $$; } <tree_classdef_enum_list_type>
-%destructor { delete $$; } <tree_classdef_enum_block_type>
-
-// Defining a generic destructor generates a warning if destructors are
-// already explicitly declared for all types.
-//
-// %destructor {
-//    warning_with_id
-//      ("Octave:parser-destructor",
-//       "possible memory leak in cleanup following parse error");
-// } <*>
-
-// Where to start.
-%start input
-
-%%
-
-// ==============================
-// Statements and statement lists
-// ==============================
-
-input           : simple_list '\n'
-                  {
-                    $$ = nullptr;
-                    parser.m_stmt_list = $1;
-                    YYACCEPT;
-                  }
-                | simple_list END_OF_INPUT
-                  {
-                    $$ = nullptr;
-                    lexer.m_end_of_input = true;
-                    parser.m_stmt_list = $1;
-                    YYACCEPT;
-                  }
-                | parse_error
-                  {
-                    $$ = nullptr;
-                    YYABORT;
-                  }
-                ;
-
-simple_list     : opt_sep_no_nl
-                  {
-                    YYUSE ($1);
-
-                    $$ = nullptr;
-                  }
-                | simple_list1 opt_sep_no_nl
-                  { $$ = parser.set_stmt_print_flag ($1, $2, false); }
-                ;
-
-simple_list1    : statement
-                  { $$ = parser.make_statement_list ($1); }
-                | simple_list1 sep_no_nl statement
-                  { $$ = parser.append_statement_list ($1, $2, $3, false); }
-                ;
-
-opt_list        : // empty
-                  { $$ = new octave::tree_statement_list (); }
-                | list
-                  { $$ = $1; }
-                ;
-
-list            : list1 opt_sep
-                  { $$ = parser.set_stmt_print_flag ($1, $2, true); }
-                ;
-
-list1           : statement
-                  { $$ = parser.make_statement_list ($1); }
-                | list1 sep statement
-                  { $$ = parser.append_statement_list ($1, $2, $3, true); }
-                ;
-
-opt_fcn_list    : // empty
-                  { $$ = new octave::tree_statement_list (); }
-                | fcn_list
-                  { $$ = $1; }
-                ;
-
-fcn_list        : fcn_list1 opt_sep
-                  {
-                    YYUSE ($2);
-
-                    $$ = $1;
-                  }
-                ;
-
-fcn_list1       : function
-                  {
-                    octave::tree_statement *stmt = parser.make_statement ($1);
-                    $$ = new octave::tree_statement_list (stmt);
-                  }
-                | fcn_list1 opt_sep function
-                  {
-                    octave::tree_statement *stmt = parser.make_statement ($3);
-                    $$ = parser.append_statement_list ($1, $2, stmt, false);
-                  }
-                ;
-
-statement       : expression
-                  { $$ = parser.make_statement ($1); }
-                | command
-                  { $$ = parser.make_statement ($1); }
-                | word_list_cmd
-                  { $$ = parser.make_statement ($1); }
-                ;
-
-// =================
-// Word-list command
-// =================
-
-// These are not really like expressions since they can't appear on
-// the RHS of an assignment.  But they are also not like commands (IF,
-// WHILE, etc.
-
-word_list_cmd   : identifier word_list
-                  {
-                    $$ = parser.make_index_expression ($1, $2, '(');
-                    if (! $$)
-                      {
-                        // make_index_expression deleted $1 and $2.
-                        YYABORT;
-                      }
-                  }
-                ;
-
-word_list       : string
-                  { $$ = new octave::tree_argument_list ($1); }
-                | word_list string
-                  {
-                    $1->append ($2);
-                    $$ = $1;
-                  }
-                ;
-
-// ===========
-// Expressions
-// ===========
-
-identifier      : NAME
-                  {
-                    octave::symbol_record sr = $1->sym_rec ();
-                    $$ = new octave::tree_identifier (sr, $1->line (), $1->column ());
-                  }
-                ;
-
-superclass_identifier
-                : SUPERCLASSREF
-                  {
-                    std::string method_nm = $1->superclass_method_name ();
-                    std::string class_nm = $1->superclass_class_name ();
-
-                    $$ = parser.make_superclass_ref (method_nm, class_nm);
-                  }
-                ;
-
-meta_identifier : METAQUERY
-                  {
-                    std::string class_nm = $1->text ();
-
-                    $$ = parser.make_meta_class_query (class_nm);
-                  }
-                ;
-
-string          : DQ_STRING
-                  { $$ = parser.make_constant (DQ_STRING, $1); }
-                | SQ_STRING
-                  { $$ = parser.make_constant (SQ_STRING, $1); }
-                ;
-
-constant        : NUM
-                  { $$ = parser.make_constant (NUM, $1); }
-                | IMAG_NUM
-                  { $$ = parser.make_constant (IMAG_NUM, $1); }
-                | string
-                  { $$ = $1; }
-                ;
-
-matrix          : '[' matrix_rows ']'
-                  { $$ = parser.finish_matrix ($2); }
-                ;
-
-matrix_rows     : cell_or_matrix_row
-                  { $$ = $1 ? new octave::tree_matrix ($1) : nullptr; }
-                | matrix_rows ';' cell_or_matrix_row
-                  {
-                    if ($1)
-                      {
-                        if ($3)
-                          $1->append ($3);
-
-                        $$ = $1;
-                      }
-                    else
-                      $$ = $3 ? new octave::tree_matrix ($3) : nullptr;
-                  }
-                ;
-
-cell            : '{' cell_rows '}'
-                  { $$ = parser.finish_cell ($2); }
-                ;
-
-cell_rows       : cell_or_matrix_row
-                  { $$ = $1 ? new octave::tree_cell ($1) : nullptr; }
-                | cell_rows ';' cell_or_matrix_row
-                  {
-                    if ($1)
-                      {
-                        if ($3)
-                          $1->append ($3);
-
-                        $$ = $1;
-                      }
-                    else
-                      $$ = $3 ? new octave::tree_cell ($3) : nullptr;
-                  }
-                ;
-
-// tree_argument_list objects can't be empty or have leading or trailing
-// commas, but those are all allowed in matrix and cell array rows.
-
-cell_or_matrix_row
-                : // empty
-                  { $$ = nullptr; }
-                | ','
-                  { $$ = nullptr; }
-                | arg_list
-                  { $$ = $1; }
-                | arg_list ','
-                  { $$ = $1; }
-                | ',' arg_list
-                  { $$ = $2; }
-                | ',' arg_list ','
-                  { $$ = $2; }
-                ;
-
-fcn_handle      : '@' FCN_HANDLE
-                  {
-                    $$ = parser.make_fcn_handle ($2);
-                    lexer.m_looking_at_function_handle--;
-                  }
-                ;
-
-anon_fcn_handle : '@' param_list stmt_begin expr_no_assign
-                  {
-                    $$ = parser.make_anon_fcn_handle ($2, $4);
-                    lexer.m_nesting_level.remove ();
-                  }
-                | '@' param_list stmt_begin error
-                  {
-                    YYUSE ($2);
-
-                    $$ = nullptr;
-                    parser.bison_error ("anonymous function bodies must be single expressions");
-                    YYABORT;
-                  }
-                ;
-
-primary_expr    : identifier
-                  { $$ = $1; }
-                | constant
-                  { $$ = $1; }
-                | fcn_handle
-                  { $$ = $1; }
-                | matrix
-                  {
-                    lexer.m_looking_at_matrix_or_assign_lhs = false;
-                    $$ = $1;
-                  }
-                | cell
-                  { $$ = $1; }
-                | meta_identifier
-                  { $$ = $1; }
-                | superclass_identifier
-                  { $$ = $1; }
-                | '(' expression ')'
-                  { $$ = $2->mark_in_parens (); }
-                ;
-
-magic_colon     : ':'
-                  {
-                    YYUSE ($1);
-
-                    octave_value tmp (octave_value::magic_colon_t);
-                    $$ = new octave::tree_constant (tmp);
-                  }
-                ;
-
-magic_tilde     : EXPR_NOT
-                  {
-                    YYUSE ($1);
-
-                    $$ = new octave::tree_black_hole ();
-                  }
-                ;
-
-arg_list        : expression
-                  { $$ = new octave::tree_argument_list ($1); }
-                | magic_colon
-                  { $$ = new octave::tree_argument_list ($1); }
-                | magic_tilde
-                  { $$ = new octave::tree_argument_list ($1); }
-                | arg_list ',' magic_colon
-                  {
-                    $1->append ($3);
-                    $$ = $1;
-                  }
-                | arg_list ',' magic_tilde
-                  {
-                    $1->append ($3);
-                    $$ = $1;
-                  }
-                | arg_list ',' expression
-                  {
-                    $1->append ($3);
-                    $$ = $1;
-                  }
-                ;
-
-indirect_ref_op : '.'
-                  {
-                    $$ = 0;
-                    lexer.m_looking_at_indirect_ref = true;
-                  }
-                ;
-
-oper_expr       : primary_expr
-                  { $$ = $1; }
-                | oper_expr PLUS_PLUS
-                  { $$ = parser.make_postfix_op (PLUS_PLUS, $1, $2); }
-                | oper_expr MINUS_MINUS
-                  { $$ = parser.make_postfix_op (MINUS_MINUS, $1, $2); }
-                | oper_expr '(' ')'
-                  {
-                    $$ = parser.make_index_expression ($1, nullptr, '(');
-                    if (! $$)
-                      {
-                        // make_index_expression deleted $1.
-                        YYABORT;
-                      }
-                  }
-                | oper_expr '(' arg_list ')'
-                  {
-                    $$ = parser.make_index_expression ($1, $3, '(');
-                    if (! $$)
-                      {
-                        // make_index_expression deleted $1 and $3.
-                        YYABORT;
-                      }
-                  }
-                | oper_expr '{' '}'
-                  {
-                    $$ = parser.make_index_expression ($1, nullptr, '{');
-                    if (! $$)
-                      {
-                        // make_index_expression deleted $1.
-                        YYABORT;
-                      }
-                  }
-                | oper_expr '{' arg_list '}'
-                  {
-                    $$ = parser.make_index_expression ($1, $3, '{');
-                    if (! $$)
-                      {
-                        // make_index_expression deleted $1 and $3.
-                        YYABORT;
-                      }
-                  }
-                | oper_expr HERMITIAN
-                  { $$ = parser.make_postfix_op (HERMITIAN, $1, $2); }
-                | oper_expr TRANSPOSE
-                  { $$ = parser.make_postfix_op (TRANSPOSE, $1, $2); }
-                | oper_expr indirect_ref_op STRUCT_ELT
-                  { $$ = parser.make_indirect_ref ($1, $3->text ()); }
-                | oper_expr indirect_ref_op '(' expression ')'
-                  { $$ = parser.make_indirect_ref ($1, $4); }
-                | PLUS_PLUS oper_expr %prec UNARY
-                  { $$ = parser.make_prefix_op (PLUS_PLUS, $2, $1); }
-                | MINUS_MINUS oper_expr %prec UNARY
-                  { $$ = parser.make_prefix_op (MINUS_MINUS, $2, $1); }
-                | EXPR_NOT oper_expr %prec UNARY
-                  { $$ = parser.make_prefix_op (EXPR_NOT, $2, $1); }
-                | '+' oper_expr %prec UNARY
-                  { $$ = parser.make_prefix_op ('+', $2, $1); }
-                | '-' oper_expr %prec UNARY
-                  { $$ = parser.make_prefix_op ('-', $2, $1); }
-                | oper_expr POW power_expr
-                  { $$ = parser.make_binary_op (POW, $1, $2, $3); }
-                | oper_expr EPOW power_expr
-                  { $$ = parser.make_binary_op (EPOW, $1, $2, $3); }
-                | oper_expr '+' oper_expr
-                  { $$ = parser.make_binary_op ('+', $1, $2, $3); }
-                | oper_expr '-' oper_expr
-                  { $$ = parser.make_binary_op ('-', $1, $2, $3); }
-                | oper_expr '*' oper_expr
-                  { $$ = parser.make_binary_op ('*', $1, $2, $3); }
-                | oper_expr '/' oper_expr
-                  { $$ = parser.make_binary_op ('/', $1, $2, $3); }
-                | oper_expr EPLUS oper_expr
-                  { $$ = parser.make_binary_op ('+', $1, $2, $3); }
-                | oper_expr EMINUS oper_expr
-                  { $$ = parser.make_binary_op ('-', $1, $2, $3); }
-                | oper_expr EMUL oper_expr
-                  { $$ = parser.make_binary_op (EMUL, $1, $2, $3); }
-                | oper_expr EDIV oper_expr
-                  { $$ = parser.make_binary_op (EDIV, $1, $2, $3); }
-                | oper_expr LEFTDIV oper_expr
-                  { $$ = parser.make_binary_op (LEFTDIV, $1, $2, $3); }
-                | oper_expr ELEFTDIV oper_expr
-                  { $$ = parser.make_binary_op (ELEFTDIV, $1, $2, $3); }
-                ;
-
-power_expr      : primary_expr
-                  { $$ = $1; }
-                | power_expr PLUS_PLUS
-                  { $$ = parser.make_postfix_op (PLUS_PLUS, $1, $2); }
-                | power_expr MINUS_MINUS
-                  { $$ = parser.make_postfix_op (MINUS_MINUS, $1, $2); }
-                | power_expr '(' ')'
-                  {
-                    $$ = parser.make_index_expression ($1, nullptr, '(');
-                    if (! $$)
-                      {
-                        // make_index_expression deleted $1.
-                        YYABORT;
-                      }
-                  }
-                | power_expr '(' arg_list ')'
-                  {
-                    $$ = parser.make_index_expression ($1, $3, '(');
-                    if (! $$)
-                      {
-                        // make_index_expression deleted $1 and $3.
-                        YYABORT;
-                      }
-                  }
-                | power_expr '{' '}'
-                  {
-                    $$ = parser.make_index_expression ($1, nullptr, '{');
-                    if (! $$)
-                      {
-                        // make_index_expression deleted $1.
-                        YYABORT;
-                      }
-                  }
-                | power_expr '{' arg_list '}'
-                  {
-                    $$ = parser.make_index_expression ($1, $3, '{');
-                    if (! $$)
-                      {
-                        // make_index_expression deleted $1 and $3.
-                        YYABORT;
-                      }
-                  }
-                | power_expr indirect_ref_op STRUCT_ELT
-                  { $$ = parser.make_indirect_ref ($1, $3->text ()); }
-                | power_expr indirect_ref_op '(' expression ')'
-                  { $$ = parser.make_indirect_ref ($1, $4); }
-                | PLUS_PLUS power_expr %prec POW
-                  { $$ = parser.make_prefix_op (PLUS_PLUS, $2, $1); }
-                | MINUS_MINUS power_expr %prec POW
-                  { $$ = parser.make_prefix_op (MINUS_MINUS, $2, $1); }
-                | EXPR_NOT power_expr %prec POW
-                  { $$ = parser.make_prefix_op (EXPR_NOT, $2, $1); }
-                | '+' power_expr %prec POW
-                  { $$ = parser.make_prefix_op ('+', $2, $1); }
-                | '-' power_expr %prec POW
-                  { $$ = parser.make_prefix_op ('-', $2, $1); }
-                ;
-
-colon_expr      : oper_expr ':' oper_expr
-                  {
-                    YYUSE ($2);
-
-                    $$ = parser.make_colon_expression ($1, $3);
-
-                    if (! $$)
-                      {
-                        // finish_colon_expression deleted $1 and $3.
-                        YYABORT;
-                      }
-                  }
-                | oper_expr ':' oper_expr ':' oper_expr
-                  {
-                    YYUSE ($2);
-                    YYUSE ($4);
-
-                    $$ = parser.make_colon_expression ($1, $5, $3);
-
-                    if (! $$)
-                      {
-                        // finish_colon_expression deleted $1, $3, and $5.
-                        YYABORT;
-                      }
-                  }
-                ;
-
-simple_expr     : oper_expr
-                  { $$ = $1; }
-                | colon_expr
-                  { $$ = $1; }
-                | simple_expr EXPR_LT simple_expr
-                  { $$ = parser.make_binary_op (EXPR_LT, $1, $2, $3); }
-                | simple_expr EXPR_LE simple_expr
-                  { $$ = parser.make_binary_op (EXPR_LE, $1, $2, $3); }
-                | simple_expr EXPR_EQ simple_expr
-                  { $$ = parser.make_binary_op (EXPR_EQ, $1, $2, $3); }
-                | simple_expr EXPR_GE simple_expr
-                  { $$ = parser.make_binary_op (EXPR_GE, $1, $2, $3); }
-                | simple_expr EXPR_GT simple_expr
-                  { $$ = parser.make_binary_op (EXPR_GT, $1, $2, $3); }
-                | simple_expr EXPR_NE simple_expr
-                  { $$ = parser.make_binary_op (EXPR_NE, $1, $2, $3); }
-                | simple_expr EXPR_AND simple_expr
-                  { $$ = parser.make_binary_op (EXPR_AND, $1, $2, $3); }
-                | simple_expr EXPR_OR simple_expr
-                  { $$ = parser.make_binary_op (EXPR_OR, $1, $2, $3); }
-                | simple_expr EXPR_AND_AND simple_expr
-                  { $$ = parser.make_boolean_op (EXPR_AND_AND, $1, $2, $3); }
-                | simple_expr EXPR_OR_OR simple_expr
-                  { $$ = parser.make_boolean_op (EXPR_OR_OR, $1, $2, $3); }
-                ;
-
-assign_lhs      : simple_expr
-                  {
-                    $$ = parser.validate_matrix_for_assignment ($1);
-
-                    if ($$)
-                      { lexer.m_looking_at_matrix_or_assign_lhs = false; }
-                    else
-                      {
-                        // validate_matrix_for_assignment deleted $1.
-                        YYABORT;
-                      }
-                  }
-                ;
-
-assign_expr     : assign_lhs '=' expression
-                  { $$ = parser.make_assign_op ('=', $1, $2, $3); }
-                | assign_lhs ADD_EQ expression
-                  { $$ = parser.make_assign_op (ADD_EQ, $1, $2, $3); }
-                | assign_lhs SUB_EQ expression
-                  { $$ = parser.make_assign_op (SUB_EQ, $1, $2, $3); }
-                | assign_lhs MUL_EQ expression
-                  { $$ = parser.make_assign_op (MUL_EQ, $1, $2, $3); }
-                | assign_lhs DIV_EQ expression
-                  { $$ = parser.make_assign_op (DIV_EQ, $1, $2, $3); }
-                | assign_lhs LEFTDIV_EQ expression
-                  { $$ = parser.make_assign_op (LEFTDIV_EQ, $1, $2, $3); }
-                | assign_lhs POW_EQ expression
-                  { $$ = parser.make_assign_op (POW_EQ, $1, $2, $3); }
-                | assign_lhs EMUL_EQ expression
-                  { $$ = parser.make_assign_op (EMUL_EQ, $1, $2, $3); }
-                | assign_lhs EDIV_EQ expression
-                  { $$ = parser.make_assign_op (EDIV_EQ, $1, $2, $3); }
-                | assign_lhs ELEFTDIV_EQ expression
-                  { $$ = parser.make_assign_op (ELEFTDIV_EQ, $1, $2, $3); }
-                | assign_lhs EPOW_EQ expression
-                  { $$ = parser.make_assign_op (EPOW_EQ, $1, $2, $3); }
-                | assign_lhs AND_EQ expression
-                  { $$ = parser.make_assign_op (AND_EQ, $1, $2, $3); }
-                | assign_lhs OR_EQ expression
-                  { $$ = parser.make_assign_op (OR_EQ, $1, $2, $3); }
-                ;
-
-expr_no_assign  : simple_expr
-                  {
-                    if ($1 && ($1->is_matrix () || $1->iscell ()))
-                      {
-                        if (parser.validate_array_list ($1))
-                          $$ = $1;
-                        else
-                          {
-                            delete $1;
-                            YYABORT;
-                          }
-                      }
-                    else
-                      $$ = $1;
-                  }
-                | anon_fcn_handle
-                  { $$ = $1; }
-                ;
-
-expression      : expr_no_assign
-                  { $$ = $1; }
-                | assign_expr
-                  {
-                    if (! $1)
-                      YYABORT;
-
-                    $$ = $1;
-                  }
-
-// ================================================
-// Commands, declarations, and function definitions
-// ================================================
-
-command         : declaration
-                  { $$ = $1; }
-                | select_command
-                  { $$ = $1; }
-                | loop_command
-                  { $$ = $1; }
-                | jump_command
-                  { $$ = $1; }
-                | except_command
-                  { $$ = $1; }
-                | function
-                  { $$ = $1; }
-                | file
-                  { $$ = $1; }
-                ;
-
-// =====================
-// Declaration statemnts
-// =====================
-
-declaration     : GLOBAL decl1
-                  {
-                    $$ = parser.make_decl_command (GLOBAL, $1, $2);
-                    lexer.m_looking_at_decl_list = false;
-                  }
-                | PERSISTENT decl1
-                  {
-                    $$ = parser.make_decl_command (PERSISTENT, $1, $2);
-                    lexer.m_looking_at_decl_list = false;
-                  }
-                ;
-
-decl1           : decl2
-                  { $$ = new octave::tree_decl_init_list ($1); }
-                | decl1 decl2
-                  {
-                    $1->append ($2);
-                    $$ = $1;
-                  }
-                ;
-
-decl_param_init : // empty
-                  {
-                    $$ = 0;
-                    lexer.m_looking_at_initializer_expression = true;
-                  }
-
-decl2           : identifier
-                  { $$ = new octave::tree_decl_elt ($1); }
-                | identifier '=' decl_param_init expression
-                  {
-                    YYUSE ($2);
-
-                    lexer.m_looking_at_initializer_expression = false;
-                    $$ = new octave::tree_decl_elt ($1, $4);
-                  }
-                ;
-
-// ====================
-// Selection statements
-// ====================
-
-select_command  : if_command
-                  { $$ = $1; }
-                | switch_command
-                  { $$ = $1; }
-                ;
-
-// ============
-// If statement
-// ============
-
-if_command      : IF stash_comment if_cmd_list END
-                  {
-                    if (! ($$ = parser.finish_if_command ($1, $3, $4, $2)))
-                      {
-                        // finish_if_command deleted $3.
-                        YYABORT;
-                      }
-                  }
-                ;
-
-if_cmd_list     : if_cmd_list1
-                  { $$ = $1; }
-                | if_cmd_list1 else_clause
-                  {
-                    $1->append ($2);
-                    $$ = $1;
-                  }
-                ;
-
-if_cmd_list1    : expression stmt_begin opt_sep opt_list
-                  {
-                    YYUSE ($3);
-
-                    $1->mark_braindead_shortcircuit ();
-
-                    $$ = parser.start_if_command ($1, $4);
-                  }
-                | if_cmd_list1 elseif_clause
-                  {
-                    $1->append ($2);
-                    $$ = $1;
-                  }
-                ;
-
-elseif_clause   : ELSEIF stash_comment opt_sep expression stmt_begin opt_sep opt_list
-                  {
-                    YYUSE ($3);
-                    YYUSE ($6);
-
-                    $4->mark_braindead_shortcircuit ();
-
-                    $$ = parser.make_elseif_clause ($1, $4, $7, $2);
-                  }
-                ;
-
-else_clause     : ELSE stash_comment opt_sep opt_list
-                  {
-                    YYUSE ($1);
-                    YYUSE ($3);
-
-                    $$ = new octave::tree_if_clause ($4, $2);
-                  }
-                ;
-
-// ================
-// Switch statement
-// ================
-
-switch_command  : SWITCH stash_comment expression opt_sep case_list END
-                  {
-                    YYUSE ($4);
-
-                    if (! ($$ = parser.finish_switch_command ($1, $3, $5, $6, $2)))
-                      {
-                        // finish_switch_command deleted $3 adn $5.
-                        YYABORT;
-                      }
-                  }
-                ;
-
-case_list       : // empty
-                  { $$ = new octave::tree_switch_case_list (); }
-                | default_case
-                  { $$ = new octave::tree_switch_case_list ($1); }
-                | case_list1
-                  { $$ = $1; }
-                | case_list1 default_case
-                  {
-                    $1->append ($2);
-                    $$ = $1;
-                  }
-                ;
-
-case_list1      : switch_case
-                  { $$ = new octave::tree_switch_case_list ($1); }
-                | case_list1 switch_case
-                  {
-                    $1->append ($2);
-                    $$ = $1;
-                  }
-                ;
-
-switch_case     : CASE stash_comment opt_sep expression stmt_begin opt_sep opt_list
-                  {
-                    YYUSE ($3);
-                    YYUSE ($6);
-
-                    $$ = parser.make_switch_case ($1, $4, $7, $2);
-                  }
-                ;
-
-default_case    : OTHERWISE stash_comment opt_sep opt_list
-                  {
-                    YYUSE ($1);
-                    YYUSE ($3);
-
-                    $$ = new octave::tree_switch_case ($4, $2);
-                  }
-                ;
-
-// =======
-// Looping
-// =======
-
-loop_command    : WHILE stash_comment expression stmt_begin opt_sep opt_list END
-                  {
-                    YYUSE ($5);
-
-                    $3->mark_braindead_shortcircuit ();
-
-                    if (! ($$ = parser.make_while_command ($1, $3, $6, $7, $2)))
-                      {
-                        // make_while_command deleted $3 and $6.
-                        YYABORT;
-                      }
-                  }
-                | DO stash_comment opt_sep opt_list UNTIL expression
-                  {
-                    YYUSE ($1);
-                    YYUSE ($3);
-
-                    $$ = parser.make_do_until_command ($5, $4, $6, $2);
-                  }
-                | FOR stash_comment assign_lhs '=' expression stmt_begin opt_sep opt_list END
-                  {
-                    YYUSE ($4);
-                    YYUSE ($7);
-
-                    if (! ($$ = parser.make_for_command (FOR, $1, $3, $5,
-                                                         nullptr, $8, $9, $2)))
-                      {
-                        // make_for_command deleted $3, $5, and $8.
-                        YYABORT;
-                      }
-                  }
-                | FOR stash_comment '(' assign_lhs '=' expression ')' opt_sep opt_list END
-                  {
-                    YYUSE ($5);
-                    YYUSE ($8);
-
-                    if (! ($$ = parser.make_for_command (FOR, $1, $4, $6,
-                                                         nullptr, $9, $10, $2)))
-                      {
-                        // make_for_command deleted $4, $6, and $9.
-                        YYABORT;
-                      }
-                  }
-                | PARFOR stash_comment assign_lhs '=' expression stmt_begin opt_sep opt_list END
-                  {
-                    YYUSE ($4);
-                    YYUSE ($7);
-
-                    if (! ($$ = parser.make_for_command (PARFOR, $1, $3, $5,
-                                                         nullptr, $8, $9, $2)))
-                      {
-                        // make_for_command deleted $3, $5, and $8.
-                        YYABORT;
-                      }
-                  }
-                | PARFOR stash_comment '(' assign_lhs '=' expression ',' expression ')' opt_sep opt_list END
-                  {
-                    YYUSE ($5);
-                    YYUSE ($10);
-
-                    if (! ($$ = parser.make_for_command (PARFOR, $1, $4, $6,
-                                                         $8, $11, $12, $2)))
-                      {
-                        // make_for_command deleted $4, $6, $8, and $11.
-                        YYABORT;
-                      }
-                  }
-                ;
-
-// =======
-// Jumping
-// =======
-
-jump_command    : BREAK
-                  {
-                    if (! ($$ = parser.make_break_command ($1)))
-                      YYABORT;
-                  }
-                | CONTINUE
-                  { $$ = parser.make_continue_command ($1); }
-                | FUNC_RET
-                  { $$ = parser.make_return_command ($1); }
-                ;
-
-// ==========
-// Exceptions
-// ==========
-
-except_command  : UNWIND stash_comment opt_sep opt_list CLEANUP
-                  stash_comment opt_sep opt_list END
-                  {
-                    YYUSE ($3);
-                    YYUSE ($5);
-                    YYUSE ($7);
-
-                    if (! ($$ = parser.make_unwind_command ($1, $4, $8, $9, $2, $6)))
-                      {
-                        // make_unwind_command deleted $4 and $8.
-                        YYABORT;
-                      }
-                  }
-                | TRY stash_comment opt_sep opt_list CATCH stash_comment
-                  opt_sep opt_list END
-                  {
-                    YYUSE ($3);
-                    YYUSE ($5);
-                    YYUSE ($7);
-
-                    if (! ($$ = parser.make_try_command ($1, $4, $7, $8, $9, $2, $6)))
-                      {
-                        // make_try_command deleted $4 and $8.
-                        YYABORT;
-                      }
-                  }
-                | TRY stash_comment opt_sep opt_list END
-                  {
-                    YYUSE ($3);
-
-                    if (! ($$ = parser.make_try_command ($1, $4, 0, nullptr,
-                                                         $5, $2, nullptr)))
-                      {
-                        // make_try_command deleted $4.
-                        YYABORT;
-                      }
-                  }
-                ;
-
-// ===========================================
-// Some 'subroutines' for function definitions
-// ===========================================
-
-push_fcn_symtab : // empty
-                  {
-                    $$ = 0;
-
-                    parser.m_curr_fcn_depth++;
-
-                    if (parser.m_max_fcn_depth < parser.m_curr_fcn_depth)
-                      parser.m_max_fcn_depth = parser.m_curr_fcn_depth;
-
-                    // Will get a real name later.
-                    lexer.m_symtab_context.push (octave::symbol_scope ("parser:push_fcn_symtab"));
-                    parser.m_function_scopes.push (lexer.m_symtab_context.curr_scope ());
-
-                    if (! lexer.m_reading_script_file
-                        && parser.m_curr_fcn_depth == 1
-                        && ! parser.m_parsing_subfunctions)
-                      parser.m_primary_fcn_scope
-                        = lexer.m_symtab_context.curr_scope ();
-
-                    if (lexer.m_reading_script_file
-                        && parser.m_curr_fcn_depth > 1)
-                      {
-                        parser.bison_error ("nested functions not implemented in this context");
-                        YYABORT;
-                      }
-                  }
-                ;
-
-// ===========================
-// List of function parameters
-// ===========================
-
-param_list_beg  : '('
-                  {
-                    $$ = 0;
-                    lexer.m_looking_at_parameter_list = true;
-
-                    if (lexer.m_looking_at_function_handle)
-                      {
-                        // Will get a real name later.
-                        lexer.m_symtab_context.push (octave::symbol_scope ("parser:param_lsit_beg"));
-                        lexer.m_looking_at_function_handle--;
-                        lexer.m_looking_at_anon_fcn_args = true;
-                      }
-                  }
-                ;
-
-param_list_end  : ')'
-                  {
-                    $$ = 0;
-                    lexer.m_looking_at_parameter_list = false;
-                    lexer.m_looking_for_object_index = false;
-                  }
-                ;
-
-opt_param_list  : // empty
-                  { $$ = nullptr; }
-                | param_list
-                  { $$ = $1; }
-                ;
-
-param_list      : param_list_beg param_list1 param_list_end
-                  {
-                    if ($2)
-                      lexer.mark_as_variables ($2->variable_names ());
-
-                    $$ = $2;
-                  }
-                | param_list_beg error
-                  {
-                    $$ = nullptr;
-                    parser.bison_error ("invalid parameter list");
-                    YYABORT;
-                  }
-                ;
-
-param_list1     : // empty
-                  { $$ = nullptr; }
-                | param_list2
-                  {
-                    $1->mark_as_formal_parameters ();
-
-                    if (parser.validate_param_list ($1, octave::tree_parameter_list::in))
-                      {
-                        lexer.mark_as_variables ($1->variable_names ());
-                        $$ = $1;
-                      }
-                    else
-                      {
-                        delete $1;
-                        YYABORT;
-                      }
-                  }
-                ;
-
-param_list2     : param_list_elt
-                  { $$ = new octave::tree_parameter_list ($1); }
-                | param_list2 ',' param_list_elt
-                  {
-                    $1->append ($3);
-                    $$ = $1;
-                  }
-                ;
-
-param_list_elt  : decl2
-                  { $$ = $1; }
-                | magic_tilde
-                  { $$ = new octave::tree_decl_elt ($1); }
-                ;
-
-// ===================================
-// List of function return value names
-// ===================================
-
-return_list     : '[' ']'
-                  {
-                    lexer.m_looking_at_return_list = false;
-
-                    $$ = new octave::tree_parameter_list ();
-                  }
-                | identifier
-                  {
-                    lexer.m_looking_at_return_list = false;
-
-                    octave::tree_parameter_list *tmp = new octave::tree_parameter_list ($1);
-
-                    // Even though this parameter list can contain only
-                    // a single identifier, we still need to validate it
-                    // to check for varargin or varargout.
-
-                    if (parser.validate_param_list (tmp, octave::tree_parameter_list::out))
-                      $$ = tmp;
-                    else
-                      {
-                        delete tmp;
-                        YYABORT;
-                      }
-                  }
-                | '[' return_list1 ']'
-                  {
-                    lexer.m_looking_at_return_list = false;
-
-                    // Check for duplicate parameter names, varargin,
-                    // or varargout.
-
-                    if (parser.validate_param_list ($2, octave::tree_parameter_list::out))
-                      $$ = $2;
-                    else
-                      {
-                        delete $2;
-                        YYABORT;
-                      }
-                  }
-                ;
-
-return_list1    : identifier
-                  { $$ = new octave::tree_parameter_list (new octave::tree_decl_elt ($1)); }
-                | return_list1 ',' identifier
-                  {
-                    $1->append (new octave::tree_decl_elt ($3));
-                    $$ = $1;
-                  }
-                ;
-
-// =======================
-// Script or function file
-// =======================
-
-parsing_local_fcns
-                : // empty
-                  { parser.m_parsing_local_functions = true; }
-                ;
-
-push_script_symtab : // empty
-                  {
-                    $$ = 0;
-
-                    // This scope may serve as the parent scope for local
-                    // functions in classdef files..
-                    lexer.m_symtab_context.push (octave::symbol_scope ("parser:push_script_symtab"));
-                  }
-                ;
-
-begin_file      : push_script_symtab INPUT_FILE
-                  { $$ = 0; }
-                ;
-
-file            : begin_file opt_nl opt_list END_OF_INPUT
-                  {
-                    YYUSE ($2);
-
-                    if (lexer.m_reading_fcn_file)
-                      {
-                        // Delete the dummy statement_list we created
-                        // after parsing the function.  Any function
-                        // definitions found in the file have already
-                        // been stored in the symbol table or in
-                        // base_parser::m_primary_fcn_ptr.
-
-                        // Unused symbol table context.
-                        lexer.m_symtab_context.pop ();
-
-                        delete $3;
-                      }
-                    else
-                      {
-                        octave::tree_statement *end_of_script
-                          = parser.make_end ("endscript", true,
-                                             lexer.m_input_line_number,
-                                             lexer.m_current_input_column);
-
-                        parser.make_script ($3, end_of_script);
-                      }
-
-                    $$ = nullptr;
-                  }
-                | begin_file opt_nl classdef parsing_local_fcns opt_sep opt_fcn_list END_OF_INPUT
-                  {
-                    YYUSE ($2);
-                    YYUSE ($5);
-
-                    // Unused symbol table context.
-                    lexer.m_symtab_context.pop ();
-
-                    parser.finish_classdef_file ($3, $6);
-
-                    $$ = nullptr;
-                  }
-                ;
-
-// ===================
-// Function definition
-// ===================
-
-function_beg    : push_fcn_symtab FCN
-                  {
-                    $$ = $2;
-                    if (lexer.m_reading_classdef_file
-                        || lexer.m_parsing_classdef)
-                      lexer.m_maybe_classdef_get_set_method = true;
-                  }
-                ;
-
-fcn_name        : identifier
-                  {
-                    std::string id = $1->name ();
-
-                    // Make classdef local functions unique from
-                    // classdef methods.
-
-                    if (parser.m_parsing_local_functions
-                        && parser.m_curr_fcn_depth == 1)
-                      id = lexer.m_fcn_file_name + ">" + id;
-
-                    if (! parser.m_function_scopes.name_current_scope (id))
-                      {
-                        parser.bison_error ("duplicate subfunction or nested function name",
-                                            $1->line (), $1->column ());
-
-                        delete $1;
-
-                        YYABORT;
-                      }
-
-                    octave::symbol_scope curr_scope
-                      = lexer.m_symtab_context.curr_scope ();
-                    curr_scope.cache_name (id);
-
-                    lexer.m_parsed_function_name.top () = true;
-                    lexer.m_maybe_classdef_get_set_method = false;
-
-                    $$ = $1;
-                  }
-                | GET '.' identifier
-                  {
-                    YYUSE ($1);
-
-                    lexer.m_parsed_function_name.top () = true;
-                    lexer.m_maybe_classdef_get_set_method = false;
-                    lexer.m_parsing_classdef_get_method = true;
-                    $$ = $3;
-                  }
-                | SET '.' identifier
-                  {
-                    YYUSE ($1);
-
-                    lexer.m_parsed_function_name.top () = true;
-                    lexer.m_maybe_classdef_get_set_method = false;
-                    lexer.m_parsing_classdef_set_method = true;
-                    $$ = $3;
-                  }
-                ;
-
-function_end    : END
-                  {
-                    parser.m_endfunction_found = true;
-
-                    if (parser.end_token_ok ($1, octave::token::function_end))
-                      $$ = parser.make_end ("endfunction", false,
-                                            $1->line (), $1->column ());
-                    else
-                      {
-                        parser.end_token_error ($1, octave::token::function_end);
-                        YYABORT;
-                      }
-                  }
-                | END_OF_INPUT
-                  {
-// A lot of tests are based on the assumption that this is OK
-//                  if (lexer.m_reading_script_file)
-//                    {
-//                      parser.bison_error ("function body open at end of script");
-//                      YYABORT;
-//                    }
-
-                    if (parser.m_endfunction_found)
-                      {
-                        parser.bison_error ("inconsistent function endings -- "
-                                 "if one function is explicitly ended, "
-                                 "so must all the others");
-                        YYABORT;
-                      }
-
-                    if (! (lexer.m_reading_fcn_file || lexer.m_reading_script_file
-                           || lexer.input_from_eval_string ()))
-                      {
-                        parser.bison_error ("function body open at end of input");
-                        YYABORT;
-                      }
-
-                    if (lexer.m_reading_classdef_file)
-                      {
-                        parser.bison_error ("classdef body open at end of input");
-                        YYABORT;
-                      }
-
-                    $$ = parser.make_end ("endfunction", true,
-                                          lexer.m_input_line_number,
-                                          lexer.m_current_input_column);
-                  }
-                ;
-
-function        : function_beg stash_comment fcn_name
-                  opt_param_list opt_sep opt_list function_end
-                  {
-                    YYUSE ($5);
-
-                    $$ = parser.make_function ($1, nullptr, $3, $4, $6, $7, $2);
-                  }
-                | function_beg stash_comment return_list '=' fcn_name
-                  opt_param_list opt_sep opt_list function_end
-                  {
-                    YYUSE ($4);
-                    YYUSE ($7);
-
-                    $$ = parser.make_function ($1, $3, $5, $6, $8, $9, $2);
-                  }
-                ;
-
-// ========
-// Classdef
-// ========
-
-classdef_beg    : CLASSDEF
-                  {
-                    if (! lexer.m_reading_classdef_file)
-                      {
-                        parser.bison_error ("classdef must appear inside a file containing only a class definition");
-                        YYABORT;
-                      }
-
-                    // Create invalid parent scope.
-                    lexer.m_symtab_context.push (octave::symbol_scope ());
-                    lexer.m_parsing_classdef = true;
-                    $$ = $1;
-                  }
-                ;
-
-classdef        : classdef_beg stash_comment opt_attr_list identifier opt_superclass_list opt_sep class_body opt_sep END
-                  {
-                    YYUSE ($6);
-                    YYUSE ($8);
-
-                    lexer.m_parsing_classdef = false;
-
-                    if (! ($$ = parser.make_classdef ($1, $3, $4, $5, $7, $9, $2)))
-                      {
-                        // make_classdef deleted $3, $4, $5, and $7.
-                        YYABORT;
-                      }
-                  }
-                | classdef_beg stash_comment opt_attr_list identifier opt_superclass_list opt_sep END
-                  {
-                    YYUSE ($6);
-
-                    lexer.m_parsing_classdef = false;
-
-                    if (! ($$ = parser.make_classdef ($1, $3, $4, $5, nullptr,
-                                                      $7, $2)))
-                      {
-                        // make_classdef deleted $3, $4, and $5.
-                        YYABORT;
-                      }
-                  }
-                ;
-
-opt_attr_list   : // empty
-                  { $$ = nullptr; }
-                | '(' attr_list ')'
-                  { $$ = $2; }
-                ;
-
-attr_list       : attr
-                  { $$ = new octave::tree_classdef_attribute_list ($1); }
-                | attr_list ',' attr
-                  {
-                    $1->append ($3);
-                    $$ = $1;
-                  }
-                ;
-
-attr            : identifier
-                  { $$ = new octave::tree_classdef_attribute ($1); }
-                | identifier '=' decl_param_init expression
-                  {
-                    YYUSE ($2);
-
-                    lexer.m_looking_at_initializer_expression = false;
-                    $$ = new octave::tree_classdef_attribute ($1, $4);
-                  }
-                | EXPR_NOT identifier
-                  {
-                    YYUSE ($1);
-
-                    $$ = new octave::tree_classdef_attribute ($2, false);
-                  }
-                ;
-
-opt_superclass_list
-                : // empty
-                  { $$ = nullptr; }
-                | superclass_list
-                  { $$ = $1; }
-                ;
-
-superclass_list : EXPR_LT
-                  {
-                    YYUSE ($1);
-
-                    lexer.enable_fq_identifier ();
-                  }
-                  superclass
-                  { $$ = new octave::tree_classdef_superclass_list ($3); }
-                | superclass_list EXPR_AND
-                  {
-                    YYUSE ($2);
-
-                    lexer.enable_fq_identifier ();
-                  }
-                  superclass
-                  {
-                    $1->append ($4);
-                    $$ = $1;
-                  }
-                ;
-
-superclass      : FQ_IDENT
-                  { $$ = new octave::tree_classdef_superclass ($1->text ()); }
-                ;
-
-class_body      : properties_block
-                  { $$ = new octave::tree_classdef_body ($1); }
-                | methods_block
-                  { $$ = new octave::tree_classdef_body ($1); }
-                | events_block
-                  { $$ = new octave::tree_classdef_body ($1); }
-                | enum_block
-                  { $$ = new octave::tree_classdef_body ($1); }
-                | class_body opt_sep properties_block
-                  {
-                    YYUSE ($2);
-
-                    $1->append ($3);
-                    $$ = $1;
-                  }
-                | class_body opt_sep methods_block
-                  {
-                    YYUSE ($2);
-
-                    $1->append ($3);
-                    $$ = $1;
-                  }
-                | class_body opt_sep events_block
-                  {
-                    YYUSE ($2);
-
-                    $1->append ($3);
-                    $$ = $1;
-                  }
-                | class_body opt_sep enum_block
-                  {
-                    YYUSE ($2);
-
-                    $1->append ($3);
-                    $$ = $1;
-                  }
-                ;
-
-properties_block
-                : PROPERTIES stash_comment opt_attr_list opt_sep property_list opt_sep END
-                  {
-                    YYUSE ($4);
-                    YYUSE ($6);
-
-                    if (! ($$ = parser.make_classdef_properties_block
-                           ($1, $3, $5, $7, $2)))
-                      {
-                        // make_classdef_properties_block delete $3 and $5.
-                        YYABORT;
-                      }
-                  }
-                | PROPERTIES stash_comment opt_attr_list opt_sep END
-                  {
-                    YYUSE ($4);
-
-                    if (! ($$ = parser.make_classdef_properties_block
-                           ($1, $3, nullptr, $5, $2)))
-                      {
-                        // make_classdef_properties_block delete $3.
-                        YYABORT;
-                      }
-                  }
-                ;
-
-property_list
-                : class_property
-                  { $$ = new octave::tree_classdef_property_list ($1); }
-                | property_list sep class_property
-                  {
-                    YYUSE ($2);
-
-                    $1->append ($3);
-                    $$ = $1;
-                  }
-                ;
-
-class_property  : identifier
-                  { $$ = new octave::tree_classdef_property ($1); }
-                | identifier '=' decl_param_init expression
-                  {
-                    YYUSE ($2);
-
-                    lexer.m_looking_at_initializer_expression = false;
-                    $$ = new octave::tree_classdef_property ($1, $4);
-                  }
-                ;
-
-methods_block   : METHODS stash_comment opt_attr_list opt_sep methods_list opt_sep END
-                  {
-                    YYUSE ($4);
-                    YYUSE ($6);
-
-                    if (! ($$ = parser.make_classdef_methods_block
-                           ($1, $3, $5, $7, $2)))
-                      {
-                        // make_classdef_methods_block deleted $3 and $5.
-                        YYABORT;
-                      }
-                  }
-                | METHODS stash_comment opt_attr_list opt_sep END
-                  {
-                    YYUSE ($4);
-
-                    if (! ($$ = parser.make_classdef_methods_block
-                           ($1, $3, nullptr, $5, $2)))
-                      {
-                        // make_classdef_methods_block deleted $3.
-                        YYABORT;
-                      }
-                  }
-                ;
-                ;
-
-method_decl1    : identifier
-                  {
-                    if (! ($$ = parser.start_classdef_external_method ($1, nullptr)))
-                      YYABORT;
-                  }
-                | identifier param_list
-                  {
-                    if (! ($$ = parser.start_classdef_external_method ($1, $2)))
-                      YYABORT;
-                  }
-                ;
-
-method_decl     : stash_comment method_decl1
-                  { $$ = parser.finish_classdef_external_method ($2, nullptr, $1); }
-                | stash_comment return_list '='
-                  {
-                    YYUSE ($3);
-
-                    lexer.m_defining_func++;
-                    lexer.m_parsed_function_name.push (false);
-                  }
-                  method_decl1
-                  {
-                    lexer.m_defining_func--;
-                    lexer.m_parsed_function_name.pop ();
-                    $$ = parser.finish_classdef_external_method ($5, $2, $1);
-                  }
-                ;
-
-method          : method_decl
-                  { $$ = $1; }
-                | function
-                  { $$ = $1; }
-                ;
-
-methods_list    : method
-                  {
-                    octave_value fcn;
-                    if ($1)
-                      fcn = $1->function ();
-                    delete $1;
-                    $$ = new octave::tree_classdef_methods_list (fcn);
-                  }
-                | methods_list opt_sep method
-                  {
-                    YYUSE ($2);
-
-                    octave_value fcn;
-                    if ($3)
-                      fcn = $3->function ();
-                    delete $3;
-
-                    $1->append (fcn);
-                    $$ = $1;
-                  }
-                ;
-
-events_block    : EVENTS stash_comment opt_attr_list opt_sep events_list opt_sep END
-                  {
-                    YYUSE ($4);
-                    YYUSE ($6);
-
-                    if (! ($$ = parser.make_classdef_events_block
-                           ($1, $3, $5, $7, $2)))
-                      {
-                        // make_classdef_events_block deleted $3 and $5.
-                        YYABORT;
-                      }
-                  }
-                | EVENTS stash_comment opt_attr_list opt_sep END
-                  {
-                    YYUSE ($4);
-
-                    if (! ($$ = parser.make_classdef_events_block
-                           ($1, $3, nullptr, $5, $2)))
-                      {
-                        // make_classdef_events_block deleted $3.
-                        YYABORT;
-                      }
-                  }
-                ;
-
-events_list     : class_event
-                  { $$ = new octave::tree_classdef_events_list ($1); }
-                | events_list opt_sep class_event
-                  {
-                    YYUSE ($2);
-
-                    $1->append ($3);
-                    $$ = $1;
-                  }
-                ;
-
-class_event     : identifier
-                  { $$ = new octave::tree_classdef_event ($1); }
-                ;
-
-enum_block      : ENUMERATION stash_comment opt_attr_list opt_sep enum_list opt_sep END
-                  {
-                    YYUSE ($4);
-                    YYUSE ($6);
-
-                    if (! ($$ = parser.make_classdef_enum_block
-                           ($1, $3, $5, $7, $2)))
-                      {
-                        // make_classdef_enum_block deleted $3 and $5.
-                        YYABORT;
-                      }
-                  }
-                | ENUMERATION stash_comment opt_attr_list opt_sep END
-                  {
-                    YYUSE ($4);
-
-                    if (! ($$ = parser.make_classdef_enum_block
-                           ($1, $3, nullptr, $5, $2)))
-                      {
-                        // make_classdef_enum_block deleted $3.
-                        YYABORT;
-                      }
-                  }
-                ;
-
-enum_list       : class_enum
-                  { $$ = new octave::tree_classdef_enum_list ($1); }
-                | enum_list opt_sep class_enum
-                  {
-                    YYUSE ($2);
-
-                    $1->append ($3);
-                    $$ = $1;
-                  }
-                ;
-
-class_enum      : identifier '(' expression ')'
-                  { $$ = new octave::tree_classdef_enum ($1, $3); }
-                ;
-
-// =============
-// Miscellaneous
-// =============
-
-stmt_begin      : // empty
-                  {
-                    $$ = 0;
-                    lexer.m_at_beginning_of_statement = true;
-                  }
-                ;
-
-stash_comment   : // empty
-                  { $$ = lexer.get_comment (); }
-                ;
-
-parse_error     : LEXICAL_ERROR
-                  {
-                    $$ = 0;
-                    std::string msg = $1->text ();
-                    parser.bison_error (msg.c_str ());
-                  }
-                | error
-                  { $$ = 0; }
-                ;
-
-sep_no_nl       : ','
-                  { $$ = ','; }
-                | ';'
-                  { $$ = ';'; }
-                | sep_no_nl ','
-                  { $$ = $1; }
-                | sep_no_nl ';'
-                  { $$ = $1; }
-                ;
-
-opt_sep_no_nl   : // empty
-                  { $$ = 0; }
-                | sep_no_nl
-                  { $$ = $1; }
-                ;
-
-opt_nl          : // empty
-                  { $$ = 0; }
-                | nl
-                  { $$ = $1; }
-                ;
-
-nl              : '\n'
-                  { $$ = '\n'; }
-                | nl '\n'
-                  { $$ = $1; }
-                ;
-
-sep             : ','
-                  { $$ = ','; }
-                | ';'
-                  { $$ = ';'; }
-                | '\n'
-                  { $$ = '\n'; }
-                | sep ','
-                  { $$ = $1; }
-                | sep ';'
-                  { $$ = $1; }
-                | sep '\n'
-                  { $$ = $1; }
-                ;
-
-opt_sep         : // empty
-                  { $$ = 0; }
-                | sep
-                  { $$ = $1; }
-                ;
-
-%%
-
-#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
-   // Restore prevailing warning state for remainder of the file.
-#  pragma GCC diagnostic pop
-#endif
-
-// Generic error messages.
-
-#undef lexer
-#undef scanner
-
-static void
-yyerror (octave::base_parser& parser, const char *s)
-{
-  parser.bison_error (s);
-}
-
-namespace octave
-{
-  size_t
-  base_parser::parent_scope_info::size (void) const
-  {
-    return m_info.size ();
-  }
-
-  void
-  base_parser::parent_scope_info::push (const value_type& elt)
-  {
-    m_info.push_back (elt);
-  }
-
-  void
-  base_parser::parent_scope_info::push (const symbol_scope& scope)
-  {
-    push (value_type (scope, ""));
-  }
-
-  void
-  base_parser::parent_scope_info::pop (void)
-  {
-    m_info.pop_back ();
-  }
-
-  bool
-  base_parser::parent_scope_info::name_ok (const std::string& name)
-  {
-    // Name can't be the same as any parent function or any other
-    // function we've already seen.  We could maintain a complex
-    // tree structure of names, or we can just store the set of
-    // full names of all the functions, which must be unique.
-
-    std::string full_name;
-
-    for (size_t i = 0; i < size()-1; i++)
-      {
-        const value_type& elt = m_info[i];
-
-        if (name == elt.second)
-          return false;
-
-        full_name += elt.second + ">";
-      }
-
-    full_name += name;
-
-    if (m_all_names.find (full_name) != m_all_names.end ())
-      return false;
-
-    m_all_names.insert (full_name);
-
-    return true;
-  }
-
-  bool
-  base_parser::parent_scope_info::name_current_scope (const std::string& name)
-  {
-    if (! name_ok (name))
-      return false;
-
-    if (size () > 0)
-      m_info.back().second = name;
-
-    return true;
-  }
-
-  symbol_scope
-  base_parser::parent_scope_info::parent_scope (void) const
-  {
-    return size () > 1 ? m_info[size()-2].first : symbol_scope ();
-  }
-
-  std::string
-  base_parser::parent_scope_info::parent_name (void) const
-  {
-    return m_info[size()-2].second;
-  }
-
-  void base_parser::parent_scope_info::clear (void)
-  {
-    m_info.clear ();
-    m_all_names.clear ();
-  }
-
-  base_parser::base_parser (base_lexer& lxr)
-    : m_endfunction_found (false), m_autoloading (false),
-      m_fcn_file_from_relative_lookup (false),
-      m_parsing_subfunctions (false), m_parsing_local_functions (false),
-      m_max_fcn_depth (0), m_curr_fcn_depth (0), m_primary_fcn_scope (),
-      m_curr_class_name (), m_curr_package_name (), m_function_scopes (),
-      m_primary_fcn_ptr (nullptr), m_subfunction_names (),
-      m_classdef_object (nullptr), m_stmt_list (nullptr), m_lexer (lxr),
-      m_parser_state (yypstate_new ())
-  { }
-
-  base_parser::~base_parser (void)
-  {
-    delete m_stmt_list;
-
-    delete &m_lexer;
-
-    // FIXME: Deleting the internal Bison parser state structure does
-    // not clean up any partial parse trees in the event of an interrupt or
-    // error.  It's not clear how to safely do that with the C language
-    // parser that Bison generates.  The C++ language parser that Bison
-    // generates would do it for us automatically whenever an exception
-    // is thrown while parsing input, but there is currently no C++
-    // interface for a push parser.
-
-    yypstate_delete (static_cast<yypstate *> (m_parser_state));
-  }
-
-  void
-  base_parser::reset (void)
-  {
-    m_endfunction_found = false;
-    m_autoloading = false;
-    m_fcn_file_from_relative_lookup = false;
-    m_parsing_subfunctions = false;
-    m_parsing_local_functions = false;
-    m_max_fcn_depth = 0;
-    m_curr_fcn_depth = 0;
-    m_primary_fcn_scope = symbol_scope ();
-    m_curr_class_name = "";
-    m_curr_package_name = "";
-    m_function_scopes.clear ();
-    m_primary_fcn_ptr  = nullptr;
-    m_subfunction_names.clear ();
-    m_classdef_object = nullptr;
-
-    delete m_stmt_list;
-    m_stmt_list = nullptr;
-
-    m_lexer.reset ();
-
-    yypstate_delete (static_cast<yypstate *> (m_parser_state));
-    m_parser_state = yypstate_new ();
-  }
-}
-
-// Error mesages for mismatched end tokens.
-
-static std::string
-end_token_as_string (octave::token::end_tok_type ettype)
-{
-  std::string retval = "<unknown>";
-
-  switch (ettype)
-    {
-    case octave::token::simple_end:
-      retval = "end";
-      break;
-
-    case octave::token::classdef_end:
-      retval = "endclassdef";
-      break;
-
-    case octave::token::enumeration_end:
-      retval = "endenumeration";
-      break;
-
-    case octave::token::events_end:
-      retval = "endevents";
-      break;
-
-    case octave::token::for_end:
-      retval = "endfor";
-      break;
-
-    case octave::token::function_end:
-      retval = "endfunction";
-      break;
-
-    case octave::token::if_end:
-      retval = "endif";
-      break;
-
-    case octave::token::methods_end:
-      retval = "endmethods";
-      break;
-
-    case octave::token::parfor_end:
-      retval = "endparfor";
-      break;
-
-    case octave::token::properties_end:
-      retval = "endproperties";
-      break;
-
-    case octave::token::switch_end:
-      retval = "endswitch";
-      break;
-
-    case octave::token::try_catch_end:
-      retval = "end_try_catch";
-      break;
-
-    case octave::token::unwind_protect_end:
-      retval = "end_unwind_protect";
-      break;
-
-    case octave::token::while_end:
-      retval = "endwhile";
-      break;
-
-    default:
-      panic_impossible ();
-      break;
-    }
-
-  return retval;
-}
-
-namespace octave
-{
-  void
-  base_parser::end_token_error (token *tok, token::end_tok_type expected)
-  {
-    std::string msg = ("'" + end_token_as_string (expected)
-                       + "' command matched by '"
-                       + end_token_as_string (tok->ettype ()) + "'");
-
-    bison_error (msg, tok->line (), tok->column ());
-  }
-
-  // Check to see that end tokens are properly matched.
-
-  bool
-  base_parser::end_token_ok (token *tok, token::end_tok_type expected)
-  {
-    token::end_tok_type ettype = tok->ettype ();
-
-    return ettype == expected || ettype == token::simple_end;
-  }
-
-  // Maybe print a warning if an assignment expression is used as the
-  // test in a logical expression.
-
-  void
-  base_parser::maybe_warn_assign_as_truth_value (tree_expression *expr)
-  {
-    if (expr->is_assignment_expression ()
-        && expr->paren_count () < 2)
-      {
-        if (m_lexer.m_fcn_file_full_name.empty ())
-          warning_with_id
-            ("Octave:assign-as-truth-value",
-             "suggest parenthesis around assignment used as truth value");
-        else
-          warning_with_id
-            ("Octave:assign-as-truth-value",
-             "suggest parenthesis around assignment used as truth value near line %d, column %d in file '%s'",
-             expr->line (), expr->column (), m_lexer.m_fcn_file_full_name.c_str ());
-      }
-  }
-
-  // Maybe print a warning about switch labels that aren't constants.
-
-  void
-  base_parser::maybe_warn_variable_switch_label (tree_expression *expr)
-  {
-    if (! expr->is_constant ())
-      {
-        if (m_lexer.m_fcn_file_full_name.empty ())
-          warning_with_id ("Octave:variable-switch-label",
-                           "variable switch label");
-        else
-          warning_with_id
-            ("Octave:variable-switch-label",
-             "variable switch label near line %d, column %d in file '%s'",
-             expr->line (), expr->column (), m_lexer.m_fcn_file_full_name.c_str ());
-      }
-  }
-
-  // Make a constant.
-
-  tree_constant *
-  base_parser::make_constant (int op, token *tok_val)
-  {
-    int l = tok_val->line ();
-    int c = tok_val->column ();
-
-    tree_constant *retval = nullptr;
-
-    switch (op)
-      {
-      case NUM:
-        {
-          octave_value tmp (tok_val->number ());
-          retval = new tree_constant (tmp, l, c);
-          retval->stash_original_text (tok_val->text_rep ());
-        }
-        break;
-
-      case IMAG_NUM:
-        {
-          octave_value tmp (Complex (0.0, tok_val->number ()));
-          retval = new tree_constant (tmp, l, c);
-          retval->stash_original_text (tok_val->text_rep ());
-        }
-        break;
-
-      case DQ_STRING:
-      case SQ_STRING:
-        {
-          std::string txt = tok_val->text ();
-
-          char delim = op == DQ_STRING ? '"' : '\'';
-          octave_value tmp (txt, delim);
-
-          if (txt.empty ())
-            {
-              if (op == DQ_STRING)
-                tmp = octave_null_str::instance;
-              else
-                tmp = octave_null_sq_str::instance;
-            }
-
-          retval = new tree_constant (tmp, l, c);
-
-          if (op == DQ_STRING)
-            txt = undo_string_escapes (txt);
-
-          // FIXME: maybe this should also be handled by
-          // tok_val->text_rep () for character strings?
-          retval->stash_original_text (delim + txt + delim);
-        }
-        break;
-
-      default:
-        panic_impossible ();
-        break;
-      }
-
-    return retval;
-  }
-
-  // Make a function handle.
-
-  tree_fcn_handle *
-  base_parser::make_fcn_handle (token *tok_val)
-  {
-    int l = tok_val->line ();
-    int c = tok_val->column ();
-
-    tree_fcn_handle *retval = new tree_fcn_handle (tok_val->text (), l, c);
-
-    return retval;
-  }
-
-  // Make an anonymous function handle.
-
-  tree_anon_fcn_handle *
-  base_parser::make_anon_fcn_handle (tree_parameter_list *param_list,
-                                     tree_expression *expr)
-  {
-    // FIXME: need to get these from the location of the @ symbol.
-    int l = m_lexer.m_input_line_number;
-    int c = m_lexer.m_current_input_column;
-
-    symbol_scope fcn_scope = m_lexer.m_symtab_context.curr_scope ();
-    symbol_scope parent_scope = m_lexer.m_symtab_context.parent_scope ();
-
-    m_lexer.m_symtab_context.pop ();
-
-    expr->set_print_flag (false);
-
-    fcn_scope.mark_static ();
-
-    tree_anon_fcn_handle *retval
-      = new tree_anon_fcn_handle (param_list, expr, fcn_scope,
-                                  parent_scope, l, c);
-
-    std::ostringstream buf;
-
-    tree_print_code tpc (buf);
-
-    retval->accept (tpc);
-
-    std::string file = m_lexer.m_fcn_file_full_name;
-    if (! file.empty ())
-      buf << ": file: " << file;
-    else if (m_lexer.input_from_terminal ())
-      buf << ": *terminal input*";
-    else if (m_lexer.input_from_eval_string ())
-      buf << ": *eval string*";
-    buf << ": line: " << l << " column: " << c;
-
-    std::string scope_name = buf.str ();
-
-    fcn_scope.cache_name (scope_name);
-
-    // FIXME: Stash the filename.  This does not work and produces
-    // errors when executed.
-    //retval->stash_file_name (m_lexer.m_fcn_file_name);
-
-    return retval;
-  }
-
-  // Build a colon expression.
-
-  tree_expression *
-  base_parser::make_colon_expression (tree_expression *base,
-                                      tree_expression *limit,
-                                      tree_expression *incr)
-  {
-    tree_expression *retval = nullptr;
-
-    unwind_protect frame;
-
-    frame.protect_var (discard_error_messages);
-    frame.protect_var (discard_warning_messages);
-
-    discard_error_messages = true;
-    discard_warning_messages = true;
-
-    if (! base || ! limit)
-      {
-        delete base;
-        delete limit;
-        delete incr;
-
-        return retval;
-      }
-
-    int l = base->line ();
-    int c = base->column ();
-
-    tree_colon_expression *e
-      = new tree_colon_expression (base, limit, incr, l, c);
-
-    if (base->is_constant () && limit->is_constant ()
-        && (! incr || (incr && incr->is_constant ())))
-      {
-        try
-          {
-            tree_evaluator& tw
-              = __get_evaluator__ ("finish_colon_expression");
-
-            octave_value tmp = tw.evaluate (e);
-
-            tree_constant *tc_retval
-              = new tree_constant (tmp, e->line (), e->column ());
-
-            std::ostringstream buf;
-
-            tree_print_code tpc (buf);
-
-            e->accept (tpc);
-
-            tc_retval->stash_original_text (buf.str ());
-
-            delete e;
-
-            retval = tc_retval;
-          }
-        catch (const execution_exception&)
-          {
-            interpreter::recover_from_exception ();
-          }
-      }
-    else
-      retval = e;
-
-    return retval;
-  }
-
-  // Build a binary expression.
-
-  tree_expression *
-  base_parser::make_binary_op (int op, tree_expression *op1,
-                               token *tok_val, tree_expression *op2)
-  {
-    octave_value::binary_op t = octave_value::unknown_binary_op;
-
-    switch (op)
-      {
-      case POW:
-        t = octave_value::op_pow;
-        break;
-
-      case EPOW:
-        t = octave_value::op_el_pow;
-        break;
-
-      case '+':
-        t = octave_value::op_add;
-        break;
-
-      case '-':
-        t = octave_value::op_sub;
-        break;
-
-      case '*':
-        t = octave_value::op_mul;
-        break;
-
-      case '/':
-        t = octave_value::op_div;
-        break;
-
-      case EMUL:
-        t = octave_value::op_el_mul;
-        break;
-
-      case EDIV:
-        t = octave_value::op_el_div;
-        break;
-
-      case LEFTDIV:
-        t = octave_value::op_ldiv;
-        break;
-
-      case ELEFTDIV:
-        t = octave_value::op_el_ldiv;
-        break;
-
-      case EXPR_LT:
-        t = octave_value::op_lt;
-        break;
-
-      case EXPR_LE:
-        t = octave_value::op_le;
-        break;
-
-      case EXPR_EQ:
-        t = octave_value::op_eq;
-        break;
-
-      case EXPR_GE:
-        t = octave_value::op_ge;
-        break;
-
-      case EXPR_GT:
-        t = octave_value::op_gt;
-        break;
-
-      case EXPR_NE:
-        t = octave_value::op_ne;
-        break;
-
-      case EXPR_AND:
-        t = octave_value::op_el_and;
-        break;
-
-      case EXPR_OR:
-        t = octave_value::op_el_or;
-        break;
-
-      default:
-        panic_impossible ();
-        break;
-      }
-
-    int l = tok_val->line ();
-    int c = tok_val->column ();
-
-    return new tree_binary_expression (op1, op2, l, c, t);
-  }
-
-  // Build a boolean expression.
-
-  tree_expression *
-  base_parser::make_boolean_op (int op, tree_expression *op1,
-                                token *tok_val, tree_expression *op2)
-  {
-    tree_boolean_expression::type t;
-
-    switch (op)
-      {
-      case EXPR_AND_AND:
-        t = tree_boolean_expression::bool_and;
-        break;
-
-      case EXPR_OR_OR:
-        t = tree_boolean_expression::bool_or;
-        break;
-
-      default:
-        panic_impossible ();
-        break;
-      }
-
-    int l = tok_val->line ();
-    int c = tok_val->column ();
-
-    return new tree_boolean_expression (op1, op2, l, c, t);
-  }
-
-  // Build a prefix expression.
-
-  tree_expression *
-  base_parser::make_prefix_op (int op, tree_expression *op1, token *tok_val)
-  {
-    octave_value::unary_op t = octave_value::unknown_unary_op;
-
-    switch (op)
-      {
-      case EXPR_NOT:
-        t = octave_value::op_not;
-        break;
-
-      case '+':
-        t = octave_value::op_uplus;
-        break;
-
-      case '-':
-        t = octave_value::op_uminus;
-        break;
-
-      case PLUS_PLUS:
-        t = octave_value::op_incr;
-        break;
-
-      case MINUS_MINUS:
-        t = octave_value::op_decr;
-        break;
-
-      default:
-        panic_impossible ();
-        break;
-      }
-
-    int l = tok_val->line ();
-    int c = tok_val->column ();
-
-    return new tree_prefix_expression (op1, l, c, t);
-  }
-
-  // Build a postfix expression.
-
-  tree_expression *
-  base_parser::make_postfix_op (int op, tree_expression *op1, token *tok_val)
-  {
-    octave_value::unary_op t = octave_value::unknown_unary_op;
-
-    switch (op)
-      {
-      case HERMITIAN:
-        t = octave_value::op_hermitian;
-        break;
-
-      case TRANSPOSE:
-        t = octave_value::op_transpose;
-        break;
-
-      case PLUS_PLUS:
-        t = octave_value::op_incr;
-        break;
-
-      case MINUS_MINUS:
-        t = octave_value::op_decr;
-        break;
-
-      default:
-        panic_impossible ();
-        break;
-      }
-
-    int l = tok_val->line ();
-    int c = tok_val->column ();
-
-    return new tree_postfix_expression (op1, l, c, t);
-  }
-
-  // Build an unwind-protect command.
-
-  tree_command *
-  base_parser::make_unwind_command (token *unwind_tok,
-                                    tree_statement_list *body,
-                                    tree_statement_list *cleanup_stmts,
-                                    token *end_tok,
-                                    comment_list *lc,
-                                    comment_list *mc)
-  {
-    tree_command *retval = nullptr;
-
-    if (end_token_ok (end_tok, token::unwind_protect_end))
-      {
-        comment_list *tc = m_lexer.m_comment_buf.get_comment ();
-
-        int l = unwind_tok->line ();
-        int c = unwind_tok->column ();
-
-        retval = new tree_unwind_protect_command (body, cleanup_stmts,
-                                                  lc, mc, tc, l, c);
-      }
-    else
-      {
-        delete body;
-        delete cleanup_stmts;
-
-        end_token_error (end_tok, token::unwind_protect_end);
-      }
-
-    return retval;
-  }
-
-  // Build a try-catch command.
-
-  tree_command *
-  base_parser::make_try_command (token *try_tok,
-                                 tree_statement_list *body,
-                                 char catch_sep,
-                                 tree_statement_list *cleanup_stmts,
-                                 token *end_tok,
-                                 comment_list *lc,
-                                 comment_list *mc)
-  {
-    tree_command *retval = nullptr;
-
-    if (end_token_ok (end_tok, token::try_catch_end))
-      {
-        comment_list *tc = m_lexer.m_comment_buf.get_comment ();
-
-        int l = try_tok->line ();
-        int c = try_tok->column ();
-
-        tree_identifier *id = nullptr;
-
-        if (! catch_sep && cleanup_stmts && ! cleanup_stmts->empty ())
-          {
-            tree_statement *stmt = cleanup_stmts->front ();
-
-            if (stmt)
-              {
-                tree_expression *expr = stmt->expression ();
-
-                if (expr && expr->is_identifier ())
-                  {
-                    id = dynamic_cast<tree_identifier *> (expr);
-
-                    cleanup_stmts->pop_front ();
-
-                    stmt->set_expression (nullptr);
-                    delete stmt;
-                  }
-              }
-          }
-
-        retval = new tree_try_catch_command (body, cleanup_stmts, id,
-                                             lc, mc, tc, l, c);
-      }
-    else
-      {
-        delete body;
-        delete cleanup_stmts;
-
-        end_token_error (end_tok, token::try_catch_end);
-      }
-
-    return retval;
-  }
-
-  // Build a while command.
-
-  tree_command *
-  base_parser::make_while_command (token *while_tok,
-                                   tree_expression *expr,
-                                   tree_statement_list *body,
-                                   token *end_tok,
-                                   comment_list *lc)
-  {
-    tree_command *retval = nullptr;
-
-    maybe_warn_assign_as_truth_value (expr);
-
-    if (end_token_ok (end_tok, token::while_end))
-      {
-        comment_list *tc = m_lexer.m_comment_buf.get_comment ();
-
-        m_lexer.m_looping--;
-
-        int l = while_tok->line ();
-        int c = while_tok->column ();
-
-        retval = new tree_while_command (expr, body, lc, tc, l, c);
-      }
-    else
-      {
-        delete expr;
-        delete body;
-
-        end_token_error (end_tok, token::while_end);
-      }
-
-    return retval;
-  }
-
-  // Build a do-until command.
-
-  tree_command *
-  base_parser::make_do_until_command (token *until_tok,
-                                      tree_statement_list *body,
-                                      tree_expression *expr,
-                                      comment_list *lc)
-  {
-    maybe_warn_assign_as_truth_value (expr);
-
-    comment_list *tc = m_lexer.m_comment_buf.get_comment ();
-
-    m_lexer.m_looping--;
-
-    int l = until_tok->line ();
-    int c = until_tok->column ();
-
-    return new tree_do_until_command (expr, body, lc, tc, l, c);
-  }
-
-  // Build a for command.
-
-  tree_command *
-  base_parser::make_for_command (int tok_id, token *for_tok,
-                                 tree_argument_list *lhs,
-                                 tree_expression *expr,
-                                 tree_expression *maxproc,
-                                 tree_statement_list *body,
-                                 token *end_tok,
-                                 comment_list *lc)
-  {
-    tree_command *retval = nullptr;
-
-    bool parfor = tok_id == PARFOR;
-
-    if (end_token_ok (end_tok, parfor ? token::parfor_end : token::for_end))
-      {
-        expr->mark_as_for_cmd_expr ();
-
-        comment_list *tc = m_lexer.m_comment_buf.get_comment ();
-
-        m_lexer.m_looping--;
-
-        int l = for_tok->line ();
-        int c = for_tok->column ();
-
-        if (lhs->length () == 1)
-          {
-            tree_expression *tmp = lhs->remove_front ();
-
-            retval = new tree_simple_for_command (parfor, tmp, expr, maxproc,
-                                                  body, lc, tc, l, c);
-
-            delete lhs;
-          }
-        else
-          {
-            if (parfor)
-              {
-                delete lhs;
-                delete expr;
-                delete maxproc;
-                delete body;
-
-                bison_error ("invalid syntax for parfor statement");
-              }
-            else
-              retval = new tree_complex_for_command (lhs, expr, body,
-                                                     lc, tc, l, c);
-          }
-      }
-    else
-      {
-        delete lhs;
-        delete expr;
-        delete maxproc;
-        delete body;
-
-        end_token_error (end_tok, parfor ? token::parfor_end : token::for_end);
-      }
-
-    return retval;
-  }
-
-  // Build a break command.
-
-  tree_command *
-  base_parser::make_break_command (token *break_tok)
-  {
-    int l = break_tok->line ();
-    int c = break_tok->column ();
-
-    if (! m_lexer.m_looping)
-      {
-        bison_error ("break must appear in a loop in the same file as loop command");
-        return nullptr;
-      }
-    else
-      return new tree_break_command (l, c);
-  }
-
-  // Build a continue command.
-
-  tree_command *
-  base_parser::make_continue_command (token *continue_tok)
-  {
-    int l = continue_tok->line ();
-    int c = continue_tok->column ();
-
-    return new tree_continue_command (l, c);
-  }
-
-  // Build a return command.
-
-  tree_command *
-  base_parser::make_return_command (token *return_tok)
-  {
-    int l = return_tok->line ();
-    int c = return_tok->column ();
-
-    return new tree_return_command (l, c);
-  }
-
-  // Start an if command.
-
-  tree_if_command_list *
-  base_parser::start_if_command (tree_expression *expr,
-                                 tree_statement_list *list)
-  {
-    maybe_warn_assign_as_truth_value (expr);
-
-    tree_if_clause *t = new tree_if_clause (expr, list);
-
-    return new tree_if_command_list (t);
-  }
-
-  // Finish an if command.
-
-  tree_if_command *
-  base_parser::finish_if_command (token *if_tok,
-                                  tree_if_command_list *list,
-                                  token *end_tok,
-                                  comment_list *lc)
-  {
-    tree_if_command *retval = nullptr;
-
-    if (end_token_ok (end_tok, token::if_end))
-      {
-        comment_list *tc = m_lexer.m_comment_buf.get_comment ();
-
-        int l = if_tok->line ();
-        int c = if_tok->column ();
-
-        if (list && ! list->empty ())
-          {
-            tree_if_clause *elt = list->front ();
-
-            if (elt)
-              {
-                elt->line (l);
-                elt->column (c);
-              }
-          }
-
-        retval = new tree_if_command (list, lc, tc, l, c);
-      }
-    else
-      {
-        delete list;
-
-        end_token_error (end_tok, token::if_end);
-      }
-
-    return retval;
-  }
-
-  // Build an elseif clause.
-
-  tree_if_clause *
-  base_parser::make_elseif_clause (token *elseif_tok,
-                                   tree_expression *expr,
-                                   tree_statement_list *list,
-                                   comment_list *lc)
-  {
-    maybe_warn_assign_as_truth_value (expr);
-
-    int l = elseif_tok->line ();
-    int c = elseif_tok->column ();
-
-    return new tree_if_clause (expr, list, lc, l, c);
-  }
-
-  // Finish a switch command.
-
-  tree_switch_command *
-  base_parser::finish_switch_command (token *switch_tok,
-                                      tree_expression *expr,
-                                      tree_switch_case_list *list,
-                                      token *end_tok,
-                                      comment_list *lc)
-  {
-    tree_switch_command *retval = nullptr;
-
-    if (end_token_ok (end_tok, token::switch_end))
-      {
-        comment_list *tc = m_lexer.m_comment_buf.get_comment ();
-
-        int l = switch_tok->line ();
-        int c = switch_tok->column ();
-
-        if (list && ! list->empty ())
-          {
-            tree_switch_case *elt = list->front ();
-
-            if (elt)
-              {
-                elt->line (l);
-                elt->column (c);
-              }
-          }
-
-        retval = new tree_switch_command (expr, list, lc, tc, l, c);
-      }
-    else
-      {
-        delete expr;
-        delete list;
-
-        end_token_error (end_tok, token::switch_end);
-      }
-
-    return retval;
-  }
-
-  // Build a switch case.
-
-  tree_switch_case *
-  base_parser::make_switch_case (token *case_tok,
-                                 tree_expression *expr,
-                                 tree_statement_list *list,
-                                 comment_list *lc)
-  {
-    maybe_warn_variable_switch_label (expr);
-
-    int l = case_tok->line ();
-    int c = case_tok->column ();
-
-    return new tree_switch_case (expr, list, lc, l, c);
-  }
-
-  // Build an assignment to a variable.
-
-  tree_expression *
-  base_parser::make_assign_op (int op, tree_argument_list *lhs,
-                               token *eq_tok, tree_expression *rhs)
-  {
-    octave_value::assign_op t = octave_value::unknown_assign_op;
-
-    switch (op)
-      {
-      case '=':
-        t = octave_value::op_asn_eq;
-        break;
-
-      case ADD_EQ:
-        t = octave_value::op_add_eq;
-        break;
-
-      case SUB_EQ:
-        t = octave_value::op_sub_eq;
-        break;
-
-      case MUL_EQ:
-        t = octave_value::op_mul_eq;
-        break;
-
-      case DIV_EQ:
-        t = octave_value::op_div_eq;
-        break;
-
-      case LEFTDIV_EQ:
-        t = octave_value::op_ldiv_eq;
-        break;
-
-      case POW_EQ:
-        t = octave_value::op_pow_eq;
-        break;
-
-      case EMUL_EQ:
-        t = octave_value::op_el_mul_eq;
-        break;
-
-      case EDIV_EQ:
-        t = octave_value::op_el_div_eq;
-        break;
-
-      case ELEFTDIV_EQ:
-        t = octave_value::op_el_ldiv_eq;
-        break;
-
-      case EPOW_EQ:
-        t = octave_value::op_el_pow_eq;
-        break;
-
-      case AND_EQ:
-        t = octave_value::op_el_and_eq;
-        break;
-
-      case OR_EQ:
-        t = octave_value::op_el_or_eq;
-        break;
-
-      default:
-        panic_impossible ();
-        break;
-      }
-
-    int l = eq_tok->line ();
-    int c = eq_tok->column ();
-
-    if (! lhs->is_simple_assign_lhs () && t != octave_value::op_asn_eq)
-      {
-        // Multiple assignments like [x,y] OP= rhs are only valid for
-        // '=', not '+=', etc.
-
-        delete lhs;
-        delete rhs;
-
-        bison_error ("computed multiple assignment not allowed", l, c);
-
-        return nullptr;
-      }
-
-    if (lhs->is_simple_assign_lhs ())
-      {
-        // We are looking at a simple assignment statement like x = rhs;
-
-        tree_expression *tmp = lhs->remove_front ();
-
-        if ((tmp->is_identifier () || tmp->is_index_expression ())
-            && is_keyword (tmp->name ()))
-          {
-            std::string kw = tmp->name ();
-
-            delete tmp;
-            delete lhs;
-            delete rhs;
-
-            bison_error ("invalid assignment to keyword \"" + kw + "\"", l, c);
-
-            return nullptr;
-          }
-
-        delete lhs;
-
-        return new tree_simple_assignment (tmp, rhs, false, l, c, t);
-      }
-    else
-      {
-        std::list<std::string> names = lhs->variable_names ();
-
-        for (const auto& kw : names)
-          {
-            if (is_keyword (kw))
-              {
-                delete lhs;
-                delete rhs;
-
-                bison_error ("invalid assignment to keyword \"" + kw + "\"",
-                             l, c);
-
-                return nullptr;
-              }
-          }
-
-        return new tree_multi_assignment (lhs, rhs, false, l, c);
-      }
-  }
-
-  // Define a script.
-
-  void
-  base_parser::make_script (tree_statement_list *cmds,
-                            tree_statement *end_script)
-  {
-    if (! cmds)
-      cmds = new tree_statement_list ();
-
-    cmds->append (end_script);
-
-    symbol_scope script_scope = m_lexer.m_symtab_context.curr_scope ();
-
-    script_scope.cache_name (m_lexer.m_fcn_file_full_name);
-
-    octave_user_script *script
-      = new octave_user_script (m_lexer.m_fcn_file_full_name,
-                                m_lexer.m_fcn_file_name, script_scope,
-                                cmds, m_lexer.m_help_text);
-
-    m_lexer.m_symtab_context.pop ();
-    m_lexer.m_help_text = "";
-
-    sys::time now;
-
-    script->stash_fcn_file_time (now);
-
-    m_primary_fcn_ptr = script;
-  }
-
-  // Define a function.
-
-  // FIXME: combining start_function, finish_function, and
-  // recover_from_parsing_function should be possible, but it makes
-  // for a large mess.  Maybe this could be a bit better organized?
-
-  tree_function_def *
-  base_parser::make_function (token *fcn_tok,
-                              tree_parameter_list *ret_list,
-                              tree_identifier *id,
-                              tree_parameter_list *param_list,
-                              tree_statement_list *body,
-                              tree_statement *end_fcn_stmt,
-                              comment_list *lc)
-  {
-    tree_function_def *retval = nullptr;
-
-    int l = fcn_tok->line ();
-    int c = fcn_tok->column ();
-
-    octave_user_function *tmp_fcn
-      = start_function (id, param_list, body, end_fcn_stmt);
-
-    retval = finish_function (ret_list, tmp_fcn, lc, l, c);
-
-    recover_from_parsing_function ();
-
-    return retval;
-  }
-
-  // Begin defining a function.
-
-  octave_user_function *
-  base_parser::start_function (tree_identifier *id,
-                               tree_parameter_list *param_list,
-                               tree_statement_list *body,
-                               tree_statement *end_fcn_stmt)
-  {
-    // We'll fill in the return list later.
-
-    std::string id_name = id->name ();
-
-    delete id;
-
-    if (m_lexer.m_parsing_classdef_get_method)
-      id_name.insert (0, "get.");
-    else if (m_lexer.m_parsing_classdef_set_method)
-      id_name.insert (0, "set.");
-
-    m_lexer.m_parsing_classdef_get_method = false;
-    m_lexer.m_parsing_classdef_set_method = false;
-
-    if (! body)
-      body = new tree_statement_list ();
-
-    body->append (end_fcn_stmt);
-
-    octave_user_function *fcn
-      = new octave_user_function (m_lexer.m_symtab_context.curr_scope (),
-                                  param_list, nullptr, body);
-
-    if (fcn)
-      {
-        comment_list *tc = m_lexer.m_comment_buf.get_comment ();
-
-        fcn->stash_trailing_comment (tc);
-        fcn->stash_fcn_end_location (end_fcn_stmt->line (),
-                                     end_fcn_stmt->column ());
-      }
-
-    // If input is coming from a file, issue a warning if the name of
-    // the file does not match the name of the function stated in the
-    // file.  Matlab doesn't provide a diagnostic (it ignores the stated
-    // name).
-    if (! m_autoloading && m_lexer.m_reading_fcn_file
-        && m_curr_fcn_depth == 1 && ! m_parsing_subfunctions)
-      {
-        // FIXME: should m_lexer.m_fcn_file_name already be
-        // preprocessed when we get here?  It seems to only be a
-        // problem with relative filenames.
-
-        std::string nm = m_lexer.m_fcn_file_name;
-
-        size_t pos = nm.find_last_of (sys::file_ops::dir_sep_chars ());
-
-        if (pos != std::string::npos)
-          nm = m_lexer.m_fcn_file_name.substr (pos+1);
-
-        if (nm != id_name)
-          {
-            warning_with_id
-              ("Octave:function-name-clash",
-               "function name '%s' does not agree with function filename '%s'",
-               id_name.c_str (), m_lexer.m_fcn_file_full_name.c_str ());
-
-            id_name = nm;
-          }
-      }
-
-    if (m_lexer.m_reading_fcn_file || m_lexer.m_reading_classdef_file || m_autoloading)
-      {
-        sys::time now;
-
-        fcn->stash_fcn_file_name (m_lexer.m_fcn_file_full_name);
-        fcn->stash_fcn_file_time (now);
-        fcn->stash_dir_name (m_lexer.m_dir_name);
-        fcn->stash_package_name (m_lexer.m_package_name);
-        fcn->mark_as_system_fcn_file ();
-
-        if (m_fcn_file_from_relative_lookup)
-          fcn->mark_relative ();
-
-        if (m_lexer.m_parsing_class_method)
-          {
-            if (m_curr_class_name == id_name)
-              fcn->mark_as_class_constructor ();
-            else
-              fcn->mark_as_class_method ();
-
-            fcn->stash_dispatch_class (m_curr_class_name);
-          }
-
-        std::string nm = fcn->fcn_file_name ();
-
-        sys::file_stat fs (nm);
-
-        if (fs && fs.is_newer (now))
-          warning_with_id ("Octave:future-time-stamp",
-                           "time stamp for '%s' is in the future", nm.c_str ());
-      }
-    else if (! input_from_tmp_history_file
-             && ! m_lexer.m_force_script
-             && m_lexer.m_reading_script_file
-             && m_lexer.m_fcn_file_name == id_name)
-      {
-        warning ("function '%s' defined within script file '%s'",
-                 id_name.c_str (), m_lexer.m_fcn_file_full_name.c_str ());
-      }
-
-    fcn->stash_function_name (id_name);
-
-    // Record help text for functions other than nested functions.
-    // We cannot currently record help for nested functions (bug #46008)
-    // because the doc_string of the outermost function is read first,
-    // whereas this function is called for the innermost function first.
-    // We could have a stack of help_text in lexer.
-    if (! m_lexer.m_help_text.empty () && m_curr_fcn_depth == 1)
-      {
-        fcn->document (m_lexer.m_help_text);
-
-        m_lexer.m_help_text = "";
-      }
-
-    if (m_lexer.m_reading_fcn_file && m_curr_fcn_depth == 1
-        && ! m_parsing_subfunctions)
-      m_primary_fcn_ptr = fcn;
-
-    return fcn;
-  }
-
-  tree_statement *
-  base_parser::make_end (const std::string& type, bool eof, int l, int c)
-  {
-    return make_statement (new tree_no_op_command (type, eof, l, c));
-  }
-
-  tree_function_def *
-  base_parser::finish_function (tree_parameter_list *ret_list,
-                                octave_user_function *fcn,
-                                comment_list *lc,
-                                int l, int c)
-  {
-    tree_function_def *retval = nullptr;
-
-    if (ret_list)
-      ret_list->mark_as_formal_parameters ();
-
-    if (fcn)
-      {
-        std::string nm = fcn->name ();
-        std::string file = fcn->fcn_file_name ();
-
-        std::string tmp = nm;
-        if (! file.empty ())
-          tmp += ": " + file;
-
-        symbol_scope fcn_scope = fcn->scope ();
-        fcn_scope.cache_name (tmp);
-
-        if (lc)
-          fcn->stash_leading_comment (lc);
-
-        fcn->define_ret_list (ret_list);
-
-        if (m_curr_fcn_depth > 1 || m_parsing_subfunctions)
-          {
-            fcn->stash_fcn_location (l, c);
-            fcn->stash_parent_fcn_name (m_lexer.m_fcn_file_name);
-
-            octave_value ov_fcn (fcn);
-
-            if (m_endfunction_found && m_function_scopes.size () > 1)
-              {
-                fcn->mark_as_nested_function ();
-                fcn_scope.mark_nested ();
-
-                symbol_scope pscope = m_function_scopes.parent_scope ();
-                fcn_scope.set_parent (pscope);
-                pscope.install_nestfunction (nm, ov_fcn, fcn_scope);
-              }
-            else
-              {
-                fcn->mark_as_subfunction ();
-                m_subfunction_names.push_back (nm);
-                fcn_scope.set_parent (m_primary_fcn_scope);
-                m_primary_fcn_scope.install_subfunction (nm, ov_fcn);
-              }
-          }
-
-        if (m_curr_fcn_depth == 1)
-          fcn_scope.update_nest ();
-
-        if (! m_lexer.m_reading_fcn_file && m_curr_fcn_depth == 1)
-          {
-            // We are either reading a script file or defining a function
-            // at the command line, so this definition creates a
-            // tree_function object that is placed in the parse tree.
-            // Otherwise, it is just inserted in the symbol table,
-            // either as a subfunction or nested function (see above),
-            // or as the primary function for the file, via
-            // m_primary_fcn_ptr (see also load_fcn_from_file,,
-            // parse_fcn_file, and
-            // fcn_info::fcn_info_rep::find_user_function).
-
-            if (m_lexer.m_buffer_function_text)
-              {
-                fcn->cache_function_text (m_lexer.m_function_text,
-                                          fcn->time_parsed ());
-                m_lexer.m_buffer_function_text = false;
-              }
-
-            retval = new tree_function_def (fcn);
-          }
-      }
-
-    return retval;
-  }
-
-  void
-  base_parser::recover_from_parsing_function (void)
-  {
-    m_lexer.m_symtab_context.pop ();
-
-    if (m_lexer.m_reading_fcn_file && m_curr_fcn_depth == 1
-        && ! m_parsing_subfunctions)
-      m_parsing_subfunctions = true;
-
-    m_curr_fcn_depth--;
-    m_function_scopes.pop ();
-
-    m_lexer.m_defining_func--;
-    m_lexer.m_parsed_function_name.pop ();
-    m_lexer.m_looking_at_return_list = false;
-    m_lexer.m_looking_at_parameter_list = false;
-  }
-
-  tree_funcall *
-  base_parser::make_superclass_ref (const std::string& method_nm,
-                                    const std::string& class_nm)
-  {
-    octave_value_list args;
-
-    args(1) = class_nm;
-    args(0) = method_nm;
-
-    symbol_table& symtab
-      = __get_symbol_table__ ("base_parser::make_superclass_ref");
-
-    octave_value fcn
-      = symtab.find_built_in_function ("__superclass_reference__");
-
-    return new tree_funcall (fcn, args);
-  }
-
-  tree_funcall *
-  base_parser::make_meta_class_query (const std::string& class_nm)
-  {
-    octave_value_list args;
-
-    args(0) = class_nm;
-
-    symbol_table& symtab
-      = __get_symbol_table__ ("base_parser::make_meta_class_query");
-
-    octave_value fcn
-      = symtab.find_built_in_function ("__meta_class_query__");
-
-    return new tree_funcall (fcn, args);
-  }
-
-  // A CLASSDEF block defines a class that has a constructor and other
-  // methods, but it is not an executable command.  Parsing the block
-  // makes some changes in the symbol table (inserting the constructor
-  // and methods, and adding to the list of known objects) and creates
-  // a parse tree containing meta information about the class.
-
-  tree_classdef *
-  base_parser::make_classdef (token *tok_val,
-                              tree_classdef_attribute_list *a,
-                              tree_identifier *id,
-                              tree_classdef_superclass_list *sc,
-                              tree_classdef_body *body, token *end_tok,
-                              comment_list *lc)
-  {
-    tree_classdef *retval = nullptr;
-
-    m_lexer.m_symtab_context.pop ();
-
-    std::string cls_name = id->name ();
-
-    std::string nm = m_lexer.m_fcn_file_name;
-
-    size_t pos = nm.find_last_of (sys::file_ops::dir_sep_chars ());
-
-    if (pos != std::string::npos)
-      nm = m_lexer.m_fcn_file_name.substr (pos+1);
-
-    if (nm != cls_name)
-      {
-        delete a;
-        delete id;
-        delete sc;
-        delete body;
-
-        bison_error ("invalid classdef definition, the class name must match the filename");
-
-      }
-    else
-      {
-        if (end_token_ok (end_tok, token::classdef_end))
-          {
-            comment_list *tc = m_lexer.m_comment_buf.get_comment ();
-
-            int l = tok_val->line ();
-            int c = tok_val->column ();
-
-            if (! body)
-              body = new tree_classdef_body ();
-
-            retval = new tree_classdef (a, id, sc, body, lc, tc,
-                                        m_curr_package_name, l, c);
-          }
-        else
-          {
-            delete a;
-            delete id;
-            delete sc;
-            delete body;
-
-            end_token_error (end_tok, token::switch_end);
-          }
-      }
-
-    return retval;
-  }
-
-  tree_classdef_properties_block *
-  base_parser::make_classdef_properties_block (token *tok_val,
-                                               tree_classdef_attribute_list *a,
-                                               tree_classdef_property_list *plist,
-                                               token *end_tok,
-                                               comment_list *lc)
-  {
-    tree_classdef_properties_block *retval = nullptr;
-
-    if (end_token_ok (end_tok, token::properties_end))
-      {
-        comment_list *tc = m_lexer.m_comment_buf.get_comment ();
-
-        int l = tok_val->line ();
-        int c = tok_val->column ();
-
-        if (! plist)
-          plist = new tree_classdef_property_list ();
-
-        retval = new tree_classdef_properties_block (a, plist, lc, tc, l, c);
-      }
-    else
-      {
-        delete a;
-        delete plist;
-
-        end_token_error (end_tok, token::properties_end);
-      }
-
-    return retval;
-  }
-
-  tree_classdef_methods_block *
-  base_parser::make_classdef_methods_block (token *tok_val,
-                                            tree_classdef_attribute_list *a,
-                                            tree_classdef_methods_list *mlist,
-                                            token *end_tok,
-                                            comment_list *lc)
-  {
-    tree_classdef_methods_block *retval = nullptr;
-
-    if (end_token_ok (end_tok, token::methods_end))
-      {
-        comment_list *tc = m_lexer.m_comment_buf.get_comment ();
-
-        int l = tok_val->line ();
-        int c = tok_val->column ();
-
-        if (! mlist)
-          mlist = new tree_classdef_methods_list ();
-
-        retval = new tree_classdef_methods_block (a, mlist, lc, tc, l, c);
-      }
-    else
-      {
-        delete a;
-        delete mlist;
-
-        end_token_error (end_tok, token::methods_end);
-      }
-
-    return retval;
-  }
-
-  tree_classdef_events_block *
-  base_parser::make_classdef_events_block (token *tok_val,
-                                           tree_classdef_attribute_list *a,
-                                           tree_classdef_events_list *elist,
-                                           token *end_tok,
-                                           comment_list *lc)
-  {
-    tree_classdef_events_block *retval = nullptr;
-
-    if (end_token_ok (end_tok, token::events_end))
-      {
-        comment_list *tc = m_lexer.m_comment_buf.get_comment ();
-
-        int l = tok_val->line ();
-        int c = tok_val->column ();
-
-        if (! elist)
-          elist = new tree_classdef_events_list ();
-
-        retval = new tree_classdef_events_block (a, elist, lc, tc, l, c);
-      }
-    else
-      {
-        delete a;
-        delete elist;
-
-        end_token_error (end_tok, token::events_end);
-      }
-
-    return retval;
-  }
-
-  tree_classdef_enum_block *
-  base_parser::make_classdef_enum_block (token *tok_val,
-                                         tree_classdef_attribute_list *a,
-                                         tree_classdef_enum_list *elist,
-                                         token *end_tok,
-                                         comment_list *lc)
-  {
-    tree_classdef_enum_block *retval = nullptr;
-
-    if (end_token_ok (end_tok, token::enumeration_end))
-      {
-        comment_list *tc = m_lexer.m_comment_buf.get_comment ();
-
-        int l = tok_val->line ();
-        int c = tok_val->column ();
-
-        if (! elist)
-          elist = new tree_classdef_enum_list ();
-
-        retval = new tree_classdef_enum_block (a, elist, lc, tc, l, c);
-      }
-    else
-      {
-        delete a;
-        delete elist;
-
-        end_token_error (end_tok, token::enumeration_end);
-      }
-
-    return retval;
-  }
-
-  octave_user_function*
-  base_parser::start_classdef_external_method (tree_identifier *id,
-                                               tree_parameter_list *pl)
-  {
-    octave_user_function* retval = nullptr;
-
-    // External methods are only allowed within @-folders. In this case,
-    // m_curr_class_name will be non-empty.
-
-    if (! m_curr_class_name.empty ())
-      {
-
-        std::string mname = id->name ();
-
-        // Methods that cannot be declared outside the classdef file:
-        // - methods with '.' character (e.g. property accessors)
-        // - class constructor
-        // - `delete'
-
-        if (mname.find_first_of (".") == std::string::npos
-            && mname != "delete"
-            && mname != m_curr_class_name)
-          {
-            // Create a dummy function that is used until the real method
-            // is loaded.
-
-            retval = new octave_user_function (symbol_scope (), pl);
-
-            retval->stash_function_name (mname);
-
-            int l = id->line ();
-            int c = id->column ();
-
-            retval->stash_fcn_location (l, c);
-          }
-        else
-          bison_error ("invalid external method declaration, an external "
-                       "method cannot be the class constructor, `delete' "
-                       "or have a dot (.) character in its name");
-      }
-    else
-      bison_error ("external methods are only allowed in @-folders");
-
-    if (! retval)
-      delete id;
-
-    return retval;
-  }
-
-  tree_function_def *
-  base_parser::finish_classdef_external_method (octave_user_function *fcn,
-                                                tree_parameter_list *ret_list,
-                                                comment_list *cl)
-  {
-    if (ret_list)
-      fcn->define_ret_list (ret_list);
-
-    if (cl)
-      fcn->stash_leading_comment (cl);
-
-    int l = fcn->beginning_line ();
-    int c = fcn->beginning_column ();
-
-    return new tree_function_def (fcn, l, c);
-  }
-
-  void
-  base_parser::finish_classdef_file (tree_classdef *cls,
-                                     tree_statement_list *local_fcns)
-  {
-    if (m_lexer.m_reading_classdef_file)
-      m_classdef_object = cls;
-
-    if (local_fcns)
-      {
-        symbol_table& symtab
-          = __get_symbol_table__ ("base_parser::finish_classdef_file");
-
-        for (tree_statement *elt : *local_fcns)
-          {
-            tree_command *cmd = elt->command ();
-
-            tree_function_def *fcn_def
-              = dynamic_cast<tree_function_def *> (cmd);
-
-            octave_value ov_fcn = fcn_def->function ();
-            octave_function *fcn = ov_fcn.function_value ();
-            std::string nm = fcn->name ();
-            std::string file = fcn->fcn_file_name ();
-
-            symtab.install_local_function (nm, ov_fcn, file);
-          }
-
-        delete local_fcns;
-      }
-  }
-
-  // Make an index expression.
-
-  tree_index_expression *
-  base_parser::make_index_expression (tree_expression *expr,
-                                      tree_argument_list *args,
-                                      char type)
-  {
-    tree_index_expression *retval = nullptr;
-
-    if (args && args->has_magic_tilde ())
-      {
-        delete expr;
-        delete args;
-
-        bison_error ("invalid use of empty argument (~) in index expression");
-      }
-    else
-      {
-        int l = expr->line ();
-        int c = expr->column ();
-
-        if (! expr->is_postfix_indexed ())
-          expr->set_postfix_index (type);
-
-        if (expr->is_index_expression ())
-          {
-            tree_index_expression *tmp =
-              static_cast<tree_index_expression *> (expr);
-
-            tmp->append (args, type);
-
-            retval = tmp;
-          }
-        else
-          retval = new tree_index_expression (expr, args, l, c, type);
-      }
-
-    return retval;
-  }
-
-  // Make an indirect reference expression.
-
-  tree_index_expression *
-  base_parser::make_indirect_ref (tree_expression *expr,
-                                  const std::string& elt)
-  {
-    tree_index_expression *retval = nullptr;
-
-    int l = expr->line ();
-    int c = expr->column ();
-
-    if (! expr->is_postfix_indexed ())
-      expr->set_postfix_index ('.');
-
-    if (expr->is_index_expression ())
-      {
-        tree_index_expression *tmp = static_cast<tree_index_expression *> (expr);
-
-        tmp->append (elt);
-
-        retval = tmp;
-      }
-    else
-      retval = new tree_index_expression (expr, elt, l, c);
-
-    m_lexer.m_looking_at_indirect_ref = false;
-
-    return retval;
-  }
-
-  // Make an indirect reference expression with dynamic field name.
-
-  tree_index_expression *
-  base_parser::make_indirect_ref (tree_expression *expr,
-                                  tree_expression *elt)
-  {
-    tree_index_expression *retval = nullptr;
-
-    int l = expr->line ();
-    int c = expr->column ();
-
-    if (! expr->is_postfix_indexed ())
-      expr->set_postfix_index ('.');
-
-    if (expr->is_index_expression ())
-      {
-        tree_index_expression *tmp = static_cast<tree_index_expression *> (expr);
-
-        tmp->append (elt);
-
-        retval = tmp;
-      }
-    else
-      retval = new tree_index_expression (expr, elt, l, c);
-
-    m_lexer.m_looking_at_indirect_ref = false;
-
-    return retval;
-  }
-
-  // Make a declaration command.
-
-  tree_decl_command *
-  base_parser::make_decl_command (int tok, token *tok_val,
-                                  tree_decl_init_list *lst)
-  {
-    tree_decl_command *retval = nullptr;
-
-    int l = tok_val->line ();
-    int c = tok_val->column ();
-
-    if (lst)
-      m_lexer.mark_as_variables (lst->variable_names ());
-
-    switch (tok)
-      {
-      case GLOBAL:
-        {
-          retval = new tree_decl_command ("global", lst, l, c);
-          retval->mark_global ();
-        }
-        break;
-
-      case PERSISTENT:
-        if (m_curr_fcn_depth > 0)
-          {
-            retval = new tree_decl_command ("persistent", lst, l, c);
-            retval->mark_persistent ();
-          }
-        else
-          {
-            if (m_lexer.m_reading_script_file)
-              warning ("ignoring persistent declaration near line %d of file '%s'",
-                       l, m_lexer.m_fcn_file_full_name.c_str ());
-            else
-              warning ("ignoring persistent declaration near line %d", l);
-          }
-        break;
-
-      default:
-        panic_impossible ();
-        break;
-      }
-
-    return retval;
-  }
-
-  bool
-  base_parser::validate_param_list (tree_parameter_list *lst,
-                                    tree_parameter_list::in_or_out type)
-  {
-    std::set<std::string> dict;
-
-    for (tree_decl_elt *elt : *lst)
-      {
-        tree_identifier *id = elt->ident ();
-
-        if (id)
-          {
-            std::string name = id->name ();
-
-            if (id->is_black_hole ())
-              {
-                if (type != tree_parameter_list::in)
-                  {
-                    bison_error ("invalid use of ~ in output list");
-                    return false;
-                  }
-              }
-            else if (dict.find (name) != dict.end ())
-              {
-                bison_error ("'" + name
-                             + "' appears more than once in parameter list");
-                return false;
-              }
-            else
-              dict.insert (name);
-          }
-      }
-
-    std::string va_type = (type == tree_parameter_list::in
-                           ? "varargin" : "varargout");
-
-    size_t len = lst->length ();
-
-    if (len > 0)
-      {
-        tree_decl_elt *elt = lst->back ();
-
-        tree_identifier *id = elt->ident ();
-
-        if (id && id->name () == va_type)
-          {
-            if (len == 1)
-              lst->mark_varargs_only ();
-            else
-              lst->mark_varargs ();
-
-            tree_parameter_list::iterator p = lst->end ();
-            --p;
-            delete *p;
-            lst->erase (p);
-          }
-      }
-
-    return true;
-  }
-
-  bool
-  base_parser::validate_array_list (tree_expression *e)
-  {
-    bool retval = true;
-
-    tree_array_list *al = dynamic_cast<tree_array_list *> (e);
-
-    for (tree_argument_list* row : *al)
-      {
-        if (row && row->has_magic_tilde ())
-          {
-            retval = false;
-
-            if (e->is_matrix ())
-              bison_error ("invalid use of tilde (~) in matrix expression");
-            else
-              bison_error ("invalid use of tilde (~) in cell expression");
-
-            break;
-          }
-      }
-
-    return retval;
-  }
-
-  tree_argument_list *
-  base_parser::validate_matrix_for_assignment (tree_expression *e)
-  {
-    tree_argument_list *retval = nullptr;
-
-    if (e->is_constant ())
-      {
-        tree_evaluator& tw
-          = __get_evaluator__ ("validate_matrix_for_assignment");
-
-        octave_value ov = tw.evaluate (e);
-
-        delete e;
-
-        if (ov.isempty ())
-          bison_error ("invalid empty left hand side of assignment");
-        else
-          bison_error ("invalid constant left hand side of assignment");
-      }
-    else
-      {
-        bool is_simple_assign = true;
-
-        tree_argument_list *tmp = nullptr;
-
-        if (e->is_matrix ())
-          {
-            tree_matrix *mat = dynamic_cast<tree_matrix *> (e);
-
-            if (mat && mat->size () == 1)
-              {
-                tmp = mat->front ();
-                mat->pop_front ();
-                delete e;
-                is_simple_assign = false;
-              }
-          }
-        else
-          tmp = new tree_argument_list (e);
-
-        if (tmp && tmp->is_valid_lvalue_list ())
-          {
-            m_lexer.mark_as_variables (tmp->variable_names ());
-            retval = tmp;
-          }
-        else
-          {
-            delete tmp;
-
-            bison_error ("invalid left hand side of assignment");
-          }
-
-        if (retval && is_simple_assign)
-          retval->mark_as_simple_assign_lhs ();
-      }
-
-    return retval;
-  }
-
-  // Finish building an array_list.
-
-  tree_expression *
-  base_parser::finish_array_list (tree_array_list *array_list)
-  {
-    tree_expression *retval = array_list;
-
-    unwind_protect frame;
-
-    frame.protect_var (discard_error_messages);
-    frame.protect_var (discard_warning_messages);
-
-    discard_error_messages = true;
-    discard_warning_messages = true;
-
-    if (array_list->all_elements_are_constant ())
-      {
-        try
-          {
-            tree_evaluator& tw
-              = __get_evaluator__ ("finish_array_list");
-
-            octave_value tmp = tw.evaluate (array_list);
-
-            tree_constant *tc_retval
-              = new tree_constant (tmp, array_list->line (),
-                                   array_list->column ());
-
-            std::ostringstream buf;
-
-            tree_print_code tpc (buf);
-
-            array_list->accept (tpc);
-
-            tc_retval->stash_original_text (buf.str ());
-
-            delete array_list;
-
-            retval = tc_retval;
-          }
-        catch (const execution_exception&)
-          {
-            interpreter::recover_from_exception ();
-          }
-      }
-
-    return retval;
-  }
-
-  // Finish building a matrix list.
-
-  tree_expression *
-  base_parser::finish_matrix (tree_matrix *m)
-  {
-    return (m
-            ? finish_array_list (m)
-            : new tree_constant (octave_null_matrix::instance));
-  }
-
-  // Finish building a cell list.
-
-  tree_expression *
-  base_parser::finish_cell (tree_cell *c)
-  {
-    return (c
-            ? finish_array_list (c)
-            : new tree_constant (octave_value (Cell ())));
-  }
-
-  void
-  base_parser::maybe_warn_missing_semi (tree_statement_list *t)
-  {
-    if (m_curr_fcn_depth > 0)
-      {
-        tree_statement *tmp = t->back ();
-
-        if (tmp->is_expression ())
-          warning_with_id
-            ("Octave:missing-semicolon",
-             "missing semicolon near line %d, column %d in file '%s'",
-             tmp->line (), tmp->column (), m_lexer.m_fcn_file_full_name.c_str ());
-      }
-  }
-
-  tree_statement_list *
-  base_parser::set_stmt_print_flag (tree_statement_list *list,
-                                    char sep, bool warn_missing_semi)
-  {
-    tree_statement *tmp = list->back ();
-
-    switch (sep)
-      {
-      case ';':
-        tmp->set_print_flag (false);
-        break;
-
-      case 0:
-      case ',':
-      case '\n':
-        tmp->set_print_flag (true);
-        if (warn_missing_semi)
-          maybe_warn_missing_semi (list);
-        break;
-
-      default:
-        warning ("unrecognized separator type!");
-        break;
-      }
-
-    // Even if a statement is null, we add it to the list then remove it
-    // here so that the print flag is applied to the correct statement.
-
-    if (tmp->is_null_statement ())
-      {
-        list->pop_back ();
-        delete tmp;
-      }
-
-    return list;
-  }
-
-  // Finish building a statement.
-  template <typename T>
-  tree_statement *
-  base_parser::make_statement (T *arg)
-  {
-    comment_list *comment = m_lexer.get_comment ();
-
-    return new tree_statement (arg, comment);
-  }
-
-  tree_statement_list *
-  base_parser::make_statement_list (tree_statement *stmt)
-  {
-    return new tree_statement_list (stmt);
-  }
-
-  tree_statement_list *
-  base_parser::append_statement_list (tree_statement_list *list,
-                                      char sep, tree_statement *stmt,
-                                      bool warn_missing_semi)
-  {
-    set_stmt_print_flag (list, sep, warn_missing_semi);
-
-    list->append (stmt);
-
-    return list;
-  }
-
-  void
-  base_parser::bison_error (const std::string& str, int l, int c)
-  {
-    int err_line = l < 0 ? m_lexer.m_input_line_number : l;
-    int err_col = c < 0 ? m_lexer.m_current_input_column - 1 : c;
-
-    std::ostringstream output_buf;
-
-    if (m_lexer.m_reading_fcn_file || m_lexer.m_reading_script_file
-        || m_lexer.m_reading_classdef_file)
-      output_buf << "parse error near line " << err_line
-                 << " of file " << m_lexer.m_fcn_file_full_name;
-    else
-      output_buf << "parse error:";
-
-    if (str != "parse error")
-      output_buf << "\n\n  " << str;
-
-    output_buf << "\n\n";
-
-    std::string curr_line = m_lexer.m_current_input_line;
-
-    if (! curr_line.empty ())
-      {
-        size_t len = curr_line.length ();
-
-        if (curr_line[len-1] == '\n')
-          curr_line.resize (len-1);
-
-        // Print the line, maybe with a pointer near the error token.
-
-        output_buf << ">>> " << curr_line << "\n";
-
-        if (err_col == 0)
-          err_col = len;
-
-        for (int i = 0; i < err_col + 3; i++)
-          output_buf << " ";
-
-        output_buf << "^";
-      }
-
-    output_buf << "\n";
-
-    m_parse_error_msg = output_buf.str ();
-  }
-
-  int
-  parser::run (void)
-  {
-    int status = -1;
-
-    yypstate *pstate = static_cast<yypstate *> (m_parser_state);
-
-    try
-      {
-        status = octave_pull_parse (pstate, *this);
-      }
-    catch (execution_exception& e)
-      {
-        std::string file = m_lexer.m_fcn_file_full_name;
-
-        if (file.empty ())
-          error (e, "parse error");
-        else
-          error (e, "parse error in %s", file.c_str ());
-      }
-    catch (const exit_exception&)
-      {
-        throw;
-      }
-    catch (interrupt_exception &)
-      {
-        throw;
-      }
-    catch (...)
-      {
-        std::string file = m_lexer.m_fcn_file_full_name;
-
-        if (file.empty ())
-          error ("unexpected exception while parsing input");
-        else
-          error ("unexpected exception while parsing %s", file.c_str ());
-      }
-
-    if (status != 0)
-      parse_error ("%s", m_parse_error_msg.c_str ());
-
-    return status;
-  }
-
-  // Parse input from INPUT.  Pass TRUE for EOF if the end of INPUT should
-  // finish the parse.
-
-  int
-  push_parser::run (const std::string& input, bool eof)
-  {
-    int status = -1;
-
-    dynamic_cast<push_lexer&> (m_lexer).append_input (input, eof);
-
-    do
-      {
-        YYSTYPE lval;
-
-        int token = octave_lex (&lval, m_lexer.m_scanner);
-
-        if (token < 0)
-          {
-            if (! eof && m_lexer.at_end_of_buffer ())
-              {
-                status = -1;
-                break;
-              }
-          }
-
-        yypstate *pstate = static_cast<yypstate *> (m_parser_state);
-
-        try
-          {
-            status = octave_push_parse (pstate, token, &lval, *this);
-          }
-        catch (execution_exception& e)
-          {
-            std::string file = m_lexer.m_fcn_file_full_name;
-
-            if (file.empty ())
-              error (e, "parse error");
-            else
-              error (e, "parse error in %s", file.c_str ());
-          }
-        catch (const exit_exception&)
-          {
-            throw;
-          }
-        catch (interrupt_exception &)
-          {
-            throw;
-          }
-        catch (...)
-          {
-            std::string file = m_lexer.m_fcn_file_full_name;
-
-            if (file.empty ())
-              error ("unexpected exception while parsing input");
-            else
-              error ("unexpected exception while parsing %s", file.c_str ());
-          }
-      }
-    while (status == YYPUSH_MORE);
-
-    if (status != 0)
-      parse_error ("%s", m_parse_error_msg.c_str ());
-
-    return status;
-  }
-}
-
-static void
-safe_fclose (FILE *f)
-{
-  if (f)
-    fclose (static_cast<FILE *> (f));
-}
-
-static octave_value
-parse_fcn_file (const std::string& full_file, const std::string& file,
-                const std::string& dir_name, const std::string& dispatch_type,
-                const std::string& package_name, bool require_file,
-                bool force_script, bool autoload, bool relative_lookup,
-                const std::string& warn_for)
-{
-  octave_value retval;
-
-  octave::unwind_protect frame;
-
-  octave_function *fcn_ptr = nullptr;
-
-  // Open function file and parse.
-
-  FILE *in_stream = octave::command_editor::get_input_stream ();
-
-  frame.add_fcn (octave::command_editor::set_input_stream, in_stream);
-
-  frame.add_fcn (octave::command_history::ignore_entries,
-                 octave::command_history::ignoring_entries ());
-
-  octave::command_history::ignore_entries ();
-
-  FILE *ffile = nullptr;
-
-  if (! full_file.empty ())
-    ffile = std::fopen (full_file.c_str (), "rb");
-
-  if (ffile)
-    {
-      frame.add_fcn (safe_fclose, ffile);
-
-      octave::parser parser (ffile);
-
-      parser.m_curr_class_name = dispatch_type;
-      parser.m_curr_package_name = package_name;
-      parser.m_autoloading = autoload;
-      parser.m_fcn_file_from_relative_lookup = relative_lookup;
-
-      parser.m_lexer.m_force_script = force_script;
-      parser.m_lexer.prep_for_file ();
-      parser.m_lexer.m_parsing_class_method = ! dispatch_type.empty ();
-
-      parser.m_lexer.m_fcn_file_name = file;
-      parser.m_lexer.m_fcn_file_full_name = full_file;
-      parser.m_lexer.m_dir_name = dir_name;
-      parser.m_lexer.m_package_name = package_name;
-
-      int status = parser.run ();
-
-      fcn_ptr = parser.m_primary_fcn_ptr;
-
-      if (status == 0)
-        {
-          if (parser.m_lexer.m_reading_classdef_file
-              && parser.m_classdef_object)
-            {
-              // Convert parse tree for classdef object to
-              // meta.class info (and stash it in the symbol
-              // table?).  Return pointer to constructor?
-
-              if (fcn_ptr)
-                panic_impossible ();
-
-              bool is_at_folder = ! dispatch_type.empty ();
-
-              octave::interpreter& interp
-                = octave::__get_interpreter__ ("parse_fcn_file");
-
-              try
-                {
-                  fcn_ptr = parser.m_classdef_object->make_meta_class (interp, is_at_folder);
-                }
-              catch (const octave::execution_exception&)
-                {
-                  delete parser.m_classdef_object;
-                  throw;
-                }
-
-              if (fcn_ptr)
-                retval = octave_value (fcn_ptr);
-
-              delete parser.m_classdef_object;
-
-              parser.m_classdef_object = nullptr;
-            }
-          else if (fcn_ptr)
-            {
-              retval = octave_value (fcn_ptr);
-
-              fcn_ptr->maybe_relocate_end ();
-
-              if (parser.m_parsing_subfunctions)
-                {
-                  if (! parser.m_endfunction_found)
-                    parser.m_subfunction_names.reverse ();
-
-                  fcn_ptr->stash_subfunction_names (parser.m_subfunction_names);
-                }
-            }
-        }
-      else
-        error ("parse error while reading file %s", full_file.c_str ());
-    }
-  else if (require_file)
-    error ("no such file, '%s'", full_file.c_str ());
-  else if (! warn_for.empty ())
-    error ("%s: unable to open file '%s'", warn_for.c_str (),
-           full_file.c_str ());
-
-  return retval;
-}
-
-namespace octave
-{
-  std::string
-  get_help_from_file (const std::string& nm, bool& symbol_found,
-                      std::string& full_file)
-  {
-    std::string retval;
-
-    full_file = fcn_file_in_path (nm);
-
-    std::string file = full_file;
-
-    size_t file_len = file.length ();
-
-    if ((file_len > 4 && file.substr (file_len-4) == ".oct")
-        || (file_len > 4 && file.substr (file_len-4) == ".mex")
-        || (file_len > 2 && file.substr (file_len-2) == ".m"))
-      {
-        file = sys::env::base_pathname (file);
-        file = file.substr (0, file.find_last_of ('.'));
-
-        size_t pos = file.find_last_of (sys::file_ops::dir_sep_str ());
-        if (pos != std::string::npos)
-          file = file.substr (pos+1);
-      }
-
-    if (! file.empty ())
-      {
-        symbol_found = true;
-
-        octave_value ov_fcn
-          = parse_fcn_file (full_file, file, "", "", "", true,
-                            false, false, false, "");
-
-        if (ov_fcn.is_defined ())
-          {
-            octave_function *fcn = ov_fcn.function_value ();
-
-            if (fcn)
-              retval = fcn->doc_string ();
-          }
-      }
-
-    return retval;
-  }
-
-  std::string
-  get_help_from_file (const std::string& nm, bool& symbol_found)
-  {
-    std::string file;
-    return get_help_from_file (nm, symbol_found, file);
-  }
-
-  std::string
-  lookup_autoload (const std::string& nm)
-  {
-    std::string retval;
-
-    typedef std::map<std::string, std::string>::const_iterator am_iter;
-
-    am_iter p = autoload_map.find (nm);
-
-    if (p != autoload_map.end ())
-      {
-        load_path& lp = __get_load_path__ ("lookup_autoload");
-
-        retval = lp.find_file (p->second);
-      }
-
-    return retval;
-  }
-
-  string_vector
-  autoloaded_functions (void)
-  {
-    string_vector names (autoload_map.size ());
-
-    octave_idx_type i = 0;
-    for (const auto& fcn_fname : autoload_map)
-      names[i++] = fcn_fname.first;
-
-    return names;
-  }
-
-  string_vector
-  reverse_lookup_autoload (const std::string& nm)
-  {
-    string_vector names;
-
-    for (const auto& fcn_fname : autoload_map)
-      if (nm == fcn_fname.second)
-        names.append (fcn_fname.first);
-
-    return names;
-  }
-
-  octave_value
-  load_fcn_from_file (const std::string& file_name,
-                      const std::string& dir_name,
-                      const std::string& dispatch_type,
-                      const std::string& package_name,
-                      const std::string& fcn_name, bool autoload)
-  {
-    octave_value retval;
-
-    unwind_protect frame;
-
-    std::string nm = file_name;
-
-    size_t nm_len = nm.length ();
-
-    std::string file;
-
-    bool relative_lookup = false;
-
-    file = nm;
-
-    if ((nm_len > 4 && nm.substr (nm_len-4) == ".oct")
-        || (nm_len > 4 && nm.substr (nm_len-4) == ".mex")
-        || (nm_len > 2 && nm.substr (nm_len-2) == ".m"))
-      {
-        nm = sys::env::base_pathname (file);
-        nm = nm.substr (0, nm.find_last_of ('.'));
-
-        size_t pos = nm.find_last_of (sys::file_ops::dir_sep_str ());
-        if (pos != std::string::npos)
-          nm = nm.substr (pos+1);
-      }
-
-    relative_lookup = ! sys::env::absolute_pathname (file);
-
-    file = sys::env::make_absolute (file);
-
-    int len = file.length ();
-
-      dynamic_loader& dyn_loader
-        = __get_dynamic_loader__ ("~octave_mex_function");
-
-    if (len > 4 && file.substr (len-4, len-1) == ".oct")
-      {
-        if (autoload && ! fcn_name.empty ())
-          nm = fcn_name;
-
-        octave_function *tmpfcn
-          = dyn_loader.load_oct (nm, file, relative_lookup);
-
-        if (tmpfcn)
-          {
-            tmpfcn->stash_package_name (package_name);
-            retval = octave_value (tmpfcn);
-          }
-      }
-    else if (len > 4 && file.substr (len-4, len-1) == ".mex")
-      {
-        // Temporarily load m-file version of mex-file, if it exists,
-        // to get the help-string to use.
-
-        std::string doc_string;
-
-        octave_value ov_fcn
-          = parse_fcn_file (file.substr (0, len - 2), nm, dir_name,
-                            dispatch_type, package_name, false,
-                            autoload, autoload, relative_lookup, "");
-
-        if (ov_fcn.is_defined ())
-          {
-            octave_function *tmpfcn = ov_fcn.function_value ();
-
-            if (tmpfcn)
-              doc_string = tmpfcn->doc_string ();
-          }
-
-        octave_function *tmpfcn
-          = dyn_loader.load_mex (nm, file, relative_lookup);
-
-        if (tmpfcn)
-          {
-            tmpfcn->document (doc_string);
-            tmpfcn->stash_package_name (package_name);
-
-            retval = octave_value (tmpfcn);
-          }
-      }
-    else if (len > 2)
-      {
-        retval = parse_fcn_file (file, nm, dir_name, dispatch_type,
-                                 package_name, true, autoload, autoload,
-                                 relative_lookup, "");
-      }
-
-    return retval;
-  }
-}
-
-DEFMETHOD (autoload, interp, args, ,
-           doc: /* -*- texinfo -*-
-@deftypefn  {} {@var{autoload_map} =} autoload ()
-@deftypefnx {} {} autoload (@var{function}, @var{file})
-@deftypefnx {} {} autoload (@dots{}, "remove")
-Define @var{function} to autoload from @var{file}.
-
-The second argument, @var{file}, should be an absolute filename or a file
-name in the same directory as the function or script from which the autoload
-command was run.  @var{file} @emph{should not} depend on the Octave load
-path.
-
-Normally, calls to @code{autoload} appear in PKG_ADD script files that are
-evaluated when a directory is added to Octave's load path.  To avoid having
-to hardcode directory names in @var{file}, if @var{file} is in the same
-directory as the PKG_ADD script then
-
-@example
-autoload ("foo", "bar.oct");
-@end example
-
-@noindent
-will load the function @code{foo} from the file @code{bar.oct}.  The above
-usage when @code{bar.oct} is not in the same directory, or usages such as
-
-@example
-autoload ("foo", file_in_loadpath ("bar.oct"))
-@end example
-
-@noindent
-are strongly discouraged, as their behavior may be unpredictable.
-
-With no arguments, return a structure containing the current autoload map.
-
-If a third argument @qcode{"remove"} is given, the function is cleared and
-not loaded anymore during the current Octave session.
-
-@seealso{PKG_ADD}
-@end deftypefn */)
-{
-  octave_value retval;
-
-  int nargin = args.length ();
-
-  if (nargin == 1 || nargin > 3)
-    print_usage ();
-
-  if (nargin == 0)
-    {
-      Cell func_names (dim_vector (autoload_map.size (), 1));
-      Cell file_names (dim_vector (autoload_map.size (), 1));
-
-      octave_idx_type i = 0;
-      for (const auto& fcn_fname : autoload_map)
-        {
-          func_names(i) = fcn_fname.first;
-          file_names(i) = fcn_fname.second;
-
-          i++;
-        }
-
-      octave_map m;
-
-      m.assign ("function", func_names);
-      m.assign ("file", file_names);
-
-      retval = m;
-    }
-  else
-    {
-      string_vector argv = args.make_argv ("autoload");
-
-      std::string nm = argv[2];
-
-      if (! octave::sys::env::absolute_pathname (nm))
-        {
-          octave::call_stack& cs = interp.get_call_stack ();
-
-          octave_user_code *fcn = cs.caller_user_code ();
-
-          bool found = false;
-
-          if (fcn)
-            {
-              std::string fname = fcn->fcn_file_name ();
-
-              if (! fname.empty ())
-                {
-                  fname = octave::sys::env::make_absolute (fname);
-                  fname = fname.substr (0, fname.find_last_of (octave::sys::file_ops::dir_sep_str ()) + 1);
-
-                  octave::sys::file_stat fs (fname + nm);
-
-                  if (fs.exists ())
-                    {
-                      nm = fname + nm;
-                      found = true;
-                    }
-                }
-            }
-          if (! found)
-            warning_with_id ("Octave:autoload-relative-file-name",
-                             "autoload: '%s' is not an absolute filename",
-                             nm.c_str ());
-        }
-      if (nargin == 2)
-        autoload_map[argv[1]] = nm;
-      else if (nargin == 3)
-        {
-          if (argv[3] != "remove")
-            error_with_id ("Octave:invalid-input-arg",
-                           "autoload: third argument can only be 'remove'");
-
-          // Remove function from symbol table and autoload map.
-          octave::symbol_table& symtab = interp.get_symbol_table ();
-          symtab.clear_dld_function (argv[1]);
-          autoload_map.erase (argv[1]);
-        }
-    }
-
-  return retval;
-}
-
-namespace octave
-{
-  // Execute the contents of a script file.  For compatibility with
-  // Matlab, also execute a function file by calling the function it
-  // defines with no arguments and nargout = 0.
-
-  void
-  source_file (const std::string& file_name, const std::string& context,
-               bool verbose, bool require_file, const std::string& warn_for)
-  {
-    // Map from absolute name of script file to recursion level.  We
-    // use a map instead of simply placing a limit on recursion in the
-    // source_file function so that two mutually recursive scripts
-    // written as
-    //
-    //   foo1.m:
-    //   ------
-    //   foo2
-    //
-    //   foo2.m:
-    //   ------
-    //   foo1
-    //
-    // and called with
-    //
-    //   foo1
-    //
-    // (for example) will behave the same if they are written as
-    //
-    //   foo1.m:
-    //   ------
-    //   source ("foo2.m")
-    //
-    //   foo2.m:
-    //   ------
-    //   source ("foo1.m")
-    //
-    // and called with
-    //
-    //   source ("foo1.m")
-    //
-    // (for example).
-
-    static std::map<std::string, int> source_call_depth;
-
-    std::string file_full_name
-      = sys::file_ops::tilde_expand (file_name);
-
-    size_t pos
-      = file_full_name.find_last_of (sys::file_ops::dir_sep_str ());
-
-    std::string dir_name = file_full_name.substr (0, pos);
-
-    file_full_name = sys::env::make_absolute (file_full_name);
-
-    unwind_protect frame;
-
-    if (source_call_depth.find (file_full_name) == source_call_depth.end ())
-      source_call_depth[file_full_name] = -1;
-
-    frame.protect_var (source_call_depth[file_full_name]);
-
-    source_call_depth[file_full_name]++;
-
-    tree_evaluator& tw = __get_evaluator__ ("source_file");
-
-    if (source_call_depth[file_full_name] >= tw.max_recursion_depth ())
-      error ("max_recursion_depth exceeded");
-
-    if (! context.empty ())
-      {
-        call_stack& cs = __get_call_stack__ ("source_file");
-
-        if (context == "caller")
-          cs.goto_caller_frame ();
-        else if (context == "base")
-          cs.goto_base_frame ();
-        else
-          error ("source: context must be \"caller\" or \"base\"");
-
-        frame.add_method (cs, &call_stack::pop);
-      }
-
-    // Find symbol name that would be in symbol_table, if it were loaded.
-    size_t dir_end
-      = file_name.find_last_of (sys::file_ops::dir_sep_chars ());
-    dir_end = (dir_end == std::string::npos) ? 0 : dir_end + 1;
-
-    size_t extension = file_name.find_last_of ('.');
-    if (extension == std::string::npos)
-      extension = file_name.length ();
-
-    std::string symbol = file_name.substr (dir_end, extension - dir_end);
-    std::string full_name = sys::canonicalize_file_name (file_name);
-
-    // Check if this file is already loaded (or in the path)
-    symbol_table& symtab = __get_symbol_table__ ("source_file");
-    octave_value ov_code = symtab.find (symbol);
-
-    // For compatibility with Matlab, accept both scripts and
-    // functions.
-
-    if (ov_code.is_user_code ())
-      {
-        octave_user_code *code = ov_code.user_code_value ();
-
-        if (! code
-            || (sys::canonicalize_file_name (code->fcn_file_name ())
-                != full_name))
-          {
-            // Wrong file, so load it below.
-            ov_code = octave_value ();
-          }
-      }
-    else
-      {
-        // Not a script, so load it below.
-        ov_code = octave_value ();
-      }
-
-    // If no symbol of this name, or the symbol is for a different
-    // file, load.
-
-    if (ov_code.is_undefined ())
-      {
-        try
-          {
-            ov_code = parse_fcn_file (file_full_name, file_name, dir_name,
-                                      "", "", require_file, true, false,
-                                      false, warn_for);
-          }
-        catch (execution_exception& e)
-          {
-            error (e, "source: error sourcing file '%s'",
-                   file_full_name.c_str ());
-          }
-      }
-
-    // Return or error if we don't have a valid script or function.
-
-    if (ov_code.is_undefined ())
-      return;
-
-    if (! ov_code.is_user_code ())
-      error ("source: %s is not a script", full_name.c_str ());
-
-    if (verbose)
-      {
-        std::cout << "executing commands from " << full_name << " ... ";
-        std::cout.flush ();
-      }
-
-    octave_user_code *code = ov_code.user_code_value ();
-
-    code->call (tw, 0, octave_value_list ());
-
-    if (verbose)
-      std::cout << "done." << std::endl;
-  }
-}
-
-DEFMETHOD (mfilename, interp, args, ,
-           doc: /* -*- texinfo -*-
-@deftypefn  {} {} mfilename ()
-@deftypefnx {} {} mfilename ("fullpath")
-@deftypefnx {} {} mfilename ("fullpathext")
-Return the name of the currently executing file.
-
-When called from outside an m-file return the empty string.
-
-Given the argument @qcode{"fullpath"}, include the directory part of the
-filename, but not the extension.
-
-Given the argument @qcode{"fullpathext"}, include the directory part of
-the filename and the extension.
-@end deftypefn */)
-{
-  octave_value retval;
-
-  int nargin = args.length ();
-
-  if (nargin > 1)
-    print_usage ();
-
-  std::string arg;
-
-  if (nargin == 1)
-    arg = args(0).xstring_value ("mfilename: argument must be a string");
-
-  std::string fname;
-
-  octave::call_stack& cs = interp.get_call_stack ();
-
-  octave_user_code *fcn = cs.caller_user_code ();
-
-  if (fcn)
-    {
-      fname = fcn->fcn_file_name ();
-
-      if (fname.empty ())
-        fname = fcn->name ();
-    }
-
-  if (arg == "fullpathext")
-    retval = fname;
-  else
-    {
-      size_t dpos = fname.rfind (octave::sys::file_ops::dir_sep_char ());
-      size_t epos = fname.rfind ('.');
-
-      if (epos <= dpos)
-        epos = std::string::npos;
-
-      fname = (epos != std::string::npos) ? fname.substr (0, epos) : fname;
-
-      if (arg == "fullpath")
-        retval = fname;
-      else
-        retval = (dpos != std::string::npos) ? fname.substr (dpos+1) : fname;
-    }
-
-  return retval;
-}
-
-DEFUN (source, args, ,
-       doc: /* -*- texinfo -*-
-@deftypefn  {} {} source (@var{file})
-@deftypefnx {} {} source (@var{file}, @var{context})
-Parse and execute the contents of @var{file}.
-
-Without specifying @var{context}, this is equivalent to executing commands
-from a script file, but without requiring the file to be named
-@file{@var{file}.m} or to be on the execution path.
-
-Instead of the current context, the script may be executed in either the
-context of the function that called the present function
-(@qcode{"caller"}), or the top-level context (@qcode{"base"}).
-@seealso{run}
-@end deftypefn */)
-{
-  octave_value_list retval;
-
-  int nargin = args.length ();
-
-  if (nargin < 1 || nargin > 2)
-    print_usage ();
-
-  std::string file_name = args(0).xstring_value ("source: FILE must be a string");
-
-  std::string context;
-
-  if (nargin == 2)
-    context = args(1).xstring_value ("source: CONTEXT must be a string");
-
-  octave::source_file (file_name, context);
-
-  return retval;
-}
-
-namespace octave
-{
-  //! Evaluate an Octave function (built-in or interpreted) and return
-  //! the list of result values.
-  //!
-  //! @param name The name of the function to call.
-  //! @param args The arguments to the function.
-  //! @param nargout The number of output arguments expected.
-  //! @return A list of output values.  The length of the list is not
-  //!         necessarily the same as @c nargout.
-
-  octave_value_list
-  feval (const std::string& name, const octave_value_list& args, int nargout)
-  {
-    octave_value_list retval;
-
-    symbol_table& symtab = __get_symbol_table__ ("feval");
-
-    octave_value fcn = symtab.find_function (name, args);
-
-    if (fcn.is_defined ())
-      {
-        tree_evaluator& tw = __get_evaluator__ ("feval");
-
-        octave_function *of = fcn.function_value ();
-
-        retval = of->call (tw, nargout, args);
-      }
-    else
-      error ("feval: function '%s' not found", name.c_str ());
-
-    return retval;
-  }
-
-  octave_value_list
-  feval (octave_function *fcn, const octave_value_list& args, int nargout)
-  {
-    octave_value_list retval;
-
-    if (fcn)
-      {
-        tree_evaluator& tw = __get_evaluator__ ("feval");
-
-        retval = fcn->call (tw, nargout, args);
-      }
-
-    return retval;
-  }
-
-  octave_value_list
-  feval (octave_value& val, const octave_value_list& args, int nargout)
-  {
-    if (val.is_function ())
-      {
-        return feval (val.function_value (), args, nargout);
-      }
-    else if (val.is_function_handle ())
-      {
-        // This covers function handles, inline functions, and anonymous
-        //  functions.
-
-        std::list<octave_value_list> arg_list;
-        arg_list.push_back (args);
-
-        return val.subsref ("(", arg_list, nargout);
-      }
-    else if (val.is_string ())
-      {
-        return feval (val.string_value (), args, nargout);
-      }
-    else
-      error ("feval: first argument must be a string, inline function, or a function handle");
-
-    return ovl ();
-  }
-}
-
-static octave_value_list
-get_feval_args (const octave_value_list& args)
-{
-  return args.slice (1, args.length () - 1, true);
-}
-
-namespace octave
-{
-  //! Evaluate an Octave function (built-in or interpreted) and return
-  //! the list of result values.
-  //!
-  //! @param args The first element of @c args is the function to call.
-  //!             It may be the name of the function as a string, a function
-  //!             handle, or an inline function.  The remaining arguments are
-  //!             passed to the function.
-  //! @param nargout The number of output arguments expected.
-  //! @return A list of output values.  The length of the list is not
-  //!         necessarily the same as @c nargout.
-
-  octave_value_list
-  feval (const octave_value_list& args, int nargout)
-  {
-    if (args.length () > 0)
-      {
-        octave_value f_arg = args(0);
-
-        octave_value_list tmp_args = get_feval_args (args);
-
-        return feval (f_arg, tmp_args, nargout);
-      }
-    else
-      error ("feval: first argument must be a string, inline function, or a function handle");
-
-    return ovl ();
-  }
-}
-
-DEFUN (feval, args, nargout,
-       doc: /* -*- texinfo -*-
-@deftypefn {} {} feval (@var{name}, @dots{})
-Evaluate the function named @var{name}.
-
-Any arguments after the first are passed as inputs to the named function.
-For example,
-
-@example
-@group
-feval ("acos", -1)
-     @result{} 3.1416
-@end group
-@end example
-
-@noindent
-calls the function @code{acos} with the argument @samp{-1}.
-
-The function @code{feval} can also be used with function handles of any sort
-(@pxref{Function Handles}).  Historically, @code{feval} was the only way to
-call user-supplied functions in strings, but function handles are now
-preferred due to the cleaner syntax they offer.  For example,
-
-@example
-@group
-@var{f} = @@exp;
-feval (@var{f}, 1)
-    @result{} 2.7183
-@var{f} (1)
-    @result{} 2.7183
-@end group
-@end example
-
-@noindent
-are equivalent ways to call the function referred to by @var{f}.  If it
-cannot be predicted beforehand whether @var{f} is a function handle,
-function name in a string, or inline function then @code{feval} can be used
-instead.
-@end deftypefn */)
-{
-  if (args.length () == 0)
-    print_usage ();
-
-  return octave::feval (args, nargout);
-}
-
-DEFMETHOD (builtin, interp, args, nargout,
-           doc: /* -*- texinfo -*-
-@deftypefn {} {[@dots{}] =} builtin (@var{f}, @dots{})
-Call the base function @var{f} even if @var{f} is overloaded to another
-function for the given type signature.
-
-This is normally useful when doing object-oriented programming and there is
-a requirement to call one of Octave's base functions rather than the
-overloaded one of a new class.
-
-A trivial example which redefines the @code{sin} function to be the
-@code{cos} function shows how @code{builtin} works.
-
-@example
-@group
-sin (0)
-  @result{} 0
-function y = sin (x), y = cos (x); endfunction
-sin (0)
-  @result{} 1
-builtin ("sin", 0)
-  @result{} 0
-@end group
-@end example
-@end deftypefn */)
-{
-  octave_value_list retval;
-
-  if (args.length () == 0)
-    print_usage ();
-
-  const std::string name (args(0).xstring_value ("builtin: function name (F) must be a string"));
-
-  octave::symbol_table& symtab = interp.get_symbol_table ();
-
-  octave_value fcn = symtab.builtin_find (name);
-
-  if (fcn.is_defined ())
-    retval = octave::feval (fcn.function_value (), args.splice (0, 1), nargout);
-  else
-    error ("builtin: lookup for symbol '%s' failed", name.c_str ());
-
-  return retval;
-}
-
-namespace octave
-{
-  octave_value_list
-  eval_string (const std::string& eval_str, bool silent,
-               int& parse_status, int nargout)
-  {
-    octave_value_list retval;
-
-    parser parser (eval_str);
-
-    do
-      {
-        parser.reset ();
-
-        parse_status = parser.run ();
-
-        if (parse_status == 0)
-          {
-            if (parser.m_stmt_list)
-              {
-                tree_statement *stmt = nullptr;
-
-                tree_evaluator& tw = __get_evaluator__ ("eval_string");
-
-                if (parser.m_stmt_list->length () == 1
-                    && (stmt = parser.m_stmt_list->front ())
-                    && stmt->is_expression ())
-                  {
-                    tree_expression *expr = stmt->expression ();
-
-                    if (silent)
-                      expr->set_print_flag (false);
-
-                    bool do_bind_ans = false;
-
-                    if (expr->is_identifier ())
-                      {
-                        octave::symbol_scope scope = tw.get_current_scope ();
-
-                        octave::symbol_record::context_id context
-                          = scope.current_context ();
-
-                        tree_identifier *id
-                          = dynamic_cast<tree_identifier *> (expr);
-
-                        do_bind_ans = (! id->is_variable (context));
-                      }
-                    else
-                      do_bind_ans = (! expr->is_assignment_expression ());
-
-                    retval = tw.evaluate_n (expr, nargout);
-
-                    if (do_bind_ans && ! retval.empty ())
-                      tw.bind_ans (retval(0), expr->print_result ());
-
-                    if (nargout == 0)
-                      retval = octave_value_list ();
-                  }
-                else if (nargout == 0)
-                  parser.m_stmt_list->accept (tw);
-                else
-                  error ("eval: invalid use of statement list");
-
-                if (tree_return_command::returning
-                    || tree_break_command::breaking
-                    || tree_continue_command::continuing)
-                  break;
-              }
-            else if (parser.m_lexer.m_end_of_input)
-              break;
-          }
-      }
-    while (parse_status == 0);
-
-    return retval;
-  }
-
-  octave_value
-  eval_string (const std::string& eval_str, bool silent, int& parse_status)
-  {
-    octave_value retval;
-
-    octave_value_list tmp = eval_string (eval_str, silent, parse_status, 1);
-
-    if (! tmp.empty ())
-      retval = tmp(0);
-
-    return retval;
-  }
-
-  static octave_value_list
-  eval_string (const octave_value& arg, bool silent, int& parse_status,
-               int nargout)
-  {
-    std::string s = arg.xstring_value ("eval: expecting std::string argument");
-
-    return eval_string (s, silent, parse_status, nargout);
-  }
-
-  void
-  cleanup_statement_list (tree_statement_list **lst)
-  {
-    if (*lst)
-      {
-        delete *lst;
-        *lst = nullptr;
-      }
-  }
-}
-
-DEFUN (eval, args, nargout,
-       doc: /* -*- texinfo -*-
-@deftypefn  {} {} eval (@var{try})
-@deftypefnx {} {} eval (@var{try}, @var{catch})
-Parse the string @var{try} and evaluate it as if it were an Octave
-program.
-
-If execution fails, evaluate the optional string @var{catch}.
-
-The string @var{try} is evaluated in the current context, so any results
-remain available after @code{eval} returns.
-
-The following example creates the variable @var{A} with the approximate
-value of 3.1416 in the current workspace.
-
-@example
-eval ("A = acos(-1);");
-@end example
-
-If an error occurs during the evaluation of @var{try} then the @var{catch}
-string is evaluated, as the following example shows:
-
-@example
-@group
-eval ('error ("This is a bad example");',
-      'printf ("This error occurred:\n%s\n", lasterr ());');
-     @print{} This error occurred:
-        This is a bad example
-@end group
-@end example
-
-Programming Note: if you are only using @code{eval} as an error-capturing
-mechanism, rather than for the execution of arbitrary code strings,
-Consider using try/catch blocks or unwind_protect/unwind_protect_cleanup
-blocks instead.  These techniques have higher performance and don't
-introduce the security considerations that the evaluation of arbitrary code
-does.
-@seealso{evalin, evalc, assignin, feval}
-@end deftypefn */)
-{
-  octave_value_list retval;
-
-  int nargin = args.length ();
-
-  if (nargin == 0)
-    print_usage ();
-
-  octave::unwind_protect frame;
-
-  if (nargin > 1)
-    {
-      frame.protect_var (buffer_error_messages);
-      buffer_error_messages++;
-    }
-
-  int parse_status = 0;
-
-  bool execution_error = false;
-
-  octave_value_list tmp;
-
-  try
-    {
-      tmp = octave::eval_string (args(0), nargout > 0, parse_status, nargout);
-    }
-  catch (const octave::execution_exception&)
-    {
-      octave::interpreter::recover_from_exception ();
-
-      execution_error = true;
-    }
-
-  if (nargin > 1 && (parse_status != 0 || execution_error))
-    {
-      // Set up for letting the user print any messages from
-      // errors that occurred in the first part of this eval().
-
-      buffer_error_messages--;
-
-      tmp = octave::eval_string (args(1), nargout > 0, parse_status, nargout);
-
-      if (nargout > 0)
-        retval = tmp;
-    }
-  else
-    {
-      if (nargout > 0)
-        retval = tmp;
-
-      // FIXME: we should really be rethrowing whatever exception occurred,
-      // not just throwing an execution exception.
-      if (execution_error)
-        octave_throw_execution_exception ();
-    }
-
-  return retval;
-}
-
-/*
-
-%!shared x
-%! x = 1;
-
-%!assert (eval ("x"), 1)
-%!assert (eval ("x;"))
-%!assert (eval ("x;"), 1)
-
-%!test
-%! y = eval ("x");
-%! assert (y, 1);
-
-%!test
-%! y = eval ("x;");
-%! assert (y, 1);
-
-%!test
-%! eval ("x = 1;");
-%! assert (x,1);
-
-%!test
-%! eval ("flipud = 2;");
-%! assert (flipud, 2);
-
-%!function y = __f ()
-%!  eval ("flipud = 2;");
-%!  y = flipud;
-%!endfunction
-%!assert (__f(), 2)
-
-% bug #35645
-%!test
-%! [a,] = gcd (1,2);
-%! [a,b,] = gcd (1, 2);
-
-%!error eval ("switch = 13;")
-
-*/
-
-DEFMETHOD (assignin, interp, args, ,
-           doc: /* -*- texinfo -*-
-@deftypefn {} {} assignin (@var{context}, @var{varname}, @var{value})
-Assign @var{value} to @var{varname} in context @var{context}, which
-may be either @qcode{"base"} or @qcode{"caller"}.
-@seealso{evalin}
-@end deftypefn */)
-{
-  octave_value_list retval;
-
-  if (args.length () != 3)
-    print_usage ();
-
-  std::string context = args(0).xstring_value ("assignin: CONTEXT must be a string");
-
-  octave::unwind_protect frame;
-
-  octave::call_stack& cs = interp.get_call_stack ();
-
-  if (context == "caller")
-    cs.goto_caller_frame ();
-  else if (context == "base")
-    cs.goto_base_frame ();
-  else
-    error ("assignin: CONTEXT must be \"caller\" or \"base\"");
-
-  frame.add_method (cs, &octave::call_stack::pop);
-
-  std::string nm = args(1).xstring_value ("assignin: VARNAME must be a string");
-
-  if (valid_identifier (nm))
-    {
-      // Put the check here so that we don't slow down assignments
-      // generally.  Any that go through Octave's parser should have
-      // already been checked.
-
-      if (octave::is_keyword (nm))
-        error ("assignin: invalid assignment to keyword '%s'", nm.c_str ());
-
-      octave::symbol_scope scope = interp.get_current_scope ();
-
-      if (scope)
-        scope.assign (nm, args(2));
-    }
-  else
-    error ("assignin: invalid variable name in argument VARNAME");
-
-  return retval;
-}
-
-/*
-
-%!error assignin ("base", "switch", "13")
-
-*/
-
-DEFMETHOD (evalin, interp, args, nargout,
-           doc: /* -*- texinfo -*-
-@deftypefn  {} {} evalin (@var{context}, @var{try})
-@deftypefnx {} {} evalin (@var{context}, @var{try}, @var{catch})
-Like @code{eval}, except that the expressions are evaluated in the context
-@var{context}, which may be either @qcode{"caller"} or @qcode{"base"}.
-@seealso{eval, assignin}
-@end deftypefn */)
-{
-  octave_value_list retval;
-
-  int nargin = args.length ();
-
-  if (nargin < 2)
-    print_usage ();
-
-  std::string context = args(0).xstring_value ("evalin: CONTEXT must be a string");
-
-  octave::unwind_protect frame;
-
-  octave::call_stack& cs = interp.get_call_stack ();
-
-  if (context == "caller")
-    cs.goto_caller_frame ();
-  else if (context == "base")
-    cs.goto_base_frame ();
-  else
-    error ("evalin: CONTEXT must be \"caller\" or \"base\"");
-
-  frame.add_method (cs, &octave::call_stack::pop);
-
-  if (nargin > 2)
-    {
-      frame.protect_var (buffer_error_messages);
-      buffer_error_messages++;
-    }
-
-  int parse_status = 0;
-
-  bool execution_error = false;
-
-  octave_value_list tmp;
-
-  try
-    {
-      tmp = octave::eval_string (args(1), nargout > 0,
-                                 parse_status, nargout);
-    }
-  catch (const octave::execution_exception&)
-    {
-      octave::interpreter::recover_from_exception ();
-
-      execution_error = true;
-    }
-
-  if (nargin > 2 && (parse_status != 0 || execution_error))
-    {
-      // Set up for letting the user print any messages from
-      // errors that occurred in the first part of this eval().
-
-      buffer_error_messages--;
-
-      tmp = octave::eval_string (args(2), nargout > 0,
-                                 parse_status, nargout);
-
-      retval = (nargout > 0) ? tmp : octave_value_list ();
-    }
-  else
-    {
-      if (nargout > 0)
-        retval = tmp;
-
-      // FIXME: we should really be rethrowing whatever
-      // exception occurred, not just throwing an
-      // execution exception.
-      if (execution_error)
-        octave_throw_execution_exception ();
-    }
-
-  return retval;
-}
-
-static void
-maybe_print_last_error_message (bool *doit)
-{
-  if (doit && *doit)
-    // Print error message again, which was lost because of the stderr buffer
-    // Note: this keeps error_state and last_error_stack intact
-    message_with_id ("error", last_error_id ().c_str (),
-                     last_error_message ().c_str ());
-}
-
-static void
-restore_octave_stdout (std::streambuf *buf)
-{
-  octave_stdout.flush ();
-  octave_stdout.rdbuf (buf);
-}
-
-static void
-restore_octave_stderr (std::streambuf *buf)
-{
-  std::cerr.flush ();
-  std::cerr.rdbuf (buf);
-}
-
-DEFUN (evalc, args, nargout,
-       doc: /* -*- texinfo -*-
-@deftypefn  {} {@var{s} =} evalc (@var{try})
-@deftypefnx {} {@var{s} =} evalc (@var{try}, @var{catch})
-Parse and evaluate the string @var{try} as if it were an Octave program,
-while capturing the output into the return variable @var{s}.
-
-If execution fails, evaluate the optional string @var{catch}.
-
-This function behaves like @code{eval}, but any output or warning messages
-which would normally be written to the console are captured and returned in
-the string @var{s}.
-
-The @code{diary} is disabled during the execution of this function.  When
-@code{system} is used, any output produced by external programs is
-@emph{not} captured, unless their output is captured by the @code{system}
-function itself.
-
-@example
-@group
-s = evalc ("t = 42"), t
-  @result{} s = t =  42
-
-  @result{} t =  42
-@end group
-@end example
-@seealso{eval, diary}
-@end deftypefn */)
-{
-  int nargin = args.length ();
-
-  if (nargin == 0 || nargin > 2)
-    print_usage ();
-
-  // redirect stdout/stderr to capturing buffer
-  std::ostringstream buffer;
-
-  std::ostream& out_stream = octave_stdout;
-  std::ostream& err_stream = std::cerr;
-
-  out_stream.flush ();
-  err_stream.flush ();
-
-  std::streambuf* old_out_buf = out_stream.rdbuf (buffer.rdbuf ());
-  std::streambuf* old_err_buf = err_stream.rdbuf (buffer.rdbuf ());
-
-  bool eval_error_occurred = true;
-
-  octave::unwind_protect frame;
-
-  frame.add_fcn (maybe_print_last_error_message, &eval_error_occurred);
-  frame.add_fcn (restore_octave_stdout, old_out_buf);
-  frame.add_fcn (restore_octave_stderr, old_err_buf);
-
-  // call standard eval function
-  octave_value_list retval;
-  int eval_nargout = std::max (0, nargout - 1);
-
-  retval = Feval (args, eval_nargout);
-  eval_error_occurred = false;
-
-  retval.prepend (buffer.str ());
-  return retval;
-}
-
-/*
-
-%!assert (evalc ("1"), "ans =  1\n")
-%!assert (evalc ("1;"), "")
-
-%!test
-%! [s, y] = evalc ("1");
-%! assert (s, "");
-%! assert (y, 1);
-
-%!test
-%! [s, y] = evalc ("1;");
-%! assert (s, "");
-%! assert (y, 1);
-
-%!test
-%! assert (evalc ("y = 2"), "y =  2\n");
-%! assert (y, 2);
-
-%!test
-%! assert (evalc ("y = 3;"), "");
-%! assert (y, 3);
-
-%!test
-%! [s, a, b] = evalc ("deal (1, 2)");
-%! assert (s, "");
-%! assert (a, 1);
-%! assert (b, 2);
-
-%!function [a, b] = __f_evalc ()
-%!  printf ("foo");
-%!  fprintf (stdout, "bar");
-%!  disp (pi);
-%!  a = 1;
-%!  b = 2;
-%!endfunction
-%!test
-%! [s, a, b] = evalc ("__f_evalc ()");
-%! assert (s, "foobar 3.1416\n");
-%! assert (a, 1);
-%! assert (b, 2);
-
-%!error <foo> (evalc ("error ('foo')"))
-%!error <bar> (evalc ("error ('foo')", "error ('bar')"))
-
-%!test
-%! warning ("off", "quiet", "local");
-%! assert (evalc ("warning ('foo')"), "warning: foo\n");
-
-%!test
-%! warning ("off", "quiet", "local");
-%! assert (evalc ("error ('foo')", "warning ('bar')"), "warning: bar\n");
-
-%!error evalc ("switch = 13;")
-
-*/
-
-DEFUN (__parser_debug_flag__, args, nargout,
-       doc: /* -*- texinfo -*-
-@deftypefn  {} {@var{val} =} __parser_debug_flag__ ()
-@deftypefnx {} {@var{old_val} =} __parser_debug_flag__ (@var{new_val})
-Query or set the internal flag that determines whether Octave's parser
-prints debug information as it processes an expression.
-@seealso{__lexer_debug_flag__}
-@end deftypefn */)
-{
-  octave_value retval;
-
-  bool debug_flag = octave_debug;
-
-  retval = set_internal_variable (debug_flag, args, nargout,
-                                  "__parser_debug_flag__");
-
-  octave_debug = debug_flag;
-
-  return retval;
-}
-
-DEFUN (__parse_file__, args, ,
-       doc: /* -*- texinfo -*-
-@deftypefn {} {} __parse_file__ (@var{file}, @var{verbose})
-Undocumented internal function.
-@end deftypefn */)
-{
-  octave_value retval;
-
-  int nargin = args.length ();
-
-  if (nargin < 1 || nargin > 2)
-    print_usage ();
-
-  std::string file = args(0).xstring_value ("__parse_file__: expecting filename as argument");
-
-  std::string full_file
-      = octave::sys::file_ops::tilde_expand (file);
-
-  full_file = octave::sys::env::make_absolute (full_file);
-
-  std::string dir_name;
-
-  size_t file_len = file.length ();
-
-  if ((file_len > 4 && file.substr (file_len-4) == ".oct")
-      || (file_len > 4 && file.substr (file_len-4) == ".mex")
-      || (file_len > 2 && file.substr (file_len-2) == ".m"))
-    {
-      file = octave::sys::env::base_pathname (file);
-      file = file.substr (0, file.find_last_of ('.'));
-
-      size_t pos = file.find_last_of (octave::sys::file_ops::dir_sep_str ());
-      if (pos != std::string::npos)
-        {
-          dir_name = file.substr (0, pos);
-          file = file.substr (pos+1);
-        }
-    }
-
-  if (nargin == 2)
-    octave_stdout << "parsing " << full_file << std::endl;
-
-  octave_value ov_fcn
-    = parse_fcn_file (full_file, file, dir_name, "", "", true, false,
-                      false, false, "__parse_file__");
-
-  return retval;
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/parse-tree/oct-parse.yy	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,5973 @@
+/*
+
+Copyright (C) 1993-2018 John W. Eaton
+Copyright (C) 2009 David Grundberg
+Copyright (C) 2009-2010 VZLU Prague
+Copyright (C) 2016-2018 Oliver Heimlich
+
+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
+<https://www.gnu.org/licenses/>.
+
+*/
+
+// Parser for Octave.
+
+// C decarations.
+
+%{
+
+#define YYDEBUG 1
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include <cassert>
+#include <cstdio>
+#include <cstdlib>
+
+#include <iostream>
+#include <map>
+#include <sstream>
+
+#include "Matrix.h"
+#include "cmd-edit.h"
+#include "cmd-hist.h"
+#include "file-ops.h"
+#include "file-stat.h"
+#include "oct-env.h"
+#include "oct-time.h"
+#include "quit.h"
+
+#include "Cell.h"
+#include "builtin-defun-decls.h"
+#include "call-stack.h"
+#include "defun.h"
+#include "dirfns.h"
+#include "dynamic-ld.h"
+#include "error.h"
+#include "input.h"
+#include "interpreter-private.h"
+#include "interpreter.h"
+#include "lex.h"
+#include "load-path.h"
+#include "lo-sysdep.h"
+#include "oct-hist.h"
+#include "oct-map.h"
+#include "ov-classdef.h"
+#include "ov-fcn-handle.h"
+#include "ov-usr-fcn.h"
+#include "ov-null-mat.h"
+#include "pager.h"
+#include "parse.h"
+#include "pt-all.h"
+#include "pt-eval.h"
+#include "pt-funcall.h"
+#include "symtab.h"
+#include "token.h"
+#include "unwind-prot.h"
+#include "utils.h"
+#include "variables.h"
+
+// oct-parse.h must be included after pt-all.h
+#include "oct-parse.h"
+
+extern int octave_lex (YYSTYPE *, void *);
+
+// List of autoloads (function -> file mapping).
+static std::map<std::string, std::string> autoload_map;
+
+// Forward declarations for some functions defined at the bottom of
+// the file.
+
+static void yyerror (octave::base_parser& parser, const char *s);
+
+#define lexer parser.m_lexer
+#define scanner lexer.m_scanner
+
+#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
+   // Disable this warning for code that is generated by Bison,
+   // including grammar rules.  Push the current state so we can
+   // restore the warning state prior to functions we define at
+   // the bottom of the file.
+#  pragma GCC diagnostic push
+#  pragma GCC diagnostic ignored "-Wold-style-cast"
+#endif
+
+%}
+
+// Bison declarations.
+
+// The grammar currently has 9 shift/reduce conflicts.  Ensure that
+// we notice if that number changes.
+
+%expect 9
+
+// We are using the pure parser interface and the reentrant lexer
+// interface but the Octave parser and lexer are NOT properly
+// reentrant because both still use many global variables.  It should be
+// safe to create a parser object and call it while another parser
+// object is active (to parse a callback function while the main
+// interactive parser is waiting for input, for example) if you take
+// care to properly save and restore (typically with an unwind_protect
+// object) relevant global values before and after the nested call.
+
+%define api.pure
+// No spaces inside the braces for the prefix and push-pull definitions!
+%define api.prefix {octave_}
+%define api.push-pull both
+%parse-param { octave::base_parser& parser }
+%lex-param { void *lexer.scanner }
+
+%union
+{
+  int dummy_type;
+
+  // The type of the basic tokens returned by the lexer.
+  octave::token *tok_val;
+
+  // Comment strings that we need to deal with mid-rule.
+  octave::comment_list *comment_type;
+
+  // Types for the nonterminals we generate.
+  char punct_type;
+  octave::tree *tree_type;
+  octave::tree_matrix *tree_matrix_type;
+  octave::tree_cell *tree_cell_type;
+  octave::tree_expression *tree_expression_type;
+  octave::tree_constant *tree_constant_type;
+  octave::tree_fcn_handle *tree_fcn_handle_type;
+  octave::tree_funcall *tree_funcall_type;
+  octave::tree_function_def *tree_function_def_type;
+  octave::tree_anon_fcn_handle *tree_anon_fcn_handle_type;
+  octave::tree_identifier *tree_identifier_type;
+  octave::tree_index_expression *tree_index_expression_type;
+  octave::tree_colon_expression *tree_colon_expression_type;
+  octave::tree_argument_list *tree_argument_list_type;
+  octave::tree_parameter_list *tree_parameter_list_type;
+  octave::tree_command *tree_command_type;
+  octave::tree_if_command *tree_if_command_type;
+  octave::tree_if_clause *tree_if_clause_type;
+  octave::tree_if_command_list *tree_if_command_list_type;
+  octave::tree_switch_command *tree_switch_command_type;
+  octave::tree_switch_case *tree_switch_case_type;
+  octave::tree_switch_case_list *tree_switch_case_list_type;
+  octave::tree_decl_elt *tree_decl_elt_type;
+  octave::tree_decl_init_list *tree_decl_init_list_type;
+  octave::tree_decl_command *tree_decl_command_type;
+  octave::tree_statement *tree_statement_type;
+  octave::tree_statement_list *tree_statement_list_type;
+  octave_user_function *octave_user_function_type;
+
+  octave::tree_classdef *tree_classdef_type;
+  octave::tree_classdef_attribute* tree_classdef_attribute_type;
+  octave::tree_classdef_attribute_list* tree_classdef_attribute_list_type;
+  octave::tree_classdef_superclass* tree_classdef_superclass_type;
+  octave::tree_classdef_superclass_list* tree_classdef_superclass_list_type;
+  octave::tree_classdef_body* tree_classdef_body_type;
+  octave::tree_classdef_property* tree_classdef_property_type;
+  octave::tree_classdef_property_list* tree_classdef_property_list_type;
+  octave::tree_classdef_properties_block* tree_classdef_properties_block_type;
+  octave::tree_classdef_methods_list* tree_classdef_methods_list_type;
+  octave::tree_classdef_methods_block* tree_classdef_methods_block_type;
+  octave::tree_classdef_event* tree_classdef_event_type;
+  octave::tree_classdef_events_list* tree_classdef_events_list_type;
+  octave::tree_classdef_events_block* tree_classdef_events_block_type;
+  octave::tree_classdef_enum* tree_classdef_enum_type;
+  octave::tree_classdef_enum_list* tree_classdef_enum_list_type;
+  octave::tree_classdef_enum_block* tree_classdef_enum_block_type;
+}
+
+// Tokens with line and column information.
+%token <tok_val> '=' ':' '-' '+' '*' '/'
+%token <tok_val> ADD_EQ SUB_EQ MUL_EQ DIV_EQ LEFTDIV_EQ POW_EQ
+%token <tok_val> EMUL_EQ EDIV_EQ ELEFTDIV_EQ EPOW_EQ AND_EQ OR_EQ
+%token <tok_val> EXPR_AND_AND EXPR_OR_OR
+%token <tok_val> EXPR_AND EXPR_OR EXPR_NOT
+%token <tok_val> EXPR_LT EXPR_LE EXPR_EQ EXPR_NE EXPR_GE EXPR_GT
+%token <tok_val> LEFTDIV EMUL EDIV ELEFTDIV EPLUS EMINUS
+%token <tok_val> HERMITIAN TRANSPOSE
+%token <tok_val> PLUS_PLUS MINUS_MINUS POW EPOW
+%token <tok_val> NUM IMAG_NUM
+%token <tok_val> STRUCT_ELT
+%token <tok_val> NAME
+%token <tok_val> END
+%token <tok_val> DQ_STRING SQ_STRING
+%token <tok_val> FOR PARFOR WHILE DO UNTIL
+%token <tok_val> IF ELSEIF ELSE
+%token <tok_val> SWITCH CASE OTHERWISE
+%token <tok_val> BREAK CONTINUE FUNC_RET
+%token <tok_val> UNWIND CLEANUP
+%token <tok_val> TRY CATCH
+%token <tok_val> GLOBAL PERSISTENT
+%token <tok_val> FCN_HANDLE
+%token <tok_val> CLASSDEF
+%token <tok_val> PROPERTIES METHODS EVENTS ENUMERATION
+%token <tok_val> METAQUERY
+%token <tok_val> SUPERCLASSREF
+%token <tok_val> FQ_IDENT
+%token <tok_val> GET SET
+%token <tok_val> FCN
+%token <tok_val> LEXICAL_ERROR
+
+// Other tokens.
+%token<dummy_type> END_OF_INPUT
+%token<dummy_type> INPUT_FILE
+// %token VARARGIN VARARGOUT
+
+%token<dummy_type> '(' ')' '[' ']' '{' '}' '.' ',' ';' '@' '\n'
+
+// Nonterminals we construct.
+%type <dummy_type> indirect_ref_op decl_param_init
+%type <dummy_type> push_fcn_symtab push_script_symtab begin_file
+%type <dummy_type> param_list_beg param_list_end stmt_begin parse_error
+%type <dummy_type> parsing_local_fcns
+%type <comment_type> stash_comment
+%type <tok_val> function_beg classdef_beg
+%type <punct_type> sep_no_nl opt_sep_no_nl nl opt_nl sep opt_sep
+%type <tree_type> input
+%type <tree_constant_type> string constant magic_colon
+%type <tree_anon_fcn_handle_type> anon_fcn_handle
+%type <tree_fcn_handle_type> fcn_handle
+%type <tree_matrix_type> matrix_rows
+%type <tree_cell_type> cell_rows
+%type <tree_expression_type> matrix cell
+%type <tree_expression_type> primary_expr oper_expr power_expr expr_no_assign
+%type <tree_expression_type> simple_expr colon_expr assign_expr expression
+%type <tree_identifier_type> identifier fcn_name magic_tilde
+%type <tree_funcall_type> superclass_identifier meta_identifier
+%type <tree_index_expression_type> word_list_cmd
+%type <tree_argument_list_type> arg_list word_list assign_lhs
+%type <tree_argument_list_type> cell_or_matrix_row
+%type <tree_parameter_list_type> opt_param_list param_list
+%type <tree_parameter_list_type> param_list1 param_list2
+%type <tree_parameter_list_type> return_list return_list1
+%type <tree_command_type> command select_command loop_command
+%type <tree_command_type> jump_command except_command
+%type <tree_function_def_type> function
+%type <tree_classdef_type> classdef
+%type <tree_command_type> file
+%type <tree_if_command_type> if_command
+%type <tree_if_clause_type> elseif_clause else_clause
+%type <tree_if_command_list_type> if_cmd_list1 if_cmd_list
+%type <tree_switch_command_type> switch_command
+%type <tree_switch_case_type> switch_case default_case
+%type <tree_switch_case_list_type> case_list1 case_list
+%type <tree_decl_elt_type> decl2 param_list_elt
+%type <tree_decl_init_list_type> decl1
+%type <tree_decl_command_type> declaration
+%type <tree_statement_type> statement function_end
+%type <tree_statement_list_type> simple_list simple_list1 list list1
+%type <tree_statement_list_type> opt_list
+%type <tree_statement_list_type> opt_fcn_list fcn_list fcn_list1
+%type <tree_classdef_attribute_type> attr
+%type <tree_classdef_attribute_list_type> attr_list opt_attr_list
+%type <tree_classdef_superclass_type> superclass
+%type <tree_classdef_superclass_list_type> superclass_list opt_superclass_list
+%type <tree_classdef_body_type> class_body
+%type <tree_classdef_property_type> class_property
+%type <tree_classdef_property_list_type> property_list
+%type <tree_classdef_properties_block_type> properties_block
+%type <tree_classdef_methods_list_type> methods_list
+%type <tree_classdef_methods_block_type> methods_block
+%type <tree_classdef_event_type> class_event
+%type <tree_classdef_events_list_type> events_list
+%type <tree_classdef_events_block_type> events_block
+%type <tree_classdef_enum_type> class_enum
+%type <tree_classdef_enum_list_type> enum_list
+%type <tree_classdef_enum_block_type> enum_block
+%type <tree_function_def_type> method_decl method
+%type <octave_user_function_type> method_decl1
+
+// Precedence and associativity.
+%right '=' ADD_EQ SUB_EQ MUL_EQ DIV_EQ LEFTDIV_EQ POW_EQ EMUL_EQ EDIV_EQ ELEFTDIV_EQ EPOW_EQ OR_EQ AND_EQ
+%left EXPR_OR_OR
+%left EXPR_AND_AND
+%left EXPR_OR
+%left EXPR_AND
+%left EXPR_LT EXPR_LE EXPR_EQ EXPR_NE EXPR_GE EXPR_GT
+%left ':'
+%left '-' '+' EPLUS EMINUS
+%left '*' '/' LEFTDIV EMUL EDIV ELEFTDIV
+%right UNARY EXPR_NOT
+%left POW EPOW HERMITIAN TRANSPOSE
+%right PLUS_PLUS MINUS_MINUS
+%left '(' '.' '{'
+
+// How to clean up if there is a parse error.  We handle deleting tokens
+// and comments seperately and separators are just characters.  The
+// remaining items are dynamically allocated parse tree objects that
+// must be deleted.  Use the wildcard case (<*>) to detect unhandled
+// cases (for example, a new semantic type is added but not handled
+// here).
+
+%destructor { } <tok_val>
+%destructor { } <punct_type>
+%destructor { } <comment_type>
+%destructor { } <>
+
+%destructor { delete $$; } <tree_type>
+%destructor { delete $$; } <tree_matrix_type>
+%destructor { delete $$; } <tree_cell_type>
+%destructor { delete $$; } <tree_expression_type>
+%destructor { delete $$; } <tree_constant_type>
+%destructor { delete $$; } <tree_fcn_handle_type>
+%destructor { delete $$; } <tree_funcall_type>
+%destructor { delete $$; } <tree_function_def_type>
+%destructor { delete $$; } <tree_anon_fcn_handle_type>
+%destructor { delete $$; } <tree_identifier_type>
+%destructor { delete $$; } <tree_index_expression_type>
+%destructor { delete $$; } <tree_argument_list_type>
+%destructor { delete $$; } <tree_parameter_list_type>
+%destructor { delete $$; } <tree_command_type>
+%destructor { delete $$; } <tree_if_command_type>
+%destructor { delete $$; } <tree_if_clause_type>
+%destructor { delete $$; } <tree_if_command_list_type>
+%destructor { delete $$; } <tree_switch_command_type>
+%destructor { delete $$; } <tree_switch_case_type>
+%destructor { delete $$; } <tree_switch_case_list_type>
+%destructor { delete $$; } <tree_decl_elt_type>
+%destructor { delete $$; } <tree_decl_init_list_type>
+%destructor { delete $$; } <tree_decl_command_type>
+%destructor { delete $$; } <tree_statement_type>
+%destructor { delete $$; } <tree_statement_list_type>
+%destructor { delete $$; } <octave_user_function_type>
+
+%destructor { delete $$; } <tree_classdef_type>
+%destructor { delete $$; } <tree_classdef_attribute_type>
+%destructor { delete $$; } <tree_classdef_attribute_list_type>
+%destructor { delete $$; } <tree_classdef_superclass_type>
+%destructor { delete $$; } <tree_classdef_superclass_list_type>
+%destructor { delete $$; } <tree_classdef_body_type>
+%destructor { delete $$; } <tree_classdef_property_type>
+%destructor { delete $$; } <tree_classdef_property_list_type>
+%destructor { delete $$; } <tree_classdef_properties_block_type>
+%destructor { delete $$; } <tree_classdef_methods_list_type>
+%destructor { delete $$; } <tree_classdef_methods_block_type>
+%destructor { delete $$; } <tree_classdef_event_type>
+%destructor { delete $$; } <tree_classdef_events_list_type>
+%destructor { delete $$; } <tree_classdef_events_block_type>
+%destructor { delete $$; } <tree_classdef_enum_type>
+%destructor { delete $$; } <tree_classdef_enum_list_type>
+%destructor { delete $$; } <tree_classdef_enum_block_type>
+
+// Defining a generic destructor generates a warning if destructors are
+// already explicitly declared for all types.
+//
+// %destructor {
+//    warning_with_id
+//      ("Octave:parser-destructor",
+//       "possible memory leak in cleanup following parse error");
+// } <*>
+
+// Where to start.
+%start input
+
+%%
+
+// ==============================
+// Statements and statement lists
+// ==============================
+
+input           : simple_list '\n'
+                  {
+                    $$ = nullptr;
+                    parser.m_stmt_list = $1;
+                    YYACCEPT;
+                  }
+                | simple_list END_OF_INPUT
+                  {
+                    $$ = nullptr;
+                    lexer.m_end_of_input = true;
+                    parser.m_stmt_list = $1;
+                    YYACCEPT;
+                  }
+                | parse_error
+                  {
+                    $$ = nullptr;
+                    YYABORT;
+                  }
+                ;
+
+simple_list     : opt_sep_no_nl
+                  {
+                    YYUSE ($1);
+
+                    $$ = nullptr;
+                  }
+                | simple_list1 opt_sep_no_nl
+                  { $$ = parser.set_stmt_print_flag ($1, $2, false); }
+                ;
+
+simple_list1    : statement
+                  { $$ = parser.make_statement_list ($1); }
+                | simple_list1 sep_no_nl statement
+                  { $$ = parser.append_statement_list ($1, $2, $3, false); }
+                ;
+
+opt_list        : // empty
+                  { $$ = new octave::tree_statement_list (); }
+                | list
+                  { $$ = $1; }
+                ;
+
+list            : list1 opt_sep
+                  { $$ = parser.set_stmt_print_flag ($1, $2, true); }
+                ;
+
+list1           : statement
+                  { $$ = parser.make_statement_list ($1); }
+                | list1 sep statement
+                  { $$ = parser.append_statement_list ($1, $2, $3, true); }
+                ;
+
+opt_fcn_list    : // empty
+                  { $$ = new octave::tree_statement_list (); }
+                | fcn_list
+                  { $$ = $1; }
+                ;
+
+fcn_list        : fcn_list1 opt_sep
+                  {
+                    YYUSE ($2);
+
+                    $$ = $1;
+                  }
+                ;
+
+fcn_list1       : function
+                  {
+                    octave::tree_statement *stmt = parser.make_statement ($1);
+                    $$ = new octave::tree_statement_list (stmt);
+                  }
+                | fcn_list1 opt_sep function
+                  {
+                    octave::tree_statement *stmt = parser.make_statement ($3);
+                    $$ = parser.append_statement_list ($1, $2, stmt, false);
+                  }
+                ;
+
+statement       : expression
+                  { $$ = parser.make_statement ($1); }
+                | command
+                  { $$ = parser.make_statement ($1); }
+                | word_list_cmd
+                  { $$ = parser.make_statement ($1); }
+                ;
+
+// =================
+// Word-list command
+// =================
+
+// These are not really like expressions since they can't appear on
+// the RHS of an assignment.  But they are also not like commands (IF,
+// WHILE, etc.
+
+word_list_cmd   : identifier word_list
+                  {
+                    $$ = parser.make_index_expression ($1, $2, '(');
+                    if (! $$)
+                      {
+                        // make_index_expression deleted $1 and $2.
+                        YYABORT;
+                      }
+                  }
+                ;
+
+word_list       : string
+                  { $$ = new octave::tree_argument_list ($1); }
+                | word_list string
+                  {
+                    $1->append ($2);
+                    $$ = $1;
+                  }
+                ;
+
+// ===========
+// Expressions
+// ===========
+
+identifier      : NAME
+                  {
+                    octave::symbol_record sr = $1->sym_rec ();
+                    $$ = new octave::tree_identifier (sr, $1->line (), $1->column ());
+                  }
+                ;
+
+superclass_identifier
+                : SUPERCLASSREF
+                  {
+                    std::string method_nm = $1->superclass_method_name ();
+                    std::string class_nm = $1->superclass_class_name ();
+
+                    $$ = parser.make_superclass_ref (method_nm, class_nm);
+                  }
+                ;
+
+meta_identifier : METAQUERY
+                  {
+                    std::string class_nm = $1->text ();
+
+                    $$ = parser.make_meta_class_query (class_nm);
+                  }
+                ;
+
+string          : DQ_STRING
+                  { $$ = parser.make_constant (DQ_STRING, $1); }
+                | SQ_STRING
+                  { $$ = parser.make_constant (SQ_STRING, $1); }
+                ;
+
+constant        : NUM
+                  { $$ = parser.make_constant (NUM, $1); }
+                | IMAG_NUM
+                  { $$ = parser.make_constant (IMAG_NUM, $1); }
+                | string
+                  { $$ = $1; }
+                ;
+
+matrix          : '[' matrix_rows ']'
+                  { $$ = parser.finish_matrix ($2); }
+                ;
+
+matrix_rows     : cell_or_matrix_row
+                  { $$ = $1 ? new octave::tree_matrix ($1) : nullptr; }
+                | matrix_rows ';' cell_or_matrix_row
+                  {
+                    if ($1)
+                      {
+                        if ($3)
+                          $1->append ($3);
+
+                        $$ = $1;
+                      }
+                    else
+                      $$ = $3 ? new octave::tree_matrix ($3) : nullptr;
+                  }
+                ;
+
+cell            : '{' cell_rows '}'
+                  { $$ = parser.finish_cell ($2); }
+                ;
+
+cell_rows       : cell_or_matrix_row
+                  { $$ = $1 ? new octave::tree_cell ($1) : nullptr; }
+                | cell_rows ';' cell_or_matrix_row
+                  {
+                    if ($1)
+                      {
+                        if ($3)
+                          $1->append ($3);
+
+                        $$ = $1;
+                      }
+                    else
+                      $$ = $3 ? new octave::tree_cell ($3) : nullptr;
+                  }
+                ;
+
+// tree_argument_list objects can't be empty or have leading or trailing
+// commas, but those are all allowed in matrix and cell array rows.
+
+cell_or_matrix_row
+                : // empty
+                  { $$ = nullptr; }
+                | ','
+                  { $$ = nullptr; }
+                | arg_list
+                  { $$ = $1; }
+                | arg_list ','
+                  { $$ = $1; }
+                | ',' arg_list
+                  { $$ = $2; }
+                | ',' arg_list ','
+                  { $$ = $2; }
+                ;
+
+fcn_handle      : '@' FCN_HANDLE
+                  {
+                    $$ = parser.make_fcn_handle ($2);
+                    lexer.m_looking_at_function_handle--;
+                  }
+                ;
+
+anon_fcn_handle : '@' param_list stmt_begin expr_no_assign
+                  {
+                    $$ = parser.make_anon_fcn_handle ($2, $4);
+                    lexer.m_nesting_level.remove ();
+                  }
+                | '@' param_list stmt_begin error
+                  {
+                    YYUSE ($2);
+
+                    $$ = nullptr;
+                    parser.bison_error ("anonymous function bodies must be single expressions");
+                    YYABORT;
+                  }
+                ;
+
+primary_expr    : identifier
+                  { $$ = $1; }
+                | constant
+                  { $$ = $1; }
+                | fcn_handle
+                  { $$ = $1; }
+                | matrix
+                  {
+                    lexer.m_looking_at_matrix_or_assign_lhs = false;
+                    $$ = $1;
+                  }
+                | cell
+                  { $$ = $1; }
+                | meta_identifier
+                  { $$ = $1; }
+                | superclass_identifier
+                  { $$ = $1; }
+                | '(' expression ')'
+                  { $$ = $2->mark_in_parens (); }
+                ;
+
+magic_colon     : ':'
+                  {
+                    YYUSE ($1);
+
+                    octave_value tmp (octave_value::magic_colon_t);
+                    $$ = new octave::tree_constant (tmp);
+                  }
+                ;
+
+magic_tilde     : EXPR_NOT
+                  {
+                    YYUSE ($1);
+
+                    $$ = new octave::tree_black_hole ();
+                  }
+                ;
+
+arg_list        : expression
+                  { $$ = new octave::tree_argument_list ($1); }
+                | magic_colon
+                  { $$ = new octave::tree_argument_list ($1); }
+                | magic_tilde
+                  { $$ = new octave::tree_argument_list ($1); }
+                | arg_list ',' magic_colon
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
+                | arg_list ',' magic_tilde
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
+                | arg_list ',' expression
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
+                ;
+
+indirect_ref_op : '.'
+                  {
+                    $$ = 0;
+                    lexer.m_looking_at_indirect_ref = true;
+                  }
+                ;
+
+oper_expr       : primary_expr
+                  { $$ = $1; }
+                | oper_expr PLUS_PLUS
+                  { $$ = parser.make_postfix_op (PLUS_PLUS, $1, $2); }
+                | oper_expr MINUS_MINUS
+                  { $$ = parser.make_postfix_op (MINUS_MINUS, $1, $2); }
+                | oper_expr '(' ')'
+                  {
+                    $$ = parser.make_index_expression ($1, nullptr, '(');
+                    if (! $$)
+                      {
+                        // make_index_expression deleted $1.
+                        YYABORT;
+                      }
+                  }
+                | oper_expr '(' arg_list ')'
+                  {
+                    $$ = parser.make_index_expression ($1, $3, '(');
+                    if (! $$)
+                      {
+                        // make_index_expression deleted $1 and $3.
+                        YYABORT;
+                      }
+                  }
+                | oper_expr '{' '}'
+                  {
+                    $$ = parser.make_index_expression ($1, nullptr, '{');
+                    if (! $$)
+                      {
+                        // make_index_expression deleted $1.
+                        YYABORT;
+                      }
+                  }
+                | oper_expr '{' arg_list '}'
+                  {
+                    $$ = parser.make_index_expression ($1, $3, '{');
+                    if (! $$)
+                      {
+                        // make_index_expression deleted $1 and $3.
+                        YYABORT;
+                      }
+                  }
+                | oper_expr HERMITIAN
+                  { $$ = parser.make_postfix_op (HERMITIAN, $1, $2); }
+                | oper_expr TRANSPOSE
+                  { $$ = parser.make_postfix_op (TRANSPOSE, $1, $2); }
+                | oper_expr indirect_ref_op STRUCT_ELT
+                  { $$ = parser.make_indirect_ref ($1, $3->text ()); }
+                | oper_expr indirect_ref_op '(' expression ')'
+                  { $$ = parser.make_indirect_ref ($1, $4); }
+                | PLUS_PLUS oper_expr %prec UNARY
+                  { $$ = parser.make_prefix_op (PLUS_PLUS, $2, $1); }
+                | MINUS_MINUS oper_expr %prec UNARY
+                  { $$ = parser.make_prefix_op (MINUS_MINUS, $2, $1); }
+                | EXPR_NOT oper_expr %prec UNARY
+                  { $$ = parser.make_prefix_op (EXPR_NOT, $2, $1); }
+                | '+' oper_expr %prec UNARY
+                  { $$ = parser.make_prefix_op ('+', $2, $1); }
+                | '-' oper_expr %prec UNARY
+                  { $$ = parser.make_prefix_op ('-', $2, $1); }
+                | oper_expr POW power_expr
+                  { $$ = parser.make_binary_op (POW, $1, $2, $3); }
+                | oper_expr EPOW power_expr
+                  { $$ = parser.make_binary_op (EPOW, $1, $2, $3); }
+                | oper_expr '+' oper_expr
+                  { $$ = parser.make_binary_op ('+', $1, $2, $3); }
+                | oper_expr '-' oper_expr
+                  { $$ = parser.make_binary_op ('-', $1, $2, $3); }
+                | oper_expr '*' oper_expr
+                  { $$ = parser.make_binary_op ('*', $1, $2, $3); }
+                | oper_expr '/' oper_expr
+                  { $$ = parser.make_binary_op ('/', $1, $2, $3); }
+                | oper_expr EPLUS oper_expr
+                  { $$ = parser.make_binary_op ('+', $1, $2, $3); }
+                | oper_expr EMINUS oper_expr
+                  { $$ = parser.make_binary_op ('-', $1, $2, $3); }
+                | oper_expr EMUL oper_expr
+                  { $$ = parser.make_binary_op (EMUL, $1, $2, $3); }
+                | oper_expr EDIV oper_expr
+                  { $$ = parser.make_binary_op (EDIV, $1, $2, $3); }
+                | oper_expr LEFTDIV oper_expr
+                  { $$ = parser.make_binary_op (LEFTDIV, $1, $2, $3); }
+                | oper_expr ELEFTDIV oper_expr
+                  { $$ = parser.make_binary_op (ELEFTDIV, $1, $2, $3); }
+                ;
+
+power_expr      : primary_expr
+                  { $$ = $1; }
+                | power_expr PLUS_PLUS
+                  { $$ = parser.make_postfix_op (PLUS_PLUS, $1, $2); }
+                | power_expr MINUS_MINUS
+                  { $$ = parser.make_postfix_op (MINUS_MINUS, $1, $2); }
+                | power_expr '(' ')'
+                  {
+                    $$ = parser.make_index_expression ($1, nullptr, '(');
+                    if (! $$)
+                      {
+                        // make_index_expression deleted $1.
+                        YYABORT;
+                      }
+                  }
+                | power_expr '(' arg_list ')'
+                  {
+                    $$ = parser.make_index_expression ($1, $3, '(');
+                    if (! $$)
+                      {
+                        // make_index_expression deleted $1 and $3.
+                        YYABORT;
+                      }
+                  }
+                | power_expr '{' '}'
+                  {
+                    $$ = parser.make_index_expression ($1, nullptr, '{');
+                    if (! $$)
+                      {
+                        // make_index_expression deleted $1.
+                        YYABORT;
+                      }
+                  }
+                | power_expr '{' arg_list '}'
+                  {
+                    $$ = parser.make_index_expression ($1, $3, '{');
+                    if (! $$)
+                      {
+                        // make_index_expression deleted $1 and $3.
+                        YYABORT;
+                      }
+                  }
+                | power_expr indirect_ref_op STRUCT_ELT
+                  { $$ = parser.make_indirect_ref ($1, $3->text ()); }
+                | power_expr indirect_ref_op '(' expression ')'
+                  { $$ = parser.make_indirect_ref ($1, $4); }
+                | PLUS_PLUS power_expr %prec POW
+                  { $$ = parser.make_prefix_op (PLUS_PLUS, $2, $1); }
+                | MINUS_MINUS power_expr %prec POW
+                  { $$ = parser.make_prefix_op (MINUS_MINUS, $2, $1); }
+                | EXPR_NOT power_expr %prec POW
+                  { $$ = parser.make_prefix_op (EXPR_NOT, $2, $1); }
+                | '+' power_expr %prec POW
+                  { $$ = parser.make_prefix_op ('+', $2, $1); }
+                | '-' power_expr %prec POW
+                  { $$ = parser.make_prefix_op ('-', $2, $1); }
+                ;
+
+colon_expr      : oper_expr ':' oper_expr
+                  {
+                    YYUSE ($2);
+
+                    $$ = parser.make_colon_expression ($1, $3);
+
+                    if (! $$)
+                      {
+                        // finish_colon_expression deleted $1 and $3.
+                        YYABORT;
+                      }
+                  }
+                | oper_expr ':' oper_expr ':' oper_expr
+                  {
+                    YYUSE ($2);
+                    YYUSE ($4);
+
+                    $$ = parser.make_colon_expression ($1, $5, $3);
+
+                    if (! $$)
+                      {
+                        // finish_colon_expression deleted $1, $3, and $5.
+                        YYABORT;
+                      }
+                  }
+                ;
+
+simple_expr     : oper_expr
+                  { $$ = $1; }
+                | colon_expr
+                  { $$ = $1; }
+                | simple_expr EXPR_LT simple_expr
+                  { $$ = parser.make_binary_op (EXPR_LT, $1, $2, $3); }
+                | simple_expr EXPR_LE simple_expr
+                  { $$ = parser.make_binary_op (EXPR_LE, $1, $2, $3); }
+                | simple_expr EXPR_EQ simple_expr
+                  { $$ = parser.make_binary_op (EXPR_EQ, $1, $2, $3); }
+                | simple_expr EXPR_GE simple_expr
+                  { $$ = parser.make_binary_op (EXPR_GE, $1, $2, $3); }
+                | simple_expr EXPR_GT simple_expr
+                  { $$ = parser.make_binary_op (EXPR_GT, $1, $2, $3); }
+                | simple_expr EXPR_NE simple_expr
+                  { $$ = parser.make_binary_op (EXPR_NE, $1, $2, $3); }
+                | simple_expr EXPR_AND simple_expr
+                  { $$ = parser.make_binary_op (EXPR_AND, $1, $2, $3); }
+                | simple_expr EXPR_OR simple_expr
+                  { $$ = parser.make_binary_op (EXPR_OR, $1, $2, $3); }
+                | simple_expr EXPR_AND_AND simple_expr
+                  { $$ = parser.make_boolean_op (EXPR_AND_AND, $1, $2, $3); }
+                | simple_expr EXPR_OR_OR simple_expr
+                  { $$ = parser.make_boolean_op (EXPR_OR_OR, $1, $2, $3); }
+                ;
+
+assign_lhs      : simple_expr
+                  {
+                    $$ = parser.validate_matrix_for_assignment ($1);
+
+                    if ($$)
+                      { lexer.m_looking_at_matrix_or_assign_lhs = false; }
+                    else
+                      {
+                        // validate_matrix_for_assignment deleted $1.
+                        YYABORT;
+                      }
+                  }
+                ;
+
+assign_expr     : assign_lhs '=' expression
+                  { $$ = parser.make_assign_op ('=', $1, $2, $3); }
+                | assign_lhs ADD_EQ expression
+                  { $$ = parser.make_assign_op (ADD_EQ, $1, $2, $3); }
+                | assign_lhs SUB_EQ expression
+                  { $$ = parser.make_assign_op (SUB_EQ, $1, $2, $3); }
+                | assign_lhs MUL_EQ expression
+                  { $$ = parser.make_assign_op (MUL_EQ, $1, $2, $3); }
+                | assign_lhs DIV_EQ expression
+                  { $$ = parser.make_assign_op (DIV_EQ, $1, $2, $3); }
+                | assign_lhs LEFTDIV_EQ expression
+                  { $$ = parser.make_assign_op (LEFTDIV_EQ, $1, $2, $3); }
+                | assign_lhs POW_EQ expression
+                  { $$ = parser.make_assign_op (POW_EQ, $1, $2, $3); }
+                | assign_lhs EMUL_EQ expression
+                  { $$ = parser.make_assign_op (EMUL_EQ, $1, $2, $3); }
+                | assign_lhs EDIV_EQ expression
+                  { $$ = parser.make_assign_op (EDIV_EQ, $1, $2, $3); }
+                | assign_lhs ELEFTDIV_EQ expression
+                  { $$ = parser.make_assign_op (ELEFTDIV_EQ, $1, $2, $3); }
+                | assign_lhs EPOW_EQ expression
+                  { $$ = parser.make_assign_op (EPOW_EQ, $1, $2, $3); }
+                | assign_lhs AND_EQ expression
+                  { $$ = parser.make_assign_op (AND_EQ, $1, $2, $3); }
+                | assign_lhs OR_EQ expression
+                  { $$ = parser.make_assign_op (OR_EQ, $1, $2, $3); }
+                ;
+
+expr_no_assign  : simple_expr
+                  {
+                    if ($1 && ($1->is_matrix () || $1->iscell ()))
+                      {
+                        if (parser.validate_array_list ($1))
+                          $$ = $1;
+                        else
+                          {
+                            delete $1;
+                            YYABORT;
+                          }
+                      }
+                    else
+                      $$ = $1;
+                  }
+                | anon_fcn_handle
+                  { $$ = $1; }
+                ;
+
+expression      : expr_no_assign
+                  { $$ = $1; }
+                | assign_expr
+                  {
+                    if (! $1)
+                      YYABORT;
+
+                    $$ = $1;
+                  }
+
+// ================================================
+// Commands, declarations, and function definitions
+// ================================================
+
+command         : declaration
+                  { $$ = $1; }
+                | select_command
+                  { $$ = $1; }
+                | loop_command
+                  { $$ = $1; }
+                | jump_command
+                  { $$ = $1; }
+                | except_command
+                  { $$ = $1; }
+                | function
+                  { $$ = $1; }
+                | file
+                  { $$ = $1; }
+                ;
+
+// =====================
+// Declaration statemnts
+// =====================
+
+declaration     : GLOBAL decl1
+                  {
+                    $$ = parser.make_decl_command (GLOBAL, $1, $2);
+                    lexer.m_looking_at_decl_list = false;
+                  }
+                | PERSISTENT decl1
+                  {
+                    $$ = parser.make_decl_command (PERSISTENT, $1, $2);
+                    lexer.m_looking_at_decl_list = false;
+                  }
+                ;
+
+decl1           : decl2
+                  { $$ = new octave::tree_decl_init_list ($1); }
+                | decl1 decl2
+                  {
+                    $1->append ($2);
+                    $$ = $1;
+                  }
+                ;
+
+decl_param_init : // empty
+                  {
+                    $$ = 0;
+                    lexer.m_looking_at_initializer_expression = true;
+                  }
+
+decl2           : identifier
+                  { $$ = new octave::tree_decl_elt ($1); }
+                | identifier '=' decl_param_init expression
+                  {
+                    YYUSE ($2);
+
+                    lexer.m_looking_at_initializer_expression = false;
+                    $$ = new octave::tree_decl_elt ($1, $4);
+                  }
+                ;
+
+// ====================
+// Selection statements
+// ====================
+
+select_command  : if_command
+                  { $$ = $1; }
+                | switch_command
+                  { $$ = $1; }
+                ;
+
+// ============
+// If statement
+// ============
+
+if_command      : IF stash_comment if_cmd_list END
+                  {
+                    if (! ($$ = parser.finish_if_command ($1, $3, $4, $2)))
+                      {
+                        // finish_if_command deleted $3.
+                        YYABORT;
+                      }
+                  }
+                ;
+
+if_cmd_list     : if_cmd_list1
+                  { $$ = $1; }
+                | if_cmd_list1 else_clause
+                  {
+                    $1->append ($2);
+                    $$ = $1;
+                  }
+                ;
+
+if_cmd_list1    : expression stmt_begin opt_sep opt_list
+                  {
+                    YYUSE ($3);
+
+                    $1->mark_braindead_shortcircuit ();
+
+                    $$ = parser.start_if_command ($1, $4);
+                  }
+                | if_cmd_list1 elseif_clause
+                  {
+                    $1->append ($2);
+                    $$ = $1;
+                  }
+                ;
+
+elseif_clause   : ELSEIF stash_comment opt_sep expression stmt_begin opt_sep opt_list
+                  {
+                    YYUSE ($3);
+                    YYUSE ($6);
+
+                    $4->mark_braindead_shortcircuit ();
+
+                    $$ = parser.make_elseif_clause ($1, $4, $7, $2);
+                  }
+                ;
+
+else_clause     : ELSE stash_comment opt_sep opt_list
+                  {
+                    YYUSE ($1);
+                    YYUSE ($3);
+
+                    $$ = new octave::tree_if_clause ($4, $2);
+                  }
+                ;
+
+// ================
+// Switch statement
+// ================
+
+switch_command  : SWITCH stash_comment expression opt_sep case_list END
+                  {
+                    YYUSE ($4);
+
+                    if (! ($$ = parser.finish_switch_command ($1, $3, $5, $6, $2)))
+                      {
+                        // finish_switch_command deleted $3 adn $5.
+                        YYABORT;
+                      }
+                  }
+                ;
+
+case_list       : // empty
+                  { $$ = new octave::tree_switch_case_list (); }
+                | default_case
+                  { $$ = new octave::tree_switch_case_list ($1); }
+                | case_list1
+                  { $$ = $1; }
+                | case_list1 default_case
+                  {
+                    $1->append ($2);
+                    $$ = $1;
+                  }
+                ;
+
+case_list1      : switch_case
+                  { $$ = new octave::tree_switch_case_list ($1); }
+                | case_list1 switch_case
+                  {
+                    $1->append ($2);
+                    $$ = $1;
+                  }
+                ;
+
+switch_case     : CASE stash_comment opt_sep expression stmt_begin opt_sep opt_list
+                  {
+                    YYUSE ($3);
+                    YYUSE ($6);
+
+                    $$ = parser.make_switch_case ($1, $4, $7, $2);
+                  }
+                ;
+
+default_case    : OTHERWISE stash_comment opt_sep opt_list
+                  {
+                    YYUSE ($1);
+                    YYUSE ($3);
+
+                    $$ = new octave::tree_switch_case ($4, $2);
+                  }
+                ;
+
+// =======
+// Looping
+// =======
+
+loop_command    : WHILE stash_comment expression stmt_begin opt_sep opt_list END
+                  {
+                    YYUSE ($5);
+
+                    $3->mark_braindead_shortcircuit ();
+
+                    if (! ($$ = parser.make_while_command ($1, $3, $6, $7, $2)))
+                      {
+                        // make_while_command deleted $3 and $6.
+                        YYABORT;
+                      }
+                  }
+                | DO stash_comment opt_sep opt_list UNTIL expression
+                  {
+                    YYUSE ($1);
+                    YYUSE ($3);
+
+                    $$ = parser.make_do_until_command ($5, $4, $6, $2);
+                  }
+                | FOR stash_comment assign_lhs '=' expression stmt_begin opt_sep opt_list END
+                  {
+                    YYUSE ($4);
+                    YYUSE ($7);
+
+                    if (! ($$ = parser.make_for_command (FOR, $1, $3, $5,
+                                                         nullptr, $8, $9, $2)))
+                      {
+                        // make_for_command deleted $3, $5, and $8.
+                        YYABORT;
+                      }
+                  }
+                | FOR stash_comment '(' assign_lhs '=' expression ')' opt_sep opt_list END
+                  {
+                    YYUSE ($5);
+                    YYUSE ($8);
+
+                    if (! ($$ = parser.make_for_command (FOR, $1, $4, $6,
+                                                         nullptr, $9, $10, $2)))
+                      {
+                        // make_for_command deleted $4, $6, and $9.
+                        YYABORT;
+                      }
+                  }
+                | PARFOR stash_comment assign_lhs '=' expression stmt_begin opt_sep opt_list END
+                  {
+                    YYUSE ($4);
+                    YYUSE ($7);
+
+                    if (! ($$ = parser.make_for_command (PARFOR, $1, $3, $5,
+                                                         nullptr, $8, $9, $2)))
+                      {
+                        // make_for_command deleted $3, $5, and $8.
+                        YYABORT;
+                      }
+                  }
+                | PARFOR stash_comment '(' assign_lhs '=' expression ',' expression ')' opt_sep opt_list END
+                  {
+                    YYUSE ($5);
+                    YYUSE ($10);
+
+                    if (! ($$ = parser.make_for_command (PARFOR, $1, $4, $6,
+                                                         $8, $11, $12, $2)))
+                      {
+                        // make_for_command deleted $4, $6, $8, and $11.
+                        YYABORT;
+                      }
+                  }
+                ;
+
+// =======
+// Jumping
+// =======
+
+jump_command    : BREAK
+                  {
+                    if (! ($$ = parser.make_break_command ($1)))
+                      YYABORT;
+                  }
+                | CONTINUE
+                  { $$ = parser.make_continue_command ($1); }
+                | FUNC_RET
+                  { $$ = parser.make_return_command ($1); }
+                ;
+
+// ==========
+// Exceptions
+// ==========
+
+except_command  : UNWIND stash_comment opt_sep opt_list CLEANUP
+                  stash_comment opt_sep opt_list END
+                  {
+                    YYUSE ($3);
+                    YYUSE ($5);
+                    YYUSE ($7);
+
+                    if (! ($$ = parser.make_unwind_command ($1, $4, $8, $9, $2, $6)))
+                      {
+                        // make_unwind_command deleted $4 and $8.
+                        YYABORT;
+                      }
+                  }
+                | TRY stash_comment opt_sep opt_list CATCH stash_comment
+                  opt_sep opt_list END
+                  {
+                    YYUSE ($3);
+                    YYUSE ($5);
+                    YYUSE ($7);
+
+                    if (! ($$ = parser.make_try_command ($1, $4, $7, $8, $9, $2, $6)))
+                      {
+                        // make_try_command deleted $4 and $8.
+                        YYABORT;
+                      }
+                  }
+                | TRY stash_comment opt_sep opt_list END
+                  {
+                    YYUSE ($3);
+
+                    if (! ($$ = parser.make_try_command ($1, $4, 0, nullptr,
+                                                         $5, $2, nullptr)))
+                      {
+                        // make_try_command deleted $4.
+                        YYABORT;
+                      }
+                  }
+                ;
+
+// ===========================================
+// Some 'subroutines' for function definitions
+// ===========================================
+
+push_fcn_symtab : // empty
+                  {
+                    $$ = 0;
+
+                    parser.m_curr_fcn_depth++;
+
+                    if (parser.m_max_fcn_depth < parser.m_curr_fcn_depth)
+                      parser.m_max_fcn_depth = parser.m_curr_fcn_depth;
+
+                    // Will get a real name later.
+                    lexer.m_symtab_context.push (octave::symbol_scope ("parser:push_fcn_symtab"));
+                    parser.m_function_scopes.push (lexer.m_symtab_context.curr_scope ());
+
+                    if (! lexer.m_reading_script_file
+                        && parser.m_curr_fcn_depth == 1
+                        && ! parser.m_parsing_subfunctions)
+                      parser.m_primary_fcn_scope
+                        = lexer.m_symtab_context.curr_scope ();
+
+                    if (lexer.m_reading_script_file
+                        && parser.m_curr_fcn_depth > 1)
+                      {
+                        parser.bison_error ("nested functions not implemented in this context");
+                        YYABORT;
+                      }
+                  }
+                ;
+
+// ===========================
+// List of function parameters
+// ===========================
+
+param_list_beg  : '('
+                  {
+                    $$ = 0;
+                    lexer.m_looking_at_parameter_list = true;
+
+                    if (lexer.m_looking_at_function_handle)
+                      {
+                        // Will get a real name later.
+                        lexer.m_symtab_context.push (octave::symbol_scope ("parser:param_lsit_beg"));
+                        lexer.m_looking_at_function_handle--;
+                        lexer.m_looking_at_anon_fcn_args = true;
+                      }
+                  }
+                ;
+
+param_list_end  : ')'
+                  {
+                    $$ = 0;
+                    lexer.m_looking_at_parameter_list = false;
+                    lexer.m_looking_for_object_index = false;
+                  }
+                ;
+
+opt_param_list  : // empty
+                  { $$ = nullptr; }
+                | param_list
+                  { $$ = $1; }
+                ;
+
+param_list      : param_list_beg param_list1 param_list_end
+                  {
+                    if ($2)
+                      lexer.mark_as_variables ($2->variable_names ());
+
+                    $$ = $2;
+                  }
+                | param_list_beg error
+                  {
+                    $$ = nullptr;
+                    parser.bison_error ("invalid parameter list");
+                    YYABORT;
+                  }
+                ;
+
+param_list1     : // empty
+                  { $$ = nullptr; }
+                | param_list2
+                  {
+                    $1->mark_as_formal_parameters ();
+
+                    if (parser.validate_param_list ($1, octave::tree_parameter_list::in))
+                      {
+                        lexer.mark_as_variables ($1->variable_names ());
+                        $$ = $1;
+                      }
+                    else
+                      {
+                        delete $1;
+                        YYABORT;
+                      }
+                  }
+                ;
+
+param_list2     : param_list_elt
+                  { $$ = new octave::tree_parameter_list ($1); }
+                | param_list2 ',' param_list_elt
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
+                ;
+
+param_list_elt  : decl2
+                  { $$ = $1; }
+                | magic_tilde
+                  { $$ = new octave::tree_decl_elt ($1); }
+                ;
+
+// ===================================
+// List of function return value names
+// ===================================
+
+return_list     : '[' ']'
+                  {
+                    lexer.m_looking_at_return_list = false;
+
+                    $$ = new octave::tree_parameter_list ();
+                  }
+                | identifier
+                  {
+                    lexer.m_looking_at_return_list = false;
+
+                    octave::tree_parameter_list *tmp = new octave::tree_parameter_list ($1);
+
+                    // Even though this parameter list can contain only
+                    // a single identifier, we still need to validate it
+                    // to check for varargin or varargout.
+
+                    if (parser.validate_param_list (tmp, octave::tree_parameter_list::out))
+                      $$ = tmp;
+                    else
+                      {
+                        delete tmp;
+                        YYABORT;
+                      }
+                  }
+                | '[' return_list1 ']'
+                  {
+                    lexer.m_looking_at_return_list = false;
+
+                    // Check for duplicate parameter names, varargin,
+                    // or varargout.
+
+                    if (parser.validate_param_list ($2, octave::tree_parameter_list::out))
+                      $$ = $2;
+                    else
+                      {
+                        delete $2;
+                        YYABORT;
+                      }
+                  }
+                ;
+
+return_list1    : identifier
+                  { $$ = new octave::tree_parameter_list (new octave::tree_decl_elt ($1)); }
+                | return_list1 ',' identifier
+                  {
+                    $1->append (new octave::tree_decl_elt ($3));
+                    $$ = $1;
+                  }
+                ;
+
+// =======================
+// Script or function file
+// =======================
+
+parsing_local_fcns
+                : // empty
+                  { parser.m_parsing_local_functions = true; }
+                ;
+
+push_script_symtab : // empty
+                  {
+                    $$ = 0;
+
+                    // This scope may serve as the parent scope for local
+                    // functions in classdef files..
+                    lexer.m_symtab_context.push (octave::symbol_scope ("parser:push_script_symtab"));
+                  }
+                ;
+
+begin_file      : push_script_symtab INPUT_FILE
+                  { $$ = 0; }
+                ;
+
+file            : begin_file opt_nl opt_list END_OF_INPUT
+                  {
+                    YYUSE ($2);
+
+                    if (lexer.m_reading_fcn_file)
+                      {
+                        // Delete the dummy statement_list we created
+                        // after parsing the function.  Any function
+                        // definitions found in the file have already
+                        // been stored in the symbol table or in
+                        // base_parser::m_primary_fcn_ptr.
+
+                        // Unused symbol table context.
+                        lexer.m_symtab_context.pop ();
+
+                        delete $3;
+                      }
+                    else
+                      {
+                        octave::tree_statement *end_of_script
+                          = parser.make_end ("endscript", true,
+                                             lexer.m_input_line_number,
+                                             lexer.m_current_input_column);
+
+                        parser.make_script ($3, end_of_script);
+                      }
+
+                    $$ = nullptr;
+                  }
+                | begin_file opt_nl classdef parsing_local_fcns opt_sep opt_fcn_list END_OF_INPUT
+                  {
+                    YYUSE ($2);
+                    YYUSE ($5);
+
+                    // Unused symbol table context.
+                    lexer.m_symtab_context.pop ();
+
+                    parser.finish_classdef_file ($3, $6);
+
+                    $$ = nullptr;
+                  }
+                ;
+
+// ===================
+// Function definition
+// ===================
+
+function_beg    : push_fcn_symtab FCN
+                  {
+                    $$ = $2;
+                    if (lexer.m_reading_classdef_file
+                        || lexer.m_parsing_classdef)
+                      lexer.m_maybe_classdef_get_set_method = true;
+                  }
+                ;
+
+fcn_name        : identifier
+                  {
+                    std::string id = $1->name ();
+
+                    // Make classdef local functions unique from
+                    // classdef methods.
+
+                    if (parser.m_parsing_local_functions
+                        && parser.m_curr_fcn_depth == 1)
+                      id = lexer.m_fcn_file_name + ">" + id;
+
+                    if (! parser.m_function_scopes.name_current_scope (id))
+                      {
+                        parser.bison_error ("duplicate subfunction or nested function name",
+                                            $1->line (), $1->column ());
+
+                        delete $1;
+
+                        YYABORT;
+                      }
+
+                    octave::symbol_scope curr_scope
+                      = lexer.m_symtab_context.curr_scope ();
+                    curr_scope.cache_name (id);
+
+                    lexer.m_parsed_function_name.top () = true;
+                    lexer.m_maybe_classdef_get_set_method = false;
+
+                    $$ = $1;
+                  }
+                | GET '.' identifier
+                  {
+                    YYUSE ($1);
+
+                    lexer.m_parsed_function_name.top () = true;
+                    lexer.m_maybe_classdef_get_set_method = false;
+                    lexer.m_parsing_classdef_get_method = true;
+                    $$ = $3;
+                  }
+                | SET '.' identifier
+                  {
+                    YYUSE ($1);
+
+                    lexer.m_parsed_function_name.top () = true;
+                    lexer.m_maybe_classdef_get_set_method = false;
+                    lexer.m_parsing_classdef_set_method = true;
+                    $$ = $3;
+                  }
+                ;
+
+function_end    : END
+                  {
+                    parser.m_endfunction_found = true;
+
+                    if (parser.end_token_ok ($1, octave::token::function_end))
+                      $$ = parser.make_end ("endfunction", false,
+                                            $1->line (), $1->column ());
+                    else
+                      {
+                        parser.end_token_error ($1, octave::token::function_end);
+                        YYABORT;
+                      }
+                  }
+                | END_OF_INPUT
+                  {
+// A lot of tests are based on the assumption that this is OK
+//                  if (lexer.m_reading_script_file)
+//                    {
+//                      parser.bison_error ("function body open at end of script");
+//                      YYABORT;
+//                    }
+
+                    if (parser.m_endfunction_found)
+                      {
+                        parser.bison_error ("inconsistent function endings -- "
+                                 "if one function is explicitly ended, "
+                                 "so must all the others");
+                        YYABORT;
+                      }
+
+                    if (! (lexer.m_reading_fcn_file || lexer.m_reading_script_file
+                           || lexer.input_from_eval_string ()))
+                      {
+                        parser.bison_error ("function body open at end of input");
+                        YYABORT;
+                      }
+
+                    if (lexer.m_reading_classdef_file)
+                      {
+                        parser.bison_error ("classdef body open at end of input");
+                        YYABORT;
+                      }
+
+                    $$ = parser.make_end ("endfunction", true,
+                                          lexer.m_input_line_number,
+                                          lexer.m_current_input_column);
+                  }
+                ;
+
+function        : function_beg stash_comment fcn_name
+                  opt_param_list opt_sep opt_list function_end
+                  {
+                    YYUSE ($5);
+
+                    $$ = parser.make_function ($1, nullptr, $3, $4, $6, $7, $2);
+                  }
+                | function_beg stash_comment return_list '=' fcn_name
+                  opt_param_list opt_sep opt_list function_end
+                  {
+                    YYUSE ($4);
+                    YYUSE ($7);
+
+                    $$ = parser.make_function ($1, $3, $5, $6, $8, $9, $2);
+                  }
+                ;
+
+// ========
+// Classdef
+// ========
+
+classdef_beg    : CLASSDEF
+                  {
+                    if (! lexer.m_reading_classdef_file)
+                      {
+                        parser.bison_error ("classdef must appear inside a file containing only a class definition");
+                        YYABORT;
+                      }
+
+                    // Create invalid parent scope.
+                    lexer.m_symtab_context.push (octave::symbol_scope ());
+                    lexer.m_parsing_classdef = true;
+                    $$ = $1;
+                  }
+                ;
+
+classdef        : classdef_beg stash_comment opt_attr_list identifier opt_superclass_list opt_sep class_body opt_sep END
+                  {
+                    YYUSE ($6);
+                    YYUSE ($8);
+
+                    lexer.m_parsing_classdef = false;
+
+                    if (! ($$ = parser.make_classdef ($1, $3, $4, $5, $7, $9, $2)))
+                      {
+                        // make_classdef deleted $3, $4, $5, and $7.
+                        YYABORT;
+                      }
+                  }
+                | classdef_beg stash_comment opt_attr_list identifier opt_superclass_list opt_sep END
+                  {
+                    YYUSE ($6);
+
+                    lexer.m_parsing_classdef = false;
+
+                    if (! ($$ = parser.make_classdef ($1, $3, $4, $5, nullptr,
+                                                      $7, $2)))
+                      {
+                        // make_classdef deleted $3, $4, and $5.
+                        YYABORT;
+                      }
+                  }
+                ;
+
+opt_attr_list   : // empty
+                  { $$ = nullptr; }
+                | '(' attr_list ')'
+                  { $$ = $2; }
+                ;
+
+attr_list       : attr
+                  { $$ = new octave::tree_classdef_attribute_list ($1); }
+                | attr_list ',' attr
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
+                ;
+
+attr            : identifier
+                  { $$ = new octave::tree_classdef_attribute ($1); }
+                | identifier '=' decl_param_init expression
+                  {
+                    YYUSE ($2);
+
+                    lexer.m_looking_at_initializer_expression = false;
+                    $$ = new octave::tree_classdef_attribute ($1, $4);
+                  }
+                | EXPR_NOT identifier
+                  {
+                    YYUSE ($1);
+
+                    $$ = new octave::tree_classdef_attribute ($2, false);
+                  }
+                ;
+
+opt_superclass_list
+                : // empty
+                  { $$ = nullptr; }
+                | superclass_list
+                  { $$ = $1; }
+                ;
+
+superclass_list : EXPR_LT
+                  {
+                    YYUSE ($1);
+
+                    lexer.enable_fq_identifier ();
+                  }
+                  superclass
+                  { $$ = new octave::tree_classdef_superclass_list ($3); }
+                | superclass_list EXPR_AND
+                  {
+                    YYUSE ($2);
+
+                    lexer.enable_fq_identifier ();
+                  }
+                  superclass
+                  {
+                    $1->append ($4);
+                    $$ = $1;
+                  }
+                ;
+
+superclass      : FQ_IDENT
+                  { $$ = new octave::tree_classdef_superclass ($1->text ()); }
+                ;
+
+class_body      : properties_block
+                  { $$ = new octave::tree_classdef_body ($1); }
+                | methods_block
+                  { $$ = new octave::tree_classdef_body ($1); }
+                | events_block
+                  { $$ = new octave::tree_classdef_body ($1); }
+                | enum_block
+                  { $$ = new octave::tree_classdef_body ($1); }
+                | class_body opt_sep properties_block
+                  {
+                    YYUSE ($2);
+
+                    $1->append ($3);
+                    $$ = $1;
+                  }
+                | class_body opt_sep methods_block
+                  {
+                    YYUSE ($2);
+
+                    $1->append ($3);
+                    $$ = $1;
+                  }
+                | class_body opt_sep events_block
+                  {
+                    YYUSE ($2);
+
+                    $1->append ($3);
+                    $$ = $1;
+                  }
+                | class_body opt_sep enum_block
+                  {
+                    YYUSE ($2);
+
+                    $1->append ($3);
+                    $$ = $1;
+                  }
+                ;
+
+properties_block
+                : PROPERTIES stash_comment opt_attr_list opt_sep property_list opt_sep END
+                  {
+                    YYUSE ($4);
+                    YYUSE ($6);
+
+                    if (! ($$ = parser.make_classdef_properties_block
+                           ($1, $3, $5, $7, $2)))
+                      {
+                        // make_classdef_properties_block delete $3 and $5.
+                        YYABORT;
+                      }
+                  }
+                | PROPERTIES stash_comment opt_attr_list opt_sep END
+                  {
+                    YYUSE ($4);
+
+                    if (! ($$ = parser.make_classdef_properties_block
+                           ($1, $3, nullptr, $5, $2)))
+                      {
+                        // make_classdef_properties_block delete $3.
+                        YYABORT;
+                      }
+                  }
+                ;
+
+property_list
+                : class_property
+                  { $$ = new octave::tree_classdef_property_list ($1); }
+                | property_list sep class_property
+                  {
+                    YYUSE ($2);
+
+                    $1->append ($3);
+                    $$ = $1;
+                  }
+                ;
+
+class_property  : identifier
+                  { $$ = new octave::tree_classdef_property ($1); }
+                | identifier '=' decl_param_init expression
+                  {
+                    YYUSE ($2);
+
+                    lexer.m_looking_at_initializer_expression = false;
+                    $$ = new octave::tree_classdef_property ($1, $4);
+                  }
+                ;
+
+methods_block   : METHODS stash_comment opt_attr_list opt_sep methods_list opt_sep END
+                  {
+                    YYUSE ($4);
+                    YYUSE ($6);
+
+                    if (! ($$ = parser.make_classdef_methods_block
+                           ($1, $3, $5, $7, $2)))
+                      {
+                        // make_classdef_methods_block deleted $3 and $5.
+                        YYABORT;
+                      }
+                  }
+                | METHODS stash_comment opt_attr_list opt_sep END
+                  {
+                    YYUSE ($4);
+
+                    if (! ($$ = parser.make_classdef_methods_block
+                           ($1, $3, nullptr, $5, $2)))
+                      {
+                        // make_classdef_methods_block deleted $3.
+                        YYABORT;
+                      }
+                  }
+                ;
+                ;
+
+method_decl1    : identifier
+                  {
+                    if (! ($$ = parser.start_classdef_external_method ($1, nullptr)))
+                      YYABORT;
+                  }
+                | identifier param_list
+                  {
+                    if (! ($$ = parser.start_classdef_external_method ($1, $2)))
+                      YYABORT;
+                  }
+                ;
+
+method_decl     : stash_comment method_decl1
+                  { $$ = parser.finish_classdef_external_method ($2, nullptr, $1); }
+                | stash_comment return_list '='
+                  {
+                    YYUSE ($3);
+
+                    lexer.m_defining_func++;
+                    lexer.m_parsed_function_name.push (false);
+                  }
+                  method_decl1
+                  {
+                    lexer.m_defining_func--;
+                    lexer.m_parsed_function_name.pop ();
+                    $$ = parser.finish_classdef_external_method ($5, $2, $1);
+                  }
+                ;
+
+method          : method_decl
+                  { $$ = $1; }
+                | function
+                  { $$ = $1; }
+                ;
+
+methods_list    : method
+                  {
+                    octave_value fcn;
+                    if ($1)
+                      fcn = $1->function ();
+                    delete $1;
+                    $$ = new octave::tree_classdef_methods_list (fcn);
+                  }
+                | methods_list opt_sep method
+                  {
+                    YYUSE ($2);
+
+                    octave_value fcn;
+                    if ($3)
+                      fcn = $3->function ();
+                    delete $3;
+
+                    $1->append (fcn);
+                    $$ = $1;
+                  }
+                ;
+
+events_block    : EVENTS stash_comment opt_attr_list opt_sep events_list opt_sep END
+                  {
+                    YYUSE ($4);
+                    YYUSE ($6);
+
+                    if (! ($$ = parser.make_classdef_events_block
+                           ($1, $3, $5, $7, $2)))
+                      {
+                        // make_classdef_events_block deleted $3 and $5.
+                        YYABORT;
+                      }
+                  }
+                | EVENTS stash_comment opt_attr_list opt_sep END
+                  {
+                    YYUSE ($4);
+
+                    if (! ($$ = parser.make_classdef_events_block
+                           ($1, $3, nullptr, $5, $2)))
+                      {
+                        // make_classdef_events_block deleted $3.
+                        YYABORT;
+                      }
+                  }
+                ;
+
+events_list     : class_event
+                  { $$ = new octave::tree_classdef_events_list ($1); }
+                | events_list opt_sep class_event
+                  {
+                    YYUSE ($2);
+
+                    $1->append ($3);
+                    $$ = $1;
+                  }
+                ;
+
+class_event     : identifier
+                  { $$ = new octave::tree_classdef_event ($1); }
+                ;
+
+enum_block      : ENUMERATION stash_comment opt_attr_list opt_sep enum_list opt_sep END
+                  {
+                    YYUSE ($4);
+                    YYUSE ($6);
+
+                    if (! ($$ = parser.make_classdef_enum_block
+                           ($1, $3, $5, $7, $2)))
+                      {
+                        // make_classdef_enum_block deleted $3 and $5.
+                        YYABORT;
+                      }
+                  }
+                | ENUMERATION stash_comment opt_attr_list opt_sep END
+                  {
+                    YYUSE ($4);
+
+                    if (! ($$ = parser.make_classdef_enum_block
+                           ($1, $3, nullptr, $5, $2)))
+                      {
+                        // make_classdef_enum_block deleted $3.
+                        YYABORT;
+                      }
+                  }
+                ;
+
+enum_list       : class_enum
+                  { $$ = new octave::tree_classdef_enum_list ($1); }
+                | enum_list opt_sep class_enum
+                  {
+                    YYUSE ($2);
+
+                    $1->append ($3);
+                    $$ = $1;
+                  }
+                ;
+
+class_enum      : identifier '(' expression ')'
+                  { $$ = new octave::tree_classdef_enum ($1, $3); }
+                ;
+
+// =============
+// Miscellaneous
+// =============
+
+stmt_begin      : // empty
+                  {
+                    $$ = 0;
+                    lexer.m_at_beginning_of_statement = true;
+                  }
+                ;
+
+stash_comment   : // empty
+                  { $$ = lexer.get_comment (); }
+                ;
+
+parse_error     : LEXICAL_ERROR
+                  {
+                    $$ = 0;
+                    std::string msg = $1->text ();
+                    parser.bison_error (msg.c_str ());
+                  }
+                | error
+                  { $$ = 0; }
+                ;
+
+sep_no_nl       : ','
+                  { $$ = ','; }
+                | ';'
+                  { $$ = ';'; }
+                | sep_no_nl ','
+                  { $$ = $1; }
+                | sep_no_nl ';'
+                  { $$ = $1; }
+                ;
+
+opt_sep_no_nl   : // empty
+                  { $$ = 0; }
+                | sep_no_nl
+                  { $$ = $1; }
+                ;
+
+opt_nl          : // empty
+                  { $$ = 0; }
+                | nl
+                  { $$ = $1; }
+                ;
+
+nl              : '\n'
+                  { $$ = '\n'; }
+                | nl '\n'
+                  { $$ = $1; }
+                ;
+
+sep             : ','
+                  { $$ = ','; }
+                | ';'
+                  { $$ = ';'; }
+                | '\n'
+                  { $$ = '\n'; }
+                | sep ','
+                  { $$ = $1; }
+                | sep ';'
+                  { $$ = $1; }
+                | sep '\n'
+                  { $$ = $1; }
+                ;
+
+opt_sep         : // empty
+                  { $$ = 0; }
+                | sep
+                  { $$ = $1; }
+                ;
+
+%%
+
+#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
+   // Restore prevailing warning state for remainder of the file.
+#  pragma GCC diagnostic pop
+#endif
+
+// Generic error messages.
+
+#undef lexer
+#undef scanner
+
+static void
+yyerror (octave::base_parser& parser, const char *s)
+{
+  parser.bison_error (s);
+}
+
+namespace octave
+{
+  size_t
+  base_parser::parent_scope_info::size (void) const
+  {
+    return m_info.size ();
+  }
+
+  void
+  base_parser::parent_scope_info::push (const value_type& elt)
+  {
+    m_info.push_back (elt);
+  }
+
+  void
+  base_parser::parent_scope_info::push (const symbol_scope& scope)
+  {
+    push (value_type (scope, ""));
+  }
+
+  void
+  base_parser::parent_scope_info::pop (void)
+  {
+    m_info.pop_back ();
+  }
+
+  bool
+  base_parser::parent_scope_info::name_ok (const std::string& name)
+  {
+    // Name can't be the same as any parent function or any other
+    // function we've already seen.  We could maintain a complex
+    // tree structure of names, or we can just store the set of
+    // full names of all the functions, which must be unique.
+
+    std::string full_name;
+
+    for (size_t i = 0; i < size()-1; i++)
+      {
+        const value_type& elt = m_info[i];
+
+        if (name == elt.second)
+          return false;
+
+        full_name += elt.second + ">";
+      }
+
+    full_name += name;
+
+    if (m_all_names.find (full_name) != m_all_names.end ())
+      return false;
+
+    m_all_names.insert (full_name);
+
+    return true;
+  }
+
+  bool
+  base_parser::parent_scope_info::name_current_scope (const std::string& name)
+  {
+    if (! name_ok (name))
+      return false;
+
+    if (size () > 0)
+      m_info.back().second = name;
+
+    return true;
+  }
+
+  symbol_scope
+  base_parser::parent_scope_info::parent_scope (void) const
+  {
+    return size () > 1 ? m_info[size()-2].first : symbol_scope ();
+  }
+
+  std::string
+  base_parser::parent_scope_info::parent_name (void) const
+  {
+    return m_info[size()-2].second;
+  }
+
+  void base_parser::parent_scope_info::clear (void)
+  {
+    m_info.clear ();
+    m_all_names.clear ();
+  }
+
+  base_parser::base_parser (base_lexer& lxr)
+    : m_endfunction_found (false), m_autoloading (false),
+      m_fcn_file_from_relative_lookup (false),
+      m_parsing_subfunctions (false), m_parsing_local_functions (false),
+      m_max_fcn_depth (0), m_curr_fcn_depth (0), m_primary_fcn_scope (),
+      m_curr_class_name (), m_curr_package_name (), m_function_scopes (),
+      m_primary_fcn_ptr (nullptr), m_subfunction_names (),
+      m_classdef_object (nullptr), m_stmt_list (nullptr), m_lexer (lxr),
+      m_parser_state (yypstate_new ())
+  { }
+
+  base_parser::~base_parser (void)
+  {
+    delete m_stmt_list;
+
+    delete &m_lexer;
+
+    // FIXME: Deleting the internal Bison parser state structure does
+    // not clean up any partial parse trees in the event of an interrupt or
+    // error.  It's not clear how to safely do that with the C language
+    // parser that Bison generates.  The C++ language parser that Bison
+    // generates would do it for us automatically whenever an exception
+    // is thrown while parsing input, but there is currently no C++
+    // interface for a push parser.
+
+    yypstate_delete (static_cast<yypstate *> (m_parser_state));
+  }
+
+  void
+  base_parser::reset (void)
+  {
+    m_endfunction_found = false;
+    m_autoloading = false;
+    m_fcn_file_from_relative_lookup = false;
+    m_parsing_subfunctions = false;
+    m_parsing_local_functions = false;
+    m_max_fcn_depth = 0;
+    m_curr_fcn_depth = 0;
+    m_primary_fcn_scope = symbol_scope ();
+    m_curr_class_name = "";
+    m_curr_package_name = "";
+    m_function_scopes.clear ();
+    m_primary_fcn_ptr  = nullptr;
+    m_subfunction_names.clear ();
+    m_classdef_object = nullptr;
+
+    delete m_stmt_list;
+    m_stmt_list = nullptr;
+
+    m_lexer.reset ();
+
+    yypstate_delete (static_cast<yypstate *> (m_parser_state));
+    m_parser_state = yypstate_new ();
+  }
+
+  // Error mesages for mismatched end tokens.
+
+  static std::string
+  end_token_as_string (token::end_tok_type ettype)
+  {
+    std::string retval = "<unknown>";
+
+    switch (ettype)
+      {
+      case token::simple_end:
+        retval = "end";
+        break;
+
+      case token::classdef_end:
+        retval = "endclassdef";
+        break;
+
+      case token::enumeration_end:
+        retval = "endenumeration";
+        break;
+
+      case token::events_end:
+        retval = "endevents";
+        break;
+
+      case token::for_end:
+        retval = "endfor";
+        break;
+
+      case token::function_end:
+        retval = "endfunction";
+        break;
+
+      case token::if_end:
+        retval = "endif";
+        break;
+
+      case token::methods_end:
+        retval = "endmethods";
+        break;
+
+      case token::parfor_end:
+        retval = "endparfor";
+        break;
+
+      case token::properties_end:
+        retval = "endproperties";
+        break;
+
+      case token::switch_end:
+        retval = "endswitch";
+        break;
+
+      case token::try_catch_end:
+        retval = "end_try_catch";
+        break;
+
+      case token::unwind_protect_end:
+        retval = "end_unwind_protect";
+        break;
+
+      case token::while_end:
+        retval = "endwhile";
+        break;
+
+      default:
+        panic_impossible ();
+        break;
+      }
+
+    return retval;
+  }
+
+  void
+  base_parser::end_token_error (token *tok, token::end_tok_type expected)
+  {
+    std::string msg = ("'" + end_token_as_string (expected)
+                       + "' command matched by '"
+                       + end_token_as_string (tok->ettype ()) + "'");
+
+    bison_error (msg, tok->line (), tok->column ());
+  }
+
+  // Check to see that end tokens are properly matched.
+
+  bool
+  base_parser::end_token_ok (token *tok, token::end_tok_type expected)
+  {
+    token::end_tok_type ettype = tok->ettype ();
+
+    return ettype == expected || ettype == token::simple_end;
+  }
+
+  // Maybe print a warning if an assignment expression is used as the
+  // test in a logical expression.
+
+  void
+  base_parser::maybe_warn_assign_as_truth_value (tree_expression *expr)
+  {
+    if (expr->is_assignment_expression ()
+        && expr->paren_count () < 2)
+      {
+        if (m_lexer.m_fcn_file_full_name.empty ())
+          warning_with_id
+            ("Octave:assign-as-truth-value",
+             "suggest parenthesis around assignment used as truth value");
+        else
+          warning_with_id
+            ("Octave:assign-as-truth-value",
+             "suggest parenthesis around assignment used as truth value near line %d, column %d in file '%s'",
+             expr->line (), expr->column (), m_lexer.m_fcn_file_full_name.c_str ());
+      }
+  }
+
+  // Maybe print a warning about switch labels that aren't constants.
+
+  void
+  base_parser::maybe_warn_variable_switch_label (tree_expression *expr)
+  {
+    if (! expr->is_constant ())
+      {
+        if (m_lexer.m_fcn_file_full_name.empty ())
+          warning_with_id ("Octave:variable-switch-label",
+                           "variable switch label");
+        else
+          warning_with_id
+            ("Octave:variable-switch-label",
+             "variable switch label near line %d, column %d in file '%s'",
+             expr->line (), expr->column (), m_lexer.m_fcn_file_full_name.c_str ());
+      }
+  }
+
+  // Make a constant.
+
+  tree_constant *
+  base_parser::make_constant (int op, token *tok_val)
+  {
+    int l = tok_val->line ();
+    int c = tok_val->column ();
+
+    tree_constant *retval = nullptr;
+
+    switch (op)
+      {
+      case NUM:
+        {
+          octave_value tmp (tok_val->number ());
+          retval = new tree_constant (tmp, l, c);
+          retval->stash_original_text (tok_val->text_rep ());
+        }
+        break;
+
+      case IMAG_NUM:
+        {
+          octave_value tmp (Complex (0.0, tok_val->number ()));
+          retval = new tree_constant (tmp, l, c);
+          retval->stash_original_text (tok_val->text_rep ());
+        }
+        break;
+
+      case DQ_STRING:
+      case SQ_STRING:
+        {
+          std::string txt = tok_val->text ();
+
+          char delim = op == DQ_STRING ? '"' : '\'';
+          octave_value tmp (txt, delim);
+
+          if (txt.empty ())
+            {
+              if (op == DQ_STRING)
+                tmp = octave_null_str::instance;
+              else
+                tmp = octave_null_sq_str::instance;
+            }
+
+          retval = new tree_constant (tmp, l, c);
+
+          if (op == DQ_STRING)
+            txt = undo_string_escapes (txt);
+
+          // FIXME: maybe this should also be handled by
+          // tok_val->text_rep () for character strings?
+          retval->stash_original_text (delim + txt + delim);
+        }
+        break;
+
+      default:
+        panic_impossible ();
+        break;
+      }
+
+    return retval;
+  }
+
+  // Make a function handle.
+
+  tree_fcn_handle *
+  base_parser::make_fcn_handle (token *tok_val)
+  {
+    int l = tok_val->line ();
+    int c = tok_val->column ();
+
+    tree_fcn_handle *retval = new tree_fcn_handle (tok_val->text (), l, c);
+
+    return retval;
+  }
+
+  // Make an anonymous function handle.
+
+  tree_anon_fcn_handle *
+  base_parser::make_anon_fcn_handle (tree_parameter_list *param_list,
+                                     tree_expression *expr)
+  {
+    // FIXME: need to get these from the location of the @ symbol.
+    int l = m_lexer.m_input_line_number;
+    int c = m_lexer.m_current_input_column;
+
+    symbol_scope fcn_scope = m_lexer.m_symtab_context.curr_scope ();
+    symbol_scope parent_scope = m_lexer.m_symtab_context.parent_scope ();
+
+    m_lexer.m_symtab_context.pop ();
+
+    expr->set_print_flag (false);
+
+    fcn_scope.mark_static ();
+
+    tree_anon_fcn_handle *retval
+      = new tree_anon_fcn_handle (param_list, expr, fcn_scope,
+                                  parent_scope, l, c);
+
+    std::ostringstream buf;
+
+    tree_print_code tpc (buf);
+
+    retval->accept (tpc);
+
+    std::string file = m_lexer.m_fcn_file_full_name;
+    if (! file.empty ())
+      buf << ": file: " << file;
+    else if (m_lexer.input_from_terminal ())
+      buf << ": *terminal input*";
+    else if (m_lexer.input_from_eval_string ())
+      buf << ": *eval string*";
+    buf << ": line: " << l << " column: " << c;
+
+    std::string scope_name = buf.str ();
+
+    fcn_scope.cache_name (scope_name);
+
+    // FIXME: Stash the filename.  This does not work and produces
+    // errors when executed.
+    //retval->stash_file_name (m_lexer.m_fcn_file_name);
+
+    return retval;
+  }
+
+  // Build a colon expression.
+
+  tree_expression *
+  base_parser::make_colon_expression (tree_expression *base,
+                                      tree_expression *limit,
+                                      tree_expression *incr)
+  {
+    tree_expression *retval = nullptr;
+
+    unwind_protect frame;
+
+    frame.protect_var (discard_error_messages);
+    frame.protect_var (discard_warning_messages);
+
+    discard_error_messages = true;
+    discard_warning_messages = true;
+
+    if (! base || ! limit)
+      {
+        delete base;
+        delete limit;
+        delete incr;
+
+        return retval;
+      }
+
+    int l = base->line ();
+    int c = base->column ();
+
+    tree_colon_expression *e
+      = new tree_colon_expression (base, limit, incr, l, c);
+
+    if (base->is_constant () && limit->is_constant ()
+        && (! incr || (incr && incr->is_constant ())))
+      {
+        try
+          {
+            tree_evaluator& tw
+              = __get_evaluator__ ("finish_colon_expression");
+
+            octave_value tmp = tw.evaluate (e);
+
+            tree_constant *tc_retval
+              = new tree_constant (tmp, e->line (), e->column ());
+
+            std::ostringstream buf;
+
+            tree_print_code tpc (buf);
+
+            e->accept (tpc);
+
+            tc_retval->stash_original_text (buf.str ());
+
+            delete e;
+
+            retval = tc_retval;
+          }
+        catch (const execution_exception&)
+          {
+            interpreter::recover_from_exception ();
+          }
+      }
+    else
+      retval = e;
+
+    return retval;
+  }
+
+  // Build a binary expression.
+
+  tree_expression *
+  base_parser::make_binary_op (int op, tree_expression *op1,
+                               token *tok_val, tree_expression *op2)
+  {
+    octave_value::binary_op t = octave_value::unknown_binary_op;
+
+    switch (op)
+      {
+      case POW:
+        t = octave_value::op_pow;
+        break;
+
+      case EPOW:
+        t = octave_value::op_el_pow;
+        break;
+
+      case '+':
+        t = octave_value::op_add;
+        break;
+
+      case '-':
+        t = octave_value::op_sub;
+        break;
+
+      case '*':
+        t = octave_value::op_mul;
+        break;
+
+      case '/':
+        t = octave_value::op_div;
+        break;
+
+      case EMUL:
+        t = octave_value::op_el_mul;
+        break;
+
+      case EDIV:
+        t = octave_value::op_el_div;
+        break;
+
+      case LEFTDIV:
+        t = octave_value::op_ldiv;
+        break;
+
+      case ELEFTDIV:
+        t = octave_value::op_el_ldiv;
+        break;
+
+      case EXPR_LT:
+        t = octave_value::op_lt;
+        break;
+
+      case EXPR_LE:
+        t = octave_value::op_le;
+        break;
+
+      case EXPR_EQ:
+        t = octave_value::op_eq;
+        break;
+
+      case EXPR_GE:
+        t = octave_value::op_ge;
+        break;
+
+      case EXPR_GT:
+        t = octave_value::op_gt;
+        break;
+
+      case EXPR_NE:
+        t = octave_value::op_ne;
+        break;
+
+      case EXPR_AND:
+        t = octave_value::op_el_and;
+        break;
+
+      case EXPR_OR:
+        t = octave_value::op_el_or;
+        break;
+
+      default:
+        panic_impossible ();
+        break;
+      }
+
+    int l = tok_val->line ();
+    int c = tok_val->column ();
+
+    return new tree_binary_expression (op1, op2, l, c, t);
+  }
+
+  // Build a boolean expression.
+
+  tree_expression *
+  base_parser::make_boolean_op (int op, tree_expression *op1,
+                                token *tok_val, tree_expression *op2)
+  {
+    tree_boolean_expression::type t;
+
+    switch (op)
+      {
+      case EXPR_AND_AND:
+        t = tree_boolean_expression::bool_and;
+        break;
+
+      case EXPR_OR_OR:
+        t = tree_boolean_expression::bool_or;
+        break;
+
+      default:
+        panic_impossible ();
+        break;
+      }
+
+    int l = tok_val->line ();
+    int c = tok_val->column ();
+
+    return new tree_boolean_expression (op1, op2, l, c, t);
+  }
+
+  // Build a prefix expression.
+
+  tree_expression *
+  base_parser::make_prefix_op (int op, tree_expression *op1, token *tok_val)
+  {
+    octave_value::unary_op t = octave_value::unknown_unary_op;
+
+    switch (op)
+      {
+      case EXPR_NOT:
+        t = octave_value::op_not;
+        break;
+
+      case '+':
+        t = octave_value::op_uplus;
+        break;
+
+      case '-':
+        t = octave_value::op_uminus;
+        break;
+
+      case PLUS_PLUS:
+        t = octave_value::op_incr;
+        break;
+
+      case MINUS_MINUS:
+        t = octave_value::op_decr;
+        break;
+
+      default:
+        panic_impossible ();
+        break;
+      }
+
+    int l = tok_val->line ();
+    int c = tok_val->column ();
+
+    return new tree_prefix_expression (op1, l, c, t);
+  }
+
+  // Build a postfix expression.
+
+  tree_expression *
+  base_parser::make_postfix_op (int op, tree_expression *op1, token *tok_val)
+  {
+    octave_value::unary_op t = octave_value::unknown_unary_op;
+
+    switch (op)
+      {
+      case HERMITIAN:
+        t = octave_value::op_hermitian;
+        break;
+
+      case TRANSPOSE:
+        t = octave_value::op_transpose;
+        break;
+
+      case PLUS_PLUS:
+        t = octave_value::op_incr;
+        break;
+
+      case MINUS_MINUS:
+        t = octave_value::op_decr;
+        break;
+
+      default:
+        panic_impossible ();
+        break;
+      }
+
+    int l = tok_val->line ();
+    int c = tok_val->column ();
+
+    return new tree_postfix_expression (op1, l, c, t);
+  }
+
+  // Build an unwind-protect command.
+
+  tree_command *
+  base_parser::make_unwind_command (token *unwind_tok,
+                                    tree_statement_list *body,
+                                    tree_statement_list *cleanup_stmts,
+                                    token *end_tok,
+                                    comment_list *lc,
+                                    comment_list *mc)
+  {
+    tree_command *retval = nullptr;
+
+    if (end_token_ok (end_tok, token::unwind_protect_end))
+      {
+        comment_list *tc = m_lexer.m_comment_buf.get_comment ();
+
+        int l = unwind_tok->line ();
+        int c = unwind_tok->column ();
+
+        retval = new tree_unwind_protect_command (body, cleanup_stmts,
+                                                  lc, mc, tc, l, c);
+      }
+    else
+      {
+        delete body;
+        delete cleanup_stmts;
+
+        end_token_error (end_tok, token::unwind_protect_end);
+      }
+
+    return retval;
+  }
+
+  // Build a try-catch command.
+
+  tree_command *
+  base_parser::make_try_command (token *try_tok,
+                                 tree_statement_list *body,
+                                 char catch_sep,
+                                 tree_statement_list *cleanup_stmts,
+                                 token *end_tok,
+                                 comment_list *lc,
+                                 comment_list *mc)
+  {
+    tree_command *retval = nullptr;
+
+    if (end_token_ok (end_tok, token::try_catch_end))
+      {
+        comment_list *tc = m_lexer.m_comment_buf.get_comment ();
+
+        int l = try_tok->line ();
+        int c = try_tok->column ();
+
+        tree_identifier *id = nullptr;
+
+        if (! catch_sep && cleanup_stmts && ! cleanup_stmts->empty ())
+          {
+            tree_statement *stmt = cleanup_stmts->front ();
+
+            if (stmt)
+              {
+                tree_expression *expr = stmt->expression ();
+
+                if (expr && expr->is_identifier ())
+                  {
+                    id = dynamic_cast<tree_identifier *> (expr);
+
+                    cleanup_stmts->pop_front ();
+
+                    stmt->set_expression (nullptr);
+                    delete stmt;
+                  }
+              }
+          }
+
+        retval = new tree_try_catch_command (body, cleanup_stmts, id,
+                                             lc, mc, tc, l, c);
+      }
+    else
+      {
+        delete body;
+        delete cleanup_stmts;
+
+        end_token_error (end_tok, token::try_catch_end);
+      }
+
+    return retval;
+  }
+
+  // Build a while command.
+
+  tree_command *
+  base_parser::make_while_command (token *while_tok,
+                                   tree_expression *expr,
+                                   tree_statement_list *body,
+                                   token *end_tok,
+                                   comment_list *lc)
+  {
+    tree_command *retval = nullptr;
+
+    maybe_warn_assign_as_truth_value (expr);
+
+    if (end_token_ok (end_tok, token::while_end))
+      {
+        comment_list *tc = m_lexer.m_comment_buf.get_comment ();
+
+        m_lexer.m_looping--;
+
+        int l = while_tok->line ();
+        int c = while_tok->column ();
+
+        retval = new tree_while_command (expr, body, lc, tc, l, c);
+      }
+    else
+      {
+        delete expr;
+        delete body;
+
+        end_token_error (end_tok, token::while_end);
+      }
+
+    return retval;
+  }
+
+  // Build a do-until command.
+
+  tree_command *
+  base_parser::make_do_until_command (token *until_tok,
+                                      tree_statement_list *body,
+                                      tree_expression *expr,
+                                      comment_list *lc)
+  {
+    maybe_warn_assign_as_truth_value (expr);
+
+    comment_list *tc = m_lexer.m_comment_buf.get_comment ();
+
+    m_lexer.m_looping--;
+
+    int l = until_tok->line ();
+    int c = until_tok->column ();
+
+    return new tree_do_until_command (expr, body, lc, tc, l, c);
+  }
+
+  // Build a for command.
+
+  tree_command *
+  base_parser::make_for_command (int tok_id, token *for_tok,
+                                 tree_argument_list *lhs,
+                                 tree_expression *expr,
+                                 tree_expression *maxproc,
+                                 tree_statement_list *body,
+                                 token *end_tok,
+                                 comment_list *lc)
+  {
+    tree_command *retval = nullptr;
+
+    bool parfor = tok_id == PARFOR;
+
+    if (end_token_ok (end_tok, parfor ? token::parfor_end : token::for_end))
+      {
+        expr->mark_as_for_cmd_expr ();
+
+        comment_list *tc = m_lexer.m_comment_buf.get_comment ();
+
+        m_lexer.m_looping--;
+
+        int l = for_tok->line ();
+        int c = for_tok->column ();
+
+        if (lhs->length () == 1)
+          {
+            tree_expression *tmp = lhs->remove_front ();
+
+            retval = new tree_simple_for_command (parfor, tmp, expr, maxproc,
+                                                  body, lc, tc, l, c);
+
+            delete lhs;
+          }
+        else
+          {
+            if (parfor)
+              {
+                delete lhs;
+                delete expr;
+                delete maxproc;
+                delete body;
+
+                bison_error ("invalid syntax for parfor statement");
+              }
+            else
+              retval = new tree_complex_for_command (lhs, expr, body,
+                                                     lc, tc, l, c);
+          }
+      }
+    else
+      {
+        delete lhs;
+        delete expr;
+        delete maxproc;
+        delete body;
+
+        end_token_error (end_tok, parfor ? token::parfor_end : token::for_end);
+      }
+
+    return retval;
+  }
+
+  // Build a break command.
+
+  tree_command *
+  base_parser::make_break_command (token *break_tok)
+  {
+    int l = break_tok->line ();
+    int c = break_tok->column ();
+
+    if (! m_lexer.m_looping)
+      {
+        bison_error ("break must appear in a loop in the same file as loop command");
+        return nullptr;
+      }
+    else
+      return new tree_break_command (l, c);
+  }
+
+  // Build a continue command.
+
+  tree_command *
+  base_parser::make_continue_command (token *continue_tok)
+  {
+    int l = continue_tok->line ();
+    int c = continue_tok->column ();
+
+    return new tree_continue_command (l, c);
+  }
+
+  // Build a return command.
+
+  tree_command *
+  base_parser::make_return_command (token *return_tok)
+  {
+    int l = return_tok->line ();
+    int c = return_tok->column ();
+
+    return new tree_return_command (l, c);
+  }
+
+  // Start an if command.
+
+  tree_if_command_list *
+  base_parser::start_if_command (tree_expression *expr,
+                                 tree_statement_list *list)
+  {
+    maybe_warn_assign_as_truth_value (expr);
+
+    tree_if_clause *t = new tree_if_clause (expr, list);
+
+    return new tree_if_command_list (t);
+  }
+
+  // Finish an if command.
+
+  tree_if_command *
+  base_parser::finish_if_command (token *if_tok,
+                                  tree_if_command_list *list,
+                                  token *end_tok,
+                                  comment_list *lc)
+  {
+    tree_if_command *retval = nullptr;
+
+    if (end_token_ok (end_tok, token::if_end))
+      {
+        comment_list *tc = m_lexer.m_comment_buf.get_comment ();
+
+        int l = if_tok->line ();
+        int c = if_tok->column ();
+
+        if (list && ! list->empty ())
+          {
+            tree_if_clause *elt = list->front ();
+
+            if (elt)
+              {
+                elt->line (l);
+                elt->column (c);
+              }
+          }
+
+        retval = new tree_if_command (list, lc, tc, l, c);
+      }
+    else
+      {
+        delete list;
+
+        end_token_error (end_tok, token::if_end);
+      }
+
+    return retval;
+  }
+
+  // Build an elseif clause.
+
+  tree_if_clause *
+  base_parser::make_elseif_clause (token *elseif_tok,
+                                   tree_expression *expr,
+                                   tree_statement_list *list,
+                                   comment_list *lc)
+  {
+    maybe_warn_assign_as_truth_value (expr);
+
+    int l = elseif_tok->line ();
+    int c = elseif_tok->column ();
+
+    return new tree_if_clause (expr, list, lc, l, c);
+  }
+
+  // Finish a switch command.
+
+  tree_switch_command *
+  base_parser::finish_switch_command (token *switch_tok,
+                                      tree_expression *expr,
+                                      tree_switch_case_list *list,
+                                      token *end_tok,
+                                      comment_list *lc)
+  {
+    tree_switch_command *retval = nullptr;
+
+    if (end_token_ok (end_tok, token::switch_end))
+      {
+        comment_list *tc = m_lexer.m_comment_buf.get_comment ();
+
+        int l = switch_tok->line ();
+        int c = switch_tok->column ();
+
+        if (list && ! list->empty ())
+          {
+            tree_switch_case *elt = list->front ();
+
+            if (elt)
+              {
+                elt->line (l);
+                elt->column (c);
+              }
+          }
+
+        retval = new tree_switch_command (expr, list, lc, tc, l, c);
+      }
+    else
+      {
+        delete expr;
+        delete list;
+
+        end_token_error (end_tok, token::switch_end);
+      }
+
+    return retval;
+  }
+
+  // Build a switch case.
+
+  tree_switch_case *
+  base_parser::make_switch_case (token *case_tok,
+                                 tree_expression *expr,
+                                 tree_statement_list *list,
+                                 comment_list *lc)
+  {
+    maybe_warn_variable_switch_label (expr);
+
+    int l = case_tok->line ();
+    int c = case_tok->column ();
+
+    return new tree_switch_case (expr, list, lc, l, c);
+  }
+
+  // Build an assignment to a variable.
+
+  tree_expression *
+  base_parser::make_assign_op (int op, tree_argument_list *lhs,
+                               token *eq_tok, tree_expression *rhs)
+  {
+    octave_value::assign_op t = octave_value::unknown_assign_op;
+
+    switch (op)
+      {
+      case '=':
+        t = octave_value::op_asn_eq;
+        break;
+
+      case ADD_EQ:
+        t = octave_value::op_add_eq;
+        break;
+
+      case SUB_EQ:
+        t = octave_value::op_sub_eq;
+        break;
+
+      case MUL_EQ:
+        t = octave_value::op_mul_eq;
+        break;
+
+      case DIV_EQ:
+        t = octave_value::op_div_eq;
+        break;
+
+      case LEFTDIV_EQ:
+        t = octave_value::op_ldiv_eq;
+        break;
+
+      case POW_EQ:
+        t = octave_value::op_pow_eq;
+        break;
+
+      case EMUL_EQ:
+        t = octave_value::op_el_mul_eq;
+        break;
+
+      case EDIV_EQ:
+        t = octave_value::op_el_div_eq;
+        break;
+
+      case ELEFTDIV_EQ:
+        t = octave_value::op_el_ldiv_eq;
+        break;
+
+      case EPOW_EQ:
+        t = octave_value::op_el_pow_eq;
+        break;
+
+      case AND_EQ:
+        t = octave_value::op_el_and_eq;
+        break;
+
+      case OR_EQ:
+        t = octave_value::op_el_or_eq;
+        break;
+
+      default:
+        panic_impossible ();
+        break;
+      }
+
+    int l = eq_tok->line ();
+    int c = eq_tok->column ();
+
+    if (! lhs->is_simple_assign_lhs () && t != octave_value::op_asn_eq)
+      {
+        // Multiple assignments like [x,y] OP= rhs are only valid for
+        // '=', not '+=', etc.
+
+        delete lhs;
+        delete rhs;
+
+        bison_error ("computed multiple assignment not allowed", l, c);
+
+        return nullptr;
+      }
+
+    if (lhs->is_simple_assign_lhs ())
+      {
+        // We are looking at a simple assignment statement like x = rhs;
+
+        tree_expression *tmp = lhs->remove_front ();
+
+        if ((tmp->is_identifier () || tmp->is_index_expression ())
+            && is_keyword (tmp->name ()))
+          {
+            std::string kw = tmp->name ();
+
+            delete tmp;
+            delete lhs;
+            delete rhs;
+
+            bison_error ("invalid assignment to keyword \"" + kw + "\"", l, c);
+
+            return nullptr;
+          }
+
+        delete lhs;
+
+        return new tree_simple_assignment (tmp, rhs, false, l, c, t);
+      }
+    else
+      {
+        std::list<std::string> names = lhs->variable_names ();
+
+        for (const auto& kw : names)
+          {
+            if (is_keyword (kw))
+              {
+                delete lhs;
+                delete rhs;
+
+                bison_error ("invalid assignment to keyword \"" + kw + "\"",
+                             l, c);
+
+                return nullptr;
+              }
+          }
+
+        return new tree_multi_assignment (lhs, rhs, false, l, c);
+      }
+  }
+
+  // Define a script.
+
+  void
+  base_parser::make_script (tree_statement_list *cmds,
+                            tree_statement *end_script)
+  {
+    if (! cmds)
+      cmds = new tree_statement_list ();
+
+    cmds->append (end_script);
+
+    symbol_scope script_scope = m_lexer.m_symtab_context.curr_scope ();
+
+    script_scope.cache_name (m_lexer.m_fcn_file_full_name);
+
+    octave_user_script *script
+      = new octave_user_script (m_lexer.m_fcn_file_full_name,
+                                m_lexer.m_fcn_file_name, script_scope,
+                                cmds, m_lexer.m_help_text);
+
+    m_lexer.m_symtab_context.pop ();
+    m_lexer.m_help_text = "";
+
+    sys::time now;
+
+    script->stash_fcn_file_time (now);
+
+    m_primary_fcn_ptr = script;
+  }
+
+  // Define a function.
+
+  // FIXME: combining start_function, finish_function, and
+  // recover_from_parsing_function should be possible, but it makes
+  // for a large mess.  Maybe this could be a bit better organized?
+
+  tree_function_def *
+  base_parser::make_function (token *fcn_tok,
+                              tree_parameter_list *ret_list,
+                              tree_identifier *id,
+                              tree_parameter_list *param_list,
+                              tree_statement_list *body,
+                              tree_statement *end_fcn_stmt,
+                              comment_list *lc)
+  {
+    tree_function_def *retval = nullptr;
+
+    int l = fcn_tok->line ();
+    int c = fcn_tok->column ();
+
+    octave_user_function *tmp_fcn
+      = start_function (id, param_list, body, end_fcn_stmt);
+
+    retval = finish_function (ret_list, tmp_fcn, lc, l, c);
+
+    recover_from_parsing_function ();
+
+    return retval;
+  }
+
+  // Begin defining a function.
+
+  octave_user_function *
+  base_parser::start_function (tree_identifier *id,
+                               tree_parameter_list *param_list,
+                               tree_statement_list *body,
+                               tree_statement *end_fcn_stmt)
+  {
+    // We'll fill in the return list later.
+
+    std::string id_name = id->name ();
+
+    delete id;
+
+    if (m_lexer.m_parsing_classdef_get_method)
+      id_name.insert (0, "get.");
+    else if (m_lexer.m_parsing_classdef_set_method)
+      id_name.insert (0, "set.");
+
+    m_lexer.m_parsing_classdef_get_method = false;
+    m_lexer.m_parsing_classdef_set_method = false;
+
+    if (! body)
+      body = new tree_statement_list ();
+
+    body->append (end_fcn_stmt);
+
+    octave_user_function *fcn
+      = new octave_user_function (m_lexer.m_symtab_context.curr_scope (),
+                                  param_list, nullptr, body);
+
+    if (fcn)
+      {
+        comment_list *tc = m_lexer.m_comment_buf.get_comment ();
+
+        fcn->stash_trailing_comment (tc);
+        fcn->stash_fcn_end_location (end_fcn_stmt->line (),
+                                     end_fcn_stmt->column ());
+      }
+
+    // If input is coming from a file, issue a warning if the name of
+    // the file does not match the name of the function stated in the
+    // file.  Matlab doesn't provide a diagnostic (it ignores the stated
+    // name).
+    if (! m_autoloading && m_lexer.m_reading_fcn_file
+        && m_curr_fcn_depth == 1 && ! m_parsing_subfunctions)
+      {
+        // FIXME: should m_lexer.m_fcn_file_name already be
+        // preprocessed when we get here?  It seems to only be a
+        // problem with relative filenames.
+
+        std::string nm = m_lexer.m_fcn_file_name;
+
+        size_t pos = nm.find_last_of (sys::file_ops::dir_sep_chars ());
+
+        if (pos != std::string::npos)
+          nm = m_lexer.m_fcn_file_name.substr (pos+1);
+
+        if (nm != id_name)
+          {
+            warning_with_id
+              ("Octave:function-name-clash",
+               "function name '%s' does not agree with function filename '%s'",
+               id_name.c_str (), m_lexer.m_fcn_file_full_name.c_str ());
+
+            id_name = nm;
+          }
+      }
+
+    if (m_lexer.m_reading_fcn_file || m_lexer.m_reading_classdef_file || m_autoloading)
+      {
+        sys::time now;
+
+        fcn->stash_fcn_file_name (m_lexer.m_fcn_file_full_name);
+        fcn->stash_fcn_file_time (now);
+        fcn->stash_dir_name (m_lexer.m_dir_name);
+        fcn->stash_package_name (m_lexer.m_package_name);
+        fcn->mark_as_system_fcn_file ();
+
+        if (m_fcn_file_from_relative_lookup)
+          fcn->mark_relative ();
+
+        if (m_lexer.m_parsing_class_method)
+          {
+            if (m_curr_class_name == id_name)
+              fcn->mark_as_class_constructor ();
+            else
+              fcn->mark_as_class_method ();
+
+            fcn->stash_dispatch_class (m_curr_class_name);
+          }
+
+        std::string nm = fcn->fcn_file_name ();
+
+        sys::file_stat fs (nm);
+
+        if (fs && fs.is_newer (now))
+          warning_with_id ("Octave:future-time-stamp",
+                           "time stamp for '%s' is in the future", nm.c_str ());
+      }
+    else if (! input_from_tmp_history_file
+             && ! m_lexer.m_force_script
+             && m_lexer.m_reading_script_file
+             && m_lexer.m_fcn_file_name == id_name)
+      {
+        warning ("function '%s' defined within script file '%s'",
+                 id_name.c_str (), m_lexer.m_fcn_file_full_name.c_str ());
+      }
+
+    fcn->stash_function_name (id_name);
+
+    // Record help text for functions other than nested functions.
+    // We cannot currently record help for nested functions (bug #46008)
+    // because the doc_string of the outermost function is read first,
+    // whereas this function is called for the innermost function first.
+    // We could have a stack of help_text in lexer.
+    if (! m_lexer.m_help_text.empty () && m_curr_fcn_depth == 1)
+      {
+        fcn->document (m_lexer.m_help_text);
+
+        m_lexer.m_help_text = "";
+      }
+
+    if (m_lexer.m_reading_fcn_file && m_curr_fcn_depth == 1
+        && ! m_parsing_subfunctions)
+      m_primary_fcn_ptr = fcn;
+
+    return fcn;
+  }
+
+  tree_statement *
+  base_parser::make_end (const std::string& type, bool eof, int l, int c)
+  {
+    return make_statement (new tree_no_op_command (type, eof, l, c));
+  }
+
+  tree_function_def *
+  base_parser::finish_function (tree_parameter_list *ret_list,
+                                octave_user_function *fcn,
+                                comment_list *lc,
+                                int l, int c)
+  {
+    tree_function_def *retval = nullptr;
+
+    if (ret_list)
+      ret_list->mark_as_formal_parameters ();
+
+    if (fcn)
+      {
+        std::string nm = fcn->name ();
+        std::string file = fcn->fcn_file_name ();
+
+        std::string tmp = nm;
+        if (! file.empty ())
+          tmp += ": " + file;
+
+        symbol_scope fcn_scope = fcn->scope ();
+        fcn_scope.cache_name (tmp);
+
+        if (lc)
+          fcn->stash_leading_comment (lc);
+
+        fcn->define_ret_list (ret_list);
+
+        if (m_curr_fcn_depth > 1 || m_parsing_subfunctions)
+          {
+            fcn->stash_fcn_location (l, c);
+            fcn->stash_parent_fcn_name (m_lexer.m_fcn_file_name);
+
+            octave_value ov_fcn (fcn);
+
+            if (m_endfunction_found && m_function_scopes.size () > 1)
+              {
+                fcn->mark_as_nested_function ();
+                fcn_scope.mark_nested ();
+
+                symbol_scope pscope = m_function_scopes.parent_scope ();
+                fcn_scope.set_parent (pscope);
+                pscope.install_nestfunction (nm, ov_fcn, fcn_scope);
+              }
+            else
+              {
+                fcn->mark_as_subfunction ();
+                m_subfunction_names.push_back (nm);
+                fcn_scope.set_parent (m_primary_fcn_scope);
+                m_primary_fcn_scope.install_subfunction (nm, ov_fcn);
+              }
+          }
+
+        if (m_curr_fcn_depth == 1)
+          fcn_scope.update_nest ();
+
+        if (! m_lexer.m_reading_fcn_file && m_curr_fcn_depth == 1)
+          {
+            // We are either reading a script file or defining a function
+            // at the command line, so this definition creates a
+            // tree_function object that is placed in the parse tree.
+            // Otherwise, it is just inserted in the symbol table,
+            // either as a subfunction or nested function (see above),
+            // or as the primary function for the file, via
+            // m_primary_fcn_ptr (see also load_fcn_from_file,,
+            // parse_fcn_file, and
+            // fcn_info::fcn_info_rep::find_user_function).
+
+            if (m_lexer.m_buffer_function_text)
+              {
+                fcn->cache_function_text (m_lexer.m_function_text,
+                                          fcn->time_parsed ());
+                m_lexer.m_buffer_function_text = false;
+              }
+
+            retval = new tree_function_def (fcn);
+          }
+      }
+
+    return retval;
+  }
+
+  void
+  base_parser::recover_from_parsing_function (void)
+  {
+    m_lexer.m_symtab_context.pop ();
+
+    if (m_lexer.m_reading_fcn_file && m_curr_fcn_depth == 1
+        && ! m_parsing_subfunctions)
+      m_parsing_subfunctions = true;
+
+    m_curr_fcn_depth--;
+    m_function_scopes.pop ();
+
+    m_lexer.m_defining_func--;
+    m_lexer.m_parsed_function_name.pop ();
+    m_lexer.m_looking_at_return_list = false;
+    m_lexer.m_looking_at_parameter_list = false;
+  }
+
+  tree_funcall *
+  base_parser::make_superclass_ref (const std::string& method_nm,
+                                    const std::string& class_nm)
+  {
+    octave_value_list args;
+
+    args(1) = class_nm;
+    args(0) = method_nm;
+
+    symbol_table& symtab
+      = __get_symbol_table__ ("base_parser::make_superclass_ref");
+
+    octave_value fcn
+      = symtab.find_built_in_function ("__superclass_reference__");
+
+    return new tree_funcall (fcn, args);
+  }
+
+  tree_funcall *
+  base_parser::make_meta_class_query (const std::string& class_nm)
+  {
+    octave_value_list args;
+
+    args(0) = class_nm;
+
+    symbol_table& symtab
+      = __get_symbol_table__ ("base_parser::make_meta_class_query");
+
+    octave_value fcn
+      = symtab.find_built_in_function ("__meta_class_query__");
+
+    return new tree_funcall (fcn, args);
+  }
+
+  // A CLASSDEF block defines a class that has a constructor and other
+  // methods, but it is not an executable command.  Parsing the block
+  // makes some changes in the symbol table (inserting the constructor
+  // and methods, and adding to the list of known objects) and creates
+  // a parse tree containing meta information about the class.
+
+  tree_classdef *
+  base_parser::make_classdef (token *tok_val,
+                              tree_classdef_attribute_list *a,
+                              tree_identifier *id,
+                              tree_classdef_superclass_list *sc,
+                              tree_classdef_body *body, token *end_tok,
+                              comment_list *lc)
+  {
+    tree_classdef *retval = nullptr;
+
+    m_lexer.m_symtab_context.pop ();
+
+    std::string cls_name = id->name ();
+
+    std::string nm = m_lexer.m_fcn_file_name;
+
+    size_t pos = nm.find_last_of (sys::file_ops::dir_sep_chars ());
+
+    if (pos != std::string::npos)
+      nm = m_lexer.m_fcn_file_name.substr (pos+1);
+
+    if (nm != cls_name)
+      {
+        delete a;
+        delete id;
+        delete sc;
+        delete body;
+
+        bison_error ("invalid classdef definition, the class name must match the filename");
+
+      }
+    else
+      {
+        if (end_token_ok (end_tok, token::classdef_end))
+          {
+            comment_list *tc = m_lexer.m_comment_buf.get_comment ();
+
+            int l = tok_val->line ();
+            int c = tok_val->column ();
+
+            if (! body)
+              body = new tree_classdef_body ();
+
+            retval = new tree_classdef (a, id, sc, body, lc, tc,
+                                        m_curr_package_name, l, c);
+          }
+        else
+          {
+            delete a;
+            delete id;
+            delete sc;
+            delete body;
+
+            end_token_error (end_tok, token::switch_end);
+          }
+      }
+
+    return retval;
+  }
+
+  tree_classdef_properties_block *
+  base_parser::make_classdef_properties_block (token *tok_val,
+                                               tree_classdef_attribute_list *a,
+                                               tree_classdef_property_list *plist,
+                                               token *end_tok,
+                                               comment_list *lc)
+  {
+    tree_classdef_properties_block *retval = nullptr;
+
+    if (end_token_ok (end_tok, token::properties_end))
+      {
+        comment_list *tc = m_lexer.m_comment_buf.get_comment ();
+
+        int l = tok_val->line ();
+        int c = tok_val->column ();
+
+        if (! plist)
+          plist = new tree_classdef_property_list ();
+
+        retval = new tree_classdef_properties_block (a, plist, lc, tc, l, c);
+      }
+    else
+      {
+        delete a;
+        delete plist;
+
+        end_token_error (end_tok, token::properties_end);
+      }
+
+    return retval;
+  }
+
+  tree_classdef_methods_block *
+  base_parser::make_classdef_methods_block (token *tok_val,
+                                            tree_classdef_attribute_list *a,
+                                            tree_classdef_methods_list *mlist,
+                                            token *end_tok,
+                                            comment_list *lc)
+  {
+    tree_classdef_methods_block *retval = nullptr;
+
+    if (end_token_ok (end_tok, token::methods_end))
+      {
+        comment_list *tc = m_lexer.m_comment_buf.get_comment ();
+
+        int l = tok_val->line ();
+        int c = tok_val->column ();
+
+        if (! mlist)
+          mlist = new tree_classdef_methods_list ();
+
+        retval = new tree_classdef_methods_block (a, mlist, lc, tc, l, c);
+      }
+    else
+      {
+        delete a;
+        delete mlist;
+
+        end_token_error (end_tok, token::methods_end);
+      }
+
+    return retval;
+  }
+
+  tree_classdef_events_block *
+  base_parser::make_classdef_events_block (token *tok_val,
+                                           tree_classdef_attribute_list *a,
+                                           tree_classdef_events_list *elist,
+                                           token *end_tok,
+                                           comment_list *lc)
+  {
+    tree_classdef_events_block *retval = nullptr;
+
+    if (end_token_ok (end_tok, token::events_end))
+      {
+        comment_list *tc = m_lexer.m_comment_buf.get_comment ();
+
+        int l = tok_val->line ();
+        int c = tok_val->column ();
+
+        if (! elist)
+          elist = new tree_classdef_events_list ();
+
+        retval = new tree_classdef_events_block (a, elist, lc, tc, l, c);
+      }
+    else
+      {
+        delete a;
+        delete elist;
+
+        end_token_error (end_tok, token::events_end);
+      }
+
+    return retval;
+  }
+
+  tree_classdef_enum_block *
+  base_parser::make_classdef_enum_block (token *tok_val,
+                                         tree_classdef_attribute_list *a,
+                                         tree_classdef_enum_list *elist,
+                                         token *end_tok,
+                                         comment_list *lc)
+  {
+    tree_classdef_enum_block *retval = nullptr;
+
+    if (end_token_ok (end_tok, token::enumeration_end))
+      {
+        comment_list *tc = m_lexer.m_comment_buf.get_comment ();
+
+        int l = tok_val->line ();
+        int c = tok_val->column ();
+
+        if (! elist)
+          elist = new tree_classdef_enum_list ();
+
+        retval = new tree_classdef_enum_block (a, elist, lc, tc, l, c);
+      }
+    else
+      {
+        delete a;
+        delete elist;
+
+        end_token_error (end_tok, token::enumeration_end);
+      }
+
+    return retval;
+  }
+
+  octave_user_function*
+  base_parser::start_classdef_external_method (tree_identifier *id,
+                                               tree_parameter_list *pl)
+  {
+    octave_user_function* retval = nullptr;
+
+    // External methods are only allowed within @-folders. In this case,
+    // m_curr_class_name will be non-empty.
+
+    if (! m_curr_class_name.empty ())
+      {
+
+        std::string mname = id->name ();
+
+        // Methods that cannot be declared outside the classdef file:
+        // - methods with '.' character (e.g. property accessors)
+        // - class constructor
+        // - `delete'
+
+        if (mname.find_first_of (".") == std::string::npos
+            && mname != "delete"
+            && mname != m_curr_class_name)
+          {
+            // Create a dummy function that is used until the real method
+            // is loaded.
+
+            retval = new octave_user_function (symbol_scope (), pl);
+
+            retval->stash_function_name (mname);
+
+            int l = id->line ();
+            int c = id->column ();
+
+            retval->stash_fcn_location (l, c);
+          }
+        else
+          bison_error ("invalid external method declaration, an external "
+                       "method cannot be the class constructor, `delete' "
+                       "or have a dot (.) character in its name");
+      }
+    else
+      bison_error ("external methods are only allowed in @-folders");
+
+    if (! retval)
+      delete id;
+
+    return retval;
+  }
+
+  tree_function_def *
+  base_parser::finish_classdef_external_method (octave_user_function *fcn,
+                                                tree_parameter_list *ret_list,
+                                                comment_list *cl)
+  {
+    if (ret_list)
+      fcn->define_ret_list (ret_list);
+
+    if (cl)
+      fcn->stash_leading_comment (cl);
+
+    int l = fcn->beginning_line ();
+    int c = fcn->beginning_column ();
+
+    return new tree_function_def (fcn, l, c);
+  }
+
+  void
+  base_parser::finish_classdef_file (tree_classdef *cls,
+                                     tree_statement_list *local_fcns)
+  {
+    if (m_lexer.m_reading_classdef_file)
+      m_classdef_object = cls;
+
+    if (local_fcns)
+      {
+        symbol_table& symtab
+          = __get_symbol_table__ ("base_parser::finish_classdef_file");
+
+        for (tree_statement *elt : *local_fcns)
+          {
+            tree_command *cmd = elt->command ();
+
+            tree_function_def *fcn_def
+              = dynamic_cast<tree_function_def *> (cmd);
+
+            octave_value ov_fcn = fcn_def->function ();
+            octave_function *fcn = ov_fcn.function_value ();
+            std::string nm = fcn->name ();
+            std::string file = fcn->fcn_file_name ();
+
+            symtab.install_local_function (nm, ov_fcn, file);
+          }
+
+        delete local_fcns;
+      }
+  }
+
+  // Make an index expression.
+
+  tree_index_expression *
+  base_parser::make_index_expression (tree_expression *expr,
+                                      tree_argument_list *args,
+                                      char type)
+  {
+    tree_index_expression *retval = nullptr;
+
+    if (args && args->has_magic_tilde ())
+      {
+        delete expr;
+        delete args;
+
+        bison_error ("invalid use of empty argument (~) in index expression");
+      }
+    else
+      {
+        int l = expr->line ();
+        int c = expr->column ();
+
+        if (! expr->is_postfix_indexed ())
+          expr->set_postfix_index (type);
+
+        if (expr->is_index_expression ())
+          {
+            tree_index_expression *tmp =
+              static_cast<tree_index_expression *> (expr);
+
+            tmp->append (args, type);
+
+            retval = tmp;
+          }
+        else
+          retval = new tree_index_expression (expr, args, l, c, type);
+      }
+
+    return retval;
+  }
+
+  // Make an indirect reference expression.
+
+  tree_index_expression *
+  base_parser::make_indirect_ref (tree_expression *expr,
+                                  const std::string& elt)
+  {
+    tree_index_expression *retval = nullptr;
+
+    int l = expr->line ();
+    int c = expr->column ();
+
+    if (! expr->is_postfix_indexed ())
+      expr->set_postfix_index ('.');
+
+    if (expr->is_index_expression ())
+      {
+        tree_index_expression *tmp = static_cast<tree_index_expression *> (expr);
+
+        tmp->append (elt);
+
+        retval = tmp;
+      }
+    else
+      retval = new tree_index_expression (expr, elt, l, c);
+
+    m_lexer.m_looking_at_indirect_ref = false;
+
+    return retval;
+  }
+
+  // Make an indirect reference expression with dynamic field name.
+
+  tree_index_expression *
+  base_parser::make_indirect_ref (tree_expression *expr,
+                                  tree_expression *elt)
+  {
+    tree_index_expression *retval = nullptr;
+
+    int l = expr->line ();
+    int c = expr->column ();
+
+    if (! expr->is_postfix_indexed ())
+      expr->set_postfix_index ('.');
+
+    if (expr->is_index_expression ())
+      {
+        tree_index_expression *tmp = static_cast<tree_index_expression *> (expr);
+
+        tmp->append (elt);
+
+        retval = tmp;
+      }
+    else
+      retval = new tree_index_expression (expr, elt, l, c);
+
+    m_lexer.m_looking_at_indirect_ref = false;
+
+    return retval;
+  }
+
+  // Make a declaration command.
+
+  tree_decl_command *
+  base_parser::make_decl_command (int tok, token *tok_val,
+                                  tree_decl_init_list *lst)
+  {
+    tree_decl_command *retval = nullptr;
+
+    int l = tok_val->line ();
+    int c = tok_val->column ();
+
+    if (lst)
+      m_lexer.mark_as_variables (lst->variable_names ());
+
+    switch (tok)
+      {
+      case GLOBAL:
+        {
+          retval = new tree_decl_command ("global", lst, l, c);
+          retval->mark_global ();
+        }
+        break;
+
+      case PERSISTENT:
+        if (m_curr_fcn_depth > 0)
+          {
+            retval = new tree_decl_command ("persistent", lst, l, c);
+            retval->mark_persistent ();
+          }
+        else
+          {
+            if (m_lexer.m_reading_script_file)
+              warning ("ignoring persistent declaration near line %d of file '%s'",
+                       l, m_lexer.m_fcn_file_full_name.c_str ());
+            else
+              warning ("ignoring persistent declaration near line %d", l);
+          }
+        break;
+
+      default:
+        panic_impossible ();
+        break;
+      }
+
+    return retval;
+  }
+
+  bool
+  base_parser::validate_param_list (tree_parameter_list *lst,
+                                    tree_parameter_list::in_or_out type)
+  {
+    std::set<std::string> dict;
+
+    for (tree_decl_elt *elt : *lst)
+      {
+        tree_identifier *id = elt->ident ();
+
+        if (id)
+          {
+            std::string name = id->name ();
+
+            if (id->is_black_hole ())
+              {
+                if (type != tree_parameter_list::in)
+                  {
+                    bison_error ("invalid use of ~ in output list");
+                    return false;
+                  }
+              }
+            else if (dict.find (name) != dict.end ())
+              {
+                bison_error ("'" + name
+                             + "' appears more than once in parameter list");
+                return false;
+              }
+            else
+              dict.insert (name);
+          }
+      }
+
+    std::string va_type = (type == tree_parameter_list::in
+                           ? "varargin" : "varargout");
+
+    size_t len = lst->length ();
+
+    if (len > 0)
+      {
+        tree_decl_elt *elt = lst->back ();
+
+        tree_identifier *id = elt->ident ();
+
+        if (id && id->name () == va_type)
+          {
+            if (len == 1)
+              lst->mark_varargs_only ();
+            else
+              lst->mark_varargs ();
+
+            tree_parameter_list::iterator p = lst->end ();
+            --p;
+            delete *p;
+            lst->erase (p);
+          }
+      }
+
+    return true;
+  }
+
+  bool
+  base_parser::validate_array_list (tree_expression *e)
+  {
+    bool retval = true;
+
+    tree_array_list *al = dynamic_cast<tree_array_list *> (e);
+
+    for (tree_argument_list* row : *al)
+      {
+        if (row && row->has_magic_tilde ())
+          {
+            retval = false;
+
+            if (e->is_matrix ())
+              bison_error ("invalid use of tilde (~) in matrix expression");
+            else
+              bison_error ("invalid use of tilde (~) in cell expression");
+
+            break;
+          }
+      }
+
+    return retval;
+  }
+
+  tree_argument_list *
+  base_parser::validate_matrix_for_assignment (tree_expression *e)
+  {
+    tree_argument_list *retval = nullptr;
+
+    if (e->is_constant ())
+      {
+        tree_evaluator& tw
+          = __get_evaluator__ ("validate_matrix_for_assignment");
+
+        octave_value ov = tw.evaluate (e);
+
+        delete e;
+
+        if (ov.isempty ())
+          bison_error ("invalid empty left hand side of assignment");
+        else
+          bison_error ("invalid constant left hand side of assignment");
+      }
+    else
+      {
+        bool is_simple_assign = true;
+
+        tree_argument_list *tmp = nullptr;
+
+        if (e->is_matrix ())
+          {
+            tree_matrix *mat = dynamic_cast<tree_matrix *> (e);
+
+            if (mat && mat->size () == 1)
+              {
+                tmp = mat->front ();
+                mat->pop_front ();
+                delete e;
+                is_simple_assign = false;
+              }
+          }
+        else
+          tmp = new tree_argument_list (e);
+
+        if (tmp && tmp->is_valid_lvalue_list ())
+          {
+            m_lexer.mark_as_variables (tmp->variable_names ());
+            retval = tmp;
+          }
+        else
+          {
+            delete tmp;
+
+            bison_error ("invalid left hand side of assignment");
+          }
+
+        if (retval && is_simple_assign)
+          retval->mark_as_simple_assign_lhs ();
+      }
+
+    return retval;
+  }
+
+  // Finish building an array_list.
+
+  tree_expression *
+  base_parser::finish_array_list (tree_array_list *array_list)
+  {
+    tree_expression *retval = array_list;
+
+    unwind_protect frame;
+
+    frame.protect_var (discard_error_messages);
+    frame.protect_var (discard_warning_messages);
+
+    discard_error_messages = true;
+    discard_warning_messages = true;
+
+    if (array_list->all_elements_are_constant ())
+      {
+        try
+          {
+            tree_evaluator& tw
+              = __get_evaluator__ ("finish_array_list");
+
+            octave_value tmp = tw.evaluate (array_list);
+
+            tree_constant *tc_retval
+              = new tree_constant (tmp, array_list->line (),
+                                   array_list->column ());
+
+            std::ostringstream buf;
+
+            tree_print_code tpc (buf);
+
+            array_list->accept (tpc);
+
+            tc_retval->stash_original_text (buf.str ());
+
+            delete array_list;
+
+            retval = tc_retval;
+          }
+        catch (const execution_exception&)
+          {
+            interpreter::recover_from_exception ();
+          }
+      }
+
+    return retval;
+  }
+
+  // Finish building a matrix list.
+
+  tree_expression *
+  base_parser::finish_matrix (tree_matrix *m)
+  {
+    return (m
+            ? finish_array_list (m)
+            : new tree_constant (octave_null_matrix::instance));
+  }
+
+  // Finish building a cell list.
+
+  tree_expression *
+  base_parser::finish_cell (tree_cell *c)
+  {
+    return (c
+            ? finish_array_list (c)
+            : new tree_constant (octave_value (Cell ())));
+  }
+
+  void
+  base_parser::maybe_warn_missing_semi (tree_statement_list *t)
+  {
+    if (m_curr_fcn_depth > 0)
+      {
+        tree_statement *tmp = t->back ();
+
+        if (tmp->is_expression ())
+          warning_with_id
+            ("Octave:missing-semicolon",
+             "missing semicolon near line %d, column %d in file '%s'",
+             tmp->line (), tmp->column (), m_lexer.m_fcn_file_full_name.c_str ());
+      }
+  }
+
+  tree_statement_list *
+  base_parser::set_stmt_print_flag (tree_statement_list *list,
+                                    char sep, bool warn_missing_semi)
+  {
+    tree_statement *tmp = list->back ();
+
+    switch (sep)
+      {
+      case ';':
+        tmp->set_print_flag (false);
+        break;
+
+      case 0:
+      case ',':
+      case '\n':
+        tmp->set_print_flag (true);
+        if (warn_missing_semi)
+          maybe_warn_missing_semi (list);
+        break;
+
+      default:
+        warning ("unrecognized separator type!");
+        break;
+      }
+
+    // Even if a statement is null, we add it to the list then remove it
+    // here so that the print flag is applied to the correct statement.
+
+    if (tmp->is_null_statement ())
+      {
+        list->pop_back ();
+        delete tmp;
+      }
+
+    return list;
+  }
+
+  // Finish building a statement.
+  template <typename T>
+  tree_statement *
+  base_parser::make_statement (T *arg)
+  {
+    comment_list *comment = m_lexer.get_comment ();
+
+    return new tree_statement (arg, comment);
+  }
+
+  tree_statement_list *
+  base_parser::make_statement_list (tree_statement *stmt)
+  {
+    return new tree_statement_list (stmt);
+  }
+
+  tree_statement_list *
+  base_parser::append_statement_list (tree_statement_list *list,
+                                      char sep, tree_statement *stmt,
+                                      bool warn_missing_semi)
+  {
+    set_stmt_print_flag (list, sep, warn_missing_semi);
+
+    list->append (stmt);
+
+    return list;
+  }
+
+  void
+  base_parser::bison_error (const std::string& str, int l, int c)
+  {
+    int err_line = l < 0 ? m_lexer.m_input_line_number : l;
+    int err_col = c < 0 ? m_lexer.m_current_input_column - 1 : c;
+
+    std::ostringstream output_buf;
+
+    if (m_lexer.m_reading_fcn_file || m_lexer.m_reading_script_file
+        || m_lexer.m_reading_classdef_file)
+      output_buf << "parse error near line " << err_line
+                 << " of file " << m_lexer.m_fcn_file_full_name;
+    else
+      output_buf << "parse error:";
+
+    if (str != "parse error")
+      output_buf << "\n\n  " << str;
+
+    output_buf << "\n\n";
+
+    std::string curr_line = m_lexer.m_current_input_line;
+
+    if (! curr_line.empty ())
+      {
+        size_t len = curr_line.length ();
+
+        if (curr_line[len-1] == '\n')
+          curr_line.resize (len-1);
+
+        // Print the line, maybe with a pointer near the error token.
+
+        output_buf << ">>> " << curr_line << "\n";
+
+        if (err_col == 0)
+          err_col = len;
+
+        for (int i = 0; i < err_col + 3; i++)
+          output_buf << " ";
+
+        output_buf << "^";
+      }
+
+    output_buf << "\n";
+
+    m_parse_error_msg = output_buf.str ();
+  }
+
+  int
+  parser::run (void)
+  {
+    int status = -1;
+
+    yypstate *pstate = static_cast<yypstate *> (m_parser_state);
+
+    try
+      {
+        status = octave_pull_parse (pstate, *this);
+      }
+    catch (execution_exception& e)
+      {
+        std::string file = m_lexer.m_fcn_file_full_name;
+
+        if (file.empty ())
+          error (e, "parse error");
+        else
+          error (e, "parse error in %s", file.c_str ());
+      }
+    catch (const exit_exception&)
+      {
+        throw;
+      }
+    catch (interrupt_exception &)
+      {
+        throw;
+      }
+    catch (...)
+      {
+        std::string file = m_lexer.m_fcn_file_full_name;
+
+        if (file.empty ())
+          error ("unexpected exception while parsing input");
+        else
+          error ("unexpected exception while parsing %s", file.c_str ());
+      }
+
+    if (status != 0)
+      parse_error ("%s", m_parse_error_msg.c_str ());
+
+    return status;
+  }
+
+  // Parse input from INPUT.  Pass TRUE for EOF if the end of INPUT should
+  // finish the parse.
+
+  int
+  push_parser::run (const std::string& input, bool eof)
+  {
+    int status = -1;
+
+    dynamic_cast<push_lexer&> (m_lexer).append_input (input, eof);
+
+    do
+      {
+        YYSTYPE lval;
+
+        int token = octave_lex (&lval, m_lexer.m_scanner);
+
+        if (token < 0)
+          {
+            if (! eof && m_lexer.at_end_of_buffer ())
+              {
+                status = -1;
+                break;
+              }
+          }
+
+        yypstate *pstate = static_cast<yypstate *> (m_parser_state);
+
+        try
+          {
+            status = octave_push_parse (pstate, token, &lval, *this);
+          }
+        catch (execution_exception& e)
+          {
+            std::string file = m_lexer.m_fcn_file_full_name;
+
+            if (file.empty ())
+              error (e, "parse error");
+            else
+              error (e, "parse error in %s", file.c_str ());
+          }
+        catch (const exit_exception&)
+          {
+            throw;
+          }
+        catch (interrupt_exception &)
+          {
+            throw;
+          }
+        catch (...)
+          {
+            std::string file = m_lexer.m_fcn_file_full_name;
+
+            if (file.empty ())
+              error ("unexpected exception while parsing input");
+            else
+              error ("unexpected exception while parsing %s", file.c_str ());
+          }
+      }
+    while (status == YYPUSH_MORE);
+
+    if (status != 0)
+      parse_error ("%s", m_parse_error_msg.c_str ());
+
+    return status;
+  }
+
+  static void
+  safe_fclose (FILE *f)
+  {
+    if (f)
+      fclose (static_cast<FILE *> (f));
+  }
+
+  static octave_value
+  parse_fcn_file (const std::string& full_file, const std::string& file,
+                  const std::string& dir_name, const std::string& dispatch_type,
+                  const std::string& package_name, bool require_file,
+                  bool force_script, bool autoload, bool relative_lookup,
+                  const std::string& warn_for)
+  {
+    octave_value retval;
+
+    unwind_protect frame;
+
+    octave_function *fcn_ptr = nullptr;
+
+    // Open function file and parse.
+
+    FILE *in_stream = command_editor::get_input_stream ();
+
+    frame.add_fcn (command_editor::set_input_stream, in_stream);
+
+    frame.add_fcn (command_history::ignore_entries,
+                   command_history::ignoring_entries ());
+
+    command_history::ignore_entries ();
+
+    FILE *ffile = nullptr;
+
+    if (! full_file.empty ())
+      ffile = octave::sys::fopen (full_file, "rb");
+
+    if (ffile)
+      {
+        frame.add_fcn (safe_fclose, ffile);
+
+        interpreter& interp = __get_interpreter__ ("parse_fcn_file");
+
+        parser parser (ffile, interp);
+
+        parser.m_curr_class_name = dispatch_type;
+        parser.m_curr_package_name = package_name;
+        parser.m_autoloading = autoload;
+        parser.m_fcn_file_from_relative_lookup = relative_lookup;
+
+        parser.m_lexer.m_force_script = force_script;
+        parser.m_lexer.prep_for_file ();
+        parser.m_lexer.m_parsing_class_method = ! dispatch_type.empty ();
+
+        parser.m_lexer.m_fcn_file_name = file;
+        parser.m_lexer.m_fcn_file_full_name = full_file;
+        parser.m_lexer.m_dir_name = dir_name;
+        parser.m_lexer.m_package_name = package_name;
+
+        int status = parser.run ();
+
+        fcn_ptr = parser.m_primary_fcn_ptr;
+
+        if (status == 0)
+          {
+            if (parser.m_lexer.m_reading_classdef_file
+                && parser.m_classdef_object)
+              {
+                // Convert parse tree for classdef object to
+                // meta.class info (and stash it in the symbol
+                // table?).  Return pointer to constructor?
+
+                if (fcn_ptr)
+                  panic_impossible ();
+
+                bool is_at_folder = ! dispatch_type.empty ();
+
+                try
+                  {
+                    fcn_ptr = parser.m_classdef_object->make_meta_class (interp, is_at_folder);
+                  }
+                catch (const execution_exception&)
+                  {
+                    delete parser.m_classdef_object;
+                    throw;
+                  }
+
+                if (fcn_ptr)
+                  retval = octave_value (fcn_ptr);
+
+                delete parser.m_classdef_object;
+
+                parser.m_classdef_object = nullptr;
+              }
+            else if (fcn_ptr)
+              {
+                retval = octave_value (fcn_ptr);
+
+                fcn_ptr->maybe_relocate_end ();
+
+                if (parser.m_parsing_subfunctions)
+                  {
+                    if (! parser.m_endfunction_found)
+                      parser.m_subfunction_names.reverse ();
+
+                    fcn_ptr->stash_subfunction_names (parser.m_subfunction_names);
+                  }
+              }
+          }
+        else
+          error ("parse error while reading file %s", full_file.c_str ());
+      }
+    else if (require_file)
+      error ("no such file, '%s'", full_file.c_str ());
+    else if (! warn_for.empty ())
+      error ("%s: unable to open file '%s'", warn_for.c_str (),
+             full_file.c_str ());
+
+    return retval;
+  }
+
+  std::string
+  get_help_from_file (const std::string& nm, bool& symbol_found,
+                      std::string& full_file)
+  {
+    std::string retval;
+
+    full_file = fcn_file_in_path (nm);
+
+    std::string file = full_file;
+
+    size_t file_len = file.length ();
+
+    if ((file_len > 4 && file.substr (file_len-4) == ".oct")
+        || (file_len > 4 && file.substr (file_len-4) == ".mex")
+        || (file_len > 2 && file.substr (file_len-2) == ".m"))
+      {
+        file = sys::env::base_pathname (file);
+        file = file.substr (0, file.find_last_of ('.'));
+
+        size_t pos = file.find_last_of (sys::file_ops::dir_sep_str ());
+        if (pos != std::string::npos)
+          file = file.substr (pos+1);
+      }
+
+    if (! file.empty ())
+      {
+        symbol_found = true;
+
+        octave_value ov_fcn
+          = parse_fcn_file (full_file, file, "", "", "", true,
+                            false, false, false, "");
+
+        if (ov_fcn.is_defined ())
+          {
+            octave_function *fcn = ov_fcn.function_value ();
+
+            if (fcn)
+              retval = fcn->doc_string ();
+          }
+      }
+
+    return retval;
+  }
+
+  std::string
+  get_help_from_file (const std::string& nm, bool& symbol_found)
+  {
+    std::string file;
+    return get_help_from_file (nm, symbol_found, file);
+  }
+
+  std::string
+  lookup_autoload (const std::string& nm)
+  {
+    std::string retval;
+
+    typedef std::map<std::string, std::string>::const_iterator am_iter;
+
+    am_iter p = autoload_map.find (nm);
+
+    if (p != autoload_map.end ())
+      {
+        load_path& lp = __get_load_path__ ("lookup_autoload");
+
+        retval = lp.find_file (p->second);
+      }
+
+    return retval;
+  }
+
+  string_vector
+  autoloaded_functions (void)
+  {
+    string_vector names (autoload_map.size ());
+
+    octave_idx_type i = 0;
+    for (const auto& fcn_fname : autoload_map)
+      names[i++] = fcn_fname.first;
+
+    return names;
+  }
+
+  string_vector
+  reverse_lookup_autoload (const std::string& nm)
+  {
+    string_vector names;
+
+    for (const auto& fcn_fname : autoload_map)
+      if (nm == fcn_fname.second)
+        names.append (fcn_fname.first);
+
+    return names;
+  }
+
+  octave_value
+  load_fcn_from_file (const std::string& file_name,
+                      const std::string& dir_name,
+                      const std::string& dispatch_type,
+                      const std::string& package_name,
+                      const std::string& fcn_name, bool autoload)
+  {
+    octave_value retval;
+
+    unwind_protect frame;
+
+    std::string nm = file_name;
+
+    size_t nm_len = nm.length ();
+
+    std::string file;
+
+    bool relative_lookup = false;
+
+    file = nm;
+
+    if ((nm_len > 4 && nm.substr (nm_len-4) == ".oct")
+        || (nm_len > 4 && nm.substr (nm_len-4) == ".mex")
+        || (nm_len > 2 && nm.substr (nm_len-2) == ".m"))
+      {
+        nm = sys::env::base_pathname (file);
+        nm = nm.substr (0, nm.find_last_of ('.'));
+
+        size_t pos = nm.find_last_of (sys::file_ops::dir_sep_str ());
+        if (pos != std::string::npos)
+          nm = nm.substr (pos+1);
+      }
+
+    relative_lookup = ! sys::env::absolute_pathname (file);
+
+    file = sys::env::make_absolute (file);
+
+    int len = file.length ();
+
+      dynamic_loader& dyn_loader
+        = __get_dynamic_loader__ ("~octave_mex_function");
+
+    if (len > 4 && file.substr (len-4, len-1) == ".oct")
+      {
+        if (autoload && ! fcn_name.empty ())
+          nm = fcn_name;
+
+        octave_function *tmpfcn
+          = dyn_loader.load_oct (nm, file, relative_lookup);
+
+        if (tmpfcn)
+          {
+            tmpfcn->stash_package_name (package_name);
+            retval = octave_value (tmpfcn);
+          }
+      }
+    else if (len > 4 && file.substr (len-4, len-1) == ".mex")
+      {
+        // Temporarily load m-file version of mex-file, if it exists,
+        // to get the help-string to use.
+
+        std::string doc_string;
+
+        octave_value ov_fcn
+          = parse_fcn_file (file.substr (0, len - 2), nm, dir_name,
+                            dispatch_type, package_name, false,
+                            autoload, autoload, relative_lookup, "");
+
+        if (ov_fcn.is_defined ())
+          {
+            octave_function *tmpfcn = ov_fcn.function_value ();
+
+            if (tmpfcn)
+              doc_string = tmpfcn->doc_string ();
+          }
+
+        octave_function *tmpfcn
+          = dyn_loader.load_mex (nm, file, relative_lookup);
+
+        if (tmpfcn)
+          {
+            tmpfcn->document (doc_string);
+            tmpfcn->stash_package_name (package_name);
+
+            retval = octave_value (tmpfcn);
+          }
+      }
+    else if (len > 2)
+      {
+        retval = parse_fcn_file (file, nm, dir_name, dispatch_type,
+                                 package_name, true, autoload, autoload,
+                                 relative_lookup, "");
+      }
+
+    return retval;
+  }
+}
+
+DEFMETHOD (autoload, interp, args, ,
+           doc: /* -*- texinfo -*-
+@deftypefn  {} {@var{autoload_map} =} autoload ()
+@deftypefnx {} {} autoload (@var{function}, @var{file})
+@deftypefnx {} {} autoload (@dots{}, "remove")
+Define @var{function} to autoload from @var{file}.
+
+The second argument, @var{file}, should be an absolute filename or a file
+name in the same directory as the function or script from which the autoload
+command was run.  @var{file} @emph{should not} depend on the Octave load
+path.
+
+Normally, calls to @code{autoload} appear in PKG_ADD script files that are
+evaluated when a directory is added to Octave's load path.  To avoid having
+to hardcode directory names in @var{file}, if @var{file} is in the same
+directory as the PKG_ADD script then
+
+@example
+autoload ("foo", "bar.oct");
+@end example
+
+@noindent
+will load the function @code{foo} from the file @code{bar.oct}.  The above
+usage when @code{bar.oct} is not in the same directory, or usages such as
+
+@example
+autoload ("foo", file_in_loadpath ("bar.oct"))
+@end example
+
+@noindent
+are strongly discouraged, as their behavior may be unpredictable.
+
+With no arguments, return a structure containing the current autoload map.
+
+If a third argument @qcode{"remove"} is given, the function is cleared and
+not loaded anymore during the current Octave session.
+
+@seealso{PKG_ADD}
+@end deftypefn */)
+{
+  octave_value retval;
+
+  int nargin = args.length ();
+
+  if (nargin == 1 || nargin > 3)
+    print_usage ();
+
+  if (nargin == 0)
+    {
+      Cell func_names (dim_vector (autoload_map.size (), 1));
+      Cell file_names (dim_vector (autoload_map.size (), 1));
+
+      octave_idx_type i = 0;
+      for (const auto& fcn_fname : autoload_map)
+        {
+          func_names(i) = fcn_fname.first;
+          file_names(i) = fcn_fname.second;
+
+          i++;
+        }
+
+      octave_map m;
+
+      m.assign ("function", func_names);
+      m.assign ("file", file_names);
+
+      retval = m;
+    }
+  else
+    {
+      string_vector argv = args.make_argv ("autoload");
+
+      std::string nm = argv[2];
+
+      if (! octave::sys::env::absolute_pathname (nm))
+        {
+          octave::call_stack& cs = interp.get_call_stack ();
+
+          octave_user_code *fcn = cs.caller_user_code ();
+
+          bool found = false;
+
+          if (fcn)
+            {
+              std::string fname = fcn->fcn_file_name ();
+
+              if (! fname.empty ())
+                {
+                  fname = octave::sys::env::make_absolute (fname);
+                  fname = fname.substr (0, fname.find_last_of (octave::sys::file_ops::dir_sep_str ()) + 1);
+
+                  octave::sys::file_stat fs (fname + nm);
+
+                  if (fs.exists ())
+                    {
+                      nm = fname + nm;
+                      found = true;
+                    }
+                }
+            }
+          if (! found)
+            warning_with_id ("Octave:autoload-relative-file-name",
+                             "autoload: '%s' is not an absolute filename",
+                             nm.c_str ());
+        }
+      if (nargin == 2)
+        autoload_map[argv[1]] = nm;
+      else if (nargin == 3)
+        {
+          if (argv[3] != "remove")
+            error_with_id ("Octave:invalid-input-arg",
+                           "autoload: third argument can only be 'remove'");
+
+          // Remove function from symbol table and autoload map.
+          octave::symbol_table& symtab = interp.get_symbol_table ();
+          symtab.clear_dld_function (argv[1]);
+          autoload_map.erase (argv[1]);
+        }
+    }
+
+  return retval;
+}
+
+namespace octave
+{
+  // Execute the contents of a script file.  For compatibility with
+  // Matlab, also execute a function file by calling the function it
+  // defines with no arguments and nargout = 0.
+
+  void
+  source_file (const std::string& file_name, const std::string& context,
+               bool verbose, bool require_file, const std::string& warn_for)
+  {
+    // Map from absolute name of script file to recursion level.  We
+    // use a map instead of simply placing a limit on recursion in the
+    // source_file function so that two mutually recursive scripts
+    // written as
+    //
+    //   foo1.m:
+    //   ------
+    //   foo2
+    //
+    //   foo2.m:
+    //   ------
+    //   foo1
+    //
+    // and called with
+    //
+    //   foo1
+    //
+    // (for example) will behave the same if they are written as
+    //
+    //   foo1.m:
+    //   ------
+    //   source ("foo2.m")
+    //
+    //   foo2.m:
+    //   ------
+    //   source ("foo1.m")
+    //
+    // and called with
+    //
+    //   source ("foo1.m")
+    //
+    // (for example).
+
+    static std::map<std::string, int> source_call_depth;
+
+    std::string file_full_name
+      = sys::file_ops::tilde_expand (file_name);
+
+    size_t pos
+      = file_full_name.find_last_of (sys::file_ops::dir_sep_str ());
+
+    std::string dir_name = file_full_name.substr (0, pos);
+
+    file_full_name = sys::env::make_absolute (file_full_name);
+
+    unwind_protect frame;
+
+    if (source_call_depth.find (file_full_name) == source_call_depth.end ())
+      source_call_depth[file_full_name] = -1;
+
+    frame.protect_var (source_call_depth[file_full_name]);
+
+    source_call_depth[file_full_name]++;
+
+    tree_evaluator& tw = __get_evaluator__ ("source_file");
+
+    if (source_call_depth[file_full_name] >= tw.max_recursion_depth ())
+      error ("max_recursion_depth exceeded");
+
+    if (! context.empty ())
+      {
+        call_stack& cs = __get_call_stack__ ("source_file");
+
+        if (context == "caller")
+          cs.goto_caller_frame ();
+        else if (context == "base")
+          cs.goto_base_frame ();
+        else
+          error ("source: context must be \"caller\" or \"base\"");
+
+        frame.add_method (cs, &call_stack::pop);
+      }
+
+    // Find symbol name that would be in symbol_table, if it were loaded.
+    size_t dir_end
+      = file_name.find_last_of (sys::file_ops::dir_sep_chars ());
+    dir_end = (dir_end == std::string::npos) ? 0 : dir_end + 1;
+
+    size_t extension = file_name.find_last_of ('.');
+    if (extension == std::string::npos)
+      extension = file_name.length ();
+
+    std::string symbol = file_name.substr (dir_end, extension - dir_end);
+    std::string full_name = sys::canonicalize_file_name (file_name);
+
+    // Check if this file is already loaded (or in the path)
+    symbol_table& symtab = __get_symbol_table__ ("source_file");
+    octave_value ov_code = symtab.find (symbol);
+
+    // For compatibility with Matlab, accept both scripts and
+    // functions.
+
+    if (ov_code.is_user_code ())
+      {
+        octave_user_code *code = ov_code.user_code_value ();
+
+        if (! code
+            || (sys::canonicalize_file_name (code->fcn_file_name ())
+                != full_name))
+          {
+            // Wrong file, so load it below.
+            ov_code = octave_value ();
+          }
+      }
+    else
+      {
+        // Not a script, so load it below.
+        ov_code = octave_value ();
+      }
+
+    // If no symbol of this name, or the symbol is for a different
+    // file, load.
+
+    if (ov_code.is_undefined ())
+      {
+        try
+          {
+            ov_code = parse_fcn_file (file_full_name, file_name, dir_name,
+                                      "", "", require_file, true, false,
+                                      false, warn_for);
+          }
+        catch (execution_exception& e)
+          {
+            error (e, "source: error sourcing file '%s'",
+                   file_full_name.c_str ());
+          }
+      }
+
+    // Return or error if we don't have a valid script or function.
+
+    if (ov_code.is_undefined ())
+      return;
+
+    if (! ov_code.is_user_code ())
+      error ("source: %s is not a script", full_name.c_str ());
+
+    if (verbose)
+      {
+        std::cout << "executing commands from " << full_name << " ... ";
+        std::cout.flush ();
+      }
+
+    octave_user_code *code = ov_code.user_code_value ();
+
+    code->call (tw, 0, octave_value_list ());
+
+    if (verbose)
+      std::cout << "done." << std::endl;
+  }
+}
+
+DEFMETHOD (mfilename, interp, args, ,
+           doc: /* -*- texinfo -*-
+@deftypefn  {} {} mfilename ()
+@deftypefnx {} {} mfilename ("fullpath")
+@deftypefnx {} {} mfilename ("fullpathext")
+Return the name of the currently executing file.
+
+The base name of the currently executing script or function is returned without
+any extension.  If called from outside an m-file, such as the command line,
+return the empty string.
+
+Given the argument @qcode{"fullpath"}, include the directory part of the
+filename, but not the extension.
+
+Given the argument @qcode{"fullpathext"}, include the directory part of
+the filename and the extension.
+@seealso{inputname, dbstack}
+@end deftypefn */)
+{
+  octave_value retval;
+
+  int nargin = args.length ();
+
+  if (nargin > 1)
+    print_usage ();
+
+  std::string arg;
+
+  if (nargin == 1)
+    arg = args(0).xstring_value ("mfilename: argument must be a string");
+
+  std::string fname;
+
+  octave::call_stack& cs = interp.get_call_stack ();
+
+  octave_user_code *fcn = cs.caller_user_code ();
+
+  if (fcn)
+    {
+      fname = fcn->fcn_file_name ();
+
+      if (fname.empty ())
+        fname = fcn->name ();
+    }
+
+  if (arg == "fullpathext")
+    retval = fname;
+  else
+    {
+      size_t dpos = fname.rfind (octave::sys::file_ops::dir_sep_char ());
+      size_t epos = fname.rfind ('.');
+
+      if (epos <= dpos+1)
+        epos = std::string::npos;
+
+      fname = (epos != std::string::npos) ? fname.substr (0, epos) : fname;
+
+      if (arg == "fullpath")
+        retval = fname;
+      else
+        retval = (dpos != std::string::npos) ? fname.substr (dpos+1) : fname;
+    }
+
+  return retval;
+}
+
+DEFUN (source, args, ,
+       doc: /* -*- texinfo -*-
+@deftypefn  {} {} source (@var{file})
+@deftypefnx {} {} source (@var{file}, @var{context})
+Parse and execute the contents of @var{file}.
+
+Without specifying @var{context}, this is equivalent to executing commands
+from a script file, but without requiring the file to be named
+@file{@var{file}.m} or to be on the execution path.
+
+Instead of the current context, the script may be executed in either the
+context of the function that called the present function
+(@qcode{"caller"}), or the top-level context (@qcode{"base"}).
+@seealso{run}
+@end deftypefn */)
+{
+  octave_value_list retval;
+
+  int nargin = args.length ();
+
+  if (nargin < 1 || nargin > 2)
+    print_usage ();
+
+  std::string file_name = args(0).xstring_value ("source: FILE must be a string");
+
+  std::string context;
+
+  if (nargin == 2)
+    context = args(1).xstring_value ("source: CONTEXT must be a string");
+
+  octave::source_file (file_name, context);
+
+  return retval;
+}
+
+namespace octave
+{
+  //! Evaluate an Octave function (built-in or interpreted) and return
+  //! the list of result values.
+  //!
+  //! @param name The name of the function to call.
+  //! @param args The arguments to the function.
+  //! @param nargout The number of output arguments expected.
+  //! @return A list of output values.  The length of the list is not
+  //!         necessarily the same as @c nargout.
+
+  octave_value_list
+  feval (const std::string& name, const octave_value_list& args, int nargout)
+  {
+    octave_value_list retval;
+
+    symbol_table& symtab = __get_symbol_table__ ("feval");
+
+    octave_value fcn = symtab.find_function (name, args);
+
+    if (fcn.is_defined ())
+      {
+        tree_evaluator& tw = __get_evaluator__ ("feval");
+
+        octave_function *of = fcn.function_value ();
+
+        retval = of->call (tw, nargout, args);
+      }
+    else
+      error ("feval: function '%s' not found", name.c_str ());
+
+    return retval;
+  }
+
+  octave_value_list
+  feval (octave_function *fcn, const octave_value_list& args, int nargout)
+  {
+    octave_value_list retval;
+
+    if (fcn)
+      {
+        tree_evaluator& tw = __get_evaluator__ ("feval");
+
+        retval = fcn->call (tw, nargout, args);
+      }
+
+    return retval;
+  }
+
+  octave_value_list
+  feval (octave_value& val, const octave_value_list& args, int nargout)
+  {
+    if (val.is_function ())
+      {
+        return feval (val.function_value (), args, nargout);
+      }
+    else if (val.is_function_handle ())
+      {
+        // This covers function handles, inline functions, and anonymous
+        //  functions.
+
+        std::list<octave_value_list> arg_list;
+        arg_list.push_back (args);
+
+        return val.subsref ("(", arg_list, nargout);
+      }
+    else if (val.is_string ())
+      {
+        return feval (val.string_value (), args, nargout);
+      }
+    else
+      error ("feval: first argument must be a string, inline function, or a function handle");
+
+    return ovl ();
+  }
+
+  static octave_value_list
+  get_feval_args (const octave_value_list& args)
+  {
+    return args.slice (1, args.length () - 1, true);
+  }
+
+  //! Evaluate an Octave function (built-in or interpreted) and return
+  //! the list of result values.
+  //!
+  //! @param args The first element of @c args is the function to call.
+  //!             It may be the name of the function as a string, a function
+  //!             handle, or an inline function.  The remaining arguments are
+  //!             passed to the function.
+  //! @param nargout The number of output arguments expected.
+  //! @return A list of output values.  The length of the list is not
+  //!         necessarily the same as @c nargout.
+
+  octave_value_list
+  feval (const octave_value_list& args, int nargout)
+  {
+    if (args.length () > 0)
+      {
+        octave_value f_arg = args(0);
+
+        octave_value_list tmp_args = get_feval_args (args);
+
+        return feval (f_arg, tmp_args, nargout);
+      }
+    else
+      error ("feval: first argument must be a string, inline function, or a function handle");
+
+    return ovl ();
+  }
+}
+
+DEFUN (feval, args, nargout,
+       doc: /* -*- texinfo -*-
+@deftypefn {} {} feval (@var{name}, @dots{})
+Evaluate the function named @var{name}.
+
+Any arguments after the first are passed as inputs to the named function.
+For example,
+
+@example
+@group
+feval ("acos", -1)
+     @result{} 3.1416
+@end group
+@end example
+
+@noindent
+calls the function @code{acos} with the argument @samp{-1}.
+
+The function @code{feval} can also be used with function handles of any sort
+(@pxref{Function Handles}).  Historically, @code{feval} was the only way to
+call user-supplied functions in strings, but function handles are now
+preferred due to the cleaner syntax they offer.  For example,
+
+@example
+@group
+@var{f} = @@exp;
+feval (@var{f}, 1)
+    @result{} 2.7183
+@var{f} (1)
+    @result{} 2.7183
+@end group
+@end example
+
+@noindent
+are equivalent ways to call the function referred to by @var{f}.  If it
+cannot be predicted beforehand whether @var{f} is a function handle,
+function name in a string, or inline function then @code{feval} can be used
+instead.
+@end deftypefn */)
+{
+  if (args.length () == 0)
+    print_usage ();
+
+  return octave::feval (args, nargout);
+}
+
+DEFMETHOD (builtin, interp, args, nargout,
+           doc: /* -*- texinfo -*-
+@deftypefn {} {[@dots{}] =} builtin (@var{f}, @dots{})
+Call the base function @var{f} even if @var{f} is overloaded to another
+function for the given type signature.
+
+This is normally useful when doing object-oriented programming and there is
+a requirement to call one of Octave's base functions rather than the
+overloaded one of a new class.
+
+A trivial example which redefines the @code{sin} function to be the
+@code{cos} function shows how @code{builtin} works.
+
+@example
+@group
+sin (0)
+  @result{} 0
+function y = sin (x), y = cos (x); endfunction
+sin (0)
+  @result{} 1
+builtin ("sin", 0)
+  @result{} 0
+@end group
+@end example
+@end deftypefn */)
+{
+  octave_value_list retval;
+
+  if (args.length () == 0)
+    print_usage ();
+
+  const std::string name (args(0).xstring_value ("builtin: function name (F) must be a string"));
+
+  octave::symbol_table& symtab = interp.get_symbol_table ();
+
+  octave_value fcn = symtab.builtin_find (name);
+
+  if (fcn.is_defined ())
+    retval = octave::feval (fcn.function_value (), args.splice (0, 1), nargout);
+  else
+    error ("builtin: lookup for symbol '%s' failed", name.c_str ());
+
+  return retval;
+}
+
+namespace octave
+{
+  octave_value_list
+  eval_string (const std::string& eval_str, bool silent,
+               int& parse_status, int nargout)
+  {
+    octave_value_list retval;
+
+    parser parser (eval_str, __get_interpreter__ ("eval_string"));
+
+    do
+      {
+        parser.reset ();
+
+        parse_status = parser.run ();
+
+        if (parse_status == 0)
+          {
+            if (parser.m_stmt_list)
+              {
+                tree_statement *stmt = nullptr;
+
+                tree_evaluator& tw = __get_evaluator__ ("eval_string");
+
+                if (parser.m_stmt_list->length () == 1
+                    && (stmt = parser.m_stmt_list->front ())
+                    && stmt->is_expression ())
+                  {
+                    tree_expression *expr = stmt->expression ();
+
+                    if (silent)
+                      expr->set_print_flag (false);
+
+                    bool do_bind_ans = false;
+
+                    if (expr->is_identifier ())
+                      {
+                        symbol_scope scope = tw.get_current_scope ();
+
+                        symbol_record::context_id context
+                          = scope.current_context ();
+
+                        tree_identifier *id
+                          = dynamic_cast<tree_identifier *> (expr);
+
+                        do_bind_ans = (! id->is_variable (context));
+                      }
+                    else
+                      do_bind_ans = (! expr->is_assignment_expression ());
+
+                    retval = tw.evaluate_n (expr, nargout);
+
+                    if (do_bind_ans && ! retval.empty ())
+                      tw.bind_ans (retval(0), expr->print_result ());
+
+                    if (nargout == 0)
+                      retval = octave_value_list ();
+                  }
+                else if (nargout == 0)
+                  parser.m_stmt_list->accept (tw);
+                else
+                  error ("eval: invalid use of statement list");
+
+                if (tw.returning () || tw.breaking () || tw.continuing ())
+                  break;
+              }
+            else if (parser.m_lexer.m_end_of_input)
+              break;
+          }
+      }
+    while (parse_status == 0);
+
+    return retval;
+  }
+
+  octave_value
+  eval_string (const std::string& eval_str, bool silent, int& parse_status)
+  {
+    octave_value retval;
+
+    octave_value_list tmp = eval_string (eval_str, silent, parse_status, 1);
+
+    if (! tmp.empty ())
+      retval = tmp(0);
+
+    return retval;
+  }
+
+  static octave_value_list
+  eval_string (const octave_value& arg, bool silent, int& parse_status,
+               int nargout)
+  {
+    std::string s = arg.xstring_value ("eval: expecting std::string argument");
+
+    return eval_string (s, silent, parse_status, nargout);
+  }
+
+  void
+  cleanup_statement_list (tree_statement_list **lst)
+  {
+    if (*lst)
+      {
+        delete *lst;
+        *lst = nullptr;
+      }
+  }
+}
+
+DEFUN (eval, args, nargout,
+       doc: /* -*- texinfo -*-
+@deftypefn  {} {} eval (@var{try})
+@deftypefnx {} {} eval (@var{try}, @var{catch})
+Parse the string @var{try} and evaluate it as if it were an Octave
+program.
+
+If execution fails, evaluate the optional string @var{catch}.
+
+The string @var{try} is evaluated in the current context, so any results
+remain available after @code{eval} returns.
+
+The following example creates the variable @var{A} with the approximate
+value of 3.1416 in the current workspace.
+
+@example
+eval ("A = acos(-1);");
+@end example
+
+If an error occurs during the evaluation of @var{try} then the @var{catch}
+string is evaluated, as the following example shows:
+
+@example
+@group
+eval ('error ("This is a bad example");',
+      'printf ("This error occurred:\n%s\n", lasterr ());');
+     @print{} This error occurred:
+        This is a bad example
+@end group
+@end example
+
+Programming Note: if you are only using @code{eval} as an error-capturing
+mechanism, rather than for the execution of arbitrary code strings,
+Consider using try/catch blocks or unwind_protect/unwind_protect_cleanup
+blocks instead.  These techniques have higher performance and don't
+introduce the security considerations that the evaluation of arbitrary code
+does.
+@seealso{evalin, evalc, assignin, feval}
+@end deftypefn */)
+{
+  octave_value_list retval;
+
+  int nargin = args.length ();
+
+  if (nargin == 0)
+    print_usage ();
+
+  octave::unwind_protect frame;
+
+  if (nargin > 1)
+    {
+      frame.protect_var (buffer_error_messages);
+      buffer_error_messages++;
+    }
+
+  int parse_status = 0;
+
+  bool execution_error = false;
+
+  octave_value_list tmp;
+
+  try
+    {
+      tmp = octave::eval_string (args(0), nargout > 0, parse_status, nargout);
+    }
+  catch (const octave::execution_exception&)
+    {
+      octave::interpreter::recover_from_exception ();
+
+      execution_error = true;
+    }
+
+  if (nargin > 1 && (parse_status != 0 || execution_error))
+    {
+      // Set up for letting the user print any messages from
+      // errors that occurred in the first part of this eval().
+
+      buffer_error_messages--;
+
+      tmp = octave::eval_string (args(1), nargout > 0, parse_status, nargout);
+
+      if (nargout > 0)
+        retval = tmp;
+    }
+  else
+    {
+      if (nargout > 0)
+        retval = tmp;
+
+      // FIXME: we should really be rethrowing whatever exception occurred,
+      // not just throwing an execution exception.
+      if (execution_error)
+        octave_throw_execution_exception ();
+    }
+
+  return retval;
+}
+
+/*
+
+%!shared x
+%! x = 1;
+
+%!assert (eval ("x"), 1)
+%!assert (eval ("x;"))
+%!assert (eval ("x;"), 1)
+
+%!test
+%! y = eval ("x");
+%! assert (y, 1);
+
+%!test
+%! y = eval ("x;");
+%! assert (y, 1);
+
+%!test
+%! eval ("x = 1;");
+%! assert (x,1);
+
+%!test
+%! eval ("flipud = 2;");
+%! assert (flipud, 2);
+
+%!function y = __f ()
+%!  eval ("flipud = 2;");
+%!  y = flipud;
+%!endfunction
+%!assert (__f(), 2)
+
+% bug #35645
+%!test
+%! [a,] = gcd (1,2);
+%! [a,b,] = gcd (1, 2);
+
+%!error eval ("switch = 13;")
+
+*/
+
+DEFMETHOD (assignin, interp, args, ,
+           doc: /* -*- texinfo -*-
+@deftypefn {} {} assignin (@var{context}, @var{varname}, @var{value})
+Assign @var{value} to @var{varname} in context @var{context}, which
+may be either @qcode{"base"} or @qcode{"caller"}.
+@seealso{evalin}
+@end deftypefn */)
+{
+  octave_value_list retval;
+
+  if (args.length () != 3)
+    print_usage ();
+
+  std::string context = args(0).xstring_value ("assignin: CONTEXT must be a string");
+
+  octave::unwind_protect frame;
+
+  octave::call_stack& cs = interp.get_call_stack ();
+
+  if (context == "caller")
+    cs.goto_caller_frame ();
+  else if (context == "base")
+    cs.goto_base_frame ();
+  else
+    error ("assignin: CONTEXT must be \"caller\" or \"base\"");
+
+  frame.add_method (cs, &octave::call_stack::pop);
+
+  std::string nm = args(1).xstring_value ("assignin: VARNAME must be a string");
+
+  if (octave::valid_identifier (nm))
+    {
+      // Put the check here so that we don't slow down assignments
+      // generally.  Any that go through Octave's parser should have
+      // already been checked.
+
+      if (octave::is_keyword (nm))
+        error ("assignin: invalid assignment to keyword '%s'", nm.c_str ());
+
+      octave::symbol_scope scope = interp.get_current_scope ();
+
+      if (scope)
+        scope.assign (nm, args(2));
+    }
+  else
+    error ("assignin: invalid variable name in argument VARNAME");
+
+  return retval;
+}
+
+/*
+
+%!error assignin ("base", "switch", "13")
+
+*/
+
+DEFMETHOD (evalin, interp, args, nargout,
+           doc: /* -*- texinfo -*-
+@deftypefn  {} {} evalin (@var{context}, @var{try})
+@deftypefnx {} {} evalin (@var{context}, @var{try}, @var{catch})
+Like @code{eval}, except that the expressions are evaluated in the context
+@var{context}, which may be either @qcode{"caller"} or @qcode{"base"}.
+@seealso{eval, assignin}
+@end deftypefn */)
+{
+  octave_value_list retval;
+
+  int nargin = args.length ();
+
+  if (nargin < 2)
+    print_usage ();
+
+  std::string context = args(0).xstring_value ("evalin: CONTEXT must be a string");
+
+  octave::unwind_protect frame;
+
+  octave::call_stack& cs = interp.get_call_stack ();
+
+  if (context == "caller")
+    cs.goto_caller_frame ();
+  else if (context == "base")
+    cs.goto_base_frame ();
+  else
+    error ("evalin: CONTEXT must be \"caller\" or \"base\"");
+
+  frame.add_method (cs, &octave::call_stack::pop);
+
+  if (nargin > 2)
+    {
+      frame.protect_var (buffer_error_messages);
+      buffer_error_messages++;
+    }
+
+  int parse_status = 0;
+
+  bool execution_error = false;
+
+  octave_value_list tmp;
+
+  try
+    {
+      tmp = octave::eval_string (args(1), nargout > 0,
+                                 parse_status, nargout);
+    }
+  catch (const octave::execution_exception&)
+    {
+      octave::interpreter::recover_from_exception ();
+
+      execution_error = true;
+    }
+
+  if (nargin > 2 && (parse_status != 0 || execution_error))
+    {
+      // Set up for letting the user print any messages from
+      // errors that occurred in the first part of this eval().
+
+      buffer_error_messages--;
+
+      tmp = octave::eval_string (args(2), nargout > 0,
+                                 parse_status, nargout);
+
+      retval = (nargout > 0) ? tmp : octave_value_list ();
+    }
+  else
+    {
+      if (nargout > 0)
+        retval = tmp;
+
+      // FIXME: we should really be rethrowing whatever
+      // exception occurred, not just throwing an
+      // execution exception.
+      if (execution_error)
+        octave_throw_execution_exception ();
+    }
+
+  return retval;
+}
+
+static void
+maybe_print_last_error_message (bool *doit)
+{
+  if (doit && *doit)
+    // Print error message again, which was lost because of the stderr buffer
+    // Note: this keeps error_state and last_error_stack intact
+    message_with_id ("error", last_error_id ().c_str (),
+                     last_error_message ().c_str ());
+}
+
+static void
+restore_octave_stdout (std::streambuf *buf)
+{
+  octave_stdout.flush ();
+  octave_stdout.rdbuf (buf);
+}
+
+static void
+restore_octave_stderr (std::streambuf *buf)
+{
+  std::cerr.flush ();
+  std::cerr.rdbuf (buf);
+}
+
+DEFUN (evalc, args, nargout,
+       doc: /* -*- texinfo -*-
+@deftypefn  {} {@var{s} =} evalc (@var{try})
+@deftypefnx {} {@var{s} =} evalc (@var{try}, @var{catch})
+Parse and evaluate the string @var{try} as if it were an Octave program,
+while capturing the output into the return variable @var{s}.
+
+If execution fails, evaluate the optional string @var{catch}.
+
+This function behaves like @code{eval}, but any output or warning messages
+which would normally be written to the console are captured and returned in
+the string @var{s}.
+
+The @code{diary} is disabled during the execution of this function.  When
+@code{system} is used, any output produced by external programs is
+@emph{not} captured, unless their output is captured by the @code{system}
+function itself.
+
+@example
+@group
+s = evalc ("t = 42"), t
+  @result{} s = t =  42
+
+  @result{} t =  42
+@end group
+@end example
+@seealso{eval, diary}
+@end deftypefn */)
+{
+  int nargin = args.length ();
+
+  if (nargin == 0 || nargin > 2)
+    print_usage ();
+
+  // redirect stdout/stderr to capturing buffer
+  std::ostringstream buffer;
+
+  std::ostream& out_stream = octave_stdout;
+  std::ostream& err_stream = std::cerr;
+
+  out_stream.flush ();
+  err_stream.flush ();
+
+  std::streambuf* old_out_buf = out_stream.rdbuf (buffer.rdbuf ());
+  std::streambuf* old_err_buf = err_stream.rdbuf (buffer.rdbuf ());
+
+  bool eval_error_occurred = true;
+
+  octave::unwind_protect frame;
+
+  frame.add_fcn (maybe_print_last_error_message, &eval_error_occurred);
+  frame.add_fcn (restore_octave_stdout, old_out_buf);
+  frame.add_fcn (restore_octave_stderr, old_err_buf);
+
+  // call standard eval function
+  octave_value_list retval;
+  int eval_nargout = std::max (0, nargout - 1);
+
+  retval = Feval (args, eval_nargout);
+  eval_error_occurred = false;
+
+  retval.prepend (buffer.str ());
+  return retval;
+}
+
+/*
+
+%!assert (evalc ("1"), "ans =  1\n")
+%!assert (evalc ("1;"), "")
+
+%!test
+%! [s, y] = evalc ("1");
+%! assert (s, "");
+%! assert (y, 1);
+
+%!test
+%! [s, y] = evalc ("1;");
+%! assert (s, "");
+%! assert (y, 1);
+
+%!test
+%! assert (evalc ("y = 2"), "y =  2\n");
+%! assert (y, 2);
+
+%!test
+%! assert (evalc ("y = 3;"), "");
+%! assert (y, 3);
+
+%!test
+%! [s, a, b] = evalc ("deal (1, 2)");
+%! assert (s, "");
+%! assert (a, 1);
+%! assert (b, 2);
+
+%!function [a, b] = __f_evalc ()
+%!  printf ("foo");
+%!  fprintf (stdout, "bar");
+%!  disp (pi);
+%!  a = 1;
+%!  b = 2;
+%!endfunction
+%!test
+%! [s, a, b] = evalc ("__f_evalc ()");
+%! assert (s, "foobar 3.1416\n");
+%! assert (a, 1);
+%! assert (b, 2);
+
+%!error <foo> (evalc ("error ('foo')"))
+%!error <bar> (evalc ("error ('foo')", "error ('bar')"))
+
+%!test
+%! warning ("off", "quiet", "local");
+%! assert (evalc ("warning ('foo')"), "warning: foo\n");
+
+%!test
+%! warning ("off", "quiet", "local");
+%! assert (evalc ("error ('foo')", "warning ('bar')"), "warning: bar\n");
+
+%!error evalc ("switch = 13;")
+
+*/
+
+DEFUN (__parser_debug_flag__, args, nargout,
+       doc: /* -*- texinfo -*-
+@deftypefn  {} {@var{val} =} __parser_debug_flag__ ()
+@deftypefnx {} {@var{old_val} =} __parser_debug_flag__ (@var{new_val})
+Query or set the internal flag that determines whether Octave's parser
+prints debug information as it processes an expression.
+@seealso{__lexer_debug_flag__}
+@end deftypefn */)
+{
+  octave_value retval;
+
+  bool debug_flag = octave_debug;
+
+  retval = set_internal_variable (debug_flag, args, nargout,
+                                  "__parser_debug_flag__");
+
+  octave_debug = debug_flag;
+
+  return retval;
+}
+
+DEFUN (__parse_file__, args, ,
+       doc: /* -*- texinfo -*-
+@deftypefn {} {} __parse_file__ (@var{file}, @var{verbose})
+Undocumented internal function.
+@end deftypefn */)
+{
+  octave_value retval;
+
+  int nargin = args.length ();
+
+  if (nargin < 1 || nargin > 2)
+    print_usage ();
+
+  std::string file = args(0).xstring_value ("__parse_file__: expecting filename as argument");
+
+  std::string full_file
+      = octave::sys::file_ops::tilde_expand (file);
+
+  full_file = octave::sys::env::make_absolute (full_file);
+
+  std::string dir_name;
+
+  size_t file_len = file.length ();
+
+  if ((file_len > 4 && file.substr (file_len-4) == ".oct")
+      || (file_len > 4 && file.substr (file_len-4) == ".mex")
+      || (file_len > 2 && file.substr (file_len-2) == ".m"))
+    {
+      file = octave::sys::env::base_pathname (file);
+      file = file.substr (0, file.find_last_of ('.'));
+
+      size_t pos = file.find_last_of (octave::sys::file_ops::dir_sep_str ());
+      if (pos != std::string::npos)
+        {
+          dir_name = file.substr (0, pos);
+          file = file.substr (pos+1);
+        }
+    }
+
+  if (nargin == 2)
+    octave_stdout << "parsing " << full_file << std::endl;
+
+  octave_value ov_fcn
+    = octave::parse_fcn_file (full_file, file, dir_name, "", "", true, false,
+                              false, false, "__parse_file__");
+
+  return retval;
+}
--- a/libinterp/parse-tree/parse.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/parse-tree/parse.h	Fri Aug 10 09:09:51 2018 +0200
@@ -486,16 +486,16 @@
   {
   public:
 
-    parser (void)
-      : base_parser (*(new lexer ()))
+    parser (interpreter& interp)
+      : base_parser (*(new lexer (interp)))
     { }
 
-    parser (FILE *file)
-      : base_parser (*(new lexer (file)))
+    parser (FILE *file, interpreter& interp)
+      : base_parser (*(new lexer (file, interp)))
     { }
 
-    parser (const std::string& eval_string)
-      : base_parser (*(new lexer (eval_string)))
+    parser (const std::string& eval_string, interpreter& interp)
+      : base_parser (*(new lexer (eval_string, interp)))
     { }
 
     parser (lexer& lxr)
@@ -517,8 +517,8 @@
   {
   public:
 
-    push_parser (void)
-      : base_parser (*(new push_lexer ()))
+    push_parser (interpreter& interp)
+      : base_parser (*(new push_lexer (interp)))
     { }
 
     // No copying!
--- a/libinterp/parse-tree/profiler.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/parse-tree/profiler.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -25,8 +25,6 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
-
 #include "defun.h"
 #include "interpreter.h"
 #include "oct-time.h"
--- a/libinterp/parse-tree/pt-arg-list.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/parse-tree/pt-arg-list.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -24,26 +24,17 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
 #include <string>
 
 #include "str-vec.h"
 
-#include "defun.h"
-#include "error.h"
 #include "ovl.h"
 #include "ov.h"
-#include "ov-usr-fcn.h"
-#include "parse.h"
 #include "pt-arg-list.h"
-#include "pt-eval.h"
 #include "pt-exp.h"
 #include "pt-id.h"
 #include "pt-idx.h"
 #include "pt-pr-code.h"
-#include "pt-walk.h"
-#include "interpreter.h"
-#include "unwind-prot.h"
 
 namespace octave
 {
@@ -53,7 +44,7 @@
   {
     while (! empty ())
       {
-        iterator p = begin ();
+        auto p = begin ();
         delete *p;
         erase (p);
       }
@@ -117,152 +108,6 @@
 
     return retval;
   }
-}
-
-// FIXME: Is there a way to do this job without global data?
-
-static const octave_value *indexed_object = nullptr;
-static int index_position = 0;
-static int num_indices = 0;
-
-// END is documented in op-kw-docs.
-DEFCONSTMETHOD (end, interp, , ,
-                doc: /* -*- texinfo -*-
-@deftypefn {} {} end
-Last element of an array or the end of any @code{for}, @code{parfor},
-@code{if}, @code{do}, @code{while}, @code{function}, @code{switch},
-@code{try}, or @code{unwind_protect} block.
-
-As an index of an array, the magic index @qcode{"end"} refers to the
-last valid entry in an indexing operation.
-
-Example:
-
-@example
-@group
-@var{x} = [ 1 2 3; 4 5 6 ];
-@var{x}(1,end)
-   @result{} 3
-@var{x}(end,1)
-   @result{} 4
-@var{x}(end,end)
-   @result{} 6
-@end group
-@end example
-@seealso{for, parfor, if, do, while, function, switch, try, unwind_protect}
-@end deftypefn */)
-{
-  octave_value retval;
-
-  if (! indexed_object)
-    error ("invalid use of end");
-
-  if (indexed_object->isobject ())
-    {
-      octave_value_list args;
-
-      args(2) = num_indices;
-      args(1) = index_position + 1;
-      args(0) = *indexed_object;
-
-      std::string class_name = indexed_object->class_name ();
-
-      octave::symbol_table& symtab = interp.get_symbol_table ();
-
-      octave_value meth = symtab.find_method ("end", class_name);
-
-      if (meth.is_defined ())
-        return octave::feval (meth.function_value (), args, 1);
-    }
-
-  dim_vector dv = indexed_object->dims ();
-  int ndims = dv.ndims ();
-
-  if (num_indices < ndims)
-    {
-      for (int i = num_indices; i < ndims; i++)
-        dv(num_indices-1) *= dv(i);
-
-      if (num_indices == 1)
-        {
-          ndims = 2;
-          dv.resize (ndims);
-          dv(1) = 1;
-        }
-      else
-        {
-          ndims = num_indices;
-          dv.resize (ndims);
-        }
-    }
-
-  if (index_position < ndims)
-    retval = dv(index_position);
-  else
-    retval = 1;
-
-  return retval;
-}
-
-namespace octave
-{
-  octave_value_list
-  tree_argument_list::convert_to_const_vector (tree_evaluator *tw,
-                                               const octave_value *object)
-  {
-    // END doesn't make sense for functions.  Maybe we need a different
-    // way of asking an octave_value object this question?
-
-    bool stash_object = (m_list_includes_magic_end
-                         && object
-                         && ! (object->is_function ()
-                               || object->is_function_handle ()));
-
-    unwind_protect frame;
-
-    if (stash_object)
-      {
-        frame.protect_var (indexed_object);
-
-        indexed_object = object;
-      }
-
-    int len = length ();
-
-    std::list<octave_value_list> args;
-
-    iterator p = begin ();
-    for (int k = 0; k < len; k++)
-      {
-        if (stash_object)
-          {
-            frame.protect_var (index_position);
-            frame.protect_var (num_indices);
-
-            index_position = k;
-            num_indices = len;
-          }
-
-        tree_expression *elt = *p++;
-
-        if (elt)
-          {
-            octave_value tmp = tw->evaluate (elt);
-
-            if (tmp.is_cs_list ())
-              args.push_back (tmp.list_value ());
-            else if (tmp.is_defined ())
-              args.push_back (tmp);
-          }
-        else
-          {
-            args.push_back (octave_value ());
-            break;
-          }
-      }
-
-    return args;
-  }
 
   string_vector
   tree_argument_list::get_arg_names (void) const
--- a/libinterp/parse-tree/pt-arg-list.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/parse-tree/pt-arg-list.h	Fri Aug 10 09:09:51 2018 +0200
@@ -67,14 +67,28 @@
 
     ~tree_argument_list (void);
 
+    // FIXME: This does not recursively check elements of the list
+    // that are also index expressions.
     bool has_magic_end (void) const;
 
+    bool includes_magic_end (void) const
+    {
+      return m_list_includes_magic_end;
+    }
+
     bool has_magic_tilde (void) const
-    { return m_list_includes_magic_tilde; }
+    {
+      return m_list_includes_magic_tilde;
+    }
+
+    bool includes_magic_tilde (void) const
+    {
+      return m_list_includes_magic_tilde;
+    }
 
     tree_expression * remove_front (void)
     {
-      iterator p = begin ();
+      auto p = begin ();
       tree_expression *retval = *p;
       erase (p);
       return retval;
@@ -90,10 +104,6 @@
 
     bool is_valid_lvalue_list (void) const;
 
-    octave_value_list
-    convert_to_const_vector (tree_evaluator *tw,
-                             const octave_value *object = nullptr);
-
     string_vector get_arg_names (void) const;
 
     std::list<std::string> variable_names (void) const;
--- a/libinterp/parse-tree/pt-array-list.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/parse-tree/pt-array-list.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -24,8 +24,6 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
-
 #include "quit.h"
 
 #include "error.h"
@@ -37,7 +35,7 @@
   {
     while (! empty ())
       {
-        iterator p = begin ();
+        auto p = begin ();
         delete *p;
         erase (p);
       }
--- a/libinterp/parse-tree/pt-assign.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/parse-tree/pt-assign.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -24,7 +24,6 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
 #include <string>
 
 #include "error.h"
--- a/libinterp/parse-tree/pt-bp.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/parse-tree/pt-bp.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -30,10 +30,6 @@
 
 namespace octave
 {
-  // TRUE means SIGINT should put us in the debugger at the next
-  // available breakpoint.
-  bool octave_debug_on_interrupt_state = false;
-
   void
   tree_breakpoint::visit_while_command (tree_while_command& cmd)
   {
--- a/libinterp/parse-tree/pt-bp.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/parse-tree/pt-bp.h	Fri Aug 10 09:09:51 2018 +0200
@@ -173,10 +173,6 @@
     // List of breakpoint conditions.
     octave_value_list m_bp_cond_list;
   };
-
-  // TRUE means SIGINT should put us in the debugger at the next
-  // available breakpoint.
-  extern bool octave_debug_on_interrupt_state;
 }
 
 #if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
--- a/libinterp/parse-tree/pt-cbinop.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/parse-tree/pt-cbinop.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -36,12 +36,12 @@
   // the argument and corresponding operator.
 
   static octave_value::unary_op
-  strip_trans_herm (octave::tree_expression_ptr_t& exp)
+  strip_trans_herm (tree_expression_ptr_t& exp)
   {
     if (exp->is_unary_expression ())
       {
-        octave::tree_unary_expression *uexp =
-          dynamic_cast<octave::tree_unary_expression *> (exp);
+        tree_unary_expression *uexp =
+          dynamic_cast<tree_unary_expression *> (exp);
 
         octave_value::unary_op op = uexp->op_type ();
 
@@ -58,12 +58,12 @@
   }
 
   static octave_value::unary_op
-  strip_not (octave::tree_expression_ptr_t& exp)
+  strip_not (tree_expression_ptr_t& exp)
   {
     if (exp->is_unary_expression ())
       {
-        octave::tree_unary_expression *uexp =
-          dynamic_cast<octave::tree_unary_expression *> (exp);
+        tree_unary_expression *uexp =
+          dynamic_cast<tree_unary_expression *> (exp);
 
         octave_value::unary_op op = uexp->op_type ();
 
@@ -82,8 +82,7 @@
   // or mul_herm.
 
   static octave_value::compound_binary_op
-  simplify_mul_op (octave::tree_expression_ptr_t& a,
-                   octave::tree_expression_ptr_t& b)
+  simplify_mul_op (tree_expression_ptr_t& a, tree_expression_ptr_t& b)
   {
     octave_value::compound_binary_op retop
       = octave_value::unknown_compound_binary_op;
@@ -110,8 +109,7 @@
   // Possibly convert left division to trans_ldiv or herm_ldiv.
 
   static octave_value::compound_binary_op
-  simplify_ldiv_op (octave::tree_expression_ptr_t& a,
-                    octave::tree_expression_ptr_t&)
+  simplify_ldiv_op (tree_expression_ptr_t& a, tree_expression_ptr_t&)
   {
     octave_value::compound_binary_op retop
       = octave_value::unknown_compound_binary_op;
@@ -129,8 +127,7 @@
   // Possibly contract and/or with negation.
 
   static octave_value::compound_binary_op
-  simplify_and_or_op (octave::tree_expression_ptr_t& a,
-                      octave::tree_expression_ptr_t& b,
+  simplify_and_or_op (tree_expression_ptr_t& a, tree_expression_ptr_t& b,
                       octave_value::binary_op op)
   {
     octave_value::compound_binary_op retop
--- a/libinterp/parse-tree/pt-cell.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/parse-tree/pt-cell.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -24,8 +24,6 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
-
 #include "Cell.h"
 #include "ovl.h"
 #include "pt-arg-list.h"
--- a/libinterp/parse-tree/pt-check.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/parse-tree/pt-check.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -34,7 +34,7 @@
   void
   tree_checker::visit_argument_list (tree_argument_list& lst)
   {
-    tree_argument_list::iterator p = lst.begin ();
+    auto p = lst.begin ();
 
     while (p != lst.end ())
       {
@@ -101,7 +101,7 @@
   void
   tree_checker::visit_decl_init_list (tree_decl_init_list& lst)
   {
-    tree_decl_init_list::iterator p = lst.begin ();
+    auto p = lst.begin ();
 
     while (p != lst.end ())
       {
@@ -243,7 +243,7 @@
   void
   tree_checker::visit_if_command_list (tree_if_command_list& lst)
   {
-    tree_if_command_list::iterator p = lst.begin ();
+    auto p = lst.begin ();
 
     while (p != lst.end ())
       {
@@ -264,7 +264,7 @@
 
     std::list<tree_argument_list *> lst = expr.arg_lists ();
 
-    std::list<tree_argument_list *>::iterator p = lst.begin ();
+    auto p = lst.begin ();
 
     while (p != lst.end ())
       {
@@ -278,7 +278,7 @@
   void
   tree_checker::visit_matrix (tree_matrix& lst)
   {
-    tree_matrix::iterator p = lst.begin ();
+    auto p = lst.begin ();
 
     while (p != lst.end ())
       {
@@ -292,7 +292,7 @@
   void
   tree_checker::visit_cell (tree_cell& lst)
   {
-    tree_matrix::iterator p = lst.begin ();
+    auto p = lst.begin ();
 
     while (p != lst.end ())
       {
@@ -346,7 +346,7 @@
   void
   tree_checker::visit_parameter_list (tree_parameter_list& lst)
   {
-    tree_parameter_list::iterator p = lst.begin ();
+    auto p = lst.begin ();
 
     while (p != lst.end ())
       {
@@ -382,7 +382,7 @@
   void
   tree_checker::visit_return_list (tree_return_list& lst)
   {
-    tree_return_list::iterator p = lst.begin ();
+    auto p = lst.begin ();
 
     while (p != lst.end ())
       {
@@ -453,7 +453,7 @@
   void
   tree_checker::visit_switch_case_list (tree_switch_case_list& lst)
   {
-    tree_switch_case_list::iterator p = lst.begin ();
+    auto p = lst.begin ();
 
     while (p != lst.end ())
       {
--- a/libinterp/parse-tree/pt-classdef.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/parse-tree/pt-classdef.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -37,7 +37,7 @@
   {
     while (! empty ())
       {
-        iterator p = begin ();
+        auto p = begin ();
         delete *p;
         erase (p);
       }
@@ -51,7 +51,7 @@
   {
     while (! empty ())
       {
-        iterator p = begin ();
+        auto p = begin ();
         delete *p;
         erase (p);
       }
@@ -65,7 +65,7 @@
   {
     while (! empty ())
       {
-        iterator p = begin ();
+        auto p = begin ();
         delete *p;
         erase (p);
       }
@@ -85,7 +85,7 @@
   {
     while (! empty ())
       {
-        iterator p = begin ();
+        auto p = begin ();
         delete *p;
         erase (p);
       }
@@ -101,7 +101,7 @@
   {
     while (! empty ())
       {
-        iterator p = begin ();
+        auto p = begin ();
         delete *p;
         erase (p);
       }
@@ -115,28 +115,28 @@
   {
     while (! m_properties_lst.empty ())
       {
-        properties_list_iterator p = m_properties_lst.begin ();
+        auto p = m_properties_lst.begin ();
         delete *p;
         m_properties_lst.erase (p);
       }
 
     while (! m_methods_lst.empty ())
       {
-        methods_list_iterator p = m_methods_lst.begin ();
+        auto p = m_methods_lst.begin ();
         delete *p;
         m_methods_lst.erase (p);
       }
 
     while (! m_events_lst.empty ())
       {
-        events_list_iterator p = m_events_lst.begin ();
+        auto p = m_events_lst.begin ();
         delete *p;
         m_events_lst.erase (p);
       }
 
     while (! m_enum_lst.empty ())
       {
-        enum_list_iterator p = m_enum_lst.begin ();
+        auto p = m_enum_lst.begin ();
         delete *p;
         m_enum_lst.erase (p);
       }
--- a/libinterp/parse-tree/pt-const.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/parse-tree/pt-const.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -24,7 +24,7 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <ostream>
 
 #include "error.h"
 #include "ovl.h"
--- a/libinterp/parse-tree/pt-decl.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/parse-tree/pt-decl.h	Fri Aug 10 09:09:51 2018 +0200
@@ -84,7 +84,7 @@
 
     bool lvalue_ok (void) { return m_id ? m_id->lvalue_ok () : false; }
 
-    octave_lvalue lvalue (tree_evaluator *tw)
+    octave_lvalue lvalue (tree_evaluator& tw)
     {
       return m_id ? m_id->lvalue (tw) : octave_lvalue ();
     }
@@ -137,7 +137,7 @@
     {
       while (! empty ())
         {
-          iterator p = begin ();
+          auto p = begin ();
           delete *p;
           erase (p);
         }
--- a/libinterp/parse-tree/pt-eval.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/parse-tree/pt-eval.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -27,11 +27,11 @@
 #include <cctype>
 
 #include <iostream>
-
-#include <fstream>
-#include <typeinfo>
+#include <list>
+#include <string>
 
 #include "cmd-edit.h"
+#include "file-ops.h"
 #include "oct-env.h"
 
 #include "bp-table.h"
@@ -60,24 +60,12 @@
 
 namespace octave
 {
-  int tree_evaluator::dbstep_flag = 0;
-
-  size_t tree_evaluator::current_frame = 0;
-
-  bool tree_evaluator::debug_mode = false;
-
-  bool tree_evaluator::quiet_breakpoint_flag = false;
-
-  tree_evaluator::stmt_list_type tree_evaluator::statement_context
-    = tree_evaluator::other;
-
-  bool tree_evaluator::in_loop_command = false;
-
   // Normal evaluator.
 
   void
   tree_evaluator::reset (void)
   {
+    m_statement_context = SC_OTHER;
     m_result_type = RT_UNDEFINED;
     m_expr_result_value = octave_value ();
     m_expr_result_value_list = octave_value_list ();
@@ -85,6 +73,126 @@
     m_nargout_stack.clear ();
   }
 
+  int tree_evaluator::repl (bool interactive)
+  {
+    int retval = 0;
+
+    lexer *lxr = (interactive
+                  ? new lexer (m_interpreter)
+                  : new lexer (stdin, m_interpreter));
+
+    parser parser (*lxr);
+
+    symbol_table& symtab = m_interpreter.get_symbol_table ();
+
+    do
+      {
+        try
+          {
+            reset_error_handler ();
+
+            parser.reset ();
+
+            if (symtab.at_top_level ())
+              reset_debug_state ();
+
+            retval = parser.run ();
+
+            if (retval == 0)
+              {
+                if (parser.m_stmt_list)
+                  {
+                    parser.m_stmt_list->accept (*this);
+
+                    octave_quit ();
+
+                    if (! interactive)
+                      {
+                        bool quit = (m_returning || m_breaking);
+
+                        if (m_returning)
+                          m_returning = 0;
+
+                        if (m_breaking)
+                          m_breaking--;
+
+                        if (quit)
+                          break;
+                      }
+
+                    if (octave_completion_matches_called)
+                      octave_completion_matches_called = false;
+                    else
+                      command_editor::increment_current_command_number ();
+                  }
+                else if (parser.m_lexer.m_end_of_input)
+                  {
+                    retval = EOF;
+                    break;
+                  }
+              }
+          }
+        catch (const interrupt_exception&)
+          {
+            m_interpreter.recover_from_exception ();
+
+            // Required newline when the user does Ctrl+C at the prompt.
+            if (interactive)
+              octave_stdout << "\n";
+          }
+        catch (const index_exception& e)
+          {
+            m_interpreter.recover_from_exception ();
+
+            std::cerr << "error: unhandled index exception: "
+                      << e.message () << " -- trying to return to prompt"
+                      << std::endl;
+          }
+        catch (const execution_exception& e)
+          {
+            std::string stack_trace = e.info ();
+
+            if (! stack_trace.empty ())
+              std::cerr << stack_trace;
+
+            if (interactive)
+              m_interpreter.recover_from_exception ();
+            else
+              {
+                // We should exit with a nonzero status.
+                retval = 1;
+                break;
+              }
+          }
+        catch (const std::bad_alloc&)
+          {
+            m_interpreter.recover_from_exception ();
+
+            std::cerr << "error: out of memory -- trying to return to prompt"
+                      << std::endl;
+          }
+
+#if defined (DBSTOP_NANINF)
+        if (Vdebug_on_naninf)
+          {
+            if (setjump (naninf_jump) != 0)
+              debug_or_throw_exception (true);  // true = stack trace
+          }
+#endif
+      }
+    while (retval == 0);
+
+    if (retval == EOF)
+      {
+        if (interactive)
+          octave_stdout << "\n";
+
+        retval = 0;
+      }
+
+    return retval;
+  }
+
   void
   tree_evaluator::visit_anon_fcn_handle (tree_anon_fcn_handle& anon_fh)
   {
@@ -151,7 +259,7 @@
 
     octave_value ov_fcn (af);
 
-    octave_value fh (octave_fcn_binder::maybe_binder (ov_fcn, this));
+    octave_value fh (octave_fcn_binder::maybe_binder (ov_fcn, *this));
 
     push_result (fh);
   }
@@ -339,11 +447,11 @@
         m_echo_file_pos = line + 1;
       }
 
-    if (debug_mode)
+    if (m_debug_mode)
       do_breakpoint (cmd.is_breakpoint (true));
 
-    if (in_loop_command)
-      tree_break_command::breaking = 1;
+    if (m_in_loop_command)
+      m_breaking = 1;
     else
       error ("break must appear in a loop in the same file as loop command");
   }
@@ -421,28 +529,34 @@
         m_echo_file_pos = line + 1;
       }
 
-    if (debug_mode)
+    if (m_debug_mode)
       do_breakpoint (cmd.is_breakpoint (true));
 
-    if (in_loop_command)
-      tree_continue_command::continuing = 1;
+    if (m_in_loop_command)
+      m_continuing = 1;
   }
 
   bool
   tree_evaluator::statement_printing_enabled (void)
   {
-    return ! (m_silent_functions && (statement_context == function
-                                     || statement_context == script));
+    return ! (m_silent_functions && (m_statement_context == SC_FUNCTION
+                                     || m_statement_context == SC_SCRIPT));
   }
 
   void
   tree_evaluator::reset_debug_state (void)
   {
-    bp_table& bptab = __get_bp_table__ ("tree_evaluator::reset_debug_state");
-
-    debug_mode = bptab.have_breakpoints () || Vdebugging;
-
-    dbstep_flag = 0;
+    m_debug_mode = m_bp_table.have_breakpoints () || Vdebugging;
+
+    m_dbstep_flag = 0;
+  }
+
+  void
+  tree_evaluator::reset_debug_state (bool mode)
+  {
+    m_debug_mode = mode;
+
+    m_dbstep_flag = 0;
   }
 
   Matrix
@@ -553,7 +667,7 @@
       {
         i++;
 
-        octave_lvalue ref = elt->lvalue (this);
+        octave_lvalue ref = elt->lvalue (*this);
 
         if (i < args.length ())
           {
@@ -575,11 +689,159 @@
   {
     for (tree_decl_elt *elt : *param_list)
       {
-        octave_lvalue ref = elt->lvalue (this);
+        octave_lvalue ref = elt->lvalue (*this);
 
         ref.assign (octave_value::op_asn_eq, octave_value ());
       }
   }
+}
+
+// END is documented in op-kw-docs.
+DEFCONSTMETHOD (end, interp, , ,
+                doc: /* -*- texinfo -*-
+@deftypefn {} {} end
+Last element of an array or the end of any @code{for}, @code{parfor},
+@code{if}, @code{do}, @code{while}, @code{function}, @code{switch},
+@code{try}, or @code{unwind_protect} block.
+
+As an index of an array, the magic index @qcode{"end"} refers to the
+last valid entry in an indexing operation.
+
+Example:
+
+@example
+@group
+@var{x} = [ 1 2 3; 4 5 6 ];
+@var{x}(1,end)
+   @result{} 3
+@var{x}(end,1)
+   @result{} 4
+@var{x}(end,end)
+   @result{} 6
+@end group
+@end example
+@seealso{for, parfor, if, do, while, function, switch, try, unwind_protect}
+@end deftypefn */)
+{
+  octave_value retval;
+
+  octave::tree_evaluator& tw = interp.get_evaluator ();
+
+  const octave_value *indexed_object = tw.indexed_object ();
+  int index_position = tw.index_position ();
+  int num_indices = tw.num_indices ();
+
+  if (! indexed_object)
+    error ("invalid use of end");
+
+  if (indexed_object->isobject ())
+    {
+      octave_value_list args;
+
+      args(2) = num_indices;
+      args(1) = index_position + 1;
+      args(0) = *indexed_object;
+
+      std::string class_name = indexed_object->class_name ();
+
+      octave::symbol_table& symtab = interp.get_symbol_table ();
+
+      octave_value meth = symtab.find_method ("end", class_name);
+
+      if (meth.is_defined ())
+        return octave::feval (meth.function_value (), args, 1);
+    }
+
+  dim_vector dv = indexed_object->dims ();
+  int ndims = dv.ndims ();
+
+  if (num_indices < ndims)
+    {
+      for (int i = num_indices; i < ndims; i++)
+        dv(num_indices-1) *= dv(i);
+
+      if (num_indices == 1)
+        {
+          ndims = 2;
+          dv.resize (ndims);
+          dv(1) = 1;
+        }
+      else
+        {
+          ndims = num_indices;
+          dv.resize (ndims);
+        }
+    }
+
+  if (index_position < ndims)
+    retval = dv(index_position);
+  else
+    retval = 1;
+
+  return retval;
+}
+
+namespace octave
+{
+  octave_value_list
+  tree_evaluator::convert_to_const_vector (tree_argument_list *arg_list,
+                                           const octave_value *object)
+  {
+    // END doesn't make sense as a direct argument for a function (i.e.,
+    // "fcn (end)" is invalid but "fcn (array (end))" is OK).  Maybe we
+    // need a different way of asking an octave_value object this
+    // question?
+
+    bool stash_object = (arg_list->includes_magic_end ()
+                         && object
+                         && ! (object->is_function ()
+                               || object->is_function_handle ()));
+
+    unwind_protect frame;
+
+    if (stash_object)
+      {
+        frame.protect_var (m_indexed_object);
+
+        m_indexed_object = object;
+      }
+
+    int len = arg_list->length ();
+
+    std::list<octave_value_list> args;
+
+    auto p = arg_list->begin ();
+    for (int k = 0; k < len; k++)
+      {
+        if (stash_object)
+          {
+            frame.protect_var (m_index_position);
+            frame.protect_var (m_num_indices);
+
+            m_index_position = k;
+            m_num_indices = len;
+          }
+
+        tree_expression *elt = *p++;
+
+        if (elt)
+          {
+            octave_value tmp = evaluate (elt);
+
+            if (tmp.is_cs_list ())
+              args.push_back (tmp.list_value ());
+            else if (tmp.is_defined ())
+              args.push_back (tmp);
+          }
+        else
+          {
+            args.push_back (octave_value ());
+            break;
+          }
+      }
+
+    return args;
+  }
 
   octave_value_list
   tree_evaluator::convert_return_list_to_const_vector
@@ -640,7 +902,7 @@
 
     if (id && expr)
       {
-        octave_lvalue ult = id->lvalue (this);
+        octave_lvalue ult = id->lvalue (*this);
 
         octave_value init_val = evaluate (expr);
 
@@ -692,6 +954,44 @@
     return symtab.current_scope ();
   }
 
+  // Return a pointer to the user-defined function FNAME.  If FNAME is empty,
+  // search backward for the first user-defined function in the
+  // current call stack.
+
+  octave_user_code *
+  tree_evaluator::get_user_code (const std::string& fname)
+  {
+    octave_user_code *user_code = nullptr;
+
+    if (fname.empty ())
+      user_code = m_call_stack.debug_user_code ();
+    else
+      {
+        std::string name = fname;
+
+        if (sys::file_ops::dir_sep_char () != '/' && name[0] == '@')
+          {
+            auto beg = name.begin () + 2;  // never have @/method
+            auto end = name.end () - 1;    // never have trailing '/'
+            std::replace (beg, end, '/', sys::file_ops::dir_sep_char ());
+          }
+
+        size_t name_len = name.length ();
+
+        if (name_len > 2 && name.substr (name_len-2) == ".m")
+          name = name.substr (0, name_len-2);
+
+        symbol_table& symtab = m_interpreter.get_symbol_table ();
+
+        octave_value fcn = symtab.find_function (name);
+
+        if (fcn.is_defined () && fcn.is_user_code ())
+          user_code = fcn.user_code_value ();
+      }
+
+    return user_code;
+  }
+
   void
   tree_evaluator::visit_decl_command (tree_decl_command& cmd)
   {
@@ -702,7 +1002,7 @@
         m_echo_file_pos = line + 1;
       }
 
-    if (debug_mode)
+    if (m_debug_mode)
       do_breakpoint (cmd.is_breakpoint (true));
 
     tree_decl_init_list *init_list = cmd.initializer_list ();
@@ -783,7 +1083,7 @@
         else
           error ("declaration list element not global or persistent");
 
-        octave_lvalue ult = id->lvalue (this);
+        octave_lvalue ult = id->lvalue (*this);
 
         if (ult.is_undefined ())
           {
@@ -801,27 +1101,6 @@
       }
   }
 
-  // Decide if it's time to quit a for or while loop.
-  static inline bool
-  quit_loop_now (void)
-  {
-    octave_quit ();
-
-    // Maybe handle 'continue N' someday...
-
-    if (octave::tree_continue_command::continuing)
-      octave::tree_continue_command::continuing--;
-
-    bool quit = (octave::tree_return_command::returning
-                 || octave::tree_break_command::breaking
-                 || octave::tree_continue_command::continuing);
-
-    if (octave::tree_break_command::breaking)
-      octave::tree_break_command::breaking--;
-
-    return quit;
-  }
-
   void
   tree_evaluator::visit_simple_for_command (tree_simple_for_command& cmd)
   {
@@ -833,7 +1112,7 @@
         line++;
       }
 
-    if (debug_mode)
+    if (m_debug_mode)
       do_breakpoint (cmd.is_breakpoint (true));
 
     // FIXME: need to handle PARFOR loops here using cmd.in_parallel ()
@@ -841,9 +1120,9 @@
 
     unwind_protect frame;
 
-    frame.protect_var (in_loop_command);
-
-    in_loop_command = true;
+    frame.protect_var (m_in_loop_command);
+
+    m_in_loop_command = true;
 
     tree_expression *expr = cmd.control_expr ();
 
@@ -859,7 +1138,7 @@
 
     tree_expression *lhs = cmd.left_hand_side ();
 
-    octave_lvalue ult = lhs->lvalue (this);
+    octave_lvalue ult = lhs->lvalue (*this);
 
     tree_statement_list *loop_body = cmd.body ();
 
@@ -971,14 +1250,14 @@
         line++;
       }
 
-    if (debug_mode)
+    if (m_debug_mode)
       do_breakpoint (cmd.is_breakpoint (true));
 
     unwind_protect frame;
 
-    frame.protect_var (in_loop_command);
-
-    in_loop_command = true;
+    frame.protect_var (m_in_loop_command);
+
+    m_in_loop_command = true;
 
     tree_expression *expr = cmd.control_expr ();
 
@@ -996,15 +1275,15 @@
 
     tree_argument_list *lhs = cmd.left_hand_side ();
 
-    tree_argument_list::iterator p = lhs->begin ();
+    auto p = lhs->begin ();
 
     tree_expression *elt = *p++;
 
-    octave_lvalue val_ref = elt->lvalue (this);
+    octave_lvalue val_ref = elt->lvalue (*this);
 
     elt = *p;
 
-    octave_lvalue key_ref = elt->lvalue (this);
+    octave_lvalue key_ref = elt->lvalue (*this);
 
     const octave_map tmp_val = rhs.map_value ();
 
@@ -1045,6 +1324,68 @@
     panic_impossible ();
   }
 
+  octave_value_list
+  tree_evaluator::execute_user_script (octave_user_script& user_script,
+                                       int nargout,
+                                       const octave_value_list& args)
+  {
+    octave_value_list retval;
+
+    std::string file_name = user_script.fcn_file_name ();
+
+    if (args.length () != 0 || nargout != 0)
+      error ("invalid call to script %s", file_name.c_str ());
+
+    tree_statement_list *cmd_list = user_script.body ();
+
+    if (! cmd_list)
+      return retval;
+
+    unwind_protect frame;
+
+    // XXX FIXME
+    frame.add_method (user_script, &octave_user_script::set_call_depth,
+                      user_script.call_depth ());
+    user_script.increment_call_depth ();
+
+    if (user_script.call_depth () >= max_recursion_depth ())
+      error ("max_recursion_depth exceeded");
+
+    m_call_stack.push (&user_script, &frame);
+
+    // Set pointer to the current unwind_protect frame to allow
+    // certain builtins register simple cleanup in a very optimized manner.
+    // This is *not* intended as a general-purpose on-cleanup mechanism,
+
+    frame.add_method (m_call_stack, &call_stack::pop);
+
+    // Update line number even if debugging.
+    frame.protect_var (Vtrack_line_num);
+    Vtrack_line_num = true;
+
+    frame.protect_var (m_statement_context);
+    m_statement_context = SC_SCRIPT;
+
+    profiler::enter<octave_user_script> block (m_profiler, user_script);
+
+    symbol_scope script_scope = user_script.scope ();
+    frame.add_method (script_scope, &symbol_scope::unbind_script_symbols);
+    script_scope.bind_script_symbols (get_current_scope ());
+
+    if (echo ())
+      push_echo_state (frame, tree_evaluator::ECHO_SCRIPTS, file_name);
+
+    cmd_list->accept (*this);
+
+    if (m_returning)
+      m_returning = 0;
+
+    if (m_breaking)
+      m_breaking--;
+
+    return retval;
+  }
+
   void
   tree_evaluator::visit_octave_user_function (octave_user_function&)
   {
@@ -1052,6 +1393,202 @@
     panic_impossible ();
   }
 
+  octave_value_list
+  tree_evaluator::execute_user_function (octave_user_function& user_function,
+                                         int nargout,
+                                         const octave_value_list& xargs)
+  {
+    octave_value_list retval;
+
+    tree_statement_list *cmd_list = user_function.body ();
+
+    if (! cmd_list)
+      return retval;
+
+    // If this function is a classdef constructor, extract the first input
+    // argument, which must be the partially constructed object instance.
+
+    octave_value_list args (xargs);
+    octave_value_list ret_args;
+
+    if (user_function.is_classdef_constructor ())
+      {
+        if (args.length () > 0)
+          {
+            ret_args = args.slice (0, 1, true);
+            args = args.slice (1, args.length () - 1, true);
+          }
+        else
+          panic_impossible ();
+      }
+
+#if defined (HAVE_LLVM)
+    if (user_function.is_special_expr ()
+        && tree_jit::execute (*this, args, retval))
+      return retval;
+#endif
+
+    unwind_protect frame;
+
+    // XXX FIXME
+    frame.add_method (user_function, &octave_user_function::set_call_depth,
+                      user_function.call_depth ());
+    user_function.increment_call_depth ();
+
+    if (user_function.call_depth () >= max_recursion_depth ())
+      error ("max_recursion_depth exceeded");
+
+    // Save old and set current symbol table context, for
+    // eval_undefined_error().
+
+    symbol_scope fcn_scope = user_function.scope ();
+
+    symbol_record::context_id context = user_function.active_context ();
+
+    m_call_stack.push (&user_function, &frame, fcn_scope, context);
+
+    frame.protect_var (Vtrack_line_num);
+    // update source line numbers, even if debugging
+    Vtrack_line_num = true;
+    frame.add_method (m_call_stack, &call_stack::pop);
+
+    if (user_function.call_depth () > 0
+        && ! user_function.is_anonymous_function ())
+      {
+        fcn_scope.push_context ();
+
+#if 0
+        std::cerr << name () << " scope: " << fcn_scope
+                  << " call depth: " << user_function.call_depth ()
+                  << " context: " << fcn_scope.current_context () << std::endl;
+#endif
+
+        frame.add_method (fcn_scope, &symbol_scope::pop_context);
+      }
+
+    string_vector arg_names = xargs.name_tags ();
+
+    tree_parameter_list *param_list = user_function.parameter_list ();
+
+    if (param_list && ! param_list->varargs_only ())
+      {
+#if 0
+        std::cerr << "defining param list, scope: " << fcn_scope
+                  << ", context: " << fcn_scope.current_context () << std::endl;
+#endif
+        define_parameter_list_from_arg_vector (param_list, args);
+      }
+
+    // For classdef constructor, pre-populate the output arguments
+    // with the pre-initialized object instance, extracted above.
+
+    tree_parameter_list *ret_list = user_function.return_list ();
+
+    if (user_function.is_classdef_constructor ())
+      {
+        if (! ret_list)
+          error ("%s: invalid classdef constructor, no output argument defined",
+                 user_function.dispatch_class ().c_str ());
+
+        define_parameter_list_from_arg_vector (ret_list, ret_args);
+      }
+
+    // Force parameter list to be undefined when this function exits.
+    // Doing so decrements the reference counts on the values of local
+    // variables that are also named function parameters.
+
+    if (param_list)
+      frame.add_method (this, &tree_evaluator::undefine_parameter_list,
+                        param_list);
+
+    // Force return list to be undefined when this function exits.
+    // Doing so decrements the reference counts on the values of local
+    // variables that are also named values returned by this function.
+
+    if (ret_list)
+      frame.add_method (this, &tree_evaluator::undefine_parameter_list,
+                        ret_list);
+
+    if (user_function.call_depth () == 0)
+      {
+        // Force symbols to be undefined again when this function
+        // exits.
+        //
+        // This cleanup function is added to the unwind_protect stack
+        // after the calls to clear the parameter lists so that local
+        // variables will be cleared before the parameter lists are
+        // cleared.  That way, any function parameters that have been
+        // declared global will be unmarked as global before they are
+        // undefined by the clear_param_list cleanup function.
+
+        frame.add_method (fcn_scope, &symbol_scope::refresh);
+      }
+
+    user_function.bind_automatic_vars (*this, arg_names, args.length (),
+                                       nargout,
+                                       user_function.all_va_args (args));
+
+    frame.add_method (&user_function,
+                      &octave_user_function::restore_warning_states);
+
+    // Evaluate the commands that make up the function.
+
+    frame.protect_var (m_statement_context);
+    m_statement_context = SC_FUNCTION;
+
+    {
+      profiler::enter<octave_user_function> block (m_profiler, user_function);
+
+      if (echo ())
+        push_echo_state (frame, tree_evaluator::ECHO_FUNCTIONS,
+                         user_function.fcn_file_name ());
+
+      if (user_function.is_special_expr ())
+        {
+          assert (cmd_list->length () == 1);
+
+          tree_statement *stmt = cmd_list->front ();
+
+          tree_expression *expr = stmt->expression ();
+
+          if (expr)
+            {
+              m_call_stack.set_location (stmt->line (), stmt->column ());
+
+              retval = evaluate_n (expr, nargout);
+            }
+        }
+      else
+        cmd_list->accept (*this);
+    }
+
+    if (m_returning)
+      m_returning = 0;
+
+    if (m_breaking)
+      m_breaking--;
+
+    // Copy return values out.
+
+    if (ret_list && ! user_function.is_special_expr ())
+      {
+        Cell varargout;
+
+        if (ret_list->takes_varargs ())
+          {
+            octave_value varargout_varval = fcn_scope.varval ("varargout");
+
+            if (varargout_varval.is_defined ())
+              varargout = varargout_varval.xcell_value ("varargout must be a cell array object");
+          }
+
+        retval = convert_return_list_to_const_vector (ret_list, nargout,
+                                                      varargout);
+      }
+
+    return retval;
+  }
+
   void
   tree_evaluator::visit_octave_user_function_header (octave_user_function&)
   {
@@ -1178,10 +1715,11 @@
       {
         tree_expression *expr = tic->condition ();
 
-        if (statement_context == function || statement_context == script)
+        if (m_statement_context == SC_FUNCTION
+            || m_statement_context == SC_SCRIPT)
           m_call_stack.set_location (tic->line (), tic->column ());
 
-        if (debug_mode && ! tic->is_else_clause ())
+        if (m_debug_mode && ! tic->is_else_clause ())
           do_breakpoint (tic->is_breakpoint (true));
 
         if (tic->is_else_clause () || is_logically_true (expr, "if"))
@@ -1196,50 +1734,6 @@
       }
   }
 
-  // Final step of processing an indexing error.  Add the name of the
-  // variable being indexed, if any, then issue an error.  (Will this also
-  // be needed by pt-lvalue, which calls subsref?)
-
-  static void
-  final_index_error (octave::index_exception& e,
-                     const octave::tree_expression *expr)
-  {
-    std::string extra_message;
-
-    // FIXME: make this a member function for direct access to symbol
-    // table and scope?
-
-    octave::symbol_scope scope
-      = octave::__require_current_scope__ ("final_index_error");
-
-    octave::symbol_record::context_id context = scope.current_context ();
-
-    if (expr->is_identifier ()
-        && dynamic_cast<const octave::tree_identifier *> (expr)->is_variable (context))
-      {
-        std::string var = expr->name ();
-
-        e.set_var (var);
-
-        octave::symbol_table& symtab =
-          octave::__get_symbol_table__ ("final_index_error");
-
-        octave_value fcn = symtab.find_function (var);
-
-        if (fcn.is_function ())
-          {
-            octave_function *fp = fcn.function_value ();
-
-            if (fp && fp->name () == var)
-              extra_message = " (note: variable '" + var + "' shadows function)";
-          }
-      }
-
-    std::string msg = e.message () + extra_message;
-
-    error_with_id (e.err_id (), msg.c_str ());
-  }
-
   // Unlike Matlab, which does not allow the result of a function call
   // or array indexing expression to be further indexed, Octave attempts
   // to handle arbitrary index expressions.  For example, Octave allows
@@ -1325,9 +1819,9 @@
 
     assert (! args.empty ());
 
-    std::list<tree_argument_list *>::iterator p_args = args.begin ();
-    std::list<string_vector>::iterator p_arg_nm = arg_nm.begin ();
-    std::list<tree_expression *>::iterator p_dyn_field = dyn_field.begin ();
+    auto p_args = args.begin ();
+    auto p_arg_nm = arg_nm.begin ();
+    auto p_dyn_field = dyn_field.begin ();
 
     int n = args.size ();
     int beg = 0;
@@ -1363,7 +1857,7 @@
                                   &value_stack<const std::list<octave_lvalue>*>::pop);
 
                 string_vector anm = *p_arg_nm;
-                first_args = al->convert_to_const_vector (this);
+                first_args = convert_to_const_vector (al);
                 first_args.stash_name_tags (anm);
               }
 
@@ -1506,7 +2000,7 @@
 
           case '.':
             idx.push_back (octave_value
-                           (idx_expr.get_struct_index (this, p_arg_nm, p_dyn_field)));
+                           (idx_expr.get_struct_index (*this, p_arg_nm, p_dyn_field)));
             break;
 
           default:
@@ -1534,7 +2028,7 @@
                 beg = n;
                 idx.clear ();
               }
-            catch (octave::index_exception& e)
+            catch (index_exception& e)
               {
                 final_index_error (e, expr);
               }
@@ -1553,7 +2047,7 @@
                   {
                     retval = fcn->call (*this, nargout, idx);
                   }
-                catch (octave::index_exception& e)
+                catch (index_exception& e)
                   {
                     final_index_error (e, expr);
                   }
@@ -1597,200 +2091,9 @@
   void
   tree_evaluator::visit_matrix (tree_matrix& expr)
   {
-    octave_value retval = Matrix ();
-
-    bool all_strings_p = false;
-    bool all_sq_strings_p = false;
-    bool all_dq_strings_p = false;
-    bool all_empty_p = false;
-    bool all_real_p = false;
-    bool any_sparse_p = false;
-    bool any_class_p = false;
-    bool frc_str_conv = false;
-
-    tm_const tmp (expr, this);
-
-    if (tmp && ! tmp.empty ())
-      {
-        dim_vector dv = tmp.dims ();
-        all_strings_p = tmp.all_strings_p ();
-        all_sq_strings_p = tmp.all_sq_strings_p ();
-        all_dq_strings_p = tmp.all_dq_strings_p ();
-        all_empty_p = tmp.all_empty_p ();
-        all_real_p = tmp.all_real_p ();
-        any_sparse_p = tmp.any_sparse_p ();
-        any_class_p = tmp.any_class_p ();
-        frc_str_conv = tmp.some_strings_p ();
-
-        // Try to speed up the common cases.
-
-        std::string result_type = tmp.class_name ();
-
-        if (any_class_p)
-          {
-            retval = do_class_concat (tmp);
-          }
-        else if (result_type == "double")
-          {
-            if (any_sparse_p)
-              {
-                if (all_real_p)
-                  retval = do_single_type_concat<SparseMatrix> (dv, tmp);
-                else
-                  retval = do_single_type_concat<SparseComplexMatrix> (dv, tmp);
-              }
-            else
-              {
-                if (all_real_p)
-                  retval = do_single_type_concat<NDArray> (dv, tmp);
-                else
-                  retval = do_single_type_concat<ComplexNDArray> (dv, tmp);
-              }
-          }
-        else if (result_type == "single")
-          {
-            if (all_real_p)
-              retval = do_single_type_concat<FloatNDArray> (dv, tmp);
-            else
-              retval = do_single_type_concat<FloatComplexNDArray> (dv, tmp);
-          }
-        else if (result_type == "char")
-          {
-            char type = (all_dq_strings_p ? '"' : '\'');
-
-            if (! all_strings_p)
-              warn_implicit_conversion ("Octave:num-to-str",
-                                        "numeric", result_type);
-            else
-              maybe_warn_string_concat (all_dq_strings_p, all_sq_strings_p);
-
-            charNDArray result (dv, m_string_fill_char);
-
-            single_type_concat<charNDArray> (result, tmp);
-
-            retval = octave_value (result, type);
-          }
-        else if (result_type == "logical")
-          {
-            if (any_sparse_p)
-              retval = do_single_type_concat<SparseBoolMatrix> (dv, tmp);
-            else
-              retval = do_single_type_concat<boolNDArray> (dv, tmp);
-          }
-        else if (result_type == "int8")
-          retval = do_single_type_concat<int8NDArray> (dv, tmp);
-        else if (result_type == "int16")
-          retval = do_single_type_concat<int16NDArray> (dv, tmp);
-        else if (result_type == "int32")
-          retval = do_single_type_concat<int32NDArray> (dv, tmp);
-        else if (result_type == "int64")
-          retval = do_single_type_concat<int64NDArray> (dv, tmp);
-        else if (result_type == "uint8")
-          retval = do_single_type_concat<uint8NDArray> (dv, tmp);
-        else if (result_type == "uint16")
-          retval = do_single_type_concat<uint16NDArray> (dv, tmp);
-        else if (result_type == "uint32")
-          retval = do_single_type_concat<uint32NDArray> (dv, tmp);
-        else if (result_type == "uint64")
-          retval = do_single_type_concat<uint64NDArray> (dv, tmp);
-        else if (result_type == "cell")
-          retval = do_single_type_concat<Cell> (dv, tmp);
-        else if (result_type == "struct")
-          retval = do_single_type_concat<octave_map> (dv, tmp);
-        else
-          {
-            // The line below might seem crazy, since we take a copy of
-            // the first argument, resize it to be empty and then resize
-            // it to be full.  This is done since it means that there is
-            // no recopying of data, as would happen if we used a single
-            // resize.  It should be noted that resize operation is also
-            // significantly slower than the do_cat_op function, so it
-            // makes sense to have an empty matrix and copy all data.
-            //
-            // We might also start with a empty octave_value using
-            //
-            //    ctmp = octave::type_info::lookup_type
-            //          (tmp.begin() -> begin() -> type_name());
-            //
-            // and then directly resize.  However, for some types there
-            // might be some additional setup needed, and so this should
-            // be avoided.
-
-            octave_value ctmp;
-
-            // Find the first non-empty object
-
-            if (any_sparse_p)
-              {
-                // Start with sparse matrix to avoid issues memory issues
-                // with things like [ones(1,4),sprandn(1e8,4,1e-4)]
-                if (all_real_p)
-                  ctmp = octave_sparse_matrix ().resize (dv);
-                else
-                  ctmp = octave_sparse_complex_matrix ().resize (dv);
-              }
-            else
-              {
-                for (tm_row_const& row : tmp)
-                  {
-                    octave_quit ();
-
-                    for (auto& elt : row)
-                      {
-                        octave_quit ();
-
-                        ctmp = elt;
-
-                        if (! ctmp.all_zero_dims ())
-                          goto found_non_empty;
-                      }
-                  }
-
-                ctmp = (*(tmp.begin () -> begin ()));
-
-              found_non_empty:
-
-                if (! all_empty_p)
-                  ctmp = ctmp.resize (dim_vector (0,0)).resize (dv);
-              }
-
-            // Now, extract the values from the individual elements and
-            // insert them in the result matrix.
-
-            type_info& ti = m_interpreter.get_type_info ();
-
-            int dv_len = dv.ndims ();
-            octave_idx_type ntmp = (dv_len > 1 ? dv_len : 2);
-            Array<octave_idx_type> ra_idx (dim_vector (ntmp, 1), 0);
-
-            for (tm_row_const& row : tmp)
-              {
-                octave_quit ();
-
-                for (auto& elt : row)
-                  {
-                    octave_quit ();
-
-                    if (elt.isempty ())
-                      continue;
-
-                    ctmp = do_cat_op (ti, ctmp, elt, ra_idx);
-
-                    ra_idx (1) += elt.columns ();
-                  }
-
-                ra_idx (0) += row.rows ();
-                ra_idx (1) = 0;
-              }
-
-            retval = ctmp;
-
-            if (frc_str_conv && ! retval.is_string ())
-              retval = retval.convert_to_str ();
-          }
-      }
-
-    push_result (retval);
+    tm_const tmp (expr, *this);
+
+    push_result (tmp.concat (m_string_fill_char));
   }
 
   void
@@ -1817,7 +2120,7 @@
 
     for (tree_argument_list *elt : expr)
       {
-        octave_value_list row = elt->convert_to_const_vector (this);
+        octave_value_list row = convert_to_const_vector (elt);
 
         if (nr == 1)
           // Optimize the single row case.
@@ -1895,7 +2198,7 @@
         // postpone joining the final values.
         std::list<octave_value_list> retval_list;
 
-        tree_argument_list::iterator q = lhs->begin ();
+        auto q = lhs->begin ();
 
         for (octave_lvalue ult : lvalue_list)
           {
@@ -2030,7 +2333,7 @@
         m_echo_file_pos = line + 1;
       }
 
-    if (debug_mode && cmd.is_end_of_fcn_or_script ())
+    if (m_debug_mode && cmd.is_end_of_fcn_or_script ())
       do_breakpoint (cmd.is_breakpoint (true), true);
   }
 
@@ -2106,7 +2409,7 @@
 
         if (etype == octave_value::op_incr || etype == octave_value::op_decr)
           {
-            octave_lvalue ref = op->lvalue (this);
+            octave_lvalue ref = op->lvalue (*this);
 
             val = ref.value ();
 
@@ -2146,7 +2449,7 @@
 
         if (etype == octave_value::op_incr || etype == octave_value::op_decr)
           {
-            octave_lvalue op_ref = op->lvalue (this);
+            octave_lvalue op_ref = op->lvalue (*this);
 
             profiler::enter<tree_prefix_expression> block (m_profiler, expr);
 
@@ -2190,20 +2493,21 @@
         m_echo_file_pos = line + 1;
       }
 
-    if (debug_mode)
+    if (m_debug_mode)
       do_breakpoint (cmd.is_breakpoint (true));
 
     // Act like dbcont.
 
-    if (Vdebugging && m_call_stack.current_frame () == current_frame)
+    if (Vdebugging && m_call_stack.current_frame () == m_current_frame)
       {
         Vdebugging = false;
 
         reset_debug_state ();
       }
-    else if (statement_context == function || statement_context == script
-             || in_loop_command)
-      tree_return_command::returning = 1;
+    else if (m_statement_context == SC_FUNCTION
+             || m_statement_context == SC_SCRIPT
+             || m_in_loop_command)
+      m_returning = 1;
   }
 
   void
@@ -2242,7 +2546,7 @@
           {
             unwind_protect frame;
 
-            octave_lvalue ult = lhs->lvalue (this);
+            octave_lvalue ult = lhs->lvalue (*this);
 
             std::list<octave_lvalue> lvalue_list;
             lvalue_list.push_back (ult);
@@ -2300,7 +2604,8 @@
 
     if (cmd || expr)
       {
-        if (statement_context == function || statement_context == script)
+        if (m_statement_context == SC_FUNCTION
+            || m_statement_context == SC_SCRIPT)
           {
             // Skip commands issued at a debug> prompt to avoid disturbing
             // the state of the program we are debugging.
@@ -2322,7 +2627,7 @@
                     m_echo_file_pos = line + 1;
                   }
 
-                if (debug_mode)
+                if (m_debug_mode)
                   do_breakpoint (expr->is_breakpoint (true));
 
                 // FIXME: maybe all of this should be packaged in
@@ -2371,12 +2676,12 @@
             error_with_id ("Octave:bad-alloc",
                            "out of memory or dimension too large for Octave's index type");
           }
-        catch (const octave::interrupt_exception&)
+        catch (const interrupt_exception&)
           {
             // If we are debugging, then continue with next statement.
             // Otherwise, jump out of here.
 
-            if (debug_mode)
+            if (m_debug_mode)
               interpreter::recover_from_exception ();
             else
               throw;
@@ -2390,7 +2695,7 @@
     // FIXME: commented out along with else clause below.
     // static octave_value_list empty_list;
 
-    tree_statement_list::iterator p = lst.begin ();
+    auto p = lst.begin ();
 
     if (p != lst.end ())
       {
@@ -2405,11 +2710,10 @@
 
             elt->accept (*this);
 
-            if (tree_break_command::breaking
-                || tree_continue_command::continuing)
+            if (m_breaking || m_continuing)
               break;
 
-            if (tree_return_command::returning)
+            if (m_returning)
               break;
 
             if (p == lst.end ())
@@ -2457,7 +2761,7 @@
         m_echo_file_pos = line + 1;
       }
 
-    if (debug_mode)
+    if (m_debug_mode)
       do_breakpoint (cmd.is_breakpoint (true));
 
     tree_expression *expr = cmd.switch_value ();
@@ -2546,7 +2850,7 @@
 
             if (expr_id)
               {
-                octave_lvalue ult = expr_id->lvalue (this);
+                octave_lvalue ult = expr_id->lvalue (*this);
 
                 octave_scalar_map err;
 
@@ -2585,11 +2889,11 @@
     // We don't have to worry about continue statements because they can
     // only occur in loops.
 
-    frame.protect_var (tree_return_command::returning);
-    tree_return_command::returning = 0;
-
-    frame.protect_var (tree_break_command::breaking);
-    tree_break_command::breaking = 0;
+    frame.protect_var (m_returning);
+    m_returning = 0;
+
+    frame.protect_var (m_breaking);
+    m_breaking = 0;
 
     try
       {
@@ -2600,7 +2904,7 @@
       {
         interpreter::recover_from_exception ();
 
-        if (tree_break_command::breaking || tree_return_command::returning)
+        if (m_breaking || m_returning)
           frame.discard (2);
         else
           frame.run (2);
@@ -2637,7 +2941,7 @@
     // break in the cleanup block, the values should be reset to
     // whatever they were when the cleanup block was entered.
 
-    if (tree_break_command::breaking || tree_return_command::returning)
+    if (m_breaking || m_returning)
       frame.discard (2);
     else
       frame.run (2);
@@ -2711,9 +3015,9 @@
 
     unwind_protect frame;
 
-    frame.protect_var (in_loop_command);
-
-    in_loop_command = true;
+    frame.protect_var (m_in_loop_command);
+
+    m_in_loop_command = true;
 
     tree_expression *expr = cmd.condition ();
 
@@ -2725,7 +3029,7 @@
         if (m_echo_state)
           m_echo_file_pos = line;
 
-        if (debug_mode)
+        if (m_debug_mode)
           do_breakpoint (cmd.is_breakpoint (true));
 
         if (is_logically_true (expr, "while"))
@@ -2761,9 +3065,9 @@
 
     unwind_protect frame;
 
-    frame.protect_var (in_loop_command);
-
-    in_loop_command = true;
+    frame.protect_var (m_in_loop_command);
+
+    m_in_loop_command = true;
 
     tree_expression *expr = cmd.condition ();
     int until_line = cmd.line ();
@@ -2785,7 +3089,7 @@
         if (quit_loop_now ())
           break;
 
-        if (debug_mode)
+        if (m_debug_mode)
           do_breakpoint (cmd.is_breakpoint (true));
 
         m_call_stack.set_location (until_line, until_column);
@@ -2825,38 +3129,30 @@
   }
 
   void
-  tree_evaluator::do_breakpoint (tree_statement& stmt) const
+  tree_evaluator::do_breakpoint (tree_statement& stmt)
   {
     do_breakpoint (stmt.is_breakpoint (true), stmt.is_end_of_fcn_or_script ());
   }
 
   void
   tree_evaluator::do_breakpoint (bool is_breakpoint,
-                                 bool is_end_of_fcn_or_script) const
+                                 bool is_end_of_fcn_or_script)
   {
     bool break_on_this_statement = false;
 
-    if (octave_debug_on_interrupt_state)
+    if (is_breakpoint)
       {
         break_on_this_statement = true;
 
-        octave_debug_on_interrupt_state = false;
-
-        current_frame = m_call_stack.current_frame ();
+        m_dbstep_flag = 0;
+
+        m_current_frame = m_call_stack.current_frame ();
       }
-    else if (is_breakpoint)
+    else if (m_dbstep_flag > 0)
       {
-        break_on_this_statement = true;
-
-        dbstep_flag = 0;
-
-        current_frame = m_call_stack.current_frame ();
-      }
-    else if (dbstep_flag > 0)
-      {
-        if (m_call_stack.current_frame () == current_frame)
+        if (m_call_stack.current_frame () == m_current_frame)
           {
-            if (dbstep_flag == 1 || is_end_of_fcn_or_script)
+            if (m_dbstep_flag == 1 || is_end_of_fcn_or_script)
               {
                 // We get here if we are doing a "dbstep" or a "dbstep N" and the
                 // count has reached 1 so that we must stop and return to debug
@@ -2866,39 +3162,39 @@
 
                 break_on_this_statement = true;
 
-                dbstep_flag = 0;
+                m_dbstep_flag = 0;
               }
             else
               {
                 // Executing "dbstep N".  Decrease N by one and continue.
 
-                dbstep_flag--;
+                m_dbstep_flag--;
               }
 
           }
-        else if (dbstep_flag == 1
-                 && m_call_stack.current_frame () < current_frame)
+        else if (m_dbstep_flag == 1
+                 && m_call_stack.current_frame () < m_current_frame)
           {
             // We stepped out from the end of a function.
 
-            current_frame = m_call_stack.current_frame ();
+            m_current_frame = m_call_stack.current_frame ();
 
             break_on_this_statement = true;
 
-            dbstep_flag = 0;
+            m_dbstep_flag = 0;
           }
       }
-    else if (dbstep_flag == -1)
+    else if (m_dbstep_flag == -1)
       {
         // We get here if we are doing a "dbstep in".
 
         break_on_this_statement = true;
 
-        dbstep_flag = 0;
-
-        current_frame = m_call_stack.current_frame ();
+        m_dbstep_flag = 0;
+
+        m_current_frame = m_call_stack.current_frame ();
       }
-    else if (dbstep_flag == -2)
+    else if (m_dbstep_flag == -2)
       {
         // We get here if we are doing a "dbstep out".  Check for end of
         // function and whether the current frame is the same as the
@@ -2907,13 +3203,16 @@
         // that frame.
 
         if (is_end_of_fcn_or_script
-            && m_call_stack.current_frame () == current_frame)
-          dbstep_flag = -1;
+            && m_call_stack.current_frame () == m_current_frame)
+          m_dbstep_flag = -1;
       }
 
     if (break_on_this_statement)
-      do_keyboard ();
-
+      {
+        input_system& input_sys = m_interpreter.get_input_system ();
+
+        input_sys.keyboard ();
+      }
   }
 
   // ARGS is currently unused, but since the do_keyboard function in
@@ -2923,7 +3222,9 @@
   octave_value
   tree_evaluator::do_keyboard (const octave_value_list& args) const
   {
-    return ::do_keyboard (args);
+    input_system& input_sys = m_interpreter.get_input_system ();
+
+    return input_sys.keyboard (args);
   }
 
   bool
@@ -2965,7 +3266,7 @@
             && object->is_undefined ())
           err_invalid_inquiry_subscript ();
 
-        retval = args->convert_to_const_vector (this, object);
+        retval = convert_to_const_vector (args, object);
       }
 
     octave_idx_type n = retval.length ();
@@ -2982,7 +3283,7 @@
     std::list<octave_lvalue> retval;
 
     for (tree_expression *elt : *lhs)
-      retval.push_back (elt->lvalue (this));
+      retval.push_back (elt->lvalue (*this));
 
     return retval;
   }
@@ -3029,6 +3330,15 @@
   }
 
   void
+  tree_evaluator::uwp_set_echo_state (bool state, const std::string& file_name,
+                                      size_t pos)
+  {
+    m_echo_state = state;
+    m_echo_file_name = file_name;
+    m_echo_file_pos = pos;
+  }
+
+  void
   tree_evaluator::maybe_set_echo_state (void)
   {
     octave_function *caller = m_call_stack.caller ();
@@ -3050,36 +3360,23 @@
   void
   tree_evaluator::push_echo_state_cleanup (unwind_protect& frame)
   {
-    frame.add_method (*this, &tree_evaluator::set_echo_state,
-                      m_echo_state);
-
-    frame.add_method (*this, &tree_evaluator::set_echo_file_name,
-                      m_echo_file_name);
-
-    frame.add_method (*this, &tree_evaluator::set_echo_file_pos,
-                      m_echo_file_pos);
+    frame.add_method (this, &tree_evaluator::uwp_set_echo_state,
+                      m_echo_state, m_echo_file_name, m_echo_file_pos);
   }
 
   bool tree_evaluator::maybe_push_echo_state_cleanup (void)
   {
     // This function is expected to be called from ECHO, which would be
     // the top of the call stack.  If the caller of ECHO is a
-    // user-defined fucntion or script, then set up unwind-protect
+    // user-defined function or script, then set up unwind-protect
     // elements to restore echo state.
 
-    octave_function *caller = m_call_stack.caller ();
-
-    if (caller && caller->is_user_code ())
+    unwind_protect *frame = m_call_stack.curr_fcn_unwind_protect_frame ();
+
+    if (frame)
       {
-        octave_user_code *fcn = dynamic_cast<octave_user_code *> (caller);
-
-        unwind_protect *frame = fcn->unwind_protect_frame ();
-
-        if (frame)
-          {
-            push_echo_state_cleanup (*frame);
-            return true;
-          }
+        push_echo_state_cleanup (*frame);
+        return true;
       }
 
     return false;
@@ -3272,6 +3569,63 @@
           octave_stdout << prefix << elt << std::endl;
       }
   }
+
+  // Final step of processing an indexing error.  Add the name of the
+  // variable being indexed, if any, then issue an error.  (Will this also
+  // be needed by pt-lvalue, which calls subsref?)
+
+  void tree_evaluator::final_index_error (index_exception& e,
+                                          const tree_expression *expr)
+  {
+    std::string extra_message;
+
+    symbol_scope scope = get_current_scope ();
+
+    symbol_record::context_id ctxt = scope.current_context ();
+
+    if (expr->is_identifier ()
+        && dynamic_cast<const tree_identifier *> (expr)->is_variable (ctxt))
+      {
+        std::string var = expr->name ();
+
+        e.set_var (var);
+
+        symbol_table& symtab = m_interpreter.get_symbol_table ();
+
+        octave_value fcn = symtab.find_function (var);
+
+        if (fcn.is_function ())
+          {
+            octave_function *fp = fcn.function_value ();
+
+            if (fp && fp->name () == var)
+              extra_message
+                = " (note: variable '" + var + "' shadows function)";
+          }
+      }
+
+    std::string msg = e.message () + extra_message;
+
+    error_with_id (e.err_id (), msg.c_str ());
+  }
+
+  // Decide if it's time to quit a for or while loop.
+  bool tree_evaluator::quit_loop_now (void)
+  {
+    octave_quit ();
+
+    // Maybe handle 'continue N' someday...
+
+    if (m_continuing)
+      m_continuing--;
+
+    bool quit = (m_returning || m_breaking || m_continuing);
+
+    if (m_breaking)
+      m_breaking--;
+
+    return quit;
+  }
 }
 
 DEFMETHOD (max_recursion_depth, interp, args, nargout,
--- a/libinterp/parse-tree/pt-eval.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/parse-tree/pt-eval.h	Fri Aug 10 09:09:51 2018 +0200
@@ -30,6 +30,7 @@
 #include <stack>
 #include <string>
 
+#include "bp-table.h"
 #include "call-stack.h"
 #include "ov.h"
 #include "ovl.h"
@@ -37,6 +38,8 @@
 #include "pt-exp.h"
 #include "pt-walk.h"
 
+class octave_user_code;
+
 namespace octave
 {
   class symbol_scope;
@@ -123,14 +126,18 @@
     typedef void (*decl_elt_init_fcn) (tree_decl_elt&);
 
     tree_evaluator (interpreter& interp)
-      : m_interpreter (interp), m_result_type (RT_UNDEFINED),
-        m_expr_result_value (), m_expr_result_value_list (),
-        m_lvalue_list_stack (), m_nargout_stack (),
-        m_call_stack (interp), m_profiler (),
-        m_max_recursion_depth (256), m_silent_functions (false),
-        m_string_fill_char (' '), m_PS4 ("+ "), m_echo (ECHO_OFF),
+      : m_interpreter (interp), m_statement_context (SC_OTHER),
+        m_result_type (RT_UNDEFINED), m_expr_result_value (),
+        m_expr_result_value_list (), m_lvalue_list_stack (),
+        m_nargout_stack (), m_bp_table (*this), m_call_stack (interp),
+        m_profiler (), m_current_frame (0), m_debug_mode (false),
+        m_quiet_breakpoint_flag (false), m_max_recursion_depth (256),
+        m_silent_functions (false), m_string_fill_char (' '),
+        m_PS4 ("+ "), m_dbstep_flag (0), m_echo (ECHO_OFF),
         m_echo_state (false), m_echo_file_name (), m_echo_file_pos (1),
-        m_echo_files ()
+        m_echo_files (), m_in_loop_command (false),
+        m_breaking (0), m_continuing (0), m_returning (0),
+        m_indexed_object (nullptr), m_index_position (0), m_num_indices (0)
     { }
 
     // No copying!
@@ -143,6 +150,8 @@
 
     void reset (void);
 
+    int repl (bool interactive);
+
     void visit_anon_fcn_handle (tree_anon_fcn_handle&);
 
     void visit_argument_list (tree_argument_list&);
@@ -171,8 +180,16 @@
 
     void visit_octave_user_script (octave_user_script&);
 
+    octave_value_list
+    execute_user_script (octave_user_script& user_script, int nargout,
+                         const octave_value_list& args);
+
     void visit_octave_user_function (octave_user_function&);
 
+    octave_value_list
+    execute_user_function (octave_user_function& user_function, int nargout,
+                           const octave_value_list& args);
+
     void visit_octave_user_function_header (octave_user_function&);
 
     void visit_octave_user_function_trailer (octave_user_function&);
@@ -238,35 +255,20 @@
 
     bool statement_printing_enabled (void);
 
-    static void reset_debug_state (void);
+    void reset_debug_state (void);
 
-    // If > 0, stop executing at the (N-1)th stopping point, counting
-    //         from the the current execution point in the current frame.
-    //
-    // If < 0, stop executing at the next possible stopping point.
-    static int dbstep_flag;
+    void reset_debug_state (bool mode);
 
-    // The number of the stack frame we are currently debugging.
-    static size_t current_frame;
-
-    static bool debug_mode;
-
-    static bool quiet_breakpoint_flag;
+    void set_dbstep_flag (int step) { m_dbstep_flag = step; }
 
     // Possible types of evaluation contexts.
     enum stmt_list_type
     {
-      function,  // function body
-      script,    // script file
-      other      // command-line input or eval string
+      SC_FUNCTION,  // function body
+      SC_SCRIPT,    // script file
+      SC_OTHER      // command-line input or eval string
     };
 
-    // The context for the current evaluation.
-    static stmt_list_type statement_context;
-
-    // TRUE means we are evaluating some kind of looping construct.
-    static bool in_loop_command;
-
     Matrix ignored_fcn_outputs (void) const;
 
     bool isargout (int nargout, int iout) const;
@@ -360,6 +362,10 @@
     void undefine_parameter_list (tree_parameter_list *param_list);
 
     octave_value_list
+    convert_to_const_vector (tree_argument_list *arg_list,
+                             const octave_value *object = nullptr);
+
+    octave_value_list
     convert_return_list_to_const_vector
       (tree_parameter_list *ret_list, int nargout, const Cell& varargout);
 
@@ -368,12 +374,18 @@
     bool switch_case_label_matches (tree_switch_case *expr,
                                     const octave_value& val);
 
+    interpreter& get_interpreter (void) { return m_interpreter; }
+
+    bp_table& get_bp_table (void) { return m_bp_table; }
+
     call_stack& get_call_stack (void) { return m_call_stack; }
 
     profiler& get_profiler (void) { return m_profiler; }
 
     symbol_scope get_current_scope (void);
 
+    octave_user_code * get_user_code (const std::string& fname = "");
+
     int max_recursion_depth (void) const { return m_max_recursion_depth; }
 
     int max_recursion_depth (int n)
@@ -398,6 +410,33 @@
     octave_value
     silent_functions (const octave_value_list& args, int nargout);
 
+    size_t current_frame (void) const { return m_current_frame; }
+
+    size_t current_frame (size_t n)
+    {
+      size_t val = m_current_frame;
+      m_current_frame = n;
+      return val;
+    }
+
+    bool debug_mode (void) const { return m_debug_mode; }
+
+    bool debug_mode (bool flag)
+    {
+      bool val = m_debug_mode;
+      m_debug_mode = flag;
+      return val;
+    }
+
+    bool quiet_breakpoint_flag (void) const { return m_quiet_breakpoint_flag; }
+
+    bool quiet_breakpoint_flag (bool flag)
+    {
+      bool val = m_quiet_breakpoint_flag;
+      m_quiet_breakpoint_flag = flag;
+      return val;
+    }
+
     char string_fill_char (void) const { return m_string_fill_char; }
 
     char string_fill_char (char c)
@@ -418,6 +457,42 @@
       return val;
     }
 
+    const octave_value * indexed_object (void) const
+    {
+      return m_indexed_object;
+    }
+
+    int index_position (void) const { return m_index_position; }
+
+    int num_indices (void) const { return m_num_indices; }
+
+    int breaking (void) const { return m_breaking; }
+
+    int breaking (int n)
+    {
+      int val = m_breaking;
+      m_breaking = n;
+      return val;
+    }
+
+    int continuing (void) const { return m_continuing; }
+
+    int continuing (int n)
+    {
+      int val = m_continuing;
+      m_continuing = n;
+      return val;
+    }
+
+    int returning (void) const { return m_returning; }
+
+    int returning (int n)
+    {
+      int val = m_returning;
+      m_returning = n;
+      return val;
+    }
+
     octave_value echo (const octave_value_list& args, int nargout);
 
     int echo (void) const { return m_echo; }
@@ -445,10 +520,10 @@
 
     bool maybe_push_echo_state_cleanup (void);
 
-    void do_breakpoint (tree_statement& stmt) const;
+    void do_breakpoint (tree_statement& stmt);
 
     void do_breakpoint (bool is_breakpoint,
-                        bool is_end_of_fcn_or_script = false) const;
+                        bool is_end_of_fcn_or_script = false);
 
     virtual octave_value
     do_keyboard (const octave_value_list& args = octave_value_list ()) const;
@@ -463,26 +538,22 @@
     std::list<octave_lvalue> make_lvalue_list (tree_argument_list *);
 
     // For unwind-protect.
-    void set_echo_state (bool val) { m_echo_state = val; }
-
-    // For unwind-protect.
-    void set_echo_file_name (const std::string& file_name)
-    {
-      m_echo_file_name = file_name;
-    }
-
-    // For unwind-protect.
-    void set_echo_file_pos (const size_t& file_pos)
-    {
-      m_echo_file_pos = file_pos;
-    }
+    void uwp_set_echo_state (bool state, const std::string& file_name,
+                             size_t pos);
 
     bool echo_this_file (const std::string& file, int type) const;
 
     void echo_code (size_t line);
 
+    void final_index_error (index_exception& e, const tree_expression *expr);
+
+    bool quit_loop_now (void);
+
     interpreter& m_interpreter;
 
+    // The context for the current evaluation.
+    stmt_list_type m_statement_context;
+
     result_type m_result_type;
     octave_value m_expr_result_value;
     octave_value_list m_expr_result_value_list;
@@ -491,10 +562,19 @@
 
     value_stack<int> m_nargout_stack;
 
+    bp_table m_bp_table;
+
     call_stack m_call_stack;
 
     profiler m_profiler;
 
+    // The number of the stack frame we are currently debugging.
+    size_t m_current_frame;
+
+    bool m_debug_mode;
+
+    bool m_quiet_breakpoint_flag;
+
     // Maximum nesting level for functions, scripts, or sourced files
     // called recursively.
     int m_max_recursion_depth;
@@ -509,6 +589,12 @@
     // String printed before echoed commands (enabled by --echo-commands).
     std::string m_PS4;
 
+    // If > 0, stop executing at the (N-1)th stopping point, counting
+    //         from the the current execution point in the current frame.
+    //
+    // If < 0, stop executing at the next possible stopping point.
+    int m_dbstep_flag;
+
     // Echo commands as they are executed?
     //
     //   1  ==>  echo commands read from script files
@@ -527,6 +613,23 @@
     size_t m_echo_file_pos;
 
     std::map<std::string, bool> m_echo_files;
+
+    // TRUE means we are evaluating some kind of looping construct.
+    bool m_in_loop_command;
+
+    // Nonzero means we're breaking out of a loop or function body.
+    int m_breaking;
+
+    // Nonzero means we're jumping to the end of a loop.
+    int m_continuing;
+
+    // Nonzero means we're returning from a function.
+    int m_returning;
+
+    // Used by END function.
+    const octave_value *m_indexed_object;
+    int m_index_position;
+    int m_num_indices;
   };
 }
 
--- a/libinterp/parse-tree/pt-exp.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/parse-tree/pt-exp.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -24,7 +24,6 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
 #include <string>
 
 #include "error.h"
@@ -38,7 +37,7 @@
   // Expressions.
 
   octave_lvalue
-  tree_expression::lvalue (tree_evaluator *)
+  tree_expression::lvalue (tree_evaluator&)
   {
     error ("invalid lvalue function called in expression");
   }
--- a/libinterp/parse-tree/pt-exp.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/parse-tree/pt-exp.h	Fri Aug 10 09:09:51 2018 +0200
@@ -84,7 +84,7 @@
 
     virtual bool rvalue_ok (void) const { return false; }
 
-    virtual octave_lvalue lvalue (tree_evaluator *);
+    virtual octave_lvalue lvalue (tree_evaluator&);
 
     int paren_count (void) const { return num_parens; }
 
--- a/libinterp/parse-tree/pt-fcn-handle.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/parse-tree/pt-fcn-handle.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -24,7 +24,7 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <ostream>
 
 #include "interpreter-private.h"
 #include "pt-fcn-handle.h"
--- a/libinterp/parse-tree/pt-id.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/parse-tree/pt-id.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -65,12 +65,12 @@
   }
 
   octave_lvalue
-  tree_identifier::lvalue (tree_evaluator *tw)
+  tree_identifier::lvalue (tree_evaluator& tw)
   {
     if (m_sym.is_added_static ())
       static_workspace_error ();
 
-    symbol_scope scope = tw->get_current_scope ();
+    symbol_scope scope = tw.get_current_scope ();
 
     return octave_lvalue (m_sym, scope.current_context ());
   }
--- a/libinterp/parse-tree/pt-id.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/parse-tree/pt-id.h	Fri Aug 10 09:09:51 2018 +0200
@@ -117,7 +117,7 @@
 
     bool lvalue_ok (void) const { return true; }
 
-    octave_lvalue lvalue (tree_evaluator *);
+    octave_lvalue lvalue (tree_evaluator&);
 
     void eval_undefined_error (void);
 
@@ -160,7 +160,7 @@
       return new tree_black_hole;
     }
 
-    octave_lvalue lvalue (tree_evaluator *)
+    octave_lvalue lvalue (tree_evaluator&)
     {
       octave_lvalue retval;
       retval.mark_black_hole ();
--- a/libinterp/parse-tree/pt-idx.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/parse-tree/pt-idx.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -110,14 +110,14 @@
 
     while (! m_args.empty ())
       {
-        std::list<tree_argument_list *>::iterator p = m_args.begin ();
+        auto p = m_args.begin ();
         delete *p;
         m_args.erase (p);
       }
 
     while (! m_dyn_field.empty ())
       {
-        std::list<tree_expression *>::iterator p = m_dyn_field.begin ();
+        auto p = m_dyn_field.begin ();
         delete *p;
         m_dyn_field.erase (p);
       }
@@ -145,8 +145,8 @@
   }
 
   static inline octave_value_list
-  make_value_list (octave::tree_evaluator *tw,
-                   octave::tree_argument_list *m_args,
+  make_value_list (tree_evaluator& tw,
+                   tree_argument_list *m_args,
                    const string_vector& m_arg_nm, const octave_value *object,
                    bool rvalue = true)
   {
@@ -158,7 +158,7 @@
             && object->is_undefined ())
           err_invalid_inquiry_subscript ();
 
-        retval = m_args->convert_to_const_vector (tw, object);
+        retval = tw.convert_to_const_vector (m_args, object);
       }
 
     octave_idx_type n = retval.length ();
@@ -171,7 +171,7 @@
 
   std::string
   tree_index_expression::get_struct_index
-  (tree_evaluator *tw,
+  (tree_evaluator& tw,
    std::list<string_vector>::const_iterator p_arg_nm,
    std::list<tree_expression *>::const_iterator p_dyn_field) const
   {
@@ -183,7 +183,7 @@
 
         if (df)
           {
-            octave_value t = tw->evaluate (df);
+            octave_value t = tw.evaluate (df);
 
             fn = t.xstring_value ("dynamic structure field names must be strings");
           }
@@ -199,18 +199,16 @@
   // be needed by pt-lvalue, which calls subsref?)
 
   static void
-  final_index_error (octave::index_exception& e,
-                     const octave::tree_expression *expr)
+  final_index_error (index_exception& e, const tree_expression *expr)
   {
     std::string extra_message;
 
-    octave::symbol_table& symtab
-      = octave::__get_symbol_table__ ("final_index_error");
+    symbol_table& symtab = __get_symbol_table__ ("final_index_error");
 
-    octave::symbol_record::context_id context = symtab.current_context ();
+    symbol_record::context_id context = symtab.current_context ();
 
     if (expr->is_identifier ()
-        && dynamic_cast<const octave::tree_identifier *> (expr)->is_variable (context))
+        && dynamic_cast<const tree_identifier *> (expr)->is_variable (context))
       {
         std::string var = expr->name ();
 
@@ -233,7 +231,7 @@
   }
 
   octave_lvalue
-  tree_index_expression::lvalue (tree_evaluator *tw)
+  tree_index_expression::lvalue (tree_evaluator& tw)
   {
     octave_lvalue retval;
 
@@ -242,9 +240,9 @@
 
     int n = m_args.size ();
 
-    std::list<tree_argument_list *>::iterator p_args = m_args.begin ();
-    std::list<string_vector>::iterator p_arg_nm = m_arg_nm.begin ();
-    std::list<tree_expression *>::iterator p_dyn_field = m_dyn_field.begin ();
+    auto p_args = m_args.begin ();
+    auto p_arg_nm = m_arg_nm.begin ();
+    auto p_dyn_field = m_dyn_field.begin ();
 
     retval = m_expr->lvalue (tw);
 
--- a/libinterp/parse-tree/pt-idx.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/parse-tree/pt-idx.h	Fri Aug 10 09:09:51 2018 +0200
@@ -93,7 +93,7 @@
 
     bool rvalue_ok (void) const { return true; }
 
-    octave_lvalue lvalue (tree_evaluator *tw);
+    octave_lvalue lvalue (tree_evaluator& tw);
 
     tree_index_expression * dup (symbol_scope& scope) const;
 
@@ -104,7 +104,7 @@
 
     std::string
     get_struct_index
-    (tree_evaluator *tw, std::list<string_vector>::const_iterator p_arg_nm,
+    (tree_evaluator& tw, std::list<string_vector>::const_iterator p_arg_nm,
      std::list<tree_expression *>::const_iterator p_dyn_field) const;
 
   private:
--- a/libinterp/parse-tree/pt-jit.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/parse-tree/pt-jit.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -29,9 +29,8 @@
 #  include "config.h"
 #endif
 
+#include <sstream>
 #include <string>
-#include <sstream>
-#include <iostream>
 
 #include "bp-table.h"
 #include "defun.h"
@@ -156,8 +155,7 @@
     m_block->append (m_factory.create<jit_branch> (m_final_block));
     m_blocks.push_back (m_final_block);
 
-    for (variable_map::iterator iter = m_vmap.begin (); iter != m_vmap.end ();
-         ++iter)
+    for (auto iter = m_vmap.begin (); iter != m_vmap.end (); ++iter)
       {
         jit_variable *var = iter->second;
         const std::string& name = var->name ();
@@ -184,7 +182,7 @@
 
     if (plist)
       {
-        tree_parameter_list::iterator piter = plist->begin ();
+        auto piter = plist->begin ();
         for (size_t i = 0; i < args.size (); ++i, ++piter)
           {
             if (piter == plist->end ())
@@ -250,7 +248,7 @@
 
     // FIXME: We should use live range analysis to delete variables where
     // needed.  For now we just delete everything at the end of the function.
-    for (variable_map::iterator iter = m_vmap.begin ();
+    for (auto iter = m_vmap.begin ();
          iter != m_vmap.end ();
          ++iter)
       {
@@ -575,7 +573,7 @@
     entry_blocks[0] = m_block;
 
     // Need to construct blocks first, because they have jumps to each other.
-    tree_if_command_list::iterator iter = lst.begin ();
+    auto iter = lst.begin ();
     ++iter;
     for (size_t i = 1; iter != lst.end (); ++iter, ++i)
       {
@@ -800,7 +798,7 @@
       visit (cmd);
     else
       {
-        // stolen from octave::tree_evaluator::visit_statement
+        // stolen from tree_evaluator::visit_statement
         bool do_bind_ans = false;
 
         if (expr->is_identifier ())
@@ -832,8 +830,7 @@
   void
   jit_convert::visit_statement_list (tree_statement_list& lst)
   {
-    for (tree_statement_list::iterator iter = lst.begin (); iter != lst.end();
-         ++iter)
+    for (auto iter = lst.begin (); iter != lst.end(); ++iter)
       {
         tree_statement *elt = *iter;
         // jwe: Can this ever be null?
@@ -899,7 +896,7 @@
 
     size_t num_incoming = 0; // number of incoming blocks to our tail
 
-    tree_switch_case_list::iterator iter = lst->begin ();
+    auto iter = lst->begin ();
     for (size_t i = 0; i < case_blocks_num; ++iter, ++i)
       {
         tree_switch_case *twc = *iter;
@@ -1234,7 +1231,7 @@
       object = visit (tree_object);
 
     size_t narg = arg_list->size ();
-    tree_argument_list::iterator iter = arg_list->begin ();
+    auto iter = arg_list->begin ();
     bool have_extra = extra_arg;
     std::vector<jit_value *> call_args (narg + 1 + have_extra);
     call_args[0] = object;
@@ -1315,8 +1312,7 @@
   void
   jit_convert::finish_breaks (jit_block *dest, const block_list& lst)
   {
-    for (block_list::const_iterator iter = lst.begin (); iter != lst.end ();
-         ++iter)
+    for (auto iter = lst.begin (); iter != lst.end (); ++iter)
       {
         jit_block *b = *iter;
         b->append (m_factory.create<jit_branch> (dest));
@@ -1335,9 +1331,8 @@
     // for now just init arguments from entry, later we will have to do
     // something more interesting
     jit_block *m_entry_block = blocks.front ();
-    for (jit_block::iterator iter = m_entry_block->begin ();
-         iter != m_entry_block->end ();
-         ++iter)
+    for (auto iter = m_entry_block->begin ();
+         iter != m_entry_block->end (); ++iter)
       if (jit_extract_argument *extract
           = dynamic_cast<jit_extract_argument *> (*iter))
         m_argument_vec.push_back (std::make_pair (extract->name (), true));
@@ -1406,8 +1401,8 @@
         tree_parameter_list *plist = fcn.parameter_list ();
         if (plist)
           {
-            tree_parameter_list::iterator piter = plist->begin ();
-            tree_parameter_list::iterator pend = plist->end ();
+            auto piter = plist->begin ();
+            auto pend = plist->end ();
             for (size_t i = 0; i < args.size () && piter != pend; ++i, ++piter)
               {
                 tree_decl_elt *elt = *piter;
@@ -1445,8 +1440,7 @@
     builder.CreateBr (first->to_llvm ());
 
     // constants aren't in the IR, we visit those first
-    for (std::list<jit_value *>::const_iterator iter = constants.begin ();
-         iter != constants.end (); ++iter)
+    for (auto iter = constants.begin (); iter != constants.end (); ++iter)
       if (! isa<jit_instruction> (*iter))
         visit (*iter);
 
@@ -1458,7 +1452,7 @@
     for (biter = blocks.begin (); biter != blocks.end (); ++biter)
       {
         jit_block& m_block = **biter;
-        for (jit_block::iterator piter = m_block.begin ();
+        for (auto piter = m_block.begin ();
              piter != m_block.end () && isa<jit_phi> (*piter); ++piter)
           {
             jit_instruction *phi = *piter;
@@ -1536,7 +1530,7 @@
   {
     llvm::BasicBlock *m_block = b.to_llvm ();
     builder.SetInsertPoint (m_block);
-    for (jit_block::iterator iter = b.begin (); iter != b.end (); ++iter)
+    for (auto iter = b.begin (); iter != b.end (); ++iter)
       visit (*iter);
   }
 
@@ -1695,8 +1689,7 @@
 
     // initialize the worklist to instructions derived from constants
     const std::list<jit_value *>& constants = m_factory.constants ();
-    for (std::list<jit_value *>::const_iterator iter = constants.begin ();
-         iter != constants.end (); ++iter)
+    for (auto iter = constants.begin (); iter != constants.end (); ++iter)
       append_users (*iter);
 
     // the entry block terminator may be a regular branch statement
@@ -1741,7 +1734,7 @@
         if (term->alive (i))
           {
             jit_block *succ = term->successor (i);
-            for (jit_block::iterator iter = succ->begin ();
+            for (auto iter = succ->begin ();
                  iter != succ->end () && isa<jit_phi> (*iter); ++iter)
               push_worklist (*iter);
 
@@ -1761,9 +1754,7 @@
     entry_block ().create_dom_tree ();
 
     // insert phi nodes where needed, this is done on a per variable basis
-    for (variable_map::const_iterator iter = m_vmap.begin ();
-         iter != m_vmap.end ();
-         ++iter)
+    for (auto iter = m_vmap.cbegin (); iter != m_vmap.cend (); ++iter)
       {
         jit_block::df_set visited, added_phi;
         std::list<jit_block *> ssa_worklist;
@@ -1776,8 +1767,7 @@
             jit_block *b = ssa_worklist.front ();
             ssa_worklist.pop_front ();
 
-            for (jit_block::df_iterator diter = b->df_begin ();
-                 diter != b->df_end (); ++diter)
+            for (auto diter = b->df_begin (); diter != b->df_end (); ++diter)
               {
                 jit_block *dblock = *diter;
                 if (! added_phi.count (dblock))
@@ -1807,9 +1797,7 @@
       return;
 
     // replace variables with their current SSA value
-    for (jit_block::iterator iter = ablock.begin ();
-         iter != ablock.end ();
-         ++iter)
+    for (auto iter = ablock.begin (); iter != ablock.end (); ++iter)
       {
         jit_instruction *instr = *iter;
         instr->construct_ssa ();
@@ -1821,7 +1809,7 @@
       {
         jit_block *finish = ablock.successor (i);
 
-        for (jit_block::iterator iter = finish->begin ();
+        for (auto  iter = finish->begin ();
              iter != finish->end () && isa<jit_phi> (*iter);)
           {
             jit_phi *phi = static_cast<jit_phi *> (*iter);
@@ -1851,9 +1839,7 @@
   jit_infer::place_releases (void)
   {
     std::set<jit_value *> temporaries;
-    for (jit_block_list::iterator iter = m_blocks.begin ();
-         iter != m_blocks.end ();
-         ++iter)
+    for (auto iter = m_blocks.begin (); iter != m_blocks.end (); ++iter)
       {
         jit_block& ablock = **iter;
         if (ablock.id () != jit_block::NO_ID)
@@ -1883,7 +1869,7 @@
         jit_block *b = *biter;
         if (b->alive ())
           {
-            for (jit_block::iterator iter = b->begin ();
+            for (auto iter = b->begin ();
                  iter != b->end () && isa<jit_phi> (*iter);)
               {
                 jit_phi *phi = static_cast<jit_phi *> (*iter);
@@ -1927,7 +1913,7 @@
   void
   jit_infer::release_dead_phi (jit_block& ablock)
   {
-    jit_block::iterator iter = ablock.begin ();
+    auto iter = ablock.begin ();
     while (iter != ablock.end () && isa<jit_phi> (*iter))
       {
         jit_phi *phi = static_cast<jit_phi *> (*iter);
@@ -1963,9 +1949,7 @@
   void
   jit_infer::release_temp (jit_block& ablock, std::set<jit_value *>& temp)
   {
-    for (jit_block::iterator iter = ablock.begin ();
-         iter != ablock.end ();
-         ++iter)
+    for (auto iter = ablock.begin (); iter != ablock.end (); ++iter)
       {
         jit_instruction *instr = *iter;
 
@@ -2005,9 +1989,7 @@
     jit_block *split = ablock.maybe_split (m_factory, m_blocks,
                                            final_block ());
     jit_terminator *term = split->terminator ();
-    for (std::set<jit_value *>::const_iterator iter = temp.begin ();
-         iter != temp.end ();
-         ++iter)
+    for (auto iter = temp.cbegin (); iter != temp.cend (); ++iter)
       {
         jit_value *value = *iter;
         jit_call *release
@@ -2020,12 +2002,10 @@
   void
   jit_infer::simplify_phi (void)
   {
-    for (jit_block_list::iterator biter = m_blocks.begin ();
-         biter != m_blocks.end ();
-         ++biter)
+    for (auto biter = m_blocks.begin (); biter != m_blocks.end (); ++biter)
       {
         jit_block &ablock = **biter;
-        for (jit_block::iterator iter = ablock.begin ();
+        for (auto iter = ablock.begin ();
              iter != ablock.end () && isa<jit_phi> (*iter); ++iter)
           simplify_phi (*static_cast<jit_phi *> (*iter));
       }
@@ -2323,8 +2303,7 @@
   bool
   tree_jit::enabled (void)
   {
-    octave::bp_table& bptab
-      = octave::__get_bp_table__ ("tree_jit::enabled");
+    bp_table& bptab = __get_bp_table__ ("tree_jit::enabled");
 
     // Ideally, we should only disable JIT if there is a breakpoint in the code
     // we are about to run. However, we can't figure this out in O(1) time, so
--- a/libinterp/parse-tree/pt-jump.cc	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
-
-Copyright (C) 1996-2018 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
-<https://www.gnu.org/licenses/>.
-
-*/
-
-#if defined (HAVE_CONFIG_H)
-#  include "config.h"
-#endif
-
-#include "pt-jump.h"
-
-class octave_value_list;
-
-namespace octave
-{
-  // Break.
-
-  // Nonzero means we're breaking out of a loop or function body.
-  int tree_break_command::breaking = 0;
-
-  // Continue.
-
-  // Nonzero means we're jumping to the end of a loop.
-  int tree_continue_command::continuing = 0;
-
-  // Return.
-
-  // Nonzero means we're returning from a function.
-  int tree_return_command::returning = 0;
-}
--- a/libinterp/parse-tree/pt-jump.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/parse-tree/pt-jump.h	Fri Aug 10 09:09:51 2018 +0200
@@ -51,8 +51,6 @@
     {
       tw.visit_break_command (*this);
     }
-
-    static int breaking;
   };
 
   // Continue.
@@ -76,8 +74,6 @@
     {
       tw.visit_continue_command (*this);
     }
-
-    static int continuing;
   };
 
   // Return.
@@ -101,8 +97,6 @@
     {
       tw.visit_return_command (*this);
     }
-
-    static int returning;
   };
 }
 
--- a/libinterp/parse-tree/pt-mat.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/parse-tree/pt-mat.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -29,7 +29,6 @@
 #include "pt-arg-list.h"
 #include "pt-exp.h"
 #include "pt-mat.h"
-#include "pt-tm-const.h"
 #include "ov.h"
 #include "variables.h"
 
@@ -131,230 +130,3 @@
     return new_matrix;
   }
 }
-
-
-/*
-## test concatenation with all zero matrices
-%!assert ([ "" 65*ones(1,10) ], "AAAAAAAAAA")
-%!assert ([ 65*ones(1,10) "" ], "AAAAAAAAAA")
-
-%!test
-%! c = {"foo"; "bar"; "bazoloa"};
-%! assert ([c; "a"; "bc"; "def"], {"foo"; "bar"; "bazoloa"; "a"; "bc"; "def"});
-
-%!assert (class ([int64(1), int64(1)]), "int64")
-%!assert (class ([int64(1), int32(1)]), "int64")
-%!assert (class ([int64(1), int16(1)]), "int64")
-%!assert (class ([int64(1), int8(1)]), "int64")
-%!assert (class ([int64(1), uint64(1)]), "int64")
-%!assert (class ([int64(1), uint32(1)]), "int64")
-%!assert (class ([int64(1), uint16(1)]), "int64")
-%!assert (class ([int64(1), uint8(1)]), "int64")
-%!assert (class ([int64(1), single(1)]), "int64")
-%!assert (class ([int64(1), double(1)]), "int64")
-%!assert (class ([int64(1), cell(1)]), "cell")
-%!assert (class ([int64(1), true]), "int64")
-%!assert (class ([int64(1), "a"]), "char")
-
-%!assert (class ([int32(1), int64(1)]), "int32")
-%!assert (class ([int32(1), int32(1)]), "int32")
-%!assert (class ([int32(1), int16(1)]), "int32")
-%!assert (class ([int32(1), int8(1)]), "int32")
-%!assert (class ([int32(1), uint64(1)]), "int32")
-%!assert (class ([int32(1), uint32(1)]), "int32")
-%!assert (class ([int32(1), uint16(1)]), "int32")
-%!assert (class ([int32(1), uint8(1)]), "int32")
-%!assert (class ([int32(1), single(1)]), "int32")
-%!assert (class ([int32(1), double(1)]), "int32")
-%!assert (class ([int32(1), cell(1)]), "cell")
-%!assert (class ([int32(1), true]), "int32")
-%!assert (class ([int32(1), "a"]), "char")
-
-%!assert (class ([int16(1), int64(1)]), "int16")
-%!assert (class ([int16(1), int32(1)]), "int16")
-%!assert (class ([int16(1), int16(1)]), "int16")
-%!assert (class ([int16(1), int8(1)]), "int16")
-%!assert (class ([int16(1), uint64(1)]), "int16")
-%!assert (class ([int16(1), uint32(1)]), "int16")
-%!assert (class ([int16(1), uint16(1)]), "int16")
-%!assert (class ([int16(1), uint8(1)]), "int16")
-%!assert (class ([int16(1), single(1)]), "int16")
-%!assert (class ([int16(1), double(1)]), "int16")
-%!assert (class ([int16(1), cell(1)]), "cell")
-%!assert (class ([int16(1), true]), "int16")
-%!assert (class ([int16(1), "a"]), "char")
-
-%!assert (class ([int8(1), int64(1)]), "int8")
-%!assert (class ([int8(1), int32(1)]), "int8")
-%!assert (class ([int8(1), int16(1)]), "int8")
-%!assert (class ([int8(1), int8(1)]), "int8")
-%!assert (class ([int8(1), uint64(1)]), "int8")
-%!assert (class ([int8(1), uint32(1)]), "int8")
-%!assert (class ([int8(1), uint16(1)]), "int8")
-%!assert (class ([int8(1), uint8(1)]), "int8")
-%!assert (class ([int8(1), single(1)]), "int8")
-%!assert (class ([int8(1), double(1)]), "int8")
-%!assert (class ([int8(1), cell(1)]), "cell")
-%!assert (class ([int8(1), true]), "int8")
-%!assert (class ([int8(1), "a"]), "char")
-
-%!assert (class ([uint64(1), int64(1)]), "uint64")
-%!assert (class ([uint64(1), int32(1)]), "uint64")
-%!assert (class ([uint64(1), int16(1)]), "uint64")
-%!assert (class ([uint64(1), int8(1)]), "uint64")
-%!assert (class ([uint64(1), uint64(1)]), "uint64")
-%!assert (class ([uint64(1), uint32(1)]), "uint64")
-%!assert (class ([uint64(1), uint16(1)]), "uint64")
-%!assert (class ([uint64(1), uint8(1)]), "uint64")
-%!assert (class ([uint64(1), single(1)]), "uint64")
-%!assert (class ([uint64(1), double(1)]), "uint64")
-%!assert (class ([uint64(1), cell(1)]), "cell")
-%!assert (class ([uint64(1), true]), "uint64")
-%!assert (class ([uint64(1), "a"]), "char")
-
-%!assert (class ([uint32(1), int64(1)]), "uint32")
-%!assert (class ([uint32(1), int32(1)]), "uint32")
-%!assert (class ([uint32(1), int16(1)]), "uint32")
-%!assert (class ([uint32(1), int8(1)]), "uint32")
-%!assert (class ([uint32(1), uint64(1)]), "uint32")
-%!assert (class ([uint32(1), uint32(1)]), "uint32")
-%!assert (class ([uint32(1), uint16(1)]), "uint32")
-%!assert (class ([uint32(1), uint8(1)]), "uint32")
-%!assert (class ([uint32(1), single(1)]), "uint32")
-%!assert (class ([uint32(1), double(1)]), "uint32")
-%!assert (class ([uint32(1), cell(1)]), "cell")
-%!assert (class ([uint32(1), true]), "uint32")
-%!assert (class ([uint32(1), "a"]), "char")
-
-%!assert (class ([uint16(1), int64(1)]), "uint16")
-%!assert (class ([uint16(1), int32(1)]), "uint16")
-%!assert (class ([uint16(1), int16(1)]), "uint16")
-%!assert (class ([uint16(1), int8(1)]), "uint16")
-%!assert (class ([uint16(1), uint64(1)]), "uint16")
-%!assert (class ([uint16(1), uint32(1)]), "uint16")
-%!assert (class ([uint16(1), uint16(1)]), "uint16")
-%!assert (class ([uint16(1), uint8(1)]), "uint16")
-%!assert (class ([uint16(1), single(1)]), "uint16")
-%!assert (class ([uint16(1), double(1)]), "uint16")
-%!assert (class ([uint16(1), cell(1)]), "cell")
-%!assert (class ([uint16(1), true]), "uint16")
-%!assert (class ([uint16(1), "a"]), "char")
-
-%!assert (class ([uint8(1), int64(1)]), "uint8")
-%!assert (class ([uint8(1), int32(1)]), "uint8")
-%!assert (class ([uint8(1), int16(1)]), "uint8")
-%!assert (class ([uint8(1), int8(1)]), "uint8")
-%!assert (class ([uint8(1), uint64(1)]), "uint8")
-%!assert (class ([uint8(1), uint32(1)]), "uint8")
-%!assert (class ([uint8(1), uint16(1)]), "uint8")
-%!assert (class ([uint8(1), uint8(1)]), "uint8")
-%!assert (class ([uint8(1), single(1)]), "uint8")
-%!assert (class ([uint8(1), double(1)]), "uint8")
-%!assert (class ([uint8(1), cell(1)]), "cell")
-%!assert (class ([uint8(1), true]), "uint8")
-%!assert (class ([uint8(1), "a"]), "char")
-
-%!assert (class ([single(1), int64(1)]), "int64")
-%!assert (class ([single(1), int32(1)]), "int32")
-%!assert (class ([single(1), int16(1)]), "int16")
-%!assert (class ([single(1), int8(1)]), "int8")
-%!assert (class ([single(1), uint64(1)]), "uint64")
-%!assert (class ([single(1), uint32(1)]), "uint32")
-%!assert (class ([single(1), uint16(1)]), "uint16")
-%!assert (class ([single(1), uint8(1)]), "uint8")
-%!assert (class ([single(1), single(1)]), "single")
-%!assert (class ([single(1), double(1)]), "single")
-%!assert (class ([single(1), cell(1)]), "cell")
-%!assert (class ([single(1), true]), "single")
-%!assert (class ([single(1), "a"]), "char")
-
-%!assert (class ([double(1), int64(1)]), "int64")
-%!assert (class ([double(1), int32(1)]), "int32")
-%!assert (class ([double(1), int16(1)]), "int16")
-%!assert (class ([double(1), int8(1)]), "int8")
-%!assert (class ([double(1), uint64(1)]), "uint64")
-%!assert (class ([double(1), uint32(1)]), "uint32")
-%!assert (class ([double(1), uint16(1)]), "uint16")
-%!assert (class ([double(1), uint8(1)]), "uint8")
-%!assert (class ([double(1), single(1)]), "single")
-%!assert (class ([double(1), double(1)]), "double")
-%!assert (class ([double(1), cell(1)]), "cell")
-%!assert (class ([double(1), true]), "double")
-%!assert (class ([double(1), "a"]), "char")
-
-%!assert (class ([cell(1), int64(1)]), "cell")
-%!assert (class ([cell(1), int32(1)]), "cell")
-%!assert (class ([cell(1), int16(1)]), "cell")
-%!assert (class ([cell(1), int8(1)]), "cell")
-%!assert (class ([cell(1), uint64(1)]), "cell")
-%!assert (class ([cell(1), uint32(1)]), "cell")
-%!assert (class ([cell(1), uint16(1)]), "cell")
-%!assert (class ([cell(1), uint8(1)]), "cell")
-%!assert (class ([cell(1), single(1)]), "cell")
-%!assert (class ([cell(1), double(1)]), "cell")
-%!assert (class ([cell(1), cell(1)]), "cell")
-%!assert (class ([cell(1), true]), "cell")
-%!assert (class ([cell(1), "a"]), "cell")
-
-%!assert (class ([true, int64(1)]), "int64")
-%!assert (class ([true, int32(1)]), "int32")
-%!assert (class ([true, int16(1)]), "int16")
-%!assert (class ([true, int8(1)]), "int8")
-%!assert (class ([true, uint64(1)]), "uint64")
-%!assert (class ([true, uint32(1)]), "uint32")
-%!assert (class ([true, uint16(1)]), "uint16")
-%!assert (class ([true, uint8(1)]), "uint8")
-%!assert (class ([true, single(1)]), "single")
-%!assert (class ([true, double(1)]), "double")
-%!assert (class ([true, cell(1)]), "cell")
-%!assert (class ([true, true]), "logical")
-%!assert (class ([true, "a"]), "char")
-
-%!assert (class (["a", int64(1)]), "char")
-%!assert (class (["a", int32(1)]), "char")
-%!assert (class (["a", int16(1)]), "char")
-%!assert (class (["a", int8(1)]), "char")
-%!assert (class (["a", int64(1)]), "char")
-%!assert (class (["a", int32(1)]), "char")
-%!assert (class (["a", int16(1)]), "char")
-%!assert (class (["a", int8(1)]), "char")
-%!assert (class (["a", single(1)]), "char")
-%!assert (class (["a", double(1)]), "char")
-%!assert (class (["a", cell(1)]), "cell")
-%!assert (class (["a", true]), "char")
-%!assert (class (["a", "a"]), "char")
-
-%!assert (class ([cell(1), struct("foo", "bar")]), "cell")
-%!error [struct("foo", "bar"), cell(1)]
-
-%!test <*39041> assert (class ([cell(0), struct()]), "cell")
-%!test <51086> assert (class ([struct(), cell(0)]), "struct")
-
-%!assert ([,1], 1)
-%!assert ([1,], 1)
-%!assert ([,1,], 1)
-%!assert ([,1,;;], 1)
-%!assert ([,1,;,;], 1)
-
-%!assert ([1,1], ones (1, 2))
-%!assert ([,1,1], ones (1, 2))
-%!assert ([1,1,], ones (1, 2))
-%!assert ([,1,1,], ones (1, 2))
-%!assert ([,1,1,;;], ones (1, 2))
-%!assert ([,1,1,;,;], ones (1, 2))
-%!assert ([,;,1,1], ones (1, 2))
-
-%!assert ([1;1], ones (2, 1))
-%!assert ([1,;1], ones (2, 1))
-%!assert ([1,;,;1], ones (2, 1))
-
-%!error eval ("[,,]")
-%!error eval ("[,,;,]")
-%!error eval ("[,;,,;,]")
-
-%!assert (isnull ([,]))
-%!assert (isnull ([;]))
-%!assert (isnull ([;;]))
-%!assert (isnull ([;,;]))
-%!assert (isnull ([,;,;,]))
-*/
--- a/libinterp/parse-tree/pt-misc.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/parse-tree/pt-misc.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -35,7 +35,7 @@
   {
     while (! empty ())
       {
-        iterator p = begin ();
+        auto p = begin ();
         delete *p;
         erase (p);
       }
@@ -96,7 +96,7 @@
   {
     while (! empty ())
       {
-        iterator p = begin ();
+        auto p = begin ();
         delete *p;
         erase (p);
       }
--- a/libinterp/parse-tree/pt-pr-code.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/parse-tree/pt-pr-code.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -26,8 +26,6 @@
 
 #include <cctype>
 
-#include <iostream>
-
 #include "comment-list.h"
 #include "error.h"
 #include "ov-usr-fcn.h"
@@ -60,7 +58,7 @@
   void
   tree_print_code::visit_argument_list (tree_argument_list& lst)
   {
-    tree_argument_list::iterator p = lst.begin ();
+    auto p = lst.begin ();
 
     while (p != lst.end ())
       {
@@ -163,7 +161,7 @@
   void
   tree_print_code::visit_decl_init_list (tree_decl_init_list& lst)
   {
-    tree_decl_init_list::iterator p = lst.begin ();
+    auto p = lst.begin ();
 
     while (p != lst.end ())
       {
@@ -495,7 +493,7 @@
   void
   tree_print_code::visit_if_command_list (tree_if_command_list& lst)
   {
-    tree_if_command_list::iterator p = lst.begin ();
+    auto p = lst.begin ();
 
     bool first_elt = true;
 
@@ -542,8 +540,8 @@
 
     int n = type_tags.length ();
 
-    std::list<tree_argument_list *>::iterator p_arg_lists = arg_lists.begin ();
-    std::list<string_vector>::iterator p_arg_names = arg_names.begin ();
+    auto p_arg_lists = arg_lists.begin ();
+    auto p_arg_names = arg_names.begin ();
 
     for (int i = 0; i < n; i++)
       {
@@ -616,7 +614,7 @@
     m_os << '[';
     m_nesting.push ('[');
 
-    tree_matrix::iterator p = lst.begin ();
+    auto p = lst.begin ();
 
     while (p != lst.end ())
       {
@@ -647,7 +645,7 @@
     m_os << '{';
     m_nesting.push ('{');
 
-    tree_cell::iterator p = lst.begin ();
+    auto p = lst.begin ();
 
     while (p != lst.end ())
       {
@@ -756,7 +754,7 @@
   void
   tree_print_code::visit_parameter_list (tree_parameter_list& lst)
   {
-    tree_parameter_list::iterator p = lst.begin ();
+    auto p = lst.begin ();
 
     while (p != lst.end ())
       {
@@ -817,7 +815,7 @@
   void
   tree_print_code::visit_return_list (tree_return_list& lst)
   {
-    tree_return_list::iterator p = lst.begin ();
+    auto p = lst.begin ();
 
     while (p != lst.end ())
       {
@@ -933,7 +931,7 @@
   void
   tree_print_code::visit_switch_case_list (tree_switch_case_list& lst)
   {
-    tree_switch_case_list::iterator p = lst.begin ();
+    auto p = lst.begin ();
 
     while (p != lst.end ())
       {
@@ -1282,7 +1280,7 @@
   {
     if (comment_list)
       {
-        comment_list::iterator p = comment_list->begin ();
+        auto p = comment_list->begin ();
 
         while (p != comment_list->end ())
           {
--- a/libinterp/parse-tree/pt-select.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/parse-tree/pt-select.h	Fri Aug 10 09:09:51 2018 +0200
@@ -104,7 +104,7 @@
     {
       while (! empty ())
         {
-          iterator p = begin ();
+          auto p = begin ();
           delete *p;
           erase (p);
         }
@@ -229,7 +229,7 @@
     {
       while (! empty ())
         {
-          iterator p = begin ();
+          auto p = begin ();
           delete *p;
           erase (p);
         }
--- a/libinterp/parse-tree/pt-stmt.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/parse-tree/pt-stmt.h	Fri Aug 10 09:09:51 2018 +0200
@@ -153,7 +153,7 @@
     {
       while (! empty ())
         {
-          iterator p = begin ();
+          auto p = begin ();
           delete *p;
           erase (p);
         }
--- a/libinterp/parse-tree/pt-tm-const.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/parse-tree/pt-tm-const.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -24,8 +24,6 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
-
 #include "oct-locbuf.h"
 #include "quit.h"
 
@@ -59,20 +57,61 @@
 
 namespace octave
 {
-  void
-  tm_row_const::tm_row_const_rep::do_init_element (const octave_value& val,
-                                                   bool& first_elem)
+  void tm_row_const::cellify (void)
   {
-    std::string this_elt_class_nm = val.isobject () ? "class"
-                                                    : val.class_name ();
+    bool elt_changed = false;
+
+    for (auto& elt : m_values)
+      {
+        octave_quit ();
+
+        if (! elt.iscell ())
+          {
+            elt_changed = true;
+
+            if (elt.isempty ())
+              elt = Cell ();
+            else
+              elt = Cell (elt);
+          }
+      }
+
+    if (! elt_changed)
+      return;
+
+    bool first_elem = true;
 
-    m_class_nm = get_concat_class (m_class_nm, this_elt_class_nm);
+    for (const auto& val : m_values)
+      {
+        octave_quit ();
+
+        dim_vector this_elt_dv = val.dims ();
+
+        if (! this_elt_dv.zero_by_zero ())
+          {
+            if (first_elem)
+              {
+                first_elem = false;
+                m_dv = this_elt_dv;
+              }
+            else if (! m_dv.hvcat (this_elt_dv, 1))
+              eval_error ("horizontal dimensions mismatch", m_dv, this_elt_dv);
+          }
+      }
+  }
+
+  void tm_row_const::init_element (const octave_value& val, bool& first_elem)
+  {
+    std::string this_elt_class_name
+      = val.isobject () ? "class" : val.class_name ();
+
+    m_class_name = get_concat_class (m_class_name, this_elt_class_name);
 
     dim_vector this_elt_dv = val.dims ();
 
     if (! this_elt_dv.zero_by_zero ())
       {
-        m_all_mt = false;
+        m_all_empty = false;
 
         if (first_elem)
           {
@@ -85,25 +124,25 @@
     else if (val.iscell ())
       first_elem = false;
 
-    append (val);
+    m_values.push_back (val);
 
-    if (m_all_str && ! val.is_string ())
-      m_all_str = false;
+    if (m_all_strings && ! val.is_string ())
+      m_all_strings = false;
 
-    if (m_all_sq_str && ! val.is_sq_string ())
-      m_all_sq_str = false;
+    if (m_all_sq_strings && ! val.is_sq_string ())
+      m_all_sq_strings = false;
 
-    if (m_all_dq_str && ! val.is_dq_string ())
-      m_all_dq_str = false;
+    if (m_all_dq_strings && ! val.is_dq_string ())
+      m_all_dq_strings = false;
 
-    if (! m_some_str && val.is_string ())
-      m_some_str = true;
+    if (! m_some_strings && val.is_string ())
+      m_some_strings = true;
 
     if (m_all_real && ! val.isreal ())
       m_all_real = false;
 
-    if (m_all_cmplx && ! (val.iscomplex () || val.isreal ()))
-      m_all_cmplx = false;
+    if (m_all_complex && ! (val.iscomplex () || val.isreal ()))
+      m_all_complex = false;
 
     if (! m_any_cell && val.iscell ())
       m_any_cell = true;
@@ -118,48 +157,32 @@
     m_all_1x1 = m_all_1x1 && ! val.issparse () && val.numel () == 1;
   }
 
-  void
-  tm_row_const::tm_row_const_rep::init (const tree_argument_list& row,
-                                        tree_evaluator *tw)
+  void tm_row_const::init (const tree_argument_list& row, tree_evaluator& tw)
   {
-    m_all_str = true;
-    m_all_sq_str = true;
-    m_all_dq_str = true;
-    m_all_real = true;
-    m_all_cmplx = true;
-    m_any_cell = false;
-    m_any_sparse = false;
-    m_any_class = false;
-
     bool first_elem = true;
 
-    for (tree_expression* elt : row)
+    for (auto *elt : row)
       {
         octave_quit ();
 
-        octave_value tmp = tw->evaluate (elt);
+        octave_value tmp = tw.evaluate (elt);
 
         if (tmp.is_undefined ())
+          return;
+
+        if (tmp.is_cs_list ())
           {
-            m_ok = true;
-            return;
+            octave_value_list tlst = tmp.list_value ();
+
+            for (octave_idx_type i = 0; i < tlst.length (); i++)
+              {
+                octave_quit ();
+
+                init_element (tlst(i), first_elem);
+              }
           }
         else
-          {
-            if (tmp.is_cs_list ())
-              {
-                octave_value_list tlst = tmp.list_value ();
-
-                for (octave_idx_type i = 0; i < tlst.length (); i++)
-                  {
-                    octave_quit ();
-
-                    do_init_element (tlst(i), first_elem);
-                  }
-              }
-            else
-              do_init_element (tmp, first_elem);
-          }
+          init_element (tmp, first_elem);
       }
 
     if (m_any_cell && ! m_any_class && ! m_first_elem_is_struct)
@@ -167,7 +190,7 @@
 
     first_elem = true;
 
-    for (const octave_value& val : *this)
+    for (const auto& val : m_values)
       {
         octave_quit ();
 
@@ -175,7 +198,7 @@
 
         if (! this_elt_dv.zero_by_zero ())
           {
-            m_all_mt = false;
+            m_all_empty = false;
 
             if (first_elem)
               {
@@ -186,129 +209,152 @@
               eval_error ("horizontal dimensions mismatch", m_dv, this_elt_dv);
           }
       }
-
-    m_ok = true;
   }
 
-  void
-  tm_row_const::tm_row_const_rep::cellify (void)
+  octave_value tm_const::concat (char string_fill_char) const
   {
-    bool elt_changed = false;
+    if (m_tm_rows.empty ())
+      return Matrix ();
 
-    for (auto& elt : *this)
-      {
-        octave_quit ();
+    // Try to speed up the common cases.
+
+    std::string result_type = m_class_name;
 
-        if (! elt.iscell ())
+    if (m_any_class)
+      return class_concat ();
+    else if (result_type == "double")
+      {
+        if (m_any_sparse)
           {
-            elt_changed = true;
-
-            if (elt.isempty ())
-              elt = Cell ();
+            if (m_all_real)
+              return sparse_array_concat<SparseMatrix> ();
             else
-              elt = Cell (elt);
+              return sparse_array_concat<SparseComplexMatrix> ();
+          }
+        else
+          {
+            if (m_all_real)
+              return array_concat<NDArray> ();
+            else
+              return array_concat<ComplexNDArray> ();
           }
       }
-
-    if (elt_changed)
+    else if (result_type == "single")
       {
-        bool first_elem = true;
-
-        for (const octave_value& val : *this)
-          {
-            octave_quit ();
-
-            dim_vector this_elt_dv = val.dims ();
+        if (m_all_real)
+          return array_concat<FloatNDArray> ();
+        else
+          return array_concat<FloatComplexNDArray> ();
+      }
+    else if (result_type == "char")
+      {
+        if (! m_all_strings)
+          warn_implicit_conversion ("Octave:num-to-str",
+                                    "numeric", result_type);
+        else
+          maybe_warn_string_concat (m_all_dq_strings, m_all_sq_strings);
 
-            if (! this_elt_dv.zero_by_zero ())
-              {
-                if (first_elem)
-                  {
-                    first_elem = false;
-                    m_dv = this_elt_dv;
-                  }
-                else if (! m_dv.hvcat (this_elt_dv, 1))
-                  eval_error ("horizontal dimensions mismatch", m_dv, this_elt_dv);
-              }
-          }
+        return char_array_concat (string_fill_char);
+      }
+    else if (result_type == "logical")
+      {
+        if (m_any_sparse)
+          return sparse_array_concat<SparseBoolMatrix> ();
+        else
+          return array_concat<boolNDArray> ();
       }
+    else if (result_type == "int8")
+      return array_concat<int8NDArray> ();
+    else if (result_type == "int16")
+      return array_concat<int16NDArray> ();
+    else if (result_type == "int32")
+      return array_concat<int32NDArray> ();
+    else if (result_type == "int64")
+      return array_concat<int64NDArray> ();
+    else if (result_type == "uint8")
+      return array_concat<uint8NDArray> ();
+    else if (result_type == "uint16")
+      return array_concat<uint16NDArray> ();
+    else if (result_type == "uint32")
+      return array_concat<uint32NDArray> ();
+    else if (result_type == "uint64")
+      return array_concat<uint64NDArray> ();
+    else if (result_type == "cell")
+      return array_concat<Cell> ();
+    else if (result_type == "struct")
+      {
+        if (m_all_1x1)
+          return map_concat<octave_scalar_map> ();
+        else
+          return map_concat<octave_map> ();
+      }
+    else
+      return generic_concat ();
   }
 
-  void
-  tm_const::init (const tree_matrix& tm, tree_evaluator *tw)
+  void tm_const::init (const tree_matrix& tm)
   {
-    m_all_str = true;
-    m_all_sq_str = true;
-    m_all_dq_str = true;
-    m_all_real = true;
-    m_all_cmplx = true;
-    m_any_cell = false;
-    m_any_sparse = false;
-    m_any_class = false;
-    m_all_1x1 = ! tm.empty ();
-
     bool first_elem = true;
     bool first_elem_is_struct = false;
 
     // Just eval and figure out if what we have is complex or all strings.
     // We can't check columns until we know that this is a numeric matrix --
     // collections of strings can have elements of different lengths.
-    for (const tree_argument_list* elt : tm)
+
+    for (const auto *elt : tm)
       {
         octave_quit ();
 
-        tm_row_const tmp (*elt, tw);
+        tm_row_const row (*elt, m_evaluator);
 
         if (first_elem)
           {
-            first_elem_is_struct = tmp.first_elem_struct_p ();
+            first_elem_is_struct = row.first_elem_struct_p ();
 
             first_elem = false;
           }
 
-        if (tmp && ! tmp.empty ())
-          {
-            if (m_all_str && ! tmp.all_strings_p ())
-              m_all_str = false;
+        if (row.empty ())
+          break;
 
-            if (m_all_sq_str && ! tmp.all_sq_strings_p ())
-              m_all_sq_str = false;
+        if (m_all_strings && ! row.all_strings_p ())
+          m_all_strings = false;
+
+        if (m_all_sq_strings && ! row.all_sq_strings_p ())
+          m_all_sq_strings = false;
 
-            if (m_all_dq_str && ! tmp.all_dq_strings_p ())
-              m_all_dq_str = false;
+        if (m_all_dq_strings && ! row.all_dq_strings_p ())
+          m_all_dq_strings = false;
 
-            if (! m_some_str && tmp.some_strings_p ())
-              m_some_str = true;
+        if (! m_some_strings && row.some_strings_p ())
+          m_some_strings = true;
 
-            if (m_all_real && ! tmp.all_real_p ())
-              m_all_real = false;
+        if (m_all_real && ! row.all_real_p ())
+          m_all_real = false;
 
-            if (m_all_cmplx && ! tmp.all_complex_p ())
-              m_all_cmplx = false;
+        if (m_all_complex && ! row.all_complex_p ())
+          m_all_complex = false;
 
-            if (m_all_mt && ! tmp.all_empty_p ())
-              m_all_mt = false;
+        if (m_all_empty && ! row.all_empty_p ())
+          m_all_empty = false;
 
-            if (! m_any_cell && tmp.any_cell_p ())
-              m_any_cell = true;
+        if (! m_any_cell && row.any_cell_p ())
+          m_any_cell = true;
 
-            if (! m_any_sparse && tmp.any_sparse_p ())
-              m_any_sparse = true;
-
-            if (! m_any_class && tmp.any_class_p ())
-              m_any_class = true;
+        if (! m_any_sparse && row.any_sparse_p ())
+          m_any_sparse = true;
 
-            m_all_1x1 = m_all_1x1 && tmp.all_1x1_p ();
+        if (! m_any_class && row.any_class_p ())
+          m_any_class = true;
 
-            append (tmp);
-          }
-        else
-          break;
+        m_all_1x1 = m_all_1x1 && row.all_1x1_p ();
+
+        m_tm_rows.push_back (row);
       }
 
     if (m_any_cell && ! m_any_class && ! first_elem_is_struct)
       {
-        for (auto& elt : *this)
+        for (auto& elt : m_tm_rows)
           {
             octave_quit ();
 
@@ -318,19 +364,19 @@
 
     first_elem = true;
 
-    for (tm_row_const& elt : *this)
+    for (const auto& elt : m_tm_rows)
       {
         octave_quit ();
 
         octave_idx_type this_elt_nr = elt.rows ();
         octave_idx_type this_elt_nc = elt.cols ();
 
-        std::string this_elt_class_nm = elt.class_name ();
-        m_class_nm = get_concat_class (m_class_nm, this_elt_class_nm);
+        std::string this_elt_class_name = elt.class_name ();
+        m_class_name = get_concat_class (m_class_name, this_elt_class_name);
 
         dim_vector this_elt_dv = elt.dims ();
 
-        m_all_mt = false;
+        m_all_empty = false;
 
         if (first_elem)
           {
@@ -338,7 +384,7 @@
 
             m_dv = this_elt_dv;
           }
-        else if (m_all_str && m_dv.ndims () == 2
+        else if (m_all_strings && m_dv.ndims () == 2
                  && this_elt_dv.ndims () == 2)
           {
             // This is Octave's specialty.
@@ -359,33 +405,27 @@
         else if ((! m_any_class) && (! m_dv.hvcat (this_elt_dv, 0)))
           eval_error ("vertical dimensions mismatch", m_dv, this_elt_dv);
       }
-
-    m_ok = true;
   }
 
-  template <>
-  octave_value
-  do_single_type_concat<octave_map> (const dim_vector& dv,
-                                     tm_const& tmp)
+  octave_value tm_const::char_array_concat (char string_fill_char) const
   {
-    octave_map result;
+    char type = (m_all_dq_strings ? '"' : '\'');
 
-    if (tmp.all_1x1_p ())
-      single_type_concat<octave_scalar_map> (result, dv, tmp);
-    else
-      single_type_concat<octave_map> (result, dv, tmp);
+    charNDArray result (m_dv, string_fill_char);
 
-    return result;
+    array_concat_internal<charNDArray> (result);
+
+    return octave_value (result, type);
   }
 
-  octave_value do_class_concat (tm_const& tmc)
+  octave_value tm_const::class_concat (void) const
   {
     octave_value retval;
 
-    octave_value_list rows (tmc.length (), octave_value ());
+    octave_value_list rows (m_tm_rows.size (), octave_value ());
 
     octave_idx_type j = 0;
-    for (tm_row_const& tmrc : tmc)
+    for (const auto& tmrc : m_tm_rows)
       {
         octave_quit ();
 
@@ -396,18 +436,493 @@
             octave_value_list row (tmrc.length (), octave_value ());
 
             octave_idx_type i = 0;
-            for (auto& elt : tmrc)
+            for (const auto& elt : tmrc)
               row(i++) = elt;
 
-            rows(j++) = do_class_concat (row, "horzcat", 1);
+            rows(j++) = ::do_class_concat (row, "horzcat", 1);
           }
       }
 
     if (rows.length () == 1)
       retval = rows(0);
     else
-      retval = do_class_concat (rows, "vertcat", 0);
+      retval = ::do_class_concat (rows, "vertcat", 0);
+
+    return retval;
+  }
+
+  octave_value tm_const::generic_concat (void) const
+  {
+    // The line below might seem crazy, since we take a copy of the
+    // first argument, resize it to be empty and then resize it to be
+    // full.  This is done since it means that there is no recopying of
+    // data, as would happen if we used a single resize.  It should be
+    // noted that resize operation is also significantly slower than the
+    // do_cat_op function, so it makes sense to have an empty matrix and
+    // copy all data.
+    //
+    // We might also start with a empty octave_value using
+    //
+    //    ctmp = octave::type_info::lookup_type
+    //          (tmp.begin() -> begin() -> type_name());
+    //
+    // and then directly resize.  However, for some types there might be
+    // some additional setup needed, and so this should be avoided.
+
+    octave_value ctmp;
+
+    // Find the first non-empty object
+
+    if (m_any_sparse)
+      {
+        // Start with sparse matrix to avoid issues memory issues with
+        // things like [ones(1,4),sprandn(1e8,4,1e-4)]
+
+        if (m_all_real)
+          ctmp = octave_sparse_matrix ().resize (m_dv);
+        else
+          ctmp = octave_sparse_complex_matrix ().resize (m_dv);
+      }
+    else
+      {
+        for (const auto& row : m_tm_rows)
+          {
+            octave_quit ();
+
+            for (const auto& elt : row)
+              {
+                octave_quit ();
+
+                ctmp = elt;
+
+                if (! ctmp.all_zero_dims ())
+                  goto found_non_empty;
+              }
+          }
+
+        ctmp = (*(m_tm_rows.begin () -> begin ()));
+
+      found_non_empty:
+
+        if (! m_all_empty)
+          ctmp = ctmp.resize (dim_vector (0,0)).resize (m_dv);
+      }
+
+    // Now, extract the values from the individual elements and insert
+    // them in the result matrix.
+
+    interpreter& interp = m_evaluator.get_interpreter ();
+
+    type_info& ti = interp.get_type_info ();
+
+    int dv_len = m_dv.ndims ();
+    octave_idx_type ntmp = (dv_len > 1 ? dv_len : 2);
+    Array<octave_idx_type> ra_idx (dim_vector (ntmp, 1), 0);
+
+    for (const auto& row : m_tm_rows)
+      {
+        octave_quit ();
+
+        for (const auto& elt : row)
+          {
+            octave_quit ();
+
+            if (elt.isempty ())
+              continue;
+
+            ctmp = do_cat_op (ti, ctmp, elt, ra_idx);
+
+            ra_idx (1) += elt.columns ();
+          }
+
+        ra_idx (0) += row.rows ();
+        ra_idx (1) = 0;
+      }
+
+    octave_value retval = ctmp;
+
+    // If some elements are strings, force the result to be a string.
+
+    if (m_some_strings && ! retval.is_string ())
+      retval = retval.convert_to_str ();
 
     return retval;
   }
+
+  // The result is passed as a parameter to this function so that the
+  // char_array_concat function can create the array externally.
+  // Otherwise, we would need a specialization of this function for
+  // character arrays just to handle string_fill_char.
+
+  template <typename TYPE>
+  void tm_const::array_concat_internal (TYPE& result) const
+  {
+    octave_idx_type r = 0;
+    octave_idx_type c = 0;
+
+    for (const auto& row : m_tm_rows)
+      {
+        // Skip empty arrays to allow looser rules.
+        if (row.dims ().any_zero ())
+          continue;
+
+        for (const auto& elt : row)
+          {
+            octave_quit ();
+
+            TYPE ra = octave_value_extract<TYPE> (elt);
+
+            // Skip empty arrays to allow looser rules.
+
+            if (! ra.isempty ())
+              {
+                result.insert (ra, r, c);
+
+                c += ra.columns ();
+              }
+          }
+
+        r += row.rows ();
+        c = 0;
+      }
+  }
+
+  template <typename TYPE>
+  TYPE tm_const::array_concat (void) const
+  {
+    typedef typename TYPE::element_type ELT_T;
+
+    if (m_dv.any_zero ())
+      return TYPE (m_dv);
+
+    if (m_tm_rows.size () == 1)
+      {
+        // If possible, forward the operation to liboctave.
+        // Single row.
+        const tm_row_const& row = m_tm_rows.front ();
+        if (! (equal_types<ELT_T, char>::value
+               || equal_types<ELT_T, octave_value>::value)
+            && row.all_1x1_p ())
+          {
+            // Optimize all scalars case.
+            TYPE result (m_dv);
+            assert (static_cast<size_t> (result.numel ()) == row.length ());
+            octave_idx_type i = 0;
+            for (const auto& elt : row)
+              result(i++) = octave_value_extract<ELT_T> (elt);
+
+            return result;
+          }
+
+        octave_idx_type ncols = row.length ();
+        octave_idx_type i = 0;
+        OCTAVE_LOCAL_BUFFER (TYPE, array_list, ncols);
+
+        for (const auto& elt : row)
+          {
+            octave_quit ();
+
+            array_list[i++] = octave_value_extract<TYPE> (elt);
+          }
+
+        return TYPE::cat (-2, ncols, array_list);
+      }
+    else
+      {
+        TYPE result (m_dv);
+        array_concat_internal<TYPE> (result);
+        return result;
+      }
+  }
+
+  template <typename TYPE>
+  TYPE tm_const::sparse_array_concat (void) const
+  {
+    if (m_dv.any_zero ())
+      return TYPE (m_dv);
+
+    // Sparse matrices require preallocation for efficient indexing; besides,
+    // only horizontal concatenation can be efficiently handled by indexing.
+    // So we just cat all rows through liboctave, then cat the final column.
+    octave_idx_type nrows = m_tm_rows.size ();
+    octave_idx_type j = 0;
+    OCTAVE_LOCAL_BUFFER (TYPE, sparse_row_list, nrows);
+    for (const auto& row : m_tm_rows)
+      {
+        octave_idx_type ncols = row.length ();
+        octave_idx_type i = 0;
+        OCTAVE_LOCAL_BUFFER (TYPE, sparse_list, ncols);
+
+        for (auto& elt : row)
+          {
+            octave_quit ();
+
+            sparse_list[i] = octave_value_extract<TYPE> (elt);
+            i++;
+          }
+
+        TYPE stmp = TYPE::cat (-2, ncols, sparse_list);
+        sparse_row_list[j] = stmp;
+        j++;
+      }
+
+    return TYPE::cat (-1, nrows, sparse_row_list);
+  }
+
+  template <typename MAP>
+  octave_map tm_const::map_concat (void) const
+  {
+    if (m_dv.any_zero ())
+      return octave_map (m_dv);
+
+    octave_idx_type nrows = m_tm_rows.size ();
+    octave_idx_type j = 0;
+    OCTAVE_LOCAL_BUFFER (octave_map, map_row_list, nrows);
+    for (const auto& row : m_tm_rows)
+      {
+        octave_idx_type ncols = row.length ();
+        octave_idx_type i = 0;
+        OCTAVE_LOCAL_BUFFER (MAP, map_list, ncols);
+
+        for (auto& elt : row)
+          {
+            octave_quit ();
+
+            map_list[i] = octave_value_extract<MAP> (elt);
+            i++;
+          }
+
+        octave_map mtmp = octave_map::cat (-2, ncols, map_list);
+        map_row_list[j] = mtmp;
+        j++;
+      }
+
+    return octave_map::cat (-1, nrows, map_row_list);
+  }
 }
+
+/*
+## test concatenation with all zero matrices
+%!assert ([ "" 65*ones(1,10) ], "AAAAAAAAAA")
+%!assert ([ 65*ones(1,10) "" ], "AAAAAAAAAA")
+
+%!test
+%! c = {"foo"; "bar"; "bazoloa"};
+%! assert ([c; "a"; "bc"; "def"], {"foo"; "bar"; "bazoloa"; "a"; "bc"; "def"});
+
+%!assert (class ([int64(1), int64(1)]), "int64")
+%!assert (class ([int64(1), int32(1)]), "int64")
+%!assert (class ([int64(1), int16(1)]), "int64")
+%!assert (class ([int64(1), int8(1)]), "int64")
+%!assert (class ([int64(1), uint64(1)]), "int64")
+%!assert (class ([int64(1), uint32(1)]), "int64")
+%!assert (class ([int64(1), uint16(1)]), "int64")
+%!assert (class ([int64(1), uint8(1)]), "int64")
+%!assert (class ([int64(1), single(1)]), "int64")
+%!assert (class ([int64(1), double(1)]), "int64")
+%!assert (class ([int64(1), cell(1)]), "cell")
+%!assert (class ([int64(1), true]), "int64")
+%!assert (class ([int64(1), "a"]), "char")
+
+%!assert (class ([int32(1), int64(1)]), "int32")
+%!assert (class ([int32(1), int32(1)]), "int32")
+%!assert (class ([int32(1), int16(1)]), "int32")
+%!assert (class ([int32(1), int8(1)]), "int32")
+%!assert (class ([int32(1), uint64(1)]), "int32")
+%!assert (class ([int32(1), uint32(1)]), "int32")
+%!assert (class ([int32(1), uint16(1)]), "int32")
+%!assert (class ([int32(1), uint8(1)]), "int32")
+%!assert (class ([int32(1), single(1)]), "int32")
+%!assert (class ([int32(1), double(1)]), "int32")
+%!assert (class ([int32(1), cell(1)]), "cell")
+%!assert (class ([int32(1), true]), "int32")
+%!assert (class ([int32(1), "a"]), "char")
+
+%!assert (class ([int16(1), int64(1)]), "int16")
+%!assert (class ([int16(1), int32(1)]), "int16")
+%!assert (class ([int16(1), int16(1)]), "int16")
+%!assert (class ([int16(1), int8(1)]), "int16")
+%!assert (class ([int16(1), uint64(1)]), "int16")
+%!assert (class ([int16(1), uint32(1)]), "int16")
+%!assert (class ([int16(1), uint16(1)]), "int16")
+%!assert (class ([int16(1), uint8(1)]), "int16")
+%!assert (class ([int16(1), single(1)]), "int16")
+%!assert (class ([int16(1), double(1)]), "int16")
+%!assert (class ([int16(1), cell(1)]), "cell")
+%!assert (class ([int16(1), true]), "int16")
+%!assert (class ([int16(1), "a"]), "char")
+
+%!assert (class ([int8(1), int64(1)]), "int8")
+%!assert (class ([int8(1), int32(1)]), "int8")
+%!assert (class ([int8(1), int16(1)]), "int8")
+%!assert (class ([int8(1), int8(1)]), "int8")
+%!assert (class ([int8(1), uint64(1)]), "int8")
+%!assert (class ([int8(1), uint32(1)]), "int8")
+%!assert (class ([int8(1), uint16(1)]), "int8")
+%!assert (class ([int8(1), uint8(1)]), "int8")
+%!assert (class ([int8(1), single(1)]), "int8")
+%!assert (class ([int8(1), double(1)]), "int8")
+%!assert (class ([int8(1), cell(1)]), "cell")
+%!assert (class ([int8(1), true]), "int8")
+%!assert (class ([int8(1), "a"]), "char")
+
+%!assert (class ([uint64(1), int64(1)]), "uint64")
+%!assert (class ([uint64(1), int32(1)]), "uint64")
+%!assert (class ([uint64(1), int16(1)]), "uint64")
+%!assert (class ([uint64(1), int8(1)]), "uint64")
+%!assert (class ([uint64(1), uint64(1)]), "uint64")
+%!assert (class ([uint64(1), uint32(1)]), "uint64")
+%!assert (class ([uint64(1), uint16(1)]), "uint64")
+%!assert (class ([uint64(1), uint8(1)]), "uint64")
+%!assert (class ([uint64(1), single(1)]), "uint64")
+%!assert (class ([uint64(1), double(1)]), "uint64")
+%!assert (class ([uint64(1), cell(1)]), "cell")
+%!assert (class ([uint64(1), true]), "uint64")
+%!assert (class ([uint64(1), "a"]), "char")
+
+%!assert (class ([uint32(1), int64(1)]), "uint32")
+%!assert (class ([uint32(1), int32(1)]), "uint32")
+%!assert (class ([uint32(1), int16(1)]), "uint32")
+%!assert (class ([uint32(1), int8(1)]), "uint32")
+%!assert (class ([uint32(1), uint64(1)]), "uint32")
+%!assert (class ([uint32(1), uint32(1)]), "uint32")
+%!assert (class ([uint32(1), uint16(1)]), "uint32")
+%!assert (class ([uint32(1), uint8(1)]), "uint32")
+%!assert (class ([uint32(1), single(1)]), "uint32")
+%!assert (class ([uint32(1), double(1)]), "uint32")
+%!assert (class ([uint32(1), cell(1)]), "cell")
+%!assert (class ([uint32(1), true]), "uint32")
+%!assert (class ([uint32(1), "a"]), "char")
+
+%!assert (class ([uint16(1), int64(1)]), "uint16")
+%!assert (class ([uint16(1), int32(1)]), "uint16")
+%!assert (class ([uint16(1), int16(1)]), "uint16")
+%!assert (class ([uint16(1), int8(1)]), "uint16")
+%!assert (class ([uint16(1), uint64(1)]), "uint16")
+%!assert (class ([uint16(1), uint32(1)]), "uint16")
+%!assert (class ([uint16(1), uint16(1)]), "uint16")
+%!assert (class ([uint16(1), uint8(1)]), "uint16")
+%!assert (class ([uint16(1), single(1)]), "uint16")
+%!assert (class ([uint16(1), double(1)]), "uint16")
+%!assert (class ([uint16(1), cell(1)]), "cell")
+%!assert (class ([uint16(1), true]), "uint16")
+%!assert (class ([uint16(1), "a"]), "char")
+
+%!assert (class ([uint8(1), int64(1)]), "uint8")
+%!assert (class ([uint8(1), int32(1)]), "uint8")
+%!assert (class ([uint8(1), int16(1)]), "uint8")
+%!assert (class ([uint8(1), int8(1)]), "uint8")
+%!assert (class ([uint8(1), uint64(1)]), "uint8")
+%!assert (class ([uint8(1), uint32(1)]), "uint8")
+%!assert (class ([uint8(1), uint16(1)]), "uint8")
+%!assert (class ([uint8(1), uint8(1)]), "uint8")
+%!assert (class ([uint8(1), single(1)]), "uint8")
+%!assert (class ([uint8(1), double(1)]), "uint8")
+%!assert (class ([uint8(1), cell(1)]), "cell")
+%!assert (class ([uint8(1), true]), "uint8")
+%!assert (class ([uint8(1), "a"]), "char")
+
+%!assert (class ([single(1), int64(1)]), "int64")
+%!assert (class ([single(1), int32(1)]), "int32")
+%!assert (class ([single(1), int16(1)]), "int16")
+%!assert (class ([single(1), int8(1)]), "int8")
+%!assert (class ([single(1), uint64(1)]), "uint64")
+%!assert (class ([single(1), uint32(1)]), "uint32")
+%!assert (class ([single(1), uint16(1)]), "uint16")
+%!assert (class ([single(1), uint8(1)]), "uint8")
+%!assert (class ([single(1), single(1)]), "single")
+%!assert (class ([single(1), double(1)]), "single")
+%!assert (class ([single(1), cell(1)]), "cell")
+%!assert (class ([single(1), true]), "single")
+%!assert (class ([single(1), "a"]), "char")
+
+%!assert (class ([double(1), int64(1)]), "int64")
+%!assert (class ([double(1), int32(1)]), "int32")
+%!assert (class ([double(1), int16(1)]), "int16")
+%!assert (class ([double(1), int8(1)]), "int8")
+%!assert (class ([double(1), uint64(1)]), "uint64")
+%!assert (class ([double(1), uint32(1)]), "uint32")
+%!assert (class ([double(1), uint16(1)]), "uint16")
+%!assert (class ([double(1), uint8(1)]), "uint8")
+%!assert (class ([double(1), single(1)]), "single")
+%!assert (class ([double(1), double(1)]), "double")
+%!assert (class ([double(1), cell(1)]), "cell")
+%!assert (class ([double(1), true]), "double")
+%!assert (class ([double(1), "a"]), "char")
+
+%!assert (class ([cell(1), int64(1)]), "cell")
+%!assert (class ([cell(1), int32(1)]), "cell")
+%!assert (class ([cell(1), int16(1)]), "cell")
+%!assert (class ([cell(1), int8(1)]), "cell")
+%!assert (class ([cell(1), uint64(1)]), "cell")
+%!assert (class ([cell(1), uint32(1)]), "cell")
+%!assert (class ([cell(1), uint16(1)]), "cell")
+%!assert (class ([cell(1), uint8(1)]), "cell")
+%!assert (class ([cell(1), single(1)]), "cell")
+%!assert (class ([cell(1), double(1)]), "cell")
+%!assert (class ([cell(1), cell(1)]), "cell")
+%!assert (class ([cell(1), true]), "cell")
+%!assert (class ([cell(1), "a"]), "cell")
+
+%!assert (class ([true, int64(1)]), "int64")
+%!assert (class ([true, int32(1)]), "int32")
+%!assert (class ([true, int16(1)]), "int16")
+%!assert (class ([true, int8(1)]), "int8")
+%!assert (class ([true, uint64(1)]), "uint64")
+%!assert (class ([true, uint32(1)]), "uint32")
+%!assert (class ([true, uint16(1)]), "uint16")
+%!assert (class ([true, uint8(1)]), "uint8")
+%!assert (class ([true, single(1)]), "single")
+%!assert (class ([true, double(1)]), "double")
+%!assert (class ([true, cell(1)]), "cell")
+%!assert (class ([true, true]), "logical")
+%!assert (class ([true, "a"]), "char")
+
+%!assert (class (["a", int64(1)]), "char")
+%!assert (class (["a", int32(1)]), "char")
+%!assert (class (["a", int16(1)]), "char")
+%!assert (class (["a", int8(1)]), "char")
+%!assert (class (["a", int64(1)]), "char")
+%!assert (class (["a", int32(1)]), "char")
+%!assert (class (["a", int16(1)]), "char")
+%!assert (class (["a", int8(1)]), "char")
+%!assert (class (["a", single(1)]), "char")
+%!assert (class (["a", double(1)]), "char")
+%!assert (class (["a", cell(1)]), "cell")
+%!assert (class (["a", true]), "char")
+%!assert (class (["a", "a"]), "char")
+
+%!assert (class ([cell(1), struct("foo", "bar")]), "cell")
+%!error [struct("foo", "bar"), cell(1)]
+
+%!test <*39041> assert (class ([cell(0), struct()]), "cell")
+%!test <51086> assert (class ([struct(), cell(0)]), "struct")
+
+%!assert ([,1], 1)
+%!assert ([1,], 1)
+%!assert ([,1,], 1)
+%!assert ([,1,;;], 1)
+%!assert ([,1,;,;], 1)
+
+%!assert ([1,1], ones (1, 2))
+%!assert ([,1,1], ones (1, 2))
+%!assert ([1,1,], ones (1, 2))
+%!assert ([,1,1,], ones (1, 2))
+%!assert ([,1,1,;;], ones (1, 2))
+%!assert ([,1,1,;,;], ones (1, 2))
+%!assert ([,;,1,1], ones (1, 2))
+
+%!assert ([1;1], ones (2, 1))
+%!assert ([1,;1], ones (2, 1))
+%!assert ([1,;,;1], ones (2, 1))
+
+%!error eval ("[,,]")
+%!error eval ("[,,;,]")
+%!error eval ("[,;,,;,]")
+
+%!assert (isnull ([,]))
+%!assert (isnull ([;]))
+%!assert (isnull ([;;]))
+%!assert (isnull ([;,;]))
+%!assert (isnull ([,;,;,]))
+*/
--- a/libinterp/parse-tree/pt-tm-const.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/parse-tree/pt-tm-const.h	Fri Aug 10 09:09:51 2018 +0200
@@ -25,11 +25,12 @@
 
 #include "octave-config.h"
 
+#include <list>
+#include <memory>
 #include <string>
 
 #include "Array.h"
 #include "Sparse.h"
-#include "base-list.h"
 
 #include "data.h"
 #include "dim-vector.h"
@@ -43,395 +44,198 @@
   class tree_evaluator;
   class tree_matrix;
 
-  // General matrices.  This list type is much more work to handle than
-  // constant matrices, but it allows us to construct matrices from
-  // other matrices, variables, and functions.
-
-  // But first, some internal classes that make our job much easier.
-
-  class
-  tm_row_const
-  {
-  private:
-
-    class
-    tm_row_const_rep : public base_list<octave_value>
-    {
-    public:
-
-      tm_row_const_rep (void)
-        : m_count (1), m_dv (0, 0), m_all_str (false),
-          m_all_sq_str (false), m_all_dq_str (false),
-          m_some_str (false), m_all_real (false), m_all_cmplx (false),
-          m_all_mt (true), m_any_cell (false), m_any_sparse (false),
-          m_any_class (false), m_all_1x1 (false),
-          m_first_elem_is_struct (false), m_class_nm (), m_ok (false)
-      { }
-
-      tm_row_const_rep (const tree_argument_list& row, tree_evaluator *tw)
-        : m_count (1), m_dv (0, 0), m_all_str (false), m_all_sq_str (false),
-          m_some_str (false), m_all_real (false), m_all_cmplx (false),
-          m_all_mt (true), m_any_cell (false), m_any_sparse (false),
-          m_any_class (false), m_all_1x1 (! row.empty ()),
-          m_first_elem_is_struct (false), m_class_nm (), m_ok (false)
-      { init (row, tw); }
-
-      ~tm_row_const_rep (void) = default;
-
-      refcount<int> m_count;
-
-      dim_vector m_dv;
-
-      bool m_all_str;
-      bool m_all_sq_str;
-      bool m_all_dq_str;
-      bool m_some_str;
-      bool m_all_real;
-      bool m_all_cmplx;
-      bool m_all_mt;
-      bool m_any_cell;
-      bool m_any_sparse;
-      bool m_any_class;
-      bool m_all_1x1;
-      bool m_first_elem_is_struct;
-
-      std::string m_class_nm;
-
-      bool m_ok;
-
-      void do_init_element (const octave_value&, bool&);
-
-      void init (const tree_argument_list&, tree_evaluator *tw);
-
-      void cellify (void);
-
-    private:
-
-      tm_row_const_rep (const tm_row_const_rep&);
-
-      tm_row_const_rep& operator = (const tm_row_const_rep&);
-
-    };
-
-  public:
-
-    typedef tm_row_const_rep::iterator iterator;
-    typedef tm_row_const_rep::const_iterator const_iterator;
+  // Evaluate tree_matrix objects and convert them to octave_value
+  // arrays (full and sparse numeric, char, cell, struct, class and
+  // anything else that works like an array).  Use a separate class
+  // (tm_const) and pass the evaluator object to it instead of doing
+  // all this work in tree_evaluator::visit_matrix because the job is
+  // fairly large and requires extra data (stored in the tm_info
+  // class) for each row and for the overall array.
 
-    tm_row_const (void)
-      : m_rep (nullptr) { }
-
-    tm_row_const (const tree_argument_list& row, tree_evaluator *tw)
-      : m_rep (new tm_row_const_rep (row, tw)) { }
-
-    tm_row_const (const tm_row_const& x)
-      : m_rep (x.m_rep)
-    {
-      if (m_rep)
-        m_rep->m_count++;
-    }
-
-    tm_row_const& operator = (const tm_row_const& x)
-    {
-      if (this != &x && m_rep != x.m_rep)
-        {
-          if (m_rep && --m_rep->m_count == 0)
-            delete m_rep;
-
-          m_rep = x.m_rep;
-
-          if (m_rep)
-            m_rep->m_count++;
-        }
-
-      return *this;
-    }
-
-    ~tm_row_const (void)
-    {
-      if (m_rep && --m_rep->m_count == 0)
-        delete m_rep;
-    }
-
-    octave_idx_type rows (void) { return m_rep->m_dv(0); }
-    octave_idx_type cols (void) { return m_rep->m_dv(1); }
+  // Evaluate all elements of the array, recording info about each
+  // row, then create summary info for the full array.  Compute the
+  // result type and dimension first before copying values.
 
-    bool empty (void) const { return m_rep->empty (); }
-
-    size_t length (void) const { return m_rep->length (); }
-
-    dim_vector dims (void) { return m_rep->m_dv; }
-
-    bool all_strings_p (void) const { return m_rep->m_all_str; }
-    bool all_sq_strings_p (void) const { return m_rep->m_all_sq_str; }
-    bool all_dq_strings_p (void) const { return m_rep->m_all_dq_str; }
-    bool some_strings_p (void) const { return m_rep->m_some_str; }
-    bool all_real_p (void) const { return m_rep->m_all_real; }
-    bool all_complex_p (void) const { return m_rep->m_all_cmplx; }
-    bool all_empty_p (void) const { return m_rep->m_all_mt; }
-    bool any_cell_p (void) const { return m_rep->m_any_cell; }
-    bool any_sparse_p (void) const { return m_rep->m_any_sparse; }
-    bool any_class_p (void) const { return m_rep->m_any_class; }
-    bool all_1x1_p (void) const { return m_rep->m_all_1x1; }
-    bool first_elem_struct_p (void) const { return m_rep->m_first_elem_is_struct; }
+  // FIXME: Handle overloading of horzcat and vertcat for for built-in
+  // types.
 
-    std::string class_name (void) const { return m_rep->m_class_nm; }
-
-    void cellify (void) { m_rep->cellify (); }
-
-    operator bool () const { return (m_rep && m_rep->m_ok); }
-
-    iterator begin (void) { return m_rep->begin (); }
-    const_iterator begin (void) const { return m_rep->begin (); }
+  // Summary info about the current row or matrix.
 
-    iterator end (void) { return m_rep->end (); }
-    const_iterator end (void) const { return m_rep->end (); }
-
-  private:
-
-    tm_row_const_rep *m_rep;
-  };
-
-  class
-  tm_const : public base_list<tm_row_const>
+  class tm_info
   {
   public:
 
-    tm_const (const tree_matrix& tm, tree_evaluator *tw = nullptr)
-      : m_dv (0, 0), m_all_str (false), m_all_sq_str (false),
-        m_all_dq_str (false),
-        m_some_str (false), m_all_real (false), m_all_cmplx (false),
-        m_all_mt (true), m_any_cell (false), m_any_sparse (false),
-        m_any_class (false), m_class_nm (), m_ok (false)
-    { init (tm, tw); }
-
-    ~tm_const (void) = default;
-
-    octave_idx_type rows (void) const { return m_dv.elem (0); }
-    octave_idx_type cols (void) const { return m_dv.elem (1); }
+    tm_info (bool obj_is_empty)
+      : m_dv (0, 0), m_all_strings (true), m_all_sq_strings (true),
+        m_all_dq_strings (true), m_some_strings (false),
+        m_all_real (true), m_all_complex (true), m_all_empty (true),
+        m_any_cell (false), m_any_sparse (false),
+        m_any_class (false), m_all_1x1 (! obj_is_empty),
+        m_first_elem_is_struct (false), m_class_name ()
+    { }
 
     dim_vector dims (void) const { return m_dv; }
 
-    bool all_strings_p (void) const { return m_all_str; }
-    bool all_sq_strings_p (void) const { return m_all_sq_str; }
-    bool all_dq_strings_p (void) const { return m_all_dq_str; }
-    bool some_strings_p (void) const { return m_some_str; }
+    octave_idx_type rows (void) const { return m_dv(0); }
+    octave_idx_type cols (void) const { return m_dv(1); }
+
+    bool all_strings_p (void) const { return m_all_strings; }
+    bool all_sq_strings_p (void) const { return m_all_sq_strings; }
+    bool all_dq_strings_p (void) const { return m_all_dq_strings; }
+    bool some_strings_p (void) const { return m_some_strings; }
     bool all_real_p (void) const { return m_all_real; }
-    bool all_complex_p (void) const { return m_all_cmplx; }
-    bool all_empty_p (void) const { return m_all_mt; }
+    bool all_complex_p (void) const { return m_all_complex; }
+    bool all_empty_p (void) const { return m_all_empty; }
     bool any_cell_p (void) const { return m_any_cell; }
     bool any_sparse_p (void) const { return m_any_sparse; }
     bool any_class_p (void) const { return m_any_class; }
     bool all_1x1_p (void) const { return m_all_1x1; }
+    bool first_elem_struct_p (void) const { return m_first_elem_is_struct; }
 
-    std::string class_name (void) const { return m_class_nm; }
+    std::string class_name (void) const { return m_class_name; }
+
+  protected:
+
+    // Size of this row or matrix after evaluation.
+    dim_vector m_dv;
+
+    // Are all elements character strings?
+    bool m_all_strings;
+
+    // Are all elements double-quoted character strings?
+    bool m_all_sq_strings;
+
+    // Are all elements single-quoted character strings?
+    bool m_all_dq_strings;
+
+    // Are any elements character strings?
+    bool m_some_strings;
+
+    // Are all elements real valued?
+    bool m_all_real;
+
+    // Are all elements complex valued?
+    bool m_all_complex;
+
+    // Are all elements empty?
+    bool m_all_empty;
+
+    // Are any elements cells?
+    bool m_any_cell;
+
+    // Are any elements sparse arrays?
+    bool m_any_sparse;
+
+    // Are any elements sparse class objects?
+    bool m_any_class;
+
+    // Do all elements have dimensions 1x1?
+    bool m_all_1x1;
 
-    operator bool () const { return m_ok; }
+    // Is the first element a struct?
+    bool m_first_elem_is_struct;
+
+    // Class name of result.
+    std::string m_class_name;
+  };
+
+  class tm_row_const : public tm_info
+  {
+  public:
+
+    typedef std::list<octave_value>::iterator iterator;
+    typedef std::list<octave_value>::const_iterator const_iterator;
+
+    tm_row_const (void) = delete;
+
+    tm_row_const (const tree_argument_list& row, tree_evaluator& tw)
+      : tm_info (row.empty ()), m_values ()
+    {
+      init (row, tw);
+    }
+
+    tm_row_const (const tm_row_const&) = default;
+
+    tm_row_const& operator = (const tm_row_const&) = delete;
+
+    ~tm_row_const (void) = default;
+
+    iterator begin (void) { return m_values.begin (); }
+    const_iterator begin (void) const { return m_values.begin (); }
+
+    iterator end (void) { return m_values.end (); }
+    const_iterator end (void) const { return m_values.end (); }
+
+    bool empty (void) const { return m_values.empty (); }
+
+    size_t length (void) const { return m_values.size (); }
+
+    void cellify (void);
 
   private:
 
-    dim_vector m_dv;
+    std::list<octave_value> m_values;
 
-    bool m_all_str;
-    bool m_all_sq_str;
-    bool m_all_dq_str;
-    bool m_some_str;
-    bool m_all_real;
-    bool m_all_cmplx;
-    bool m_all_mt;
-    bool m_any_cell;
-    bool m_any_sparse;
-    bool m_any_class;
-    bool m_all_1x1;
+    void init_element (const octave_value&, bool&);
 
-    std::string m_class_nm;
-
-    bool m_ok;
-
-    tm_const (void);
-
-    tm_const (const tm_const&);
-
-    tm_const& operator = (const tm_const&);
-
-    void init (const tree_matrix& tm, tree_evaluator *tw);
+    void init (const tree_argument_list&, tree_evaluator& tw);
   };
 
-  template <typename TYPE, typename T>
-  void
-  single_type_concat (Array<T>& result, tm_const& tmp)
-  {
-    octave_idx_type r = 0;
-    octave_idx_type c = 0;
-
-    for (tm_row_const& row : tmp)
-      {
-        // Skip empty arrays to allow looser rules.
-        if (row.dims ().any_zero ())
-          continue;
-
-        for (auto& elt : row)
-          {
-            octave_quit ();
-
-            TYPE ra = octave_value_extract<TYPE> (elt);
-
-            // Skip empty arrays to allow looser rules.
-
-            if (! ra.isempty ())
-              {
-                result.insert (ra, r, c);
-
-                c += ra.columns ();
-              }
-          }
-
-        r += row.rows ();
-        c = 0;
-      }
-  }
-
-  template <typename TYPE, typename T>
-  void
-  single_type_concat (Array<T>& result, const dim_vector& dv,
-                      tm_const& tmp)
-  {
-    if (dv.any_zero ())
-      {
-        result = Array<T> (dv);
-        return;
-      }
-
-    if (tmp.length () == 1)
-      {
-        // If possible, forward the operation to liboctave.
-        // Single row.
-        tm_row_const& row = tmp.front ();
-        if (! (equal_types<T, char>::value || equal_types<T, octave_value>::value)
-            && row.all_1x1_p ())
-          {
-            // Optimize all scalars case.
-            result.clear (dv);
-            assert (static_cast<size_t> (result.numel ()) == row.length ());
-            octave_idx_type i = 0;
-            for (const auto& elt : row)
-              result(i++) = octave_value_extract<T> (elt);
-
-            return;
-          }
-
-        octave_idx_type ncols = row.length ();
-        octave_idx_type i = 0;
-        OCTAVE_LOCAL_BUFFER (Array<T>, array_list, ncols);
-
-        for (const auto& elt : row)
-          {
-            octave_quit ();
-
-            array_list[i++] = octave_value_extract<TYPE> (elt);
-          }
-
-        result = Array<T>::cat (-2, ncols, array_list);
-      }
-    else
-      {
-        result = Array<T> (dv);
-        single_type_concat<TYPE> (result, tmp);
-      }
-  }
-
-  template <typename TYPE, typename T>
-  void
-  single_type_concat (Sparse<T>& result, const dim_vector& dv,
-                      tm_const& tmp)
+  class tm_const : public tm_info
   {
-    if (dv.any_zero ())
-      {
-        result = Sparse<T> (dv);
-        return;
-      }
+  public:
+
+    typedef std::list<tm_row_const>::iterator iterator;
+    typedef std::list<tm_row_const>::const_iterator const_iterator;
+
+    tm_const (void) = delete;
+
+    tm_const (const tree_matrix& tm, tree_evaluator& tw)
+      : tm_info (tm.empty ()), m_evaluator (tw), m_tm_rows ()
+    {
+      init (tm);
+    }
 
-    // Sparse matrices require preallocation for efficient indexing; besides,
-    // only horizontal concatenation can be efficiently handled by indexing.
-    // So we just cat all rows through liboctave, then cat the final column.
-    octave_idx_type nrows = tmp.length ();
-    octave_idx_type j = 0;
-    OCTAVE_LOCAL_BUFFER (Sparse<T>, sparse_row_list, nrows);
-    for (tm_row_const& row : tmp)
-      {
-        octave_idx_type ncols = row.length ();
-        octave_idx_type i = 0;
-        OCTAVE_LOCAL_BUFFER (Sparse<T>, sparse_list, ncols);
+    // No copying!
+
+    tm_const (const tm_const&) = delete;
+
+    tm_const& operator = (const tm_const&) = delete;
 
-        for (auto& elt : row)
-          {
-            octave_quit ();
+    ~tm_const (void) = default;
 
-            sparse_list[i] = octave_value_extract<TYPE> (elt);
-            i++;
-          }
+    octave_value concat (char string_fill_char) const;
 
-        Sparse<T> stmp = Sparse<T>::cat (-2, ncols, sparse_list);
-        sparse_row_list[j] = stmp;
-        j++;
-      }
+  private:
 
-    result = Sparse<T>::cat (-1, nrows, sparse_row_list);
-  }
+    tree_evaluator& m_evaluator;
 
-  template <typename MAP>
-  void
-  single_type_concat (octave_map& result, const dim_vector& dv,
-                      tm_const& tmp)
-  {
-    if (dv.any_zero ())
-      {
-        result = octave_map (dv);
-        return;
-      }
+    // The list of lists of octave_value objects that contain the
+    // values of elements in each row of the tree_matrix object we are
+    // evaluating.
+
+    std::list<tm_row_const> m_tm_rows;
 
-    octave_idx_type nrows = tmp.length ();
-    octave_idx_type j = 0;
-    OCTAVE_LOCAL_BUFFER (octave_map, map_row_list, nrows);
-    for (tm_row_const& row : tmp)
-      {
-        octave_idx_type ncols = row.length ();
-        octave_idx_type i = 0;
-        OCTAVE_LOCAL_BUFFER (MAP, map_list, ncols);
+    void init (const tree_matrix& tm);
 
-        for (auto& elt : row)
-          {
-            octave_quit ();
+    octave_value char_array_concat (char string_fill_char) const;
+
+    octave_value class_concat (void) const;
 
-            map_list[i] = octave_value_extract<MAP> (elt);
-            i++;
-          }
+    octave_value generic_concat (void) const;
 
-        octave_map mtmp = octave_map::cat (-2, ncols, map_list);
-        map_row_list[j] = mtmp;
-        j++;
-      }
-
-    result = octave_map::cat (-1, nrows, map_row_list);
-  }
+    template <typename TYPE>
+    void array_concat_internal (TYPE& result) const;
 
-  template <typename TYPE>
-  octave_value
-  do_single_type_concat (const dim_vector& dv, tm_const& tmp)
-  {
-    TYPE result;
-
-    single_type_concat<TYPE> (result, dv, tmp);
+    template <typename TYPE>
+    TYPE array_concat (void) const;
 
-    return result;
-  }
+    template <typename TYPE>
+    TYPE sparse_array_concat (void) const;
 
-  template <>
-  octave_value
-  do_single_type_concat<octave_map> (const dim_vector& dv,
-                                     tm_const& tmp);
-
-  extern octave_value do_class_concat (tm_const& tmc);
+    template <typename MAP>
+    octave_map map_concat (void) const;
+  };
 }
 
 #endif
--- a/libinterp/parse-tree/pt-unop.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/parse-tree/pt-unop.h	Fri Aug 10 09:09:51 2018 +0200
@@ -30,6 +30,7 @@
 class octave_value;
 class octave_value_list;
 
+#include "ov.h"
 #include "pt-exp.h"
 #include "pt-walk.h"
 
--- a/libinterp/parse-tree/pt.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/libinterp/parse-tree/pt.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -24,7 +24,6 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
 #include <sstream>
 #include <string>
 
--- a/libinterp/version.cc	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,133 +0,0 @@
-/*
-
-Copyright (C) 2013-2018 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
-<https://www.gnu.org/licenses/>.
-
-*/
-
-#if defined (HAVE_CONFIG_H)
-#  include "config.h"
-#endif
-
-#include <string>
-
-#include "defaults.h"
-#include "version.h"
-
-static std::string
-octave_warranty_statement (const std::string& extra_info = "")
-{
-  return "There is ABSOLUTELY NO WARRANTY; not even for MERCHANTABILITY or\n\
-FITNESS FOR A PARTICULAR PURPOSE."
-         + extra_info;
-}
-
-static std::string
-format_url (bool html, const std::string& url)
-{
-  return html ? R"(<a href=")" + url + R"(">)" + url + "</a>" : url;
-}
-
-std::string
-octave_www_statement (bool html)
-{
-  return "Additional information about Octave is available at "
-         + format_url (html, "https://www.octave.org") + ".";
-}
-
-std::string
-octave_contrib_statement (bool html)
-{
-  return "Please contribute if you find this software useful.\n\
-For more information, visit "
-         + format_url (html, "https://www.octave.org/get-involved.html");
-}
-
-std::string
-octave_bugs_statement (bool html)
-{
-  return "Read " + format_url (html, "https://www.octave.org/bugs.html")
-         + " to learn how to submit bug reports.";
-}
-
-std::string
-octave_name_version_and_copyright (void)
-{
-  // The GNU coding standards say that on the first line printed by
-  // --version, the version number should follow the last space on the
-  // line.
-
-  return "GNU Octave, version " OCTAVE_VERSION "\n" OCTAVE_COPYRIGHT;
-}
-
-std::string
-octave_name_version_copyright_copying_and_warranty
-  (bool html, const std::string& extra_info)
-{
-  std::string br = (html ? "<br>\n" : "\n");
-  std::string sep = (html ? "\n</p>\n<p>\n" : "\n\n");
-
-  return octave_name_version_and_copyright ()
-         + br
-         + "This is free software; see the source code for copying conditions."
-         + br
-         + octave_warranty_statement (extra_info)
-         + sep
-         + R"(Octave was configured for ")"
-         + octave::config::canonical_host_type ()
-         + R"(".)";
-}
-
-std::string
-octave_name_version_copyright_copying_warranty_and_bugs
-  (bool html, const std::string& extra_info)
-{
-  std::string sep = (html ? "\n</p>\n<p>\n" : "\n\n");
-
-  std::string msg;
-
-  if (html)
-    msg = "<p>\n";
-
-  msg += octave_name_version_copyright_copying_and_warranty (html, extra_info)
-         + sep
-         + octave_www_statement (html)
-         + sep
-         + octave_contrib_statement (html)
-         + sep
-         + octave_bugs_statement (html)
-         + (html ? "\n</p>" : "");
-
-  return msg;
-}
-
-std::string
-octave_startup_message (bool html)
-{
-  std::string msg
-    = octave_name_version_copyright_copying_warranty_and_bugs
-        (html, "  For details, type 'warranty'.");
-
-  msg += (html ? "<p>\n" : "\n");
-
-  msg += "For information about changes from previous versions, type 'news'.";
-
-  msg += (html ? "\n</p>" : "");
-
-  return msg;
-}
--- a/libinterp/version.in.h	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-// %NO_EDIT_WARNING%
-/*
-
-Copyright (C) 1992-2018 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
-<https://www.gnu.org/licenses/>.
-
-*/
-
-#if ! defined (octave_version_h)
-#define octave_version_h 1
-
-#include "octave-config.h"
-
-#define OCTAVE_VERSION %OCTAVE_VERSION%
-
-#define OCTAVE_MAJOR_VERSION %OCTAVE_MAJOR_VERSION%
-
-#define OCTAVE_MINOR_VERSION %OCTAVE_MINOR_VERSION%
-
-#define OCTAVE_PATCH_VERSION %OCTAVE_PATCH_VERSION%
-
-// The "API version" is used as a way of checking that interfaces in the
-// liboctave and libinterp libraries haven't changed in a backwardly
-// incompatible way when loading .oct files.  A better way to do that is
-// with library versioning, but not all systems support that.
-// NOTE: This macro will be removed in a future version of Octave.  If
-// you insist on checking for features using a version number, use the
-// OCTAVE_MAJOR_VERSION, OCTAVE_MINOR_VERSION, and
-// OCTAVE_PATCH_VERSION macros instead.
-#define OCTAVE_API_VERSION %OCTAVE_API_VERSION%
-
-#define OCTAVE_RELEASE_DATE %OCTAVE_RELEASE_DATE%
-
-#define OCTAVE_COPYRIGHT %OCTAVE_COPYRIGHT%
-
-#include <string>
-
-extern OCTINTERP_API std::string octave_www_statement (bool html = false);
-
-extern OCTINTERP_API std::string octave_contrib_statement (bool html = false);
-
-extern OCTINTERP_API std::string octave_bugs_statement (bool html = false);
-
-extern OCTINTERP_API std::string octave_name_version_and_copyright (void);
-
-extern OCTINTERP_API std::string
-octave_name_version_copyright_copying_and_warranty
-  (bool html = false, const std::string& extra_info = "");
-
-extern OCTINTERP_API std::string
-octave_name_version_copyright_copying_warranty_and_bugs
-  (bool html = false, const std::string& extra_info = "");
-
-extern OCTINTERP_API std::string octave_startup_message (bool html = false);
-
-#endif
--- a/liboctave/array/Array.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/array/Array.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -26,7 +26,7 @@
 // C++ source files that should have included config.h before including
 // this file.
 
-#include <iostream>
+#include <ostream>
 
 #include "Array-util.h"
 #include "Array.h"
--- a/liboctave/array/CColVector.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/array/CColVector.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -25,7 +25,8 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <istream>
+#include <ostream>
 
 #include "Array-util.h"
 #include "functor.h"
--- a/liboctave/array/CDiagMatrix.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/array/CDiagMatrix.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -25,7 +25,7 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <ostream>
 
 #include "Array-util.h"
 #include "lo-error.h"
@@ -261,7 +261,7 @@
 
   char c = *s;
   if (c == 'f' || c == 'F')
-    return row (static_cast<octave_idx_type>(0));
+    return row (static_cast<octave_idx_type> (0));
   else if (c == 'l' || c == 'L')
     return row (rows () - 1);
   else
@@ -291,7 +291,7 @@
 
   char c = *s;
   if (c == 'f' || c == 'F')
-    return column (static_cast<octave_idx_type>(0));
+    return column (static_cast<octave_idx_type> (0));
   else if (c == 'l' || c == 'L')
     return column (cols () - 1);
   else
--- a/liboctave/array/CMatrix.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/array/CMatrix.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -28,8 +28,9 @@
 
 #include <algorithm>
 #include <complex>
-#include <iostream>
+#include <istream>
 #include <limits>
+#include <ostream>
 
 #include "Array-util.h"
 #include "CDiagMatrix.h"
@@ -1104,234 +1105,40 @@
 
 #else
 
-#include "lo-fftpack-proto.h"
-
 ComplexMatrix
 ComplexMatrix::fourier (void) const
 {
-  ComplexMatrix retval;
-
-  octave_idx_type nr = rows ();
-  octave_idx_type nc = cols ();
-  octave_idx_type nsamples;
-
-  F77_INT npts;
-
-  if (nr == 1 || nc == 1)
-    {
-      npts = octave::to_f77_int (nr > nc ? nr : nc);
-      nsamples = 1;
-    }
-  else
-    {
-      npts = octave::to_f77_int (nr);
-      nsamples = nc;
-    }
-
-  octave_idx_type nn = 4*npts+15;
-
-  Array<Complex> wsave (dim_vector (nn, 1));
-  Complex *pwsave = wsave.fortran_vec ();
-
-  retval = *this;
-  Complex *tmp_data = retval.fortran_vec ();
-
-  F77_FUNC (zffti, ZFFTI) (npts, F77_DBLE_CMPLX_ARG (pwsave));
-
-  for (octave_idx_type j = 0; j < nsamples; j++)
-    {
-      octave_quit ();
-
-      F77_FUNC (zfftf, ZFFTF) (npts, F77_DBLE_CMPLX_ARG (&tmp_data[npts*j]),
-                               F77_DBLE_CMPLX_ARG (pwsave));
-    }
-
-  return retval;
+  (*current_liboctave_error_handler)
+    ("support for FFTW was unavailable or disabled when liboctave was built");
+
+  return ComplexMatrix ();
 }
 
 ComplexMatrix
 ComplexMatrix::ifourier (void) const
 {
-  ComplexMatrix retval;
-
-  octave_idx_type nr = rows ();
-  octave_idx_type nc = cols ();
-  octave_idx_type nsamples;
-
-  F77_INT npts;
-
-  if (nr == 1 || nc == 1)
-    {
-      npts = octave::to_f77_int (nr > nc ? nr : nc);
-      nsamples = 1;
-    }
-  else
-    {
-      npts = octave::to_f77_int (nr);
-      nsamples = nc;
-    }
-
-  octave_idx_type nn = 4*npts+15;
-
-  Array<Complex> wsave (dim_vector (nn, 1));
-  Complex *pwsave = wsave.fortran_vec ();
-
-  retval = *this;
-  Complex *tmp_data = retval.fortran_vec ();
-
-  F77_FUNC (zffti, ZFFTI) (npts, F77_DBLE_CMPLX_ARG (pwsave));
-
-  for (octave_idx_type j = 0; j < nsamples; j++)
-    {
-      octave_quit ();
-
-      F77_FUNC (zfftb, ZFFTB) (npts, F77_DBLE_CMPLX_ARG (&tmp_data[npts*j]),
-                               F77_DBLE_CMPLX_ARG (pwsave));
-    }
-
-  for (octave_idx_type j = 0; j < npts*nsamples; j++)
-    tmp_data[j] = tmp_data[j] / static_cast<double> (npts);
-
-  return retval;
+  (*current_liboctave_error_handler)
+    ("support for FFTW was unavailable or disabled when liboctave was built");
+
+  return ComplexMatrix ();
 }
 
 ComplexMatrix
 ComplexMatrix::fourier2d (void) const
 {
-  ComplexMatrix retval;
-
-  F77_INT nr = octave::to_f77_int (rows ());
-  F77_INT nc = octave::to_f77_int (cols ());
-
-  F77_INT npts, nsamples;
-
-  if (nr == 1 || nc == 1)
-    {
-      npts = (nr > nc ? nr : nc);
-      nsamples = 1;
-    }
-  else
-    {
-      npts = nr;
-      nsamples = nc;
-    }
-
-  F77_INT nn = 4*npts+15;
-
-  Array<Complex> wsave (dim_vector (nn, 1));
-  Complex *pwsave = wsave.fortran_vec ();
-
-  retval = *this;
-  Complex *tmp_data = retval.fortran_vec ();
-
-  F77_FUNC (zffti, ZFFTI) (npts, F77_DBLE_CMPLX_ARG (pwsave));
-
-  for (F77_INT j = 0; j < nsamples; j++)
-    {
-      octave_quit ();
-
-      F77_FUNC (zfftf, ZFFTF) (npts, F77_DBLE_CMPLX_ARG (&tmp_data[npts*j]),
-                               F77_DBLE_CMPLX_ARG (pwsave));
-    }
-
-  npts = nc;
-  nsamples = nr;
-  nn = 4*npts+15;
-
-  wsave.resize (dim_vector (nn, 1));
-  pwsave = wsave.fortran_vec ();
-
-  Array<Complex> tmp (dim_vector (npts, 1));
-  Complex *prow = tmp.fortran_vec ();
-
-  F77_FUNC (zffti, ZFFTI) (npts, F77_DBLE_CMPLX_ARG (pwsave));
-
-  for (F77_INT j = 0; j < nsamples; j++)
-    {
-      octave_quit ();
-
-      for (F77_INT i = 0; i < npts; i++)
-        prow[i] = tmp_data[i*nr + j];
-
-      F77_FUNC (zfftf, ZFFTF) (npts, F77_DBLE_CMPLX_ARG (prow),
-                               F77_DBLE_CMPLX_ARG (pwsave));
-
-      for (F77_INT i = 0; i < npts; i++)
-        tmp_data[i*nr + j] = prow[i];
-    }
-
-  return retval;
+  (*current_liboctave_error_handler)
+    ("support for FFTW was unavailable or disabled when liboctave was built");
+
+  return ComplexMatrix ();
 }
 
 ComplexMatrix
 ComplexMatrix::ifourier2d (void) const
 {
-  ComplexMatrix retval;
-
-  F77_INT nr = octave::to_f77_int (rows ());
-  F77_INT nc = octave::to_f77_int (cols ());
-
-  F77_INT npts, nsamples;
-
-  if (nr == 1 || nc == 1)
-    {
-      npts = (nr > nc ? nr : nc);
-      nsamples = 1;
-    }
-  else
-    {
-      npts = nr;
-      nsamples = nc;
-    }
-
-  F77_INT nn = 4*npts+15;
-
-  Array<Complex> wsave (dim_vector (nn, 1));
-  Complex *pwsave = wsave.fortran_vec ();
-
-  retval = *this;
-  Complex *tmp_data = retval.fortran_vec ();
-
-  F77_FUNC (zffti, ZFFTI) (npts, F77_DBLE_CMPLX_ARG (pwsave));
-
-  for (F77_INT j = 0; j < nsamples; j++)
-    {
-      octave_quit ();
-
-      F77_FUNC (zfftb, ZFFTB) (npts, F77_DBLE_CMPLX_ARG (&tmp_data[npts*j]),
-                               F77_DBLE_CMPLX_ARG (pwsave));
-    }
-
-  for (F77_INT j = 0; j < npts*nsamples; j++)
-    tmp_data[j] = tmp_data[j] / static_cast<double> (npts);
-
-  npts = nc;
-  nsamples = nr;
-  nn = 4*npts+15;
-
-  wsave.resize (dim_vector (nn, 1));
-  pwsave = wsave.fortran_vec ();
-
-  Array<Complex> tmp (dim_vector (npts, 1));
-  Complex *prow = tmp.fortran_vec ();
-
-  F77_FUNC (zffti, ZFFTI) (npts, F77_DBLE_CMPLX_ARG (pwsave));
-
-  for (F77_INT j = 0; j < nsamples; j++)
-    {
-      octave_quit ();
-
-      for (F77_INT i = 0; i < npts; i++)
-        prow[i] = tmp_data[i*nr + j];
-
-      F77_FUNC (zfftb, ZFFTB) (npts, F77_DBLE_CMPLX_ARG (prow),
-                               F77_DBLE_CMPLX_ARG (pwsave));
-
-      for (F77_INT i = 0; i < npts; i++)
-        tmp_data[i*nr + j] = prow[i] / static_cast<double> (npts);
-    }
-
-  return retval;
+  (*current_liboctave_error_handler)
+    ("support for FFTW was unavailable or disabled when liboctave was built");
+
+  return ComplexMatrix ();
 }
 
 #endif
@@ -3819,7 +3626,7 @@
   // The last column is unused so temporarily store delta there
   Complex *delta = &retval(0, n-1);
   for (octave_idx_type i = 0; i < m; i++)
-    delta[i] = (x2(i) - x1(i)) / (n - 1.0);
+    delta[i] = (x1(i) == x2(i)) ? 0 : (x2(i) - x1(i)) / (n - 1.0);
 
   for (octave_idx_type j = 1; j < n-1; j++)
     for (octave_idx_type i = 0; i < m; i++)
--- a/liboctave/array/CNDArray.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/array/CNDArray.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -26,7 +26,8 @@
 #endif
 
 #include <complex>
-#include <iostream>
+#include <istream>
+#include <ostream>
 
 #include "Array-util.h"
 #include "CNDArray.h"
@@ -186,299 +187,58 @@
 
 #else
 
-#include "lo-fftpack-proto.h"
-
 ComplexNDArray
 ComplexNDArray::fourier (int dim) const
 {
-  dim_vector dv = dims ();
-
-  if (dim > dv.ndims () || dim < 0)
-    return ComplexNDArray ();
-
-  ComplexNDArray retval (dv);
-  octave_idx_type npts = dv(dim);
-  octave_idx_type nn = 4*npts+15;
-  Array<Complex> wsave (dim_vector (nn, 1));
-  Complex *pwsave = wsave.fortran_vec ();
-
-  OCTAVE_LOCAL_BUFFER (Complex, tmp, npts);
-
-  octave_idx_type stride = 1;
-
-  for (int i = 0; i < dim; i++)
-    stride *= dv(i);
+  (*current_liboctave_error_handler)
+    ("support for FFTW was unavailable or disabled when liboctave was built");
 
-  octave_idx_type howmany = numel () / npts;
-  howmany = (stride == 1 ? howmany : (howmany > stride ? stride : howmany));
-  octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
-  octave_idx_type dist = (stride == 1 ? npts : 1);
-
-  F77_FUNC (zffti, ZFFTI) (npts, F77_DBLE_CMPLX_ARG (pwsave));
-
-  for (octave_idx_type k = 0; k < nloop; k++)
-    {
-      for (octave_idx_type j = 0; j < howmany; j++)
-        {
-          octave_quit ();
-
-          for (octave_idx_type i = 0; i < npts; i++)
-            tmp[i] = elem ((i + k*npts)*stride + j*dist);
-
-          F77_FUNC (zfftf, ZFFTF) (npts, F77_DBLE_CMPLX_ARG (tmp),
-                                   F77_DBLE_CMPLX_ARG (pwsave));
-
-          for (octave_idx_type i = 0; i < npts; i++)
-            retval((i + k*npts)*stride + j*dist) = tmp[i];
-        }
-    }
-
-  return retval;
+  return ComplexNDArray ();
 }
 
 ComplexNDArray
 ComplexNDArray::ifourier (int dim) const
 {
-  dim_vector dv = dims ();
-
-  if (dim > dv.ndims () || dim < 0)
-    return ComplexNDArray ();
-
-  ComplexNDArray retval (dv);
-  octave_idx_type npts = dv(dim);
-  octave_idx_type nn = 4*npts+15;
-  Array<Complex> wsave (dim_vector (nn, 1));
-  Complex *pwsave = wsave.fortran_vec ();
-
-  OCTAVE_LOCAL_BUFFER (Complex, tmp, npts);
-
-  octave_idx_type stride = 1;
-
-  for (int i = 0; i < dim; i++)
-    stride *= dv(i);
+  (*current_liboctave_error_handler)
+    ("support for FFTW was unavailable or disabled when liboctave was built");
 
-  octave_idx_type howmany = numel () / npts;
-  howmany = (stride == 1 ? howmany : (howmany > stride ? stride : howmany));
-  octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
-  octave_idx_type dist = (stride == 1 ? npts : 1);
-
-  F77_FUNC (zffti, ZFFTI) (npts, F77_DBLE_CMPLX_ARG (pwsave));
-
-  for (octave_idx_type k = 0; k < nloop; k++)
-    {
-      for (octave_idx_type j = 0; j < howmany; j++)
-        {
-          octave_quit ();
-
-          for (octave_idx_type i = 0; i < npts; i++)
-            tmp[i] = elem ((i + k*npts)*stride + j*dist);
-
-          F77_FUNC (zfftb, ZFFTB) (npts, F77_DBLE_CMPLX_ARG (tmp),
-                                   F77_DBLE_CMPLX_ARG (pwsave));
-
-          for (octave_idx_type i = 0; i < npts; i++)
-            retval((i + k*npts)*stride + j*dist) = tmp[i] /
-                                                   static_cast<double> (npts);
-        }
-    }
-
-  return retval;
+  return ComplexNDArray ();
 }
 
 ComplexNDArray
 ComplexNDArray::fourier2d (void) const
 {
-  dim_vector dv = dims ();
-  dim_vector dv2 (dv(0), dv(1));
-  int rank = 2;
-  ComplexNDArray retval (*this);
-  octave_idx_type stride = 1;
-
-  for (int i = 0; i < rank; i++)
-    {
-      octave_idx_type npts = dv2(i);
-      octave_idx_type nn = 4*npts+15;
-      Array<Complex> wsave (dim_vector (nn, 1));
-      Complex *pwsave = wsave.fortran_vec ();
-      Array<Complex> row (dim_vector (npts, 1));
-      Complex *prow = row.fortran_vec ();
-
-      octave_idx_type howmany = numel () / npts;
-      howmany = (stride == 1 ? howmany
-                             : (howmany > stride ? stride : howmany));
-      octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
-      octave_idx_type dist = (stride == 1 ? npts : 1);
+  (*current_liboctave_error_handler)
+    ("support for FFTW was unavailable or disabled when liboctave was built");
 
-      F77_FUNC (zffti, ZFFTI) (npts, F77_DBLE_CMPLX_ARG (pwsave));
-
-      for (octave_idx_type k = 0; k < nloop; k++)
-        {
-          for (octave_idx_type j = 0; j < howmany; j++)
-            {
-              octave_quit ();
-
-              for (octave_idx_type l = 0; l < npts; l++)
-                prow[l] = retval((l + k*npts)*stride + j*dist);
-
-              F77_FUNC (zfftf, ZFFTF) (npts, F77_DBLE_CMPLX_ARG (prow),
-                                       F77_DBLE_CMPLX_ARG (pwsave));
-
-              for (octave_idx_type l = 0; l < npts; l++)
-                retval((l + k*npts)*stride + j*dist) = prow[l];
-            }
-        }
-
-      stride *= dv2(i);
-    }
-
-  return retval;
+  return ComplexNDArray ();
 }
 
 ComplexNDArray
 ComplexNDArray::ifourier2d (void) const
 {
-  dim_vector dv = dims ();
-  dim_vector dv2 (dv(0), dv(1));
-  int rank = 2;
-  ComplexNDArray retval (*this);
-  octave_idx_type stride = 1;
-
-  for (int i = 0; i < rank; i++)
-    {
-      octave_idx_type npts = dv2(i);
-      octave_idx_type nn = 4*npts+15;
-      Array<Complex> wsave (dim_vector (nn, 1));
-      Complex *pwsave = wsave.fortran_vec ();
-      Array<Complex> row (dim_vector (npts, 1));
-      Complex *prow = row.fortran_vec ();
-
-      octave_idx_type howmany = numel () / npts;
-      howmany = (stride == 1 ? howmany
-                             : (howmany > stride ? stride : howmany));
-      octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
-      octave_idx_type dist = (stride == 1 ? npts : 1);
-
-      F77_FUNC (zffti, ZFFTI) (npts, F77_DBLE_CMPLX_ARG (pwsave));
+  (*current_liboctave_error_handler)
+    ("support for FFTW was unavailable or disabled when liboctave was built");
 
-      for (octave_idx_type k = 0; k < nloop; k++)
-        {
-          for (octave_idx_type j = 0; j < howmany; j++)
-            {
-              octave_quit ();
-
-              for (octave_idx_type l = 0; l < npts; l++)
-                prow[l] = retval((l + k*npts)*stride + j*dist);
-
-              F77_FUNC (zfftb, ZFFTB) (npts, F77_DBLE_CMPLX_ARG (prow),
-                                       F77_DBLE_CMPLX_ARG (pwsave));
-
-              for (octave_idx_type l = 0; l < npts; l++)
-                retval((l + k*npts)*stride + j*dist) =
-                  prow[l] / static_cast<double> (npts);
-            }
-        }
-
-      stride *= dv2(i);
-    }
-
-  return retval;
+  return ComplexNDArray ();
 }
 
 ComplexNDArray
 ComplexNDArray::fourierNd (void) const
 {
-  dim_vector dv = dims ();
-  int rank = dv.ndims ();
-  ComplexNDArray retval (*this);
-  octave_idx_type stride = 1;
-
-  for (int i = 0; i < rank; i++)
-    {
-      octave_idx_type npts = dv(i);
-      octave_idx_type nn = 4*npts+15;
-      Array<Complex> wsave (dim_vector (nn, 1));
-      Complex *pwsave = wsave.fortran_vec ();
-      Array<Complex> row (dim_vector (npts, 1));
-      Complex *prow = row.fortran_vec ();
-
-      octave_idx_type howmany = numel () / npts;
-      howmany = (stride == 1 ? howmany
-                             : (howmany > stride ? stride : howmany));
-      octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
-      octave_idx_type dist = (stride == 1 ? npts : 1);
-
-      F77_FUNC (zffti, ZFFTI) (npts, F77_DBLE_CMPLX_ARG (pwsave));
+  (*current_liboctave_error_handler)
+    ("support for FFTW was unavailable or disabled when liboctave was built");
 
-      for (octave_idx_type k = 0; k < nloop; k++)
-        {
-          for (octave_idx_type j = 0; j < howmany; j++)
-            {
-              octave_quit ();
-
-              for (octave_idx_type l = 0; l < npts; l++)
-                prow[l] = retval((l + k*npts)*stride + j*dist);
-
-              F77_FUNC (zfftf, ZFFTF) (npts, F77_DBLE_CMPLX_ARG (prow),
-                                       F77_DBLE_CMPLX_ARG (pwsave));
-
-              for (octave_idx_type l = 0; l < npts; l++)
-                retval((l + k*npts)*stride + j*dist) = prow[l];
-            }
-        }
-
-      stride *= dv(i);
-    }
-
-  return retval;
+  return ComplexNDArray ();
 }
 
 ComplexNDArray
 ComplexNDArray::ifourierNd (void) const
 {
-  dim_vector dv = dims ();
-  int rank = dv.ndims ();
-  ComplexNDArray retval (*this);
-  octave_idx_type stride = 1;
-
-  for (int i = 0; i < rank; i++)
-    {
-      octave_idx_type npts = dv(i);
-      octave_idx_type nn = 4*npts+15;
-      Array<Complex> wsave (dim_vector (nn, 1));
-      Complex *pwsave = wsave.fortran_vec ();
-      Array<Complex> row (dim_vector (npts, 1));
-      Complex *prow = row.fortran_vec ();
-
-      octave_idx_type howmany = numel () / npts;
-      howmany = (stride == 1 ? howmany
-                             : (howmany > stride ? stride : howmany));
-      octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
-      octave_idx_type dist = (stride == 1 ? npts : 1);
-
-      F77_FUNC (zffti, ZFFTI) (npts, F77_DBLE_CMPLX_ARG (pwsave));
+  (*current_liboctave_error_handler)
+    ("support for FFTW was unavailable or disabled when liboctave was built");
 
-      for (octave_idx_type k = 0; k < nloop; k++)
-        {
-          for (octave_idx_type j = 0; j < howmany; j++)
-            {
-              octave_quit ();
-
-              for (octave_idx_type l = 0; l < npts; l++)
-                prow[l] = retval((l + k*npts)*stride + j*dist);
-
-              F77_FUNC (zfftb, ZFFTB) (npts, F77_DBLE_CMPLX_ARG (prow),
-                                       F77_DBLE_CMPLX_ARG (pwsave));
-
-              for (octave_idx_type l = 0; l < npts; l++)
-                retval((l + k*npts)*stride + j*dist) =
-                  prow[l] / static_cast<double> (npts);
-            }
-        }
-
-      stride *= dv(i);
-    }
-
-  return retval;
+  return ComplexNDArray ();
 }
 
 #endif
--- a/liboctave/array/CRowVector.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/array/CRowVector.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -24,7 +24,8 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <istream>
+#include <ostream>
 
 #include "Array-util.h"
 #include "functor.h"
@@ -432,7 +433,7 @@
 
   retval(0) = x1;
 
-  Complex delta = (x2 - x1) / (n - 1.0);
+  Complex delta = (x1 == x2) ? 0 : (x2 - x1) / (n - 1.0);
   for (octave_idx_type i = 1; i < n-1; i++)
     retval(i) = x1 + static_cast<double> (i)*delta;
 
--- a/liboctave/array/CSparse.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/array/CSparse.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -27,7 +27,8 @@
 #endif
 
 #include <complex>
-#include <iostream>
+#include <istream>
+#include <ostream>
 
 #include "quit.h"
 #include "lo-ieee.h"
@@ -6045,14 +6046,14 @@
               END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
 
               retval = SparseComplexMatrix
-                       (static_cast<octave_idx_type>(X->nrow),
-                        static_cast<octave_idx_type>(X->ncol),
-                        static_cast<octave_idx_type>(X->nzmax));
+                       (static_cast<octave_idx_type> (X->nrow),
+                        static_cast<octave_idx_type> (X->ncol),
+                        static_cast<octave_idx_type> (X->nzmax));
               for (octave_idx_type j = 0;
-                   j <= static_cast<octave_idx_type>(X->ncol); j++)
+                   j <= static_cast<octave_idx_type> (X->ncol); j++)
                 retval.xcidx (j) = static_cast<octave_idx_type *>(X->p)[j];
               for (octave_idx_type j = 0;
-                   j < static_cast<octave_idx_type>(X->nzmax); j++)
+                   j < static_cast<octave_idx_type> (X->nzmax); j++)
                 {
                   retval.xridx (j) = static_cast<octave_idx_type *>(X->i)[j];
                   retval.xdata (j) = static_cast<Complex *>(X->x)[j];
@@ -6579,14 +6580,14 @@
               END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
 
               retval = SparseComplexMatrix
-                       (static_cast<octave_idx_type>(X->nrow),
-                        static_cast<octave_idx_type>(X->ncol),
-                        static_cast<octave_idx_type>(X->nzmax));
+                       (static_cast<octave_idx_type> (X->nrow),
+                        static_cast<octave_idx_type> (X->ncol),
+                        static_cast<octave_idx_type> (X->nzmax));
               for (octave_idx_type j = 0;
-                   j <= static_cast<octave_idx_type>(X->ncol); j++)
+                   j <= static_cast<octave_idx_type> (X->ncol); j++)
                 retval.xcidx (j) = static_cast<octave_idx_type *>(X->p)[j];
               for (octave_idx_type j = 0;
-                   j < static_cast<octave_idx_type>(X->nzmax); j++)
+                   j < static_cast<octave_idx_type> (X->nzmax); j++)
                 {
                   retval.xridx (j) = static_cast<octave_idx_type *>(X->i)[j];
                   retval.xdata (j) = static_cast<Complex *>(X->x)[j];
@@ -7525,61 +7526,61 @@
 ComplexMatrix
 operator * (const ComplexMatrix& m, const SparseMatrix& a)
 {
-  FULL_SPARSE_MUL (ComplexMatrix, double, Complex (0.,0.));
+  FULL_SPARSE_MUL (ComplexMatrix, double);
 }
 
 ComplexMatrix
 operator * (const Matrix& m, const SparseComplexMatrix& a)
 {
-  FULL_SPARSE_MUL (ComplexMatrix, Complex, Complex (0.,0.));
+  FULL_SPARSE_MUL (ComplexMatrix, Complex);
 }
 
 ComplexMatrix
 operator * (const ComplexMatrix& m, const SparseComplexMatrix& a)
 {
-  FULL_SPARSE_MUL (ComplexMatrix, Complex, Complex (0.,0.));
+  FULL_SPARSE_MUL (ComplexMatrix, Complex);
 }
 
 ComplexMatrix
 mul_trans (const ComplexMatrix& m, const SparseComplexMatrix& a)
 {
-  FULL_SPARSE_MUL_TRANS (ComplexMatrix, Complex, Complex (0.,0.), );
+  FULL_SPARSE_MUL_TRANS (ComplexMatrix, Complex, );
 }
 
 ComplexMatrix
 mul_herm (const ComplexMatrix& m, const SparseComplexMatrix& a)
 {
-  FULL_SPARSE_MUL_TRANS (ComplexMatrix, Complex, Complex (0.,0.), conj);
+  FULL_SPARSE_MUL_TRANS (ComplexMatrix, Complex, conj);
 }
 
 ComplexMatrix
 operator * (const SparseComplexMatrix& m, const Matrix& a)
 {
-  SPARSE_FULL_MUL (ComplexMatrix, double, Complex (0.,0.));
+  SPARSE_FULL_MUL (ComplexMatrix, double);
 }
 
 ComplexMatrix
 operator * (const SparseMatrix& m, const ComplexMatrix& a)
 {
-  SPARSE_FULL_MUL (ComplexMatrix, Complex, Complex (0.,0.));
+  SPARSE_FULL_MUL (ComplexMatrix, Complex);
 }
 
 ComplexMatrix
 operator * (const SparseComplexMatrix& m, const ComplexMatrix& a)
 {
-  SPARSE_FULL_MUL (ComplexMatrix, Complex, Complex (0.,0.));
+  SPARSE_FULL_MUL (ComplexMatrix, Complex);
 }
 
 ComplexMatrix
 trans_mul (const SparseComplexMatrix& m, const ComplexMatrix& a)
 {
-  SPARSE_FULL_TRANS_MUL (ComplexMatrix, Complex, Complex (0.,0.), );
+  SPARSE_FULL_TRANS_MUL (ComplexMatrix, Complex, );
 }
 
 ComplexMatrix
 herm_mul (const SparseComplexMatrix& m, const ComplexMatrix& a)
 {
-  SPARSE_FULL_TRANS_MUL (ComplexMatrix, Complex, Complex (0.,0.), conj);
+  SPARSE_FULL_TRANS_MUL (ComplexMatrix, Complex, conj);
 }
 
 // diag * sparse and sparse * diag
@@ -7932,14 +7933,11 @@
   return r;
 }
 
-SPARSE_SMS_CMP_OPS (SparseComplexMatrix, 0.0, real, Complex,
-                    0.0, real)
-SPARSE_SMS_BOOL_OPS (SparseComplexMatrix, Complex, 0.0)
-
-SPARSE_SSM_CMP_OPS (Complex, 0.0, real, SparseComplexMatrix,
-                    0.0, real)
-SPARSE_SSM_BOOL_OPS (Complex, SparseComplexMatrix, 0.0)
-
-SPARSE_SMSM_CMP_OPS (SparseComplexMatrix, 0.0, real, SparseComplexMatrix,
-                     0.0, real)
-SPARSE_SMSM_BOOL_OPS (SparseComplexMatrix, SparseComplexMatrix, 0.0)
+SPARSE_SMS_CMP_OPS (SparseComplexMatrix, Complex)
+SPARSE_SMS_BOOL_OPS (SparseComplexMatrix, Complex)
+
+SPARSE_SSM_CMP_OPS (Complex, SparseComplexMatrix)
+SPARSE_SSM_BOOL_OPS (Complex, SparseComplexMatrix)
+
+SPARSE_SMSM_CMP_OPS (SparseComplexMatrix, SparseComplexMatrix)
+SPARSE_SMSM_BOOL_OPS (SparseComplexMatrix, SparseComplexMatrix)
--- a/liboctave/array/DiagArray2.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/array/DiagArray2.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -27,8 +27,6 @@
 
 #include <cassert>
 
-#include <iostream>
-
 #include <algorithm>
 
 #include "DiagArray2.h"
--- a/liboctave/array/MArray-i.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/array/MArray-i.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -36,15 +36,6 @@
 template class OCTAVE_API MArray<int64_t>;
 #endif
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-// Explicit instantiation, as this seems to be required by weird compilers
-// like MSVC.  This should be harmless on other compilers.
-template int xmin<int> (int, int);
-template int xmax<int> (int, int);
-template long xmin<long> (long, long);
-template long xmax<long> (long, long);
-#endif
-
 INSTANTIATE_MARRAY_FRIENDS (int, OCTAVE_API)
 #if defined (OCTAVE_ENABLE_64)
 INSTANTIATE_MARRAY_FRIENDS (int64_t, OCTAVE_API)
--- a/liboctave/array/MArray-s.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/array/MArray-s.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -31,13 +31,6 @@
 
 template class OCTAVE_API MArray<short>;
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-// Explicit instantiation, as this seems to be required by weird compilers
-// like MSVC.  This should be harmless on other compilers.
-template short xmin<short> (short, short);
-template short xmax<short> (short, short);
-#endif
-
 INSTANTIATE_MARRAY_FRIENDS (short, OCTAVE_API)
 
 #include "MDiagArray2.h"
--- a/liboctave/array/MArray.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/array/MArray.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -134,8 +134,6 @@
                                                          vals.data ()));
 }
 
-#include <iostream>
-
 template <typename T>
 void MArray<T>::idx_add_nd (const idx_vector& idx, const MArray<T>& vals,
                             int dim)
--- a/liboctave/array/MDiagArray2.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/array/MDiagArray2.h	Fri Aug 10 09:09:51 2018 +0200
@@ -91,10 +91,10 @@
 
     octave_idx_type nel = this->length ();
 
-    const T zero = T ();
+    static constexpr T zero = T ();
 
     return std::count_if (d, d + nel,
-                          [zero] (T elem) { return elem != zero; });
+                          [] (T elem) { return elem != zero; });
   }
 
   MArray<T> diag (octave_idx_type k = 0) const
--- a/liboctave/array/MatrixType.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/array/MatrixType.h	Fri Aug 10 09:09:51 2018 +0200
@@ -192,7 +192,7 @@
   MatrixType transpose (void) const;
 
 private:
-  void type (int new_typ) { typ = static_cast<matrix_type>(new_typ); }
+  void type (int new_typ) { typ = static_cast<matrix_type> (new_typ); }
 
   matrix_type typ;
   double sp_bandden;
--- a/liboctave/array/Range.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/array/Range.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -26,8 +26,9 @@
 
 #include <cmath>
 
-#include <iostream>
+#include <istream>
 #include <limits>
+#include <ostream>
 
 #include "Array-util.h"
 #include "Range.h"
--- a/liboctave/array/Sparse.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/array/Sparse.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -29,8 +29,8 @@
 #include <cassert>
 
 #include <algorithm>
-#include <iostream>
-#include <limits>
+#include <istream>
+#include <ostream>
 #include <sstream>
 #include <vector>
 
--- a/liboctave/array/boolMatrix.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/array/boolMatrix.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -25,7 +25,7 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <ostream>
 
 #include "Array-util.h"
 #include "boolMatrix.h"
--- a/liboctave/array/boolSparse.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/array/boolSparse.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -26,7 +26,8 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <istream>
+#include <ostream>
 #include <vector>
 
 #include "quit.h"
@@ -320,11 +321,11 @@
   return Sparse<bool>::ipermute (vec);
 }
 
-SPARSE_SMS_EQNE_OPS (SparseBoolMatrix, false, , bool, false, )
-SPARSE_SMS_BOOL_OPS (SparseBoolMatrix, bool, false)
+SPARSE_SMS_EQNE_OPS (SparseBoolMatrix, bool)
+SPARSE_SMS_BOOL_OPS (SparseBoolMatrix, bool)
 
-SPARSE_SSM_EQNE_OPS (bool, false, , SparseBoolMatrix, false, )
-SPARSE_SSM_BOOL_OPS (bool, SparseBoolMatrix, false)
+SPARSE_SSM_EQNE_OPS (bool, SparseBoolMatrix)
+SPARSE_SSM_BOOL_OPS (bool, SparseBoolMatrix)
 
-SPARSE_SMSM_EQNE_OPS (SparseBoolMatrix, false, , SparseBoolMatrix, false, )
-SPARSE_SMSM_BOOL_OPS (SparseBoolMatrix, SparseBoolMatrix, false)
+SPARSE_SMSM_EQNE_OPS (SparseBoolMatrix, SparseBoolMatrix)
+SPARSE_SMSM_BOOL_OPS (SparseBoolMatrix, SparseBoolMatrix)
--- a/liboctave/array/chMatrix.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/array/chMatrix.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -27,7 +27,7 @@
 
 #include <cstring>
 
-#include <iostream>
+#include <ostream>
 #include <string>
 
 #include "lo-error.h"
--- a/liboctave/array/chNDArray.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/array/chNDArray.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -128,7 +128,7 @@
         // FIXME: is there something better to do? Should we warn the user?
         ival = 0;
 
-      tmp.elem (i) = static_cast<char>(ival);
+      tmp.elem (i) = static_cast<char> (ival);
     }
 
   insert (tmp, ra_idx);
--- a/liboctave/array/dColVector.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/array/dColVector.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -25,7 +25,8 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <istream>
+#include <ostream>
 
 #include "Array-util.h"
 #include "functor.h"
--- a/liboctave/array/dDiagMatrix.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/array/dDiagMatrix.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -25,7 +25,7 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <ostream>
 
 #include "Array-util.h"
 #include "lo-error.h"
@@ -184,7 +184,7 @@
 
   char c = *s;
   if (c == 'f' || c == 'F')
-    return row (static_cast<octave_idx_type>(0));
+    return row (static_cast<octave_idx_type> (0));
   else if (c == 'l' || c == 'L')
     return row (rows () - 1);
   else
@@ -214,7 +214,7 @@
 
   char c = *s;
   if (c == 'f' || c == 'F')
-    return column (static_cast<octave_idx_type>(0));
+    return column (static_cast<octave_idx_type> (0));
   else if (c == 'l' || c == 'L')
     return column (cols () - 1);
   else
--- a/liboctave/array/dMatrix.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/array/dMatrix.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -27,8 +27,9 @@
 #endif
 
 #include <algorithm>
-#include <iostream>
+#include <istream>
 #include <limits>
+#include <ostream>
 
 #include "Array-util.h"
 #include "CColVector.h"
@@ -799,234 +800,40 @@
 
 #else
 
-#include "lo-fftpack-proto.h"
-
 ComplexMatrix
 Matrix::fourier (void) const
 {
-  ComplexMatrix retval;
-
-  octave_idx_type nr = rows ();
-  octave_idx_type nc = cols ();
-  octave_idx_type nsamples;
-
-  F77_INT npts;
-
-  if (nr == 1 || nc == 1)
-    {
-      npts = octave::to_f77_int (nr > nc ? nr : nc);
-      nsamples = 1;
-    }
-  else
-    {
-      npts = octave::to_f77_int (nr);
-      nsamples = nc;
-    }
-
-  octave_idx_type nn = 4*npts+15;
-
-  Array<Complex> wsave (dim_vector (nn, 1));
-  Complex *pwsave = wsave.fortran_vec ();
-
-  retval = ComplexMatrix (*this);
-  Complex *tmp_data = retval.fortran_vec ();
-
-  F77_FUNC (zffti, ZFFTI) (npts, F77_DBLE_CMPLX_ARG (pwsave));
-
-  for (octave_idx_type j = 0; j < nsamples; j++)
-    {
-      octave_quit ();
-
-      F77_FUNC (zfftf, ZFFTF) (npts, F77_DBLE_CMPLX_ARG (&tmp_data[npts*j]),
-                               F77_DBLE_CMPLX_ARG (pwsave));
-    }
-
-  return retval;
+  (*current_liboctave_error_handler)
+    ("support for FFTW was unavailable or disabled when liboctave was built");
+
+  return ComplexMatrix ();
 }
 
 ComplexMatrix
 Matrix::ifourier (void) const
 {
-  ComplexMatrix retval;
-
-  octave_idx_type nr = rows ();
-  octave_idx_type nc = cols ();
-  octave_idx_type nsamples;
-
-  F77_INT npts;
-
-  if (nr == 1 || nc == 1)
-    {
-      npts = octave::to_f77_int (nr > nc ? nr : nc);
-      nsamples = 1;
-    }
-  else
-    {
-      npts = octave::to_f77_int (nr);
-      nsamples = nc;
-    }
-
-  octave_idx_type nn = 4*npts+15;
-
-  Array<Complex> wsave (dim_vector (nn, 1));
-  Complex *pwsave = wsave.fortran_vec ();
-
-  retval = ComplexMatrix (*this);
-  Complex *tmp_data = retval.fortran_vec ();
-
-  F77_FUNC (zffti, ZFFTI) (npts, F77_DBLE_CMPLX_ARG (pwsave));
-
-  for (octave_idx_type j = 0; j < nsamples; j++)
-    {
-      octave_quit ();
-
-      F77_FUNC (zfftb, ZFFTB) (npts, F77_DBLE_CMPLX_ARG (&tmp_data[npts*j]),
-                               F77_DBLE_CMPLX_ARG (pwsave));
-    }
-
-  for (octave_idx_type j = 0; j < npts*nsamples; j++)
-    tmp_data[j] = tmp_data[j] / static_cast<double> (npts);
-
-  return retval;
+  (*current_liboctave_error_handler)
+    ("support for FFTW was unavailable or disabled when liboctave was built");
+
+  return ComplexMatrix ();
 }
 
 ComplexMatrix
 Matrix::fourier2d (void) const
 {
-  ComplexMatrix retval;
-
-  F77_INT nr = octave::to_f77_int (rows ());
-  F77_INT nc = octave::to_f77_int (cols ());
-
-  F77_INT npts, nsamples;
-
-  if (nr == 1 || nc == 1)
-    {
-      npts = (nr > nc ? nr : nc);
-      nsamples = 1;
-    }
-  else
-    {
-      npts = nr;
-      nsamples = nc;
-    }
-
-  F77_INT nn = 4*npts+15;
-
-  Array<Complex> wsave (dim_vector (nn, 1));
-  Complex *pwsave = wsave.fortran_vec ();
-
-  retval = ComplexMatrix (*this);
-  Complex *tmp_data = retval.fortran_vec ();
-
-  F77_FUNC (zffti, ZFFTI) (npts, F77_DBLE_CMPLX_ARG (pwsave));
-
-  for (F77_INT j = 0; j < nsamples; j++)
-    {
-      octave_quit ();
-
-      F77_FUNC (zfftf, ZFFTF) (npts, F77_DBLE_CMPLX_ARG (&tmp_data[npts*j]),
-                               F77_DBLE_CMPLX_ARG (pwsave));
-    }
-
-  npts = nc;
-  nsamples = nr;
-  nn = 4*npts+15;
-
-  wsave.resize (dim_vector (nn, 1));
-  pwsave = wsave.fortran_vec ();
-
-  Array<Complex> tmp (dim_vector (npts, 1));
-  Complex *prow = tmp.fortran_vec ();
-
-  F77_FUNC (zffti, ZFFTI) (npts, F77_DBLE_CMPLX_ARG (pwsave));
-
-  for (F77_INT j = 0; j < nsamples; j++)
-    {
-      octave_quit ();
-
-      for (F77_INT i = 0; i < npts; i++)
-        prow[i] = tmp_data[i*nr + j];
-
-      F77_FUNC (zfftf, ZFFTF) (npts, F77_DBLE_CMPLX_ARG (prow),
-                               F77_DBLE_CMPLX_ARG (pwsave));
-
-      for (F77_INT i = 0; i < npts; i++)
-        tmp_data[i*nr + j] = prow[i];
-    }
-
-  return retval;
+  (*current_liboctave_error_handler)
+    ("support for FFTW was unavailable or disabled when liboctave was built");
+
+  return ComplexMatrix ();
 }
 
 ComplexMatrix
 Matrix::ifourier2d (void) const
 {
-  ComplexMatrix retval;
-
-  F77_INT nr = octave::to_f77_int (rows ());
-  F77_INT nc = octave::to_f77_int (cols ());
-
-  F77_INT npts, nsamples;
-
-  if (nr == 1 || nc == 1)
-    {
-      npts = (nr > nc ? nr : nc);
-      nsamples = 1;
-    }
-  else
-    {
-      npts = nr;
-      nsamples = nc;
-    }
-
-  F77_INT nn = 4*npts+15;
-
-  Array<Complex> wsave (dim_vector (nn, 1));
-  Complex *pwsave = wsave.fortran_vec ();
-
-  retval = ComplexMatrix (*this);
-  Complex *tmp_data = retval.fortran_vec ();
-
-  F77_FUNC (zffti, ZFFTI) (npts, F77_DBLE_CMPLX_ARG (pwsave));
-
-  for (F77_INT j = 0; j < nsamples; j++)
-    {
-      octave_quit ();
-
-      F77_FUNC (zfftb, ZFFTB) (npts, F77_DBLE_CMPLX_ARG (&tmp_data[npts*j]),
-                               F77_DBLE_CMPLX_ARG (pwsave));
-    }
-
-  for (F77_INT j = 0; j < npts*nsamples; j++)
-    tmp_data[j] = tmp_data[j] / static_cast<double> (npts);
-
-  npts = nc;
-  nsamples = nr;
-  nn = 4*npts+15;
-
-  wsave.resize (dim_vector (nn, 1));
-  pwsave = wsave.fortran_vec ();
-
-  Array<Complex> tmp (dim_vector (npts, 1));
-  Complex *prow = tmp.fortran_vec ();
-
-  F77_FUNC (zffti, ZFFTI) (npts, F77_DBLE_CMPLX_ARG (pwsave));
-
-  for (F77_INT j = 0; j < nsamples; j++)
-    {
-      octave_quit ();
-
-      for (F77_INT i = 0; i < npts; i++)
-        prow[i] = tmp_data[i*nr + j];
-
-      F77_FUNC (zfftb, ZFFTB) (npts, F77_DBLE_CMPLX_ARG (prow),
-                               F77_DBLE_CMPLX_ARG (pwsave));
-
-      for (F77_INT i = 0; i < npts; i++)
-        tmp_data[i*nr + j] = prow[i] / static_cast<double> (npts);
-    }
-
-  return retval;
+  (*current_liboctave_error_handler)
+    ("support for FFTW was unavailable or disabled when liboctave was built");
+
+  return ComplexMatrix ();
 }
 
 #endif
@@ -3210,7 +3017,7 @@
   // The last column is unused so temporarily store delta there
   double *delta = &retval(0, n-1);
   for (octave_idx_type i = 0; i < m; i++)
-    delta[i] = (x2(i) - x1(i)) / (n - 1);
+    delta[i] = (x1(i) == x2(i)) ? 0 : (x2(i) - x1(i)) / (n - 1);
 
   for (octave_idx_type j = 1; j < n-1; j++)
     for (octave_idx_type i = 0; i < m; i++)
--- a/liboctave/array/dNDArray.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/array/dNDArray.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -25,8 +25,9 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <istream>
 #include <limits>
+#include <ostream>
 
 #include "Array-util.h"
 #include "dNDArray.h"
@@ -227,299 +228,58 @@
 
 #else
 
-#include "lo-fftpack-proto.h"
-
 ComplexNDArray
 NDArray::fourier (int dim) const
 {
-  dim_vector dv = dims ();
-
-  if (dim > dv.ndims () || dim < 0)
-    return ComplexNDArray ();
-
-  ComplexNDArray retval (dv);
-  octave_idx_type npts = dv(dim);
-  octave_idx_type nn = 4*npts+15;
-  Array<Complex> wsave (dim_vector (nn, 1));
-  Complex *pwsave = wsave.fortran_vec ();
-
-  OCTAVE_LOCAL_BUFFER (Complex, tmp, npts);
-
-  octave_idx_type stride = 1;
-
-  for (int i = 0; i < dim; i++)
-    stride *= dv(i);
+  (*current_liboctave_error_handler)
+    ("support for FFTW was unavailable or disabled when liboctave was built");
 
-  octave_idx_type howmany = numel () / npts;
-  howmany = (stride == 1 ? howmany : (howmany > stride ? stride : howmany));
-  octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
-  octave_idx_type dist = (stride == 1 ? npts : 1);
-
-  F77_FUNC (zffti, ZFFTI) (npts, F77_DBLE_CMPLX_ARG (pwsave));
-
-  for (octave_idx_type k = 0; k < nloop; k++)
-    {
-      for (octave_idx_type j = 0; j < howmany; j++)
-        {
-          octave_quit ();
-
-          for (octave_idx_type i = 0; i < npts; i++)
-            tmp[i] = elem ((i + k*npts)*stride + j*dist);
-
-          F77_FUNC (zfftf, ZFFTF) (npts, F77_DBLE_CMPLX_ARG (tmp),
-                                   F77_DBLE_CMPLX_ARG (pwsave));
-
-          for (octave_idx_type i = 0; i < npts; i++)
-            retval((i + k*npts)*stride + j*dist) = tmp[i];
-        }
-    }
-
-  return retval;
+  return ComplexNDArray ();
 }
 
 ComplexNDArray
 NDArray::ifourier (int dim) const
 {
-  dim_vector dv = dims ();
-
-  if (dim > dv.ndims () || dim < 0)
-    return ComplexNDArray ();
-
-  ComplexNDArray retval (dv);
-  octave_idx_type npts = dv(dim);
-  octave_idx_type nn = 4*npts+15;
-  Array<Complex> wsave (dim_vector (nn, 1));
-  Complex *pwsave = wsave.fortran_vec ();
-
-  OCTAVE_LOCAL_BUFFER (Complex, tmp, npts);
-
-  octave_idx_type stride = 1;
-
-  for (int i = 0; i < dim; i++)
-    stride *= dv(i);
+  (*current_liboctave_error_handler)
+    ("support for FFTW was unavailable or disabled when liboctave was built");
 
-  octave_idx_type howmany = numel () / npts;
-  howmany = (stride == 1 ? howmany : (howmany > stride ? stride : howmany));
-  octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
-  octave_idx_type dist = (stride == 1 ? npts : 1);
-
-  F77_FUNC (zffti, ZFFTI) (npts, F77_DBLE_CMPLX_ARG (pwsave));
-
-  for (octave_idx_type k = 0; k < nloop; k++)
-    {
-      for (octave_idx_type j = 0; j < howmany; j++)
-        {
-          octave_quit ();
-
-          for (octave_idx_type i = 0; i < npts; i++)
-            tmp[i] = elem ((i + k*npts)*stride + j*dist);
-
-          F77_FUNC (zfftb, ZFFTB) (npts, F77_DBLE_CMPLX_ARG (tmp),
-                                   F77_DBLE_CMPLX_ARG (pwsave));
-
-          for (octave_idx_type i = 0; i < npts; i++)
-            retval((i + k*npts)*stride + j*dist) = tmp[i] /
-                                                   static_cast<double> (npts);
-        }
-    }
-
-  return retval;
+  return ComplexNDArray ();
 }
 
 ComplexNDArray
 NDArray::fourier2d (void) const
 {
-  dim_vector dv = dims ();
-  dim_vector dv2 (dv(0), dv(1));
-  int rank = 2;
-  ComplexNDArray retval (*this);
-  octave_idx_type stride = 1;
-
-  for (int i = 0; i < rank; i++)
-    {
-      octave_idx_type npts = dv2(i);
-      octave_idx_type nn = 4*npts+15;
-      Array<Complex> wsave (dim_vector (nn, 1));
-      Complex *pwsave = wsave.fortran_vec ();
-      Array<Complex> row (dim_vector (npts, 1));
-      Complex *prow = row.fortran_vec ();
-
-      octave_idx_type howmany = numel () / npts;
-      howmany = (stride == 1 ? howmany
-                             : (howmany > stride ? stride : howmany));
-      octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
-      octave_idx_type dist = (stride == 1 ? npts : 1);
+  (*current_liboctave_error_handler)
+    ("support for FFTW was unavailable or disabled when liboctave was built");
 
-      F77_FUNC (zffti, ZFFTI) (npts, F77_DBLE_CMPLX_ARG (pwsave));
-
-      for (octave_idx_type k = 0; k < nloop; k++)
-        {
-          for (octave_idx_type j = 0; j < howmany; j++)
-            {
-              octave_quit ();
-
-              for (octave_idx_type l = 0; l < npts; l++)
-                prow[l] = retval((l + k*npts)*stride + j*dist);
-
-              F77_FUNC (zfftf, ZFFTF) (npts, F77_DBLE_CMPLX_ARG (prow),
-                                       F77_DBLE_CMPLX_ARG (pwsave));
-
-              for (octave_idx_type l = 0; l < npts; l++)
-                retval((l + k*npts)*stride + j*dist) = prow[l];
-            }
-        }
-
-      stride *= dv2(i);
-    }
-
-  return retval;
+  return ComplexNDArray ();
 }
 
 ComplexNDArray
 NDArray::ifourier2d (void) const
 {
-  dim_vector dv = dims ();
-  dim_vector dv2 (dv(0), dv(1));
-  int rank = 2;
-  ComplexNDArray retval (*this);
-  octave_idx_type stride = 1;
-
-  for (int i = 0; i < rank; i++)
-    {
-      octave_idx_type npts = dv2(i);
-      octave_idx_type nn = 4*npts+15;
-      Array<Complex> wsave (dim_vector (nn, 1));
-      Complex *pwsave = wsave.fortran_vec ();
-      Array<Complex> row (dim_vector (npts, 1));
-      Complex *prow = row.fortran_vec ();
-
-      octave_idx_type howmany = numel () / npts;
-      howmany = (stride == 1 ? howmany
-                             : (howmany > stride ? stride : howmany));
-      octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
-      octave_idx_type dist = (stride == 1 ? npts : 1);
-
-      F77_FUNC (zffti, ZFFTI) (npts, F77_DBLE_CMPLX_ARG (pwsave));
+  (*current_liboctave_error_handler)
+    ("support for FFTW was unavailable or disabled when liboctave was built");
 
-      for (octave_idx_type k = 0; k < nloop; k++)
-        {
-          for (octave_idx_type j = 0; j < howmany; j++)
-            {
-              octave_quit ();
-
-              for (octave_idx_type l = 0; l < npts; l++)
-                prow[l] = retval((l + k*npts)*stride + j*dist);
-
-              F77_FUNC (zfftb, ZFFTB) (npts, F77_DBLE_CMPLX_ARG (prow),
-                                       F77_DBLE_CMPLX_ARG (pwsave));
-
-              for (octave_idx_type l = 0; l < npts; l++)
-                retval((l + k*npts)*stride + j*dist) =
-                  prow[l] / static_cast<double> (npts);
-            }
-        }
-
-      stride *= dv2(i);
-    }
-
-  return retval;
+  return ComplexNDArray ();
 }
 
 ComplexNDArray
 NDArray::fourierNd (void) const
 {
-  dim_vector dv = dims ();
-  int rank = dv.ndims ();
-  ComplexNDArray retval (*this);
-  octave_idx_type stride = 1;
-
-  for (int i = 0; i < rank; i++)
-    {
-      octave_idx_type npts = dv(i);
-      octave_idx_type nn = 4*npts+15;
-      Array<Complex> wsave (dim_vector (nn, 1));
-      Complex *pwsave = wsave.fortran_vec ();
-      Array<Complex> row (dim_vector (npts, 1));
-      Complex *prow = row.fortran_vec ();
-
-      octave_idx_type howmany = numel () / npts;
-      howmany = (stride == 1 ? howmany
-                             : (howmany > stride ? stride : howmany));
-      octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
-      octave_idx_type dist = (stride == 1 ? npts : 1);
-
-      F77_FUNC (zffti, ZFFTI) (npts, F77_DBLE_CMPLX_ARG (pwsave));
+  (*current_liboctave_error_handler)
+    ("support for FFTW was unavailable or disabled when liboctave was built");
 
-      for (octave_idx_type k = 0; k < nloop; k++)
-        {
-          for (octave_idx_type j = 0; j < howmany; j++)
-            {
-              octave_quit ();
-
-              for (octave_idx_type l = 0; l < npts; l++)
-                prow[l] = retval((l + k*npts)*stride + j*dist);
-
-              F77_FUNC (zfftf, ZFFTF) (npts, F77_DBLE_CMPLX_ARG (prow),
-                                       F77_DBLE_CMPLX_ARG (pwsave));
-
-              for (octave_idx_type l = 0; l < npts; l++)
-                retval((l + k*npts)*stride + j*dist) = prow[l];
-            }
-        }
-
-      stride *= dv(i);
-    }
-
-  return retval;
+  return ComplexNDArray ();
 }
 
 ComplexNDArray
 NDArray::ifourierNd (void) const
 {
-  dim_vector dv = dims ();
-  int rank = dv.ndims ();
-  ComplexNDArray retval (*this);
-  octave_idx_type stride = 1;
-
-  for (int i = 0; i < rank; i++)
-    {
-      octave_idx_type npts = dv(i);
-      octave_idx_type nn = 4*npts+15;
-      Array<Complex> wsave (dim_vector (nn, 1));
-      Complex *pwsave = wsave.fortran_vec ();
-      Array<Complex> row (dim_vector (npts, 1));
-      Complex *prow = row.fortran_vec ();
-
-      octave_idx_type howmany = numel () / npts;
-      howmany = (stride == 1 ? howmany
-                             : (howmany > stride ? stride : howmany));
-      octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
-      octave_idx_type dist = (stride == 1 ? npts : 1);
-
-      F77_FUNC (zffti, ZFFTI) (npts, F77_DBLE_CMPLX_ARG (pwsave));
+  (*current_liboctave_error_handler)
+    ("support for FFTW was unavailable or disabled when liboctave was built");
 
-      for (octave_idx_type k = 0; k < nloop; k++)
-        {
-          for (octave_idx_type j = 0; j < howmany; j++)
-            {
-              octave_quit ();
-
-              for (octave_idx_type l = 0; l < npts; l++)
-                prow[l] = retval((l + k*npts)*stride + j*dist);
-
-              F77_FUNC (zfftb, ZFFTB) (npts, F77_DBLE_CMPLX_ARG (prow),
-                                       F77_DBLE_CMPLX_ARG (pwsave));
-
-              for (octave_idx_type l = 0; l < npts; l++)
-                retval((l + k*npts)*stride + j*dist) =
-                  prow[l] / static_cast<double> (npts);
-            }
-        }
-
-      stride *= dv(i);
-    }
-
-  return retval;
+  return ComplexNDArray ();
 }
 
 #endif
@@ -765,7 +525,7 @@
         // FIXME: is there something better to do? Should we warn the user?
         ival = 0;
 
-      retval.elem (i) = static_cast<char>(ival);
+      retval.elem (i) = static_cast<char> (ival);
     }
 
   if (rb.isempty ())
--- a/liboctave/array/dRowVector.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/array/dRowVector.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -24,7 +24,8 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <istream>
+#include <ostream>
 
 #include "Array-util.h"
 #include "functor.h"
@@ -275,7 +276,7 @@
 
   retval(0) = x1;
 
-  double delta = (x2 - x1) / (n - 1);
+  double delta = (x1 == x2) ? 0 : ((x2 - x1) / (n - 1));
   for (octave_idx_type i = 1; i < n-1; i++)
     retval(i) = x1 + i*delta;
 
--- a/liboctave/array/dSparse.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/array/dSparse.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -26,7 +26,8 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <istream>
+#include <ostream>
 
 #include "quit.h"
 #include "lo-ieee.h"
@@ -6058,14 +6059,14 @@
               X = CHOLMOD_NAME(spsolve) (CHOLMOD_A, L, B, cm);
               END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
 
-              retval = SparseMatrix (static_cast<octave_idx_type>(X->nrow),
-                                     static_cast<octave_idx_type>(X->ncol),
-                                     static_cast<octave_idx_type>(X->nzmax));
+              retval = SparseMatrix (static_cast<octave_idx_type> (X->nrow),
+                                     static_cast<octave_idx_type> (X->ncol),
+                                     static_cast<octave_idx_type> (X->nzmax));
               for (octave_idx_type j = 0;
-                   j <= static_cast<octave_idx_type>(X->ncol); j++)
+                   j <= static_cast<octave_idx_type> (X->ncol); j++)
                 retval.xcidx (j) = static_cast<octave_idx_type *>(X->p)[j];
               for (octave_idx_type j = 0;
-                   j < static_cast<octave_idx_type>(X->nzmax); j++)
+                   j < static_cast<octave_idx_type> (X->nzmax); j++)
                 {
                   retval.xridx (j) = static_cast<octave_idx_type *>(X->i)[j];
                   retval.xdata (j) = static_cast<double *>(X->x)[j];
@@ -6577,14 +6578,14 @@
               END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
 
               retval = SparseComplexMatrix
-                       (static_cast<octave_idx_type>(X->nrow),
-                        static_cast<octave_idx_type>(X->ncol),
-                        static_cast<octave_idx_type>(X->nzmax));
+                       (static_cast<octave_idx_type> (X->nrow),
+                        static_cast<octave_idx_type> (X->ncol),
+                        static_cast<octave_idx_type> (X->nzmax));
               for (octave_idx_type j = 0;
-                   j <= static_cast<octave_idx_type>(X->ncol); j++)
+                   j <= static_cast<octave_idx_type> (X->ncol); j++)
                 retval.xcidx (j) = static_cast<octave_idx_type *>(X->p)[j];
               for (octave_idx_type j = 0;
-                   j < static_cast<octave_idx_type>(X->nzmax); j++)
+                   j < static_cast<octave_idx_type> (X->nzmax); j++)
                 {
                   retval.xridx (j) = static_cast<octave_idx_type *>(X->i)[j];
                   retval.xdata (j) = static_cast<Complex *>(X->x)[j];
@@ -7544,25 +7545,25 @@
 Matrix
 operator * (const Matrix& m, const SparseMatrix& a)
 {
-  FULL_SPARSE_MUL (Matrix, double, 0.);
+  FULL_SPARSE_MUL (Matrix, double);
 }
 
 Matrix
 mul_trans (const Matrix& m, const SparseMatrix& a)
 {
-  FULL_SPARSE_MUL_TRANS (Matrix, double, 0., );
+  FULL_SPARSE_MUL_TRANS (Matrix, double, );
 }
 
 Matrix
 operator * (const SparseMatrix& m, const Matrix& a)
 {
-  SPARSE_FULL_MUL (Matrix, double, 0.);
+  SPARSE_FULL_MUL (Matrix, double);
 }
 
 Matrix
 trans_mul (const SparseMatrix& m, const Matrix& a)
 {
-  SPARSE_FULL_TRANS_MUL (Matrix, double, 0., );
+  SPARSE_FULL_TRANS_MUL (Matrix, double, );
 }
 
 // diag * sparse and sparse * diag
@@ -7923,11 +7924,11 @@
   return r;
 }
 
-SPARSE_SMS_CMP_OPS (SparseMatrix, 0.0, , double, 0.0, )
-SPARSE_SMS_BOOL_OPS (SparseMatrix, double, 0.0)
-
-SPARSE_SSM_CMP_OPS (double, 0.0, , SparseMatrix, 0.0, )
-SPARSE_SSM_BOOL_OPS (double, SparseMatrix, 0.0)
-
-SPARSE_SMSM_CMP_OPS (SparseMatrix, 0.0, , SparseMatrix, 0.0, )
-SPARSE_SMSM_BOOL_OPS (SparseMatrix, SparseMatrix, 0.0)
+SPARSE_SMS_CMP_OPS (SparseMatrix, double)
+SPARSE_SMS_BOOL_OPS (SparseMatrix, double)
+
+SPARSE_SSM_CMP_OPS (double, SparseMatrix)
+SPARSE_SSM_BOOL_OPS (double, SparseMatrix)
+
+SPARSE_SMSM_CMP_OPS (SparseMatrix, SparseMatrix)
+SPARSE_SMSM_BOOL_OPS (SparseMatrix, SparseMatrix)
--- a/liboctave/array/fCColVector.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/array/fCColVector.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -25,7 +25,8 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <istream>
+#include <ostream>
 
 #include "Array-util.h"
 #include "functor.h"
--- a/liboctave/array/fCDiagMatrix.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/array/fCDiagMatrix.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -25,7 +25,7 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <ostream>
 
 #include "Array-util.h"
 #include "lo-error.h"
@@ -265,7 +265,7 @@
 
   char c = *s;
   if (c == 'f' || c == 'F')
-    return row (static_cast<octave_idx_type>(0));
+    return row (static_cast<octave_idx_type> (0));
   else if (c == 'l' || c == 'L')
     return row (rows () - 1);
   else
@@ -295,7 +295,7 @@
 
   char c = *s;
   if (c == 'f' || c == 'F')
-    return column (static_cast<octave_idx_type>(0));
+    return column (static_cast<octave_idx_type> (0));
   else if (c == 'l' || c == 'L')
     return column (cols () - 1);
   else
--- a/liboctave/array/fCMatrix.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/array/fCMatrix.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -28,8 +28,9 @@
 
 #include <algorithm>
 #include <complex>
-#include <iostream>
+#include <istream>
 #include <limits>
+#include <ostream>
 
 #include "Array-util.h"
 #include "DET.h"
@@ -1107,232 +1108,40 @@
 
 #else
 
-#include "lo-fftpack-proto.h"
-
 FloatComplexMatrix
 FloatComplexMatrix::fourier (void) const
 {
-  FloatComplexMatrix retval;
-
-  octave_idx_type nr = rows ();
-  octave_idx_type nc = cols ();
-  octave_idx_type nsamples;
-
-  F77_INT npts;
-
-  if (nr == 1 || nc == 1)
-    {
-      npts = octave::to_f77_int (nr > nc ? nr : nc);
-      nsamples = 1;
-    }
-  else
-    {
-      npts = octave::to_f77_int (nr);
-      nsamples = nc;
-    }
-
-  octave_idx_type nn = 4*npts+15;
-
-  Array<FloatComplex> wsave (dim_vector (nn, 1));
-  FloatComplex *pwsave = wsave.fortran_vec ();
-
-  retval = *this;
-  FloatComplex *tmp_data = retval.fortran_vec ();
-
-  F77_FUNC (cffti, CFFTI) (npts, F77_CMPLX_ARG (pwsave));
-
-  for (octave_idx_type j = 0; j < nsamples; j++)
-    {
-      octave_quit ();
-
-      F77_FUNC (cfftf, CFFTF) (npts, F77_CMPLX_ARG (&tmp_data[npts*j]),
-                               F77_CMPLX_ARG (pwsave));
-    }
-
-  return retval;
+  (*current_liboctave_error_handler)
+    ("support for FFTW was unavailable or disabled when liboctave was built");
+
+  return FloatComplexMatrix ();
 }
 
 FloatComplexMatrix
 FloatComplexMatrix::ifourier (void) const
 {
-  FloatComplexMatrix retval;
-
-  octave_idx_type nr = rows ();
-  octave_idx_type nc = cols ();
-  octave_idx_type nsamples;
-
-  F77_INT npts;
-
-  if (nr == 1 || nc == 1)
-    {
-      npts = octave::to_f77_int (nr > nc ? nr : nc);
-      nsamples = 1;
-    }
-  else
-    {
-      npts = octave::to_f77_int (nr);
-      nsamples = nc;
-    }
-
-  octave_idx_type nn = 4*npts+15;
-
-  Array<FloatComplex> wsave (dim_vector (nn, 1));
-  FloatComplex *pwsave = wsave.fortran_vec ();
-
-  retval = *this;
-  FloatComplex *tmp_data = retval.fortran_vec ();
-
-  F77_FUNC (cffti, CFFTI) (npts, F77_CMPLX_ARG (pwsave));
-
-  for (octave_idx_type j = 0; j < nsamples; j++)
-    {
-      octave_quit ();
-
-      F77_FUNC (cfftb, CFFTB) (npts, F77_CMPLX_ARG (&tmp_data[npts*j]),
-                               F77_CMPLX_ARG (pwsave));
-    }
-
-  for (octave_idx_type j = 0; j < npts*nsamples; j++)
-    tmp_data[j] = tmp_data[j] / static_cast<float> (npts);
-
-  return retval;
+  (*current_liboctave_error_handler)
+    ("support for FFTW was unavailable or disabled when liboctave was built");
+
+  return FloatComplexMatrix ();
 }
 
 FloatComplexMatrix
 FloatComplexMatrix::fourier2d (void) const
 {
-  FloatComplexMatrix retval;
-
-  F77_INT nr = octave::to_f77_int (rows ());
-  F77_INT nc = octave::to_f77_int (cols ());
-
-  F77_INT npts, nsamples;
-
-  if (nr == 1 || nc == 1)
-    {
-      npts = (nr > nc ? nr : nc);
-      nsamples = 1;
-    }
-  else
-    {
-      npts = nr;
-      nsamples = nc;
-    }
-
-  F77_INT nn = 4*npts+15;
-
-  Array<FloatComplex> wsave (dim_vector (nn, 1));
-  FloatComplex *pwsave = wsave.fortran_vec ();
-
-  retval = *this;
-  FloatComplex *tmp_data = retval.fortran_vec ();
-
-  F77_FUNC (cffti, CFFTI) (npts, F77_CMPLX_ARG (pwsave));
-
-  for (F77_INT j = 0; j < nsamples; j++)
-    {
-      octave_quit ();
-
-      F77_FUNC (cfftf, CFFTF) (npts, F77_CMPLX_ARG (&tmp_data[npts*j]),
-                               F77_CMPLX_ARG (pwsave));
-    }
-
-  npts = nc;
-  nsamples = nr;
-  nn = 4*npts+15;
-
-  wsave.resize (dim_vector (nn, 1));
-  pwsave = wsave.fortran_vec ();
-
-  Array<FloatComplex> tmp (dim_vector (npts, 1));
-  FloatComplex *prow = tmp.fortran_vec ();
-
-  F77_FUNC (cffti, CFFTI) (npts, F77_CMPLX_ARG (pwsave));
-
-  for (F77_INT j = 0; j < nsamples; j++)
-    {
-      octave_quit ();
-
-      for (F77_INT i = 0; i < npts; i++)
-        prow[i] = tmp_data[i*nr + j];
-
-      F77_FUNC (cfftf, CFFTF) (npts, F77_CMPLX_ARG (prow), F77_CMPLX_ARG (pwsave));
-
-      for (F77_INT i = 0; i < npts; i++)
-        tmp_data[i*nr + j] = prow[i];
-    }
-
-  return retval;
+  (*current_liboctave_error_handler)
+    ("support for FFTW was unavailable or disabled when liboctave was built");
+
+  return FloatComplexMatrix ();
 }
 
 FloatComplexMatrix
 FloatComplexMatrix::ifourier2d (void) const
 {
-  FloatComplexMatrix retval;
-
-  F77_INT nr = octave::to_f77_int (rows ());
-  F77_INT nc = octave::to_f77_int (cols ());
-
-  F77_INT npts, nsamples;
-
-  if (nr == 1 || nc == 1)
-    {
-      npts = (nr > nc ? nr : nc);
-      nsamples = 1;
-    }
-  else
-    {
-      npts = nr;
-      nsamples = nc;
-    }
-
-  F77_INT nn = 4*npts+15;
-
-  Array<FloatComplex> wsave (dim_vector (nn, 1));
-  FloatComplex *pwsave = wsave.fortran_vec ();
-
-  retval = *this;
-  FloatComplex *tmp_data = retval.fortran_vec ();
-
-  F77_FUNC (cffti, CFFTI) (npts, F77_CMPLX_ARG (pwsave));
-
-  for (F77_INT j = 0; j < nsamples; j++)
-    {
-      octave_quit ();
-
-      F77_FUNC (cfftb, CFFTB) (npts, F77_CMPLX_ARG (&tmp_data[npts*j]),
-                               F77_CMPLX_ARG (pwsave));
-    }
-
-  for (F77_INT j = 0; j < npts*nsamples; j++)
-    tmp_data[j] = tmp_data[j] / static_cast<float> (npts);
-
-  npts = nc;
-  nsamples = nr;
-  nn = 4*npts+15;
-
-  wsave.resize (dim_vector (nn, 1));
-  pwsave = wsave.fortran_vec ();
-
-  Array<FloatComplex> tmp (dim_vector (npts, 1));
-  FloatComplex *prow = tmp.fortran_vec ();
-
-  F77_FUNC (cffti, CFFTI) (npts, F77_CMPLX_ARG (pwsave));
-
-  for (F77_INT j = 0; j < nsamples; j++)
-    {
-      octave_quit ();
-
-      for (F77_INT i = 0; i < npts; i++)
-        prow[i] = tmp_data[i*nr + j];
-
-      F77_FUNC (cfftb, CFFTB) (npts, F77_CMPLX_ARG (prow), F77_CMPLX_ARG (pwsave));
-
-      for (F77_INT i = 0; i < npts; i++)
-        tmp_data[i*nr + j] = prow[i] / static_cast<float> (npts);
-    }
-
-  return retval;
+  (*current_liboctave_error_handler)
+    ("support for FFTW was unavailable or disabled when liboctave was built");
+
+  return FloatComplexMatrix ();
 }
 
 #endif
@@ -3848,7 +3657,7 @@
   // The last column is unused so temporarily store delta there
   FloatComplex *delta = &retval(0, n-1);
   for (octave_idx_type i = 0; i < m; i++)
-    delta[i] = (x2(i) - x1(i)) / (n - 1.0f);
+    delta[i] = (x1(i) == x2(i)) ? 0 : (x2(i) - x1(i)) / (n - 1.0f);
 
   for (octave_idx_type j = 1; j < n-1; j++)
     for (octave_idx_type i = 0; i < m; i++)
--- a/liboctave/array/fCNDArray.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/array/fCNDArray.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -26,7 +26,8 @@
 #endif
 
 #include <complex>
-#include <iostream>
+#include <istream>
+#include <ostream>
 
 #include "Array-util.h"
 #include "f77-fcn.h"
@@ -186,293 +187,58 @@
 
 #else
 
-#include "lo-fftpack-proto.h"
-
 FloatComplexNDArray
 FloatComplexNDArray::fourier (int dim) const
 {
-  dim_vector dv = dims ();
-
-  if (dim > dv.ndims () || dim < 0)
-    return FloatComplexNDArray ();
-
-  FloatComplexNDArray retval (dv);
-  octave_idx_type npts = dv(dim);
-  octave_idx_type nn = 4*npts+15;
-  Array<FloatComplex> wsave (dim_vector (nn, 1));
-  FloatComplex *pwsave = wsave.fortran_vec ();
-
-  OCTAVE_LOCAL_BUFFER (FloatComplex, tmp, npts);
-
-  octave_idx_type stride = 1;
-
-  for (int i = 0; i < dim; i++)
-    stride *= dv(i);
+  (*current_liboctave_error_handler)
+    ("support for FFTW was unavailable or disabled when liboctave was built");
 
-  octave_idx_type howmany = numel () / npts;
-  howmany = (stride == 1 ? howmany : (howmany > stride ? stride : howmany));
-  octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
-  octave_idx_type dist = (stride == 1 ? npts : 1);
-
-  F77_FUNC (cffti, CFFTI) (npts, F77_CMPLX_ARG (pwsave));
-
-  for (octave_idx_type k = 0; k < nloop; k++)
-    {
-      for (octave_idx_type j = 0; j < howmany; j++)
-        {
-          octave_quit ();
-
-          for (octave_idx_type i = 0; i < npts; i++)
-            tmp[i] = elem ((i + k*npts)*stride + j*dist);
-
-          F77_FUNC (cfftf, CFFTF) (npts, F77_CMPLX_ARG (tmp), F77_CMPLX_ARG (pwsave));
-
-          for (octave_idx_type i = 0; i < npts; i++)
-            retval((i + k*npts)*stride + j*dist) = tmp[i];
-        }
-    }
-
-  return retval;
+  return FloatComplexNDArray ();
 }
 
 FloatComplexNDArray
 FloatComplexNDArray::ifourier (int dim) const
 {
-  dim_vector dv = dims ();
-
-  if (dim > dv.ndims () || dim < 0)
-    return FloatComplexNDArray ();
-
-  FloatComplexNDArray retval (dv);
-  octave_idx_type npts = dv(dim);
-  octave_idx_type nn = 4*npts+15;
-  Array<FloatComplex> wsave (dim_vector (nn, 1));
-  FloatComplex *pwsave = wsave.fortran_vec ();
-
-  OCTAVE_LOCAL_BUFFER (FloatComplex, tmp, npts);
-
-  octave_idx_type stride = 1;
-
-  for (int i = 0; i < dim; i++)
-    stride *= dv(i);
+  (*current_liboctave_error_handler)
+    ("support for FFTW was unavailable or disabled when liboctave was built");
 
-  octave_idx_type howmany = numel () / npts;
-  howmany = (stride == 1 ? howmany : (howmany > stride ? stride : howmany));
-  octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
-  octave_idx_type dist = (stride == 1 ? npts : 1);
-
-  F77_FUNC (cffti, CFFTI) (npts, F77_CMPLX_ARG (pwsave));
-
-  for (octave_idx_type k = 0; k < nloop; k++)
-    {
-      for (octave_idx_type j = 0; j < howmany; j++)
-        {
-          octave_quit ();
-
-          for (octave_idx_type i = 0; i < npts; i++)
-            tmp[i] = elem ((i + k*npts)*stride + j*dist);
-
-          F77_FUNC (cfftb, CFFTB) (npts, F77_CMPLX_ARG (tmp), F77_CMPLX_ARG (pwsave));
-
-          for (octave_idx_type i = 0; i < npts; i++)
-            retval((i + k*npts)*stride + j*dist) = tmp[i] /
-                                                   static_cast<float> (npts);
-        }
-    }
-
-  return retval;
+  return FloatComplexNDArray ();
 }
 
 FloatComplexNDArray
 FloatComplexNDArray::fourier2d (void) const
 {
-  dim_vector dv = dims ();
-  dim_vector dv2 (dv(0), dv(1));
-  int rank = 2;
-  FloatComplexNDArray retval (*this);
-  octave_idx_type stride = 1;
-
-  for (int i = 0; i < rank; i++)
-    {
-      octave_idx_type npts = dv2(i);
-      octave_idx_type nn = 4*npts+15;
-      Array<FloatComplex> wsave (dim_vector (nn, 1));
-      FloatComplex *pwsave = wsave.fortran_vec ();
-      Array<FloatComplex> row (dim_vector (npts, 1));
-      FloatComplex *prow = row.fortran_vec ();
-
-      octave_idx_type howmany = numel () / npts;
-      howmany = (stride == 1 ? howmany
-                             : (howmany > stride ? stride : howmany));
-      octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
-      octave_idx_type dist = (stride == 1 ? npts : 1);
+  (*current_liboctave_error_handler)
+    ("support for FFTW was unavailable or disabled when liboctave was built");
 
-      F77_FUNC (cffti, CFFTI) (npts, F77_CMPLX_ARG (pwsave));
-
-      for (octave_idx_type k = 0; k < nloop; k++)
-        {
-          for (octave_idx_type j = 0; j < howmany; j++)
-            {
-              octave_quit ();
-
-              for (octave_idx_type l = 0; l < npts; l++)
-                prow[l] = retval((l + k*npts)*stride + j*dist);
-
-              F77_FUNC (cfftf, CFFTF) (npts, F77_CMPLX_ARG (prow), F77_CMPLX_ARG (pwsave));
-
-              for (octave_idx_type l = 0; l < npts; l++)
-                retval((l + k*npts)*stride + j*dist) = prow[l];
-            }
-        }
-
-      stride *= dv2(i);
-    }
-
-  return retval;
+  return FloatComplexNDArray ();
 }
 
 FloatComplexNDArray
 FloatComplexNDArray::ifourier2d (void) const
 {
-  dim_vector dv = dims ();
-  dim_vector dv2 (dv(0), dv(1));
-  int rank = 2;
-  FloatComplexNDArray retval (*this);
-  octave_idx_type stride = 1;
-
-  for (int i = 0; i < rank; i++)
-    {
-      octave_idx_type npts = dv2(i);
-      octave_idx_type nn = 4*npts+15;
-      Array<FloatComplex> wsave (dim_vector (nn, 1));
-      FloatComplex *pwsave = wsave.fortran_vec ();
-      Array<FloatComplex> row (dim_vector (npts, 1));
-      FloatComplex *prow = row.fortran_vec ();
-
-      octave_idx_type howmany = numel () / npts;
-      howmany = (stride == 1 ? howmany
-                             : (howmany > stride ? stride : howmany));
-      octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
-      octave_idx_type dist = (stride == 1 ? npts : 1);
+  (*current_liboctave_error_handler)
+    ("support for FFTW was unavailable or disabled when liboctave was built");
 
-      F77_FUNC (cffti, CFFTI) (npts, F77_CMPLX_ARG (pwsave));
-
-      for (octave_idx_type k = 0; k < nloop; k++)
-        {
-          for (octave_idx_type j = 0; j < howmany; j++)
-            {
-              octave_quit ();
-
-              for (octave_idx_type l = 0; l < npts; l++)
-                prow[l] = retval((l + k*npts)*stride + j*dist);
-
-              F77_FUNC (cfftb, CFFTB) (npts, F77_CMPLX_ARG (prow), F77_CMPLX_ARG (pwsave));
-
-              for (octave_idx_type l = 0; l < npts; l++)
-                retval((l + k*npts)*stride + j*dist) =
-                  prow[l] / static_cast<float> (npts);
-            }
-        }
-
-      stride *= dv2(i);
-    }
-
-  return retval;
+  return FloatComplexNDArray ();
 }
 
 FloatComplexNDArray
 FloatComplexNDArray::fourierNd (void) const
 {
-  dim_vector dv = dims ();
-  int rank = dv.ndims ();
-  FloatComplexNDArray retval (*this);
-  octave_idx_type stride = 1;
-
-  for (int i = 0; i < rank; i++)
-    {
-      octave_idx_type npts = dv(i);
-      octave_idx_type nn = 4*npts+15;
-      Array<FloatComplex> wsave (dim_vector (nn, 1));
-      FloatComplex *pwsave = wsave.fortran_vec ();
-      Array<FloatComplex> row (dim_vector (npts, 1));
-      FloatComplex *prow = row.fortran_vec ();
-
-      octave_idx_type howmany = numel () / npts;
-      howmany = (stride == 1 ? howmany
-                             : (howmany > stride ? stride : howmany));
-      octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
-      octave_idx_type dist = (stride == 1 ? npts : 1);
+  (*current_liboctave_error_handler)
+    ("support for FFTW was unavailable or disabled when liboctave was built");
 
-      F77_FUNC (cffti, CFFTI) (npts, F77_CMPLX_ARG (pwsave));
-
-      for (octave_idx_type k = 0; k < nloop; k++)
-        {
-          for (octave_idx_type j = 0; j < howmany; j++)
-            {
-              octave_quit ();
-
-              for (octave_idx_type l = 0; l < npts; l++)
-                prow[l] = retval((l + k*npts)*stride + j*dist);
-
-              F77_FUNC (cfftf, CFFTF) (npts, F77_CMPLX_ARG (prow), F77_CMPLX_ARG (pwsave));
-
-              for (octave_idx_type l = 0; l < npts; l++)
-                retval((l + k*npts)*stride + j*dist) = prow[l];
-            }
-        }
-
-      stride *= dv(i);
-    }
-
-  return retval;
+  return FloatComplexNDArray ();
 }
 
 FloatComplexNDArray
 FloatComplexNDArray::ifourierNd (void) const
 {
-  dim_vector dv = dims ();
-  int rank = dv.ndims ();
-  FloatComplexNDArray retval (*this);
-  octave_idx_type stride = 1;
-
-  for (int i = 0; i < rank; i++)
-    {
-      octave_idx_type npts = dv(i);
-      octave_idx_type nn = 4*npts+15;
-      Array<FloatComplex> wsave (dim_vector (nn, 1));
-      FloatComplex *pwsave = wsave.fortran_vec ();
-      Array<FloatComplex> row (dim_vector (npts, 1));
-      FloatComplex *prow = row.fortran_vec ();
-
-      octave_idx_type howmany = numel () / npts;
-      howmany = (stride == 1 ? howmany
-                             : (howmany > stride ? stride : howmany));
-      octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
-      octave_idx_type dist = (stride == 1 ? npts : 1);
-
-      F77_FUNC (cffti, CFFTI) (npts, F77_CMPLX_ARG (pwsave));
+  (*current_liboctave_error_handler)
+    ("support for FFTW was unavailable or disabled when liboctave was built");
 
-      for (octave_idx_type k = 0; k < nloop; k++)
-        {
-          for (octave_idx_type j = 0; j < howmany; j++)
-            {
-              octave_quit ();
-
-              for (octave_idx_type l = 0; l < npts; l++)
-                prow[l] = retval((l + k*npts)*stride + j*dist);
-
-              F77_FUNC (cfftb, CFFTB) (npts, F77_CMPLX_ARG (prow), F77_CMPLX_ARG (pwsave));
-
-              for (octave_idx_type l = 0; l < npts; l++)
-                retval((l + k*npts)*stride + j*dist) =
-                  prow[l] / static_cast<float> (npts);
-            }
-        }
-
-      stride *= dv(i);
-    }
-
-  return retval;
+  return FloatComplexNDArray ();
 }
 
 #endif
--- a/liboctave/array/fCRowVector.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/array/fCRowVector.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -24,7 +24,8 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <istream>
+#include <ostream>
 
 #include "Array-util.h"
 #include "functor.h"
@@ -434,7 +435,7 @@
 
   retval(0) = x1;
 
-  FloatComplex delta = (x2 - x1) / (n - 1.0f);
+  FloatComplex delta = (x1 == x2) ? 0 : (x2 - x1) / (n - 1.0f);
   for (octave_idx_type i = 1; i < n-1; i++)
     retval(i) = x1 + static_cast<float> (i)*delta;
 
--- a/liboctave/array/fColVector.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/array/fColVector.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -25,7 +25,8 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <istream>
+#include <ostream>
 
 #include "Array-util.h"
 #include "functor.h"
--- a/liboctave/array/fDiagMatrix.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/array/fDiagMatrix.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -25,7 +25,7 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <ostream>
 
 #include "Array-util.h"
 #include "lo-error.h"
@@ -184,7 +184,7 @@
 
   char c = *s;
   if (c == 'f' || c == 'F')
-    return row (static_cast<octave_idx_type>(0));
+    return row (static_cast<octave_idx_type> (0));
   else if (c == 'l' || c == 'L')
     return row (rows () - 1);
   else
@@ -214,7 +214,7 @@
 
   char c = *s;
   if (c == 'f' || c == 'F')
-    return column (static_cast<octave_idx_type>(0));
+    return column (static_cast<octave_idx_type> (0));
   else if (c == 'l' || c == 'L')
     return column (cols () - 1);
   else
--- a/liboctave/array/fMatrix.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/array/fMatrix.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -27,8 +27,9 @@
 #endif
 
 #include <algorithm>
-#include <iostream>
+#include <istream>
 #include <limits>
+#include <ostream>
 
 #include "Array-util.h"
 #include "DET.h"
@@ -805,232 +806,40 @@
 
 #else
 
-#include "lo-fftpack-proto.h"
-
 FloatComplexMatrix
 FloatMatrix::fourier (void) const
 {
-  FloatComplexMatrix retval;
-
-  octave_idx_type nr = rows ();
-  octave_idx_type nc = cols ();
-  octave_idx_type nsamples;
-
-  F77_INT npts;
-
-  if (nr == 1 || nc == 1)
-    {
-      npts = octave::to_f77_int (nr > nc ? nr : nc);
-      nsamples = 1;
-    }
-  else
-    {
-      npts = octave::to_f77_int (nr);
-      nsamples = nc;
-    }
-
-  octave_idx_type nn = 4*npts+15;
-
-  Array<FloatComplex> wsave (dim_vector (nn, 1));
-  FloatComplex *pwsave = wsave.fortran_vec ();
-
-  retval = FloatComplexMatrix (*this);
-  FloatComplex *tmp_data = retval.fortran_vec ();
-
-  F77_FUNC (cffti, CFFTI) (npts, F77_CMPLX_ARG (pwsave));
-
-  for (octave_idx_type j = 0; j < nsamples; j++)
-    {
-      octave_quit ();
-
-      F77_FUNC (cfftf, CFFTF) (npts, F77_CMPLX_ARG (&tmp_data[npts*j]),
-                               F77_CMPLX_ARG (pwsave));
-    }
-
-  return retval;
+  (*current_liboctave_error_handler)
+    ("support for FFTW was unavailable or disabled when liboctave was built");
+
+  return FloatComplexMatrix ();
 }
 
 FloatComplexMatrix
 FloatMatrix::ifourier (void) const
 {
-  FloatComplexMatrix retval;
-
-  octave_idx_type nr = rows ();
-  octave_idx_type nc = cols ();
-  octave_idx_type nsamples;
-
-  F77_INT npts;
-
-  if (nr == 1 || nc == 1)
-    {
-      npts = octave::to_f77_int (nr > nc ? nr : nc);
-      nsamples = 1;
-    }
-  else
-    {
-      npts = F77_INT (nr);
-      nsamples = nc;
-    }
-
-  octave_idx_type nn = 4*npts+15;
-
-  Array<FloatComplex> wsave (dim_vector (nn, 1));
-  FloatComplex *pwsave = wsave.fortran_vec ();
-
-  retval = FloatComplexMatrix (*this);
-  FloatComplex *tmp_data = retval.fortran_vec ();
-
-  F77_FUNC (cffti, CFFTI) (npts, F77_CMPLX_ARG (pwsave));
-
-  for (octave_idx_type j = 0; j < nsamples; j++)
-    {
-      octave_quit ();
-
-      F77_FUNC (cfftb, CFFTB) (npts, F77_CMPLX_ARG (&tmp_data[npts*j]),
-                               F77_CMPLX_ARG (pwsave));
-    }
-
-  for (octave_idx_type j = 0; j < npts*nsamples; j++)
-    tmp_data[j] = tmp_data[j] / static_cast<float> (npts);
-
-  return retval;
+  (*current_liboctave_error_handler)
+    ("support for FFTW was unavailable or disabled when liboctave was built");
+
+  return FloatComplexMatrix ();
 }
 
 FloatComplexMatrix
 FloatMatrix::fourier2d (void) const
 {
-  FloatComplexMatrix retval;
-
-  F77_INT nr = octave::to_f77_int (rows ());
-  F77_INT nc = octave::to_f77_int (cols ());
-
-  F77_INT npts, nsamples;
-
-  if (nr == 1 || nc == 1)
-    {
-      npts = (nr > nc ? nr : nc);
-      nsamples = 1;
-    }
-  else
-    {
-      npts = nr;
-      nsamples = nc;
-    }
-
-  F77_INT nn = 4*npts+15;
-
-  Array<FloatComplex> wsave (dim_vector (nn, 1));
-  FloatComplex *pwsave = wsave.fortran_vec ();
-
-  retval = FloatComplexMatrix (*this);
-  FloatComplex *tmp_data = retval.fortran_vec ();
-
-  F77_FUNC (cffti, CFFTI) (npts, F77_CMPLX_ARG (pwsave));
-
-  for (F77_INT j = 0; j < nsamples; j++)
-    {
-      octave_quit ();
-
-      F77_FUNC (cfftf, CFFTF) (npts, F77_CMPLX_ARG (&tmp_data[npts*j]),
-                               F77_CMPLX_ARG (pwsave));
-    }
-
-  npts = nc;
-  nsamples = nr;
-  nn = 4*npts+15;
-
-  wsave.resize (dim_vector (nn, 1));
-  pwsave = wsave.fortran_vec ();
-
-  Array<FloatComplex> tmp (dim_vector (npts, 1));
-  FloatComplex *prow = tmp.fortran_vec ();
-
-  F77_FUNC (cffti, CFFTI) (npts, F77_CMPLX_ARG (pwsave));
-
-  for (F77_INT j = 0; j < nsamples; j++)
-    {
-      octave_quit ();
-
-      for (F77_INT i = 0; i < npts; i++)
-        prow[i] = tmp_data[i*nr + j];
-
-      F77_FUNC (cfftf, CFFTF) (npts, F77_CMPLX_ARG (prow), F77_CMPLX_ARG (pwsave));
-
-      for (F77_INT i = 0; i < npts; i++)
-        tmp_data[i*nr + j] = prow[i];
-    }
-
-  return retval;
+  (*current_liboctave_error_handler)
+    ("support for FFTW was unavailable or disabled when liboctave was built");
+
+  return FloatComplexMatrix ();
 }
 
 FloatComplexMatrix
 FloatMatrix::ifourier2d (void) const
 {
-  FloatComplexMatrix retval;
-
-  F77_INT nr = octave::to_f77_int (rows ());
-  F77_INT nc = octave::to_f77_int (cols ());
-
-  F77_INT npts, nsamples;
-
-  if (nr == 1 || nc == 1)
-    {
-      npts = (nr > nc ? nr : nc);
-      nsamples = 1;
-    }
-  else
-    {
-      npts = nr;
-      nsamples = nc;
-    }
-
-  F77_INT nn = 4*npts+15;
-
-  Array<FloatComplex> wsave (dim_vector (nn, 1));
-  FloatComplex *pwsave = wsave.fortran_vec ();
-
-  retval = FloatComplexMatrix (*this);
-  FloatComplex *tmp_data = retval.fortran_vec ();
-
-  F77_FUNC (cffti, CFFTI) (npts, F77_CMPLX_ARG (pwsave));
-
-  for (F77_INT j = 0; j < nsamples; j++)
-    {
-      octave_quit ();
-
-      F77_FUNC (cfftb, CFFTB) (npts, F77_CMPLX_ARG (&tmp_data[npts*j]),
-                               F77_CMPLX_ARG (pwsave));
-    }
-
-  for (F77_INT j = 0; j < npts*nsamples; j++)
-    tmp_data[j] = tmp_data[j] / static_cast<float> (npts);
-
-  npts = nc;
-  nsamples = nr;
-  nn = 4*npts+15;
-
-  wsave.resize (dim_vector (nn, 1));
-  pwsave = wsave.fortran_vec ();
-
-  Array<FloatComplex> tmp (dim_vector (npts, 1));
-  FloatComplex *prow = tmp.fortran_vec ();
-
-  F77_FUNC (cffti, CFFTI) (npts, F77_CMPLX_ARG (pwsave));
-
-  for (F77_INT j = 0; j < nsamples; j++)
-    {
-      octave_quit ();
-
-      for (F77_INT i = 0; i < npts; i++)
-        prow[i] = tmp_data[i*nr + j];
-
-      F77_FUNC (cfftb, CFFTB) (npts, F77_CMPLX_ARG (prow), F77_CMPLX_ARG (pwsave));
-
-      for (F77_INT i = 0; i < npts; i++)
-        tmp_data[i*nr + j] = prow[i] / static_cast<float> (npts);
-    }
-
-  return retval;
+  (*current_liboctave_error_handler)
+    ("support for FFTW was unavailable or disabled when liboctave was built");
+
+  return FloatComplexMatrix ();
 }
 
 #endif
@@ -3215,7 +3024,7 @@
   // The last column is unused so temporarily store delta there
   float *delta = &retval(0, n-1);
   for (octave_idx_type i = 0; i < m; i++)
-    delta[i] = (x2(i) - x1(i)) / (n - 1);
+    delta[i] = (x1(i) == x2(i)) ? 0 : (x2(i) - x1(i)) / (n - 1);
 
   for (octave_idx_type j = 1; j < n-1; j++)
     for (octave_idx_type i = 0; i < m; i++)
--- a/liboctave/array/fNDArray.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/array/fNDArray.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -25,8 +25,9 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <istream>
 #include <limits>
+#include <ostream>
 
 #include "Array-util.h"
 #include "f77-fcn.h"
@@ -185,293 +186,57 @@
 
 #else
 
-#include "lo-fftpack-proto.h"
-
 FloatComplexNDArray
 FloatNDArray::fourier (int dim) const
 {
-  dim_vector dv = dims ();
-
-  if (dim > dv.ndims () || dim < 0)
-    return FloatComplexNDArray ();
-
-  FloatComplexNDArray retval (dv);
-  octave_idx_type npts = dv(dim);
-  octave_idx_type nn = 4*npts+15;
-  Array<FloatComplex> wsave (dim_vector (nn, 1));
-  FloatComplex *pwsave = wsave.fortran_vec ();
-
-  OCTAVE_LOCAL_BUFFER (FloatComplex, tmp, npts);
-
-  octave_idx_type stride = 1;
-
-  for (int i = 0; i < dim; i++)
-    stride *= dv(i);
+  (*current_liboctave_error_handler)
+    ("support for FFTW was unavailable or disabled when liboctave was built");
 
-  octave_idx_type howmany = numel () / npts;
-  howmany = (stride == 1 ? howmany : (howmany > stride ? stride : howmany));
-  octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
-  octave_idx_type dist = (stride == 1 ? npts : 1);
-
-  F77_FUNC (cffti, CFFTI) (npts, F77_CMPLX_ARG (pwsave));
-
-  for (octave_idx_type k = 0; k < nloop; k++)
-    {
-      for (octave_idx_type j = 0; j < howmany; j++)
-        {
-          octave_quit ();
-
-          for (octave_idx_type i = 0; i < npts; i++)
-            tmp[i] = elem ((i + k*npts)*stride + j*dist);
-
-          F77_FUNC (cfftf, CFFTF) (npts, F77_CMPLX_ARG (tmp), F77_CMPLX_ARG (pwsave));
-
-          for (octave_idx_type i = 0; i < npts; i++)
-            retval((i + k*npts)*stride + j*dist) = tmp[i];
-        }
-    }
-
-  return retval;
+  return FloatComplexNDArray ();
 }
 
 FloatComplexNDArray
 FloatNDArray::ifourier (int dim) const
 {
-  dim_vector dv = dims ();
-
-  if (dim > dv.ndims () || dim < 0)
-    return FloatComplexNDArray ();
-
-  FloatComplexNDArray retval (dv);
-  octave_idx_type npts = dv(dim);
-  octave_idx_type nn = 4*npts+15;
-  Array<FloatComplex> wsave (dim_vector (nn, 1));
-  FloatComplex *pwsave = wsave.fortran_vec ();
-
-  OCTAVE_LOCAL_BUFFER (FloatComplex, tmp, npts);
-
-  octave_idx_type stride = 1;
-
-  for (int i = 0; i < dim; i++)
-    stride *= dv(i);
-
-  octave_idx_type howmany = numel () / npts;
-  howmany = (stride == 1 ? howmany : (howmany > stride ? stride : howmany));
-  octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
-  octave_idx_type dist = (stride == 1 ? npts : 1);
-
-  F77_FUNC (cffti, CFFTI) (npts, F77_CMPLX_ARG (pwsave));
-
-  for (octave_idx_type k = 0; k < nloop; k++)
-    {
-      for (octave_idx_type j = 0; j < howmany; j++)
-        {
-          octave_quit ();
-
-          for (octave_idx_type i = 0; i < npts; i++)
-            tmp[i] = elem ((i + k*npts)*stride + j*dist);
-
-          F77_FUNC (cfftb, CFFTB) (npts, F77_CMPLX_ARG (tmp), F77_CMPLX_ARG (pwsave));
-
-          for (octave_idx_type i = 0; i < npts; i++)
-            retval((i + k*npts)*stride + j*dist) = tmp[i] /
-                                                   static_cast<float> (npts);
-        }
-    }
-
-  return retval;
+  (*current_liboctave_error_handler)
+    ("support for FFTW was unavailable or disabled when liboctave was built");
+  return FloatComplexNDArray ();
 }
 
 FloatComplexNDArray
 FloatNDArray::fourier2d (void) const
 {
-  dim_vector dv = dims ();
-  dim_vector dv2 (dv(0), dv(1));
-  int rank = 2;
-  FloatComplexNDArray retval (*this);
-  octave_idx_type stride = 1;
-
-  for (int i = 0; i < rank; i++)
-    {
-      octave_idx_type npts = dv2(i);
-      octave_idx_type nn = 4*npts+15;
-      Array<FloatComplex> wsave (dim_vector (nn, 1));
-      FloatComplex *pwsave = wsave.fortran_vec ();
-      Array<FloatComplex> row (dim_vector (npts, 1));
-      FloatComplex *prow = row.fortran_vec ();
-
-      octave_idx_type howmany = numel () / npts;
-      howmany = (stride == 1 ? howmany
-                             : (howmany > stride ? stride : howmany));
-      octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
-      octave_idx_type dist = (stride == 1 ? npts : 1);
+  (*current_liboctave_error_handler)
+    ("support for FFTW was unavailable or disabled when liboctave was built");
 
-      F77_FUNC (cffti, CFFTI) (npts, F77_CMPLX_ARG (pwsave));
-
-      for (octave_idx_type k = 0; k < nloop; k++)
-        {
-          for (octave_idx_type j = 0; j < howmany; j++)
-            {
-              octave_quit ();
-
-              for (octave_idx_type l = 0; l < npts; l++)
-                prow[l] = retval((l + k*npts)*stride + j*dist);
-
-              F77_FUNC (cfftf, CFFTF) (npts, F77_CMPLX_ARG (prow), F77_CMPLX_ARG (pwsave));
-
-              for (octave_idx_type l = 0; l < npts; l++)
-                retval((l + k*npts)*stride + j*dist) = prow[l];
-            }
-        }
-
-      stride *= dv2(i);
-    }
-
-  return retval;
+  return FloatComplexNDArray ();
 }
 
 FloatComplexNDArray
 FloatNDArray::ifourier2d (void) const
 {
-  dim_vector dv = dims ();
-  dim_vector dv2 (dv(0), dv(1));
-  int rank = 2;
-  FloatComplexNDArray retval (*this);
-  octave_idx_type stride = 1;
-
-  for (int i = 0; i < rank; i++)
-    {
-      octave_idx_type npts = dv2(i);
-      octave_idx_type nn = 4*npts+15;
-      Array<FloatComplex> wsave (dim_vector (nn, 1));
-      FloatComplex *pwsave = wsave.fortran_vec ();
-      Array<FloatComplex> row (dim_vector (npts, 1));
-      FloatComplex *prow = row.fortran_vec ();
-
-      octave_idx_type howmany = numel () / npts;
-      howmany = (stride == 1 ? howmany
-                             : (howmany > stride ? stride : howmany));
-      octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
-      octave_idx_type dist = (stride == 1 ? npts : 1);
+  (*current_liboctave_error_handler)
+    ("support for FFTW was unavailable or disabled when liboctave was built");
 
-      F77_FUNC (cffti, CFFTI) (npts, F77_CMPLX_ARG (pwsave));
-
-      for (octave_idx_type k = 0; k < nloop; k++)
-        {
-          for (octave_idx_type j = 0; j < howmany; j++)
-            {
-              octave_quit ();
-
-              for (octave_idx_type l = 0; l < npts; l++)
-                prow[l] = retval((l + k*npts)*stride + j*dist);
-
-              F77_FUNC (cfftb, CFFTB) (npts, F77_CMPLX_ARG (prow), F77_CMPLX_ARG (pwsave));
-
-              for (octave_idx_type l = 0; l < npts; l++)
-                retval((l + k*npts)*stride + j*dist) =
-                  prow[l] / static_cast<float> (npts);
-            }
-        }
-
-      stride *= dv2(i);
-    }
-
-  return retval;
+  return FloatComplexNDArray ();
 }
 
 FloatComplexNDArray
 FloatNDArray::fourierNd (void) const
 {
-  dim_vector dv = dims ();
-  int rank = dv.ndims ();
-  FloatComplexNDArray retval (*this);
-  octave_idx_type stride = 1;
-
-  for (int i = 0; i < rank; i++)
-    {
-      octave_idx_type npts = dv(i);
-      octave_idx_type nn = 4*npts+15;
-      Array<FloatComplex> wsave (dim_vector (nn, 1));
-      FloatComplex *pwsave = wsave.fortran_vec ();
-      Array<FloatComplex> row (dim_vector (npts, 1));
-      FloatComplex *prow = row.fortran_vec ();
-
-      octave_idx_type howmany = numel () / npts;
-      howmany = (stride == 1 ? howmany
-                             : (howmany > stride ? stride : howmany));
-      octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
-      octave_idx_type dist = (stride == 1 ? npts : 1);
+  (*current_liboctave_error_handler)
+    ("support for FFTW was unavailable or disabled when liboctave was built");
 
-      F77_FUNC (cffti, CFFTI) (npts, F77_CMPLX_ARG (pwsave));
-
-      for (octave_idx_type k = 0; k < nloop; k++)
-        {
-          for (octave_idx_type j = 0; j < howmany; j++)
-            {
-              octave_quit ();
-
-              for (octave_idx_type l = 0; l < npts; l++)
-                prow[l] = retval((l + k*npts)*stride + j*dist);
-
-              F77_FUNC (cfftf, CFFTF) (npts, F77_CMPLX_ARG (prow), F77_CMPLX_ARG (pwsave));
-
-              for (octave_idx_type l = 0; l < npts; l++)
-                retval((l + k*npts)*stride + j*dist) = prow[l];
-            }
-        }
-
-      stride *= dv(i);
-    }
-
-  return retval;
+  return FloatComplexNDArray ();
 }
 
 FloatComplexNDArray
 FloatNDArray::ifourierNd (void) const
 {
-  dim_vector dv = dims ();
-  int rank = dv.ndims ();
-  FloatComplexNDArray retval (*this);
-  octave_idx_type stride = 1;
-
-  for (int i = 0; i < rank; i++)
-    {
-      octave_idx_type npts = dv(i);
-      octave_idx_type nn = 4*npts+15;
-      Array<FloatComplex> wsave (dim_vector (nn, 1));
-      FloatComplex *pwsave = wsave.fortran_vec ();
-      Array<FloatComplex> row (dim_vector (npts, 1));
-      FloatComplex *prow = row.fortran_vec ();
-
-      octave_idx_type howmany = numel () / npts;
-      howmany = (stride == 1 ? howmany
-                             : (howmany > stride ? stride : howmany));
-      octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
-      octave_idx_type dist = (stride == 1 ? npts : 1);
-
-      F77_FUNC (cffti, CFFTI) (npts, F77_CMPLX_ARG (pwsave));
+  (*current_liboctave_error_handler)
+    ("support for FFTW was unavailable or disabled when liboctave was built");
 
-      for (octave_idx_type k = 0; k < nloop; k++)
-        {
-          for (octave_idx_type j = 0; j < howmany; j++)
-            {
-              octave_quit ();
-
-              for (octave_idx_type l = 0; l < npts; l++)
-                prow[l] = retval((l + k*npts)*stride + j*dist);
-
-              F77_FUNC (cfftb, CFFTB) (npts, F77_CMPLX_ARG (prow), F77_CMPLX_ARG (pwsave));
-
-              for (octave_idx_type l = 0; l < npts; l++)
-                retval((l + k*npts)*stride + j*dist) =
-                  prow[l] / static_cast<float> (npts);
-            }
-        }
-
-      stride *= dv(i);
-    }
-
-  return retval;
+  return FloatComplexNDArray ();
 }
 
 #endif
@@ -726,7 +491,7 @@
         // FIXME: is there something better to do?  Should we warn the user?
         ival = 0;
 
-      retval.elem (i) = static_cast<char>(ival);
+      retval.elem (i) = static_cast<char> (ival);
     }
 
   if (rb.isempty ())
--- a/liboctave/array/fRowVector.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/array/fRowVector.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -24,7 +24,8 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <istream>
+#include <ostream>
 
 #include "Array-util.h"
 #include "functor.h"
@@ -275,7 +276,7 @@
 
   retval(0) = x1;
 
-  float delta = (x2 - x1) / (n - 1);
+  float delta = (x1 == x2) ? 0 : (x2 - x1) / (n - 1);
   for (octave_idx_type i = 1; i < n-1; i++)
     retval(i) = x1 + i*delta;
 
--- a/liboctave/array/idx-vector.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/array/idx-vector.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -28,7 +28,7 @@
 
 #include <cstdlib>
 
-#include <iostream>
+#include <ostream>
 
 #include "idx-vector.h"
 #include "Array.h"
--- a/liboctave/array/module.mk	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/array/module.mk	Fri Aug 10 09:09:51 2018 +0200
@@ -132,8 +132,4 @@
   $(FFTW_XCPPFLAGS) \
   $(SPARSE_XCPPFLAGS)
 
-%canon_reldir%_libarray_la_CFLAGS = $(liboctave_liboctave_la_CFLAGS)
-
-%canon_reldir%_libarray_la_CXXFLAGS = $(liboctave_liboctave_la_CXXFLAGS)
-
 liboctave_liboctave_la_LIBADD += %reldir%/libarray.la
--- a/liboctave/external/blas-xtra/module.mk	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/external/blas-xtra/module.mk	Fri Aug 10 09:09:51 2018 +0200
@@ -25,7 +25,7 @@
   %reldir%/zdconv2.f
 
 XERBLA_SRC = \
-  %reldir%/xerbla.c
+  %reldir%/xerbla.cc
 
 %canon_reldir%_libxerbla_la_SOURCES = $(XERBLA_SRC)
 
--- a/liboctave/external/blas-xtra/xerbla.c	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
-
-Copyright (C) 1996-2018 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
-<https://www.gnu.org/licenses/>.
-
-*/
-
-#if defined (HAVE_CONFIG_H)
-#  include "config.h"
-#endif
-
-#include <stdio.h>
-
-#include "f77-fcn.h"
-
-typedef void (*xerbla_handler_fptr) (void);
-
-/* Pointer to function to call to handle error.  In the Octave
-   interpreter we set this to a function that throws an exception and
-   transfers control to the enclosing try/catch block.  That is
-   typically at the top-level REPL.
-
-   We must use a function pointer instead of simply calling error
-   directly here because this function is called by LAPACK and BLAS
-   subroutines.  To build shared libraries of those packages on Windows
-   requires that all symbols be known when the shared library is
-   constructed.  If we call error directly, that would mean that the
-   BLAS and LAPACK libraries would have to depend on Octave...  */
-
-static xerbla_handler_fptr xerbla_handler = NULL;
-
-void
-octave_set_xerbla_handler (xerbla_handler_fptr fcn)
-{
-  xerbla_handler = fcn;
-}
-
-/* Replacement for BLAS and LAPACK XERBLA subroutine that calls an
-   optionally installed handler function.  */
-
-F77_RET_T
-F77_FUNC (xerbla, XERBLA) (F77_CONST_CHAR_ARG_DEF (s_arg, len),
-                           const F77_INT *info
-                           F77_CHAR_ARG_LEN_DEF (len))
-{
-  const char *s = F77_CHAR_ARG_USE (s_arg);
-  int slen = F77_CHAR_ARG_LEN_USE (s_arg, len);
-
-  fprintf (stderr, "%.*s: parameter number %ld is invalid\n", slen, s,
-           (long) (*info));
-
-   if (xerbla_handler)
-     (*xerbla_handler) ();
-
-  F77_RETURN (0)
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/liboctave/external/blas-xtra/xerbla.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,72 @@
+/*
+
+Copyright (C) 1996-2018 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
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include <iostream>
+
+#include "f77-fcn.h"
+#include "lo-blas-proto.h"
+
+typedef void (*xerbla_handler_fptr) (void);
+
+/* Pointer to function to call to handle error.  In the Octave
+   interpreter we set this to a function that throws an exception and
+   transfers control to the enclosing try/catch block.  That is
+   typically at the top-level REPL.
+
+   We must use a function pointer instead of simply calling error
+   directly here because this function is called by LAPACK and BLAS
+   subroutines.  To build shared libraries of those packages on Windows
+   requires that all symbols be known when the shared library is
+   constructed.  If we call error directly, that would mean that the
+   BLAS and LAPACK libraries would have to depend on Octave...  */
+
+static xerbla_handler_fptr xerbla_handler = nullptr;
+
+extern "C" void
+octave_set_xerbla_handler (xerbla_handler_fptr fcn)
+{
+  xerbla_handler = fcn;
+}
+
+/* Replacement for BLAS and LAPACK XERBLA subroutine that calls an
+   optionally installed handler function.  */
+
+F77_RET_T
+F77_FUNC (xerbla, XERBLA) (F77_CONST_CHAR_ARG_DEF (s_arg, len),
+                           const F77_INT& info
+                           F77_CHAR_ARG_LEN_DEF (len))
+{
+  const char *s = F77_CHAR_ARG_USE (s_arg);
+  int slen = F77_CHAR_ARG_LEN_USE (s_arg, len);
+
+  std::cerr << std::string (s, slen) << ": parameter number " << info
+            << " is invalid" << std::endl;
+
+   if (xerbla_handler)
+     (*xerbla_handler) ();
+
+  F77_RETURN (0)
+}
--- a/liboctave/external/fftpack/cfftb.f	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-      subroutine cfftb (n,c,wsave)
-      dimension       c(*)       ,wsave(*)
-      if (n .eq. 1) return
-      iw1 = n+n+1
-      iw2 = iw1+n+n
-      call cfftb1 (n,c,wsave,wsave(iw1),wsave(iw2))
-      return
-      end
--- a/liboctave/external/fftpack/cfftb1.f	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-      subroutine cfftb1 (n,c,ch,wa,ifac)
-      dimension       ch(*)      ,c(*)       ,wa(*)      ,ifac(*)
-      nf = ifac(2)
-      na = 0
-      l1 = 1
-      iw = 1
-      do 116 k1=1,nf
-         ip = ifac(k1+2)
-         l2 = ip*l1
-         ido = n/l2
-         idot = ido+ido
-         idl1 = idot*l1
-         if (ip .ne. 4) go to 103
-         ix2 = iw+idot
-         ix3 = ix2+idot
-         if (na .ne. 0) go to 101
-         call passb4 (idot,l1,c,ch,wa(iw),wa(ix2),wa(ix3))
-         go to 102
-  101    call passb4 (idot,l1,ch,c,wa(iw),wa(ix2),wa(ix3))
-  102    na = 1-na
-         go to 115
-  103    if (ip .ne. 2) go to 106
-         if (na .ne. 0) go to 104
-         call passb2 (idot,l1,c,ch,wa(iw))
-         go to 105
-  104    call passb2 (idot,l1,ch,c,wa(iw))
-  105    na = 1-na
-         go to 115
-  106    if (ip .ne. 3) go to 109
-         ix2 = iw+idot
-         if (na .ne. 0) go to 107
-         call passb3 (idot,l1,c,ch,wa(iw),wa(ix2))
-         go to 108
-  107    call passb3 (idot,l1,ch,c,wa(iw),wa(ix2))
-  108    na = 1-na
-         go to 115
-  109    if (ip .ne. 5) go to 112
-         ix2 = iw+idot
-         ix3 = ix2+idot
-         ix4 = ix3+idot
-         if (na .ne. 0) go to 110
-         call passb5 (idot,l1,c,ch,wa(iw),wa(ix2),wa(ix3),wa(ix4))
-         go to 111
-  110    call passb5 (idot,l1,ch,c,wa(iw),wa(ix2),wa(ix3),wa(ix4))
-  111    na = 1-na
-         go to 115
-  112    if (na .ne. 0) go to 113
-         call passb (nac,idot,ip,l1,idl1,c,c,c,ch,ch,wa(iw))
-         go to 114
-  113    call passb (nac,idot,ip,l1,idl1,ch,ch,ch,c,c,wa(iw))
-  114    if (nac .ne. 0) na = 1-na
-  115    l1 = l2
-         iw = iw+(ip-1)*idot
-  116 continue
-      if (na .eq. 0) return
-      n2 = n+n
-      do 117 i=1,n2
-         c(i) = ch(i)
-  117 continue
-      return
-      end
--- a/liboctave/external/fftpack/cfftf.f	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-      subroutine cfftf (n,c,wsave)
-      dimension       c(*)       ,wsave(*)
-      if (n .eq. 1) return
-      iw1 = n+n+1
-      iw2 = iw1+n+n
-      call cfftf1 (n,c,wsave,wsave(iw1),wsave(iw2))
-      return
-      end
--- a/liboctave/external/fftpack/cfftf1.f	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-      subroutine cfftf1 (n,c,ch,wa,ifac)
-      dimension       ch(*)      ,c(*)       ,wa(*)      ,ifac(*)
-      nf = ifac(2)
-      na = 0
-      l1 = 1
-      iw = 1
-      do 116 k1=1,nf
-         ip = ifac(k1+2)
-         l2 = ip*l1
-         ido = n/l2
-         idot = ido+ido
-         idl1 = idot*l1
-         if (ip .ne. 4) go to 103
-         ix2 = iw+idot
-         ix3 = ix2+idot
-         if (na .ne. 0) go to 101
-         call passf4 (idot,l1,c,ch,wa(iw),wa(ix2),wa(ix3))
-         go to 102
-  101    call passf4 (idot,l1,ch,c,wa(iw),wa(ix2),wa(ix3))
-  102    na = 1-na
-         go to 115
-  103    if (ip .ne. 2) go to 106
-         if (na .ne. 0) go to 104
-         call passf2 (idot,l1,c,ch,wa(iw))
-         go to 105
-  104    call passf2 (idot,l1,ch,c,wa(iw))
-  105    na = 1-na
-         go to 115
-  106    if (ip .ne. 3) go to 109
-         ix2 = iw+idot
-         if (na .ne. 0) go to 107
-         call passf3 (idot,l1,c,ch,wa(iw),wa(ix2))
-         go to 108
-  107    call passf3 (idot,l1,ch,c,wa(iw),wa(ix2))
-  108    na = 1-na
-         go to 115
-  109    if (ip .ne. 5) go to 112
-         ix2 = iw+idot
-         ix3 = ix2+idot
-         ix4 = ix3+idot
-         if (na .ne. 0) go to 110
-         call passf5 (idot,l1,c,ch,wa(iw),wa(ix2),wa(ix3),wa(ix4))
-         go to 111
-  110    call passf5 (idot,l1,ch,c,wa(iw),wa(ix2),wa(ix3),wa(ix4))
-  111    na = 1-na
-         go to 115
-  112    if (na .ne. 0) go to 113
-         call passf (nac,idot,ip,l1,idl1,c,c,c,ch,ch,wa(iw))
-         go to 114
-  113    call passf (nac,idot,ip,l1,idl1,ch,ch,ch,c,c,wa(iw))
-  114    if (nac .ne. 0) na = 1-na
-  115    l1 = l2
-         iw = iw+(ip-1)*idot
-  116 continue
-      if (na .eq. 0) return
-      n2 = n+n
-      do 117 i=1,n2
-         c(i) = ch(i)
-  117 continue
-      return
-      end
--- a/liboctave/external/fftpack/cffti.f	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-      subroutine cffti (n,wsave)
-      dimension       wsave(*)
-      if (n .eq. 1) return
-      iw1 = n+n+1
-      iw2 = iw1+n+n
-      call cffti1 (n,wsave(iw1),wsave(iw2))
-      return
-      end
--- a/liboctave/external/fftpack/cffti1.f	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-      subroutine cffti1 (n,wa,ifac)
-      dimension       wa(*)      ,ifac(*)    ,ntryh(4)
-      data ntryh(1),ntryh(2),ntryh(3),ntryh(4)/3,4,2,5/
-      nl = n
-      nf = 0
-      j = 0
-  101 j = j+1
-      if (j-4) 102,102,103
-  102 ntry = ntryh(j)
-      go to 104
-  103 ntry = ntry+2
-  104 nq = nl/ntry
-      nr = nl-ntry*nq
-      if (nr) 101,105,101
-  105 nf = nf+1
-      ifac(nf+2) = ntry
-      nl = nq
-      if (ntry .ne. 2) go to 107
-      if (nf .eq. 1) go to 107
-      do 106 i=2,nf
-         ib = nf-i+2
-         ifac(ib+2) = ifac(ib+1)
-  106 continue
-      ifac(3) = 2
-  107 if (nl .ne. 1) go to 104
-      ifac(1) = n
-      ifac(2) = nf
-      tpi = 6.28318530717959
-      argh = tpi/dble(n)
-      i = 2
-      l1 = 1
-      do 110 k1=1,nf
-         ip = ifac(k1+2)
-         ld = 0
-         l2 = l1*ip
-         ido = n/l2
-         idot = ido+ido+2
-         ipm = ip-1
-         do 109 j=1,ipm
-            i1 = i
-            wa(i-1) = 1.
-            wa(i) = 0.
-            ld = ld+l1
-            fi = 0.
-            argld = dble(ld)*argh
-            do 108 ii=4,idot,2
-               i = i+2
-               fi = fi+1.
-               arg = fi*argld
-               wa(i-1) = cos(arg)
-               wa(i) = sin(arg)
-  108       continue
-            if (ip .le. 5) go to 109
-            wa(i1-1) = wa(i-1)
-            wa(i1) = wa(i)
-  109    continue
-         l1 = l2
-  110 continue
-      return
-      end
--- a/liboctave/external/fftpack/fftpack.doc	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,865 +0,0 @@
-
-                      FFTPACK
-
-* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-
-                  version 4  april 1985
-
-     a package of fortran subprograms for the fast fourier
-      transform of periodic and other symmetric sequences
-
-                         by
-
-                  paul n swarztrauber
-
-  national center for atmospheric research  boulder,colorado 80307
-
-   which is sponsored by the national science foundation
-
-* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-
-
-this package consists of programs which perform fast fourier
-transforms for both complex and real periodic sequences and
-certain other symmetric sequences that are listed below.
-
-1.   rffti     initialize  rfftf and rfftb
-2.   rfftf     forward transform of a real periodic sequence
-3.   rfftb     backward transform of a real coefficient array
-
-4.   ezffti    initialize ezfftf and ezfftb
-5.   ezfftf    a simplified real periodic forward transform
-6.   ezfftb    a simplified real periodic backward transform
-
-7.   sinti     initialize sint
-8.   sint      sine transform of a real odd sequence
-
-9.   costi     initialize cost
-10.  cost      cosine transform of a real even sequence
-
-11.  sinqi     initialize sinqf and sinqb
-12.  sinqf     forward sine transform with odd wave numbers
-13.  sinqb     unnormalized inverse of sinqf
-
-14.  cosqi     initialize cosqf and cosqb
-15.  cosqf     forward cosine transform with odd wave numbers
-16.  cosqb     unnormalized inverse of cosqf
-
-17.  cffti     initialize cfftf and cfftb
-18.  cfftf     forward transform of a complex periodic sequence
-19.  cfftb     unnormalized inverse of cfftf
-
-
-******************************************************************
-
-subroutine rffti(n,wsave)
-
-  ****************************************************************
-
-subroutine rffti initializes the array wsave which is used in
-both rfftf and rfftb. the prime factorization of n together with
-a tabulation of the trigonometric functions are computed and
-stored in wsave.
-
-input parameter
-
-n       the length of the sequence to be transformed.
-
-output parameter
-
-wsave   a work array which must be dimensioned at least 2*n+15.
-        the same work array can be used for both rfftf and rfftb
-        as long as n remains unchanged. different wsave arrays
-        are required for different values of n. the contents of
-        wsave must not be changed between calls of rfftf or rfftb.
-
-******************************************************************
-
-subroutine rfftf(n,r,wsave)
-
-******************************************************************
-
-subroutine rfftf computes the fourier coefficients of a real
-perodic sequence (fourier analysis). the transform is defined
-below at output parameter r.
-
-input parameters
-
-n       the length of the array r to be transformed.  the method
-        is most efficient when n is a product of small primes.
-        n may change so long as different work arrays are provided
-
-r       a real array of length n which contains the sequence
-        to be transformed
-
-wsave   a work array which must be dimensioned at least 2*n+15.
-        in the program that calls rfftf. the wsave array must be
-        initialized by calling subroutine rffti(n,wsave) and a
-        different wsave array must be used for each different
-        value of n. this initialization does not have to be
-        repeated so long as n remains unchanged thus subsequent
-        transforms can be obtained faster than the first.
-        the same wsave array can be used by rfftf and rfftb.
-
-
-output parameters
-
-r       r(1) = the sum from i=1 to i=n of r(i)
-
-        if n is even set l =n/2   , if n is odd set l = (n+1)/2
-
-          then for k = 2,...,l
-
-             r(2*k-2) = the sum from i = 1 to i = n of
-
-                  r(i)*cos((k-1)*(i-1)*2*pi/n)
-
-             r(2*k-1) = the sum from i = 1 to i = n of
-
-                 -r(i)*sin((k-1)*(i-1)*2*pi/n)
-
-        if n is even
-
-             r(n) = the sum from i = 1 to i = n of
-
-                  (-1)**(i-1)*r(i)
-
- *****  note
-             this transform is unnormalized since a call of rfftf
-             followed by a call of rfftb will multiply the input
-             sequence by n.
-
-wsave   contains results which must not be destroyed between
-        calls of rfftf or rfftb.
-
-
-******************************************************************
-
-subroutine rfftb(n,r,wsave)
-
-******************************************************************
-
-subroutine rfftb computes the real perodic sequence from its
-fourier coefficients (fourier synthesis). the transform is defined
-below at output parameter r.
-
-input parameters
-
-n       the length of the array r to be transformed.  the method
-        is most efficient when n is a product of small primes.
-        n may change so long as different work arrays are provided
-
-r       a real array of length n which contains the sequence
-        to be transformed
-
-wsave   a work array which must be dimensioned at least 2*n+15.
-        in the program that calls rfftb. the wsave array must be
-        initialized by calling subroutine rffti(n,wsave) and a
-        different wsave array must be used for each different
-        value of n. this initialization does not have to be
-        repeated so long as n remains unchanged thus subsequent
-        transforms can be obtained faster than the first.
-        the same wsave array can be used by rfftf and rfftb.
-
-
-output parameters
-
-r       for n even and for i = 1,...,n
-
-             r(i) = r(1)+(-1)**(i-1)*r(n)
-
-                  plus the sum from k=2 to k=n/2 of
-
-                   2.*r(2*k-2)*cos((k-1)*(i-1)*2*pi/n)
-
-                  -2.*r(2*k-1)*sin((k-1)*(i-1)*2*pi/n)
-
-        for n odd and for i = 1,...,n
-
-             r(i) = r(1) plus the sum from k=2 to k=(n+1)/2 of
-
-                  2.*r(2*k-2)*cos((k-1)*(i-1)*2*pi/n)
-
-                 -2.*r(2*k-1)*sin((k-1)*(i-1)*2*pi/n)
-
- *****  note
-             this transform is unnormalized since a call of rfftf
-             followed by a call of rfftb will multiply the input
-             sequence by n.
-
-wsave   contains results which must not be destroyed between
-        calls of rfftb or rfftf.
-
-
-******************************************************************
-
-subroutine ezffti(n,wsave)
-
-******************************************************************
-
-subroutine ezffti initializes the array wsave which is used in
-both ezfftf and ezfftb. the prime factorization of n together with
-a tabulation of the trigonometric functions are computed and
-stored in wsave.
-
-input parameter
-
-n       the length of the sequence to be transformed.
-
-output parameter
-
-wsave   a work array which must be dimensioned at least 3*n+15.
-        the same work array can be used for both ezfftf and ezfftb
-        as long as n remains unchanged. different wsave arrays
-        are required for different values of n.
-
-
-******************************************************************
-
-subroutine ezfftf(n,r,azero,a,b,wsave)
-
-******************************************************************
-
-subroutine ezfftf computes the fourier coefficients of a real
-perodic sequence (fourier analysis). the transform is defined
-below at output parameters azero,a and b. ezfftf is a simplified
-but slower version of rfftf.
-
-input parameters
-
-n       the length of the array r to be transformed.  the method
-        is must efficient when n is the product of small primes.
-
-r       a real array of length n which contains the sequence
-        to be transformed. r is not destroyed.
-
-
-wsave   a work array which must be dimensioned at least 3*n+15.
-        in the program that calls ezfftf. the wsave array must be
-        initialized by calling subroutine ezffti(n,wsave) and a
-        different wsave array must be used for each different
-        value of n. this initialization does not have to be
-        repeated so long as n remains unchanged thus subsequent
-        transforms can be obtained faster than the first.
-        the same wsave array can be used by ezfftf and ezfftb.
-
-output parameters
-
-azero   the sum from i=1 to i=n of r(i)/n
-
-a,b     for n even b(n/2)=0. and a(n/2) is the sum from i=1 to
-        i=n of (-1)**(i-1)*r(i)/n
-
-        for n even define kmax=n/2-1
-        for n odd  define kmax=(n-1)/2
-
-        then for  k=1,...,kmax
-
-             a(k) equals the sum from i=1 to i=n of
-
-                  2./n*r(i)*cos(k*(i-1)*2*pi/n)
-
-             b(k) equals the sum from i=1 to i=n of
-
-                  2./n*r(i)*sin(k*(i-1)*2*pi/n)
-
-
-******************************************************************
-
-subroutine ezfftb(n,r,azero,a,b,wsave)
-
-******************************************************************
-
-subroutine ezfftb computes a real perodic sequence from its
-fourier coefficients (fourier synthesis). the transform is
-defined below at output parameter r. ezfftb is a simplified
-but slower version of rfftb.
-
-input parameters
-
-n       the length of the output array r.  the method is most
-        efficient when n is the product of small primes.
-
-azero   the constant fourier coefficient
-
-a,b     arrays which contain the remaining fourier coefficients
-        these arrays are not destroyed.
-
-        the length of these arrays depends on whether n is even or
-        odd.
-
-        if n is even n/2    locations are required
-        if n is odd (n-1)/2 locations are required
-
-wsave   a work array which must be dimensioned at least 3*n+15.
-        in the program that calls ezfftb. the wsave array must be
-        initialized by calling subroutine ezffti(n,wsave) and a
-        different wsave array must be used for each different
-        value of n. this initialization does not have to be
-        repeated so long as n remains unchanged thus subsequent
-        transforms can be obtained faster than the first.
-        the same wsave array can be used by ezfftf and ezfftb.
-
-
-output parameters
-
-r       if n is even define kmax=n/2
-        if n is odd  define kmax=(n-1)/2
-
-        then for i=1,...,n
-
-             r(i)=azero plus the sum from k=1 to k=kmax of
-
-             a(k)*cos(k*(i-1)*2*pi/n)+b(k)*sin(k*(i-1)*2*pi/n)
-
-********************* complex notation **************************
-
-        for j=1,...,n
-
-        r(j) equals the sum from k=-kmax to k=kmax of
-
-             c(k)*exp(i*k*(j-1)*2*pi/n)
-
-        where
-
-             c(k) = .5*cmplx(a(k),-b(k))   for k=1,...,kmax
-
-             c(-k) = conjg(c(k))
-
-             c(0) = azero
-
-                  and i=sqrt(-1)
-
-*************** amplitude - phase notation ***********************
-
-        for i=1,...,n
-
-        r(i) equals azero plus the sum from k=1 to k=kmax of
-
-             alpha(k)*cos(k*(i-1)*2*pi/n+beta(k))
-
-        where
-
-             alpha(k) = sqrt(a(k)*a(k)+b(k)*b(k))
-
-             cos(beta(k))=a(k)/alpha(k)
-
-             sin(beta(k))=-b(k)/alpha(k)
-
-******************************************************************
-
-subroutine sinti(n,wsave)
-
-******************************************************************
-
-subroutine sinti initializes the array wsave which is used in
-subroutine sint. the prime factorization of n together with
-a tabulation of the trigonometric functions are computed and
-stored in wsave.
-
-input parameter
-
-n       the length of the sequence to be transformed.  the method
-        is most efficient when n+1 is a product of small primes.
-
-output parameter
-
-wsave   a work array with at least int(2.5*n+15) locations.
-        different wsave arrays are required for different values
-        of n. the contents of wsave must not be changed between
-        calls of sint.
-
-******************************************************************
-
-subroutine sint(n,x,wsave)
-
-******************************************************************
-
-subroutine sint computes the discrete fourier sine transform
-of an odd sequence x(i). the transform is defined below at
-output parameter x.
-
-sint is the unnormalized inverse of itself since a call of sint
-followed by another call of sint will multiply the input sequence
-x by 2*(n+1).
-
-the array wsave which is used by subroutine sint must be
-initialized by calling subroutine sinti(n,wsave).
-
-input parameters
-
-n       the length of the sequence to be transformed.  the method
-        is most efficient when n+1 is the product of small primes.
-
-x       an array which contains the sequence to be transformed
-
-
-wsave   a work array with dimension at least int(2.5*n+15)
-        in the program that calls sint. the wsave array must be
-        initialized by calling subroutine sinti(n,wsave) and a
-        different wsave array must be used for each different
-        value of n. this initialization does not have to be
-        repeated so long as n remains unchanged thus subsequent
-        transforms can be obtained faster than the first.
-
-output parameters
-
-x       for i=1,...,n
-
-             x(i)= the sum from k=1 to k=n
-
-                  2*x(k)*sin(k*i*pi/(n+1))
-
-             a call of sint followed by another call of
-             sint will multiply the sequence x by 2*(n+1).
-             hence sint is the unnormalized inverse
-             of itself.
-
-wsave   contains initialization calculations which must not be
-        destroyed between calls of sint.
-
-******************************************************************
-
-subroutine costi(n,wsave)
-
-******************************************************************
-
-subroutine costi initializes the array wsave which is used in
-subroutine cost. the prime factorization of n together with
-a tabulation of the trigonometric functions are computed and
-stored in wsave.
-
-input parameter
-
-n       the length of the sequence to be transformed.  the method
-        is most efficient when n-1 is a product of small primes.
-
-output parameter
-
-wsave   a work array which must be dimensioned at least 3*n+15.
-        different wsave arrays are required for different values
-        of n. the contents of wsave must not be changed between
-        calls of cost.
-
-******************************************************************
-
-subroutine cost(n,x,wsave)
-
-******************************************************************
-
-subroutine cost computes the discrete fourier cosine transform
-of an even sequence x(i). the transform is defined below at output
-parameter x.
-
-cost is the unnormalized inverse of itself since a call of cost
-followed by another call of cost will multiply the input sequence
-x by 2*(n-1). the transform is defined below at output parameter x
-
-the array wsave which is used by subroutine cost must be
-initialized by calling subroutine costi(n,wsave).
-
-input parameters
-
-n       the length of the sequence x. n must be greater than 1.
-        the method is most efficient when n-1 is a product of
-        small primes.
-
-x       an array which contains the sequence to be transformed
-
-wsave   a work array which must be dimensioned at least 3*n+15
-        in the program that calls cost. the wsave array must be
-        initialized by calling subroutine costi(n,wsave) and a
-        different wsave array must be used for each different
-        value of n. this initialization does not have to be
-        repeated so long as n remains unchanged thus subsequent
-        transforms can be obtained faster than the first.
-
-output parameters
-
-x       for i=1,...,n
-
-            x(i) = x(1)+(-1)**(i-1)*x(n)
-
-             + the sum from k=2 to k=n-1
-
-                 2*x(k)*cos((k-1)*(i-1)*pi/(n-1))
-
-             a call of cost followed by another call of
-             cost will multiply the sequence x by 2*(n-1)
-             hence cost is the unnormalized inverse
-             of itself.
-
-wsave   contains initialization calculations which must not be
-        destroyed between calls of cost.
-
-******************************************************************
-
-subroutine sinqi(n,wsave)
-
-******************************************************************
-
-subroutine sinqi initializes the array wsave which is used in
-both sinqf and sinqb. the prime factorization of n together with
-a tabulation of the trigonometric functions are computed and
-stored in wsave.
-
-input parameter
-
-n       the length of the sequence to be transformed. the method
-        is most efficient when n is a product of small primes.
-
-output parameter
-
-wsave   a work array which must be dimensioned at least 3*n+15.
-        the same work array can be used for both sinqf and sinqb
-        as long as n remains unchanged. different wsave arrays
-        are required for different values of n. the contents of
-        wsave must not be changed between calls of sinqf or sinqb.
-
-******************************************************************
-
-subroutine sinqf(n,x,wsave)
-
-******************************************************************
-
-subroutine sinqf computes the fast fourier transform of quarter
-wave data. that is , sinqf computes the coefficients in a sine
-series representation with only odd wave numbers. the transform
-is defined below at output parameter x.
-
-sinqb is the unnormalized inverse of sinqf since a call of sinqf
-followed by a call of sinqb will multiply the input sequence x
-by 4*n.
-
-the array wsave which is used by subroutine sinqf must be
-initialized by calling subroutine sinqi(n,wsave).
-
-
-input parameters
-
-n       the length of the array x to be transformed.  the method
-        is most efficient when n is a product of small primes.
-
-x       an array which contains the sequence to be transformed
-
-wsave   a work array which must be dimensioned at least 3*n+15.
-        in the program that calls sinqf. the wsave array must be
-        initialized by calling subroutine sinqi(n,wsave) and a
-        different wsave array must be used for each different
-        value of n. this initialization does not have to be
-        repeated so long as n remains unchanged thus subsequent
-        transforms can be obtained faster than the first.
-
-output parameters
-
-x       for i=1,...,n
-
-             x(i) = (-1)**(i-1)*x(n)
-
-                + the sum from k=1 to k=n-1 of
-
-                2*x(k)*sin((2*i-1)*k*pi/(2*n))
-
-             a call of sinqf followed by a call of
-             sinqb will multiply the sequence x by 4*n.
-             therefore sinqb is the unnormalized inverse
-             of sinqf.
-
-wsave   contains initialization calculations which must not
-        be destroyed between calls of sinqf or sinqb.
-
-******************************************************************
-
-subroutine sinqb(n,x,wsave)
-
-******************************************************************
-
-subroutine sinqb computes the fast fourier transform of quarter
-wave data. that is , sinqb computes a sequence from its
-representation in terms of a sine series with odd wave numbers.
-the transform is defined below at output parameter x.
-
-sinqf is the unnormalized inverse of sinqb since a call of sinqb
-followed by a call of sinqf will multiply the input sequence x
-by 4*n.
-
-the array wsave which is used by subroutine sinqb must be
-initialized by calling subroutine sinqi(n,wsave).
-
-
-input parameters
-
-n       the length of the array x to be transformed.  the method
-        is most efficient when n is a product of small primes.
-
-x       an array which contains the sequence to be transformed
-
-wsave   a work array which must be dimensioned at least 3*n+15.
-        in the program that calls sinqb. the wsave array must be
-        initialized by calling subroutine sinqi(n,wsave) and a
-        different wsave array must be used for each different
-        value of n. this initialization does not have to be
-        repeated so long as n remains unchanged thus subsequent
-        transforms can be obtained faster than the first.
-
-output parameters
-
-x       for i=1,...,n
-
-             x(i)= the sum from k=1 to k=n of
-
-               4*x(k)*sin((2k-1)*i*pi/(2*n))
-
-             a call of sinqb followed by a call of
-             sinqf will multiply the sequence x by 4*n.
-             therefore sinqf is the unnormalized inverse
-             of sinqb.
-
-wsave   contains initialization calculations which must not
-        be destroyed between calls of sinqb or sinqf.
-
-******************************************************************
-
-subroutine cosqi(n,wsave)
-
-******************************************************************
-
-subroutine cosqi initializes the array wsave which is used in
-both cosqf and cosqb. the prime factorization of n together with
-a tabulation of the trigonometric functions are computed and
-stored in wsave.
-
-input parameter
-
-n       the length of the array to be transformed.  the method
-        is most efficient when n is a product of small primes.
-
-output parameter
-
-wsave   a work array which must be dimensioned at least 3*n+15.
-        the same work array can be used for both cosqf and cosqb
-        as long as n remains unchanged. different wsave arrays
-        are required for different values of n. the contents of
-        wsave must not be changed between calls of cosqf or cosqb.
-
-******************************************************************
-
-subroutine cosqf(n,x,wsave)
-
-******************************************************************
-
-subroutine cosqf computes the fast fourier transform of quarter
-wave data. that is , cosqf computes the coefficients in a cosine
-series representation with only odd wave numbers. the transform
-is defined below at output parameter x
-
-cosqf is the unnormalized inverse of cosqb since a call of cosqf
-followed by a call of cosqb will multiply the input sequence x
-by 4*n.
-
-the array wsave which is used by subroutine cosqf must be
-initialized by calling subroutine cosqi(n,wsave).
-
-
-input parameters
-
-n       the length of the array x to be transformed.  the method
-        is most efficient when n is a product of small primes.
-
-x       an array which contains the sequence to be transformed
-
-wsave   a work array which must be dimensioned at least 3*n+15
-        in the program that calls cosqf. the wsave array must be
-        initialized by calling subroutine cosqi(n,wsave) and a
-        different wsave array must be used for each different
-        value of n. this initialization does not have to be
-        repeated so long as n remains unchanged thus subsequent
-        transforms can be obtained faster than the first.
-
-output parameters
-
-x       for i=1,...,n
-
-             x(i) = x(1) plus the sum from k=2 to k=n of
-
-                2*x(k)*cos((2*i-1)*(k-1)*pi/(2*n))
-
-             a call of cosqf followed by a call of
-             cosqb will multiply the sequence x by 4*n.
-             therefore cosqb is the unnormalized inverse
-             of cosqf.
-
-wsave   contains initialization calculations which must not
-        be destroyed between calls of cosqf or cosqb.
-
-******************************************************************
-
-subroutine cosqb(n,x,wsave)
-
-******************************************************************
-
-subroutine cosqb computes the fast fourier transform of quarter
-wave data. that is , cosqb computes a sequence from its
-representation in terms of a cosine series with odd wave numbers.
-the transform is defined below at output parameter x.
-
-cosqb is the unnormalized inverse of cosqf since a call of cosqb
-followed by a call of cosqf will multiply the input sequence x
-by 4*n.
-
-the array wsave which is used by subroutine cosqb must be
-initialized by calling subroutine cosqi(n,wsave).
-
-
-input parameters
-
-n       the length of the array x to be transformed.  the method
-        is most efficient when n is a product of small primes.
-
-x       an array which contains the sequence to be transformed
-
-wsave   a work array that must be dimensioned at least 3*n+15
-        in the program that calls cosqb. the wsave array must be
-        initialized by calling subroutine cosqi(n,wsave) and a
-        different wsave array must be used for each different
-        value of n. this initialization does not have to be
-        repeated so long as n remains unchanged thus subsequent
-        transforms can be obtained faster than the first.
-
-output parameters
-
-x       for i=1,...,n
-
-             x(i)= the sum from k=1 to k=n of
-
-               4*x(k)*cos((2*k-1)*(i-1)*pi/(2*n))
-
-             a call of cosqb followed by a call of
-             cosqf will multiply the sequence x by 4*n.
-             therefore cosqf is the unnormalized inverse
-             of cosqb.
-
-wsave   contains initialization calculations which must not
-        be destroyed between calls of cosqb or cosqf.
-
-******************************************************************
-
-subroutine cffti(n,wsave)
-
-******************************************************************
-
-subroutine cffti initializes the array wsave which is used in
-both cfftf and cfftb. the prime factorization of n together with
-a tabulation of the trigonometric functions are computed and
-stored in wsave.
-
-input parameter
-
-n       the length of the sequence to be transformed
-
-output parameter
-
-wsave   a work array which must be dimensioned at least 4*n+15
-        the same work array can be used for both cfftf and cfftb
-        as long as n remains unchanged. different wsave arrays
-        are required for different values of n. the contents of
-        wsave must not be changed between calls of cfftf or cfftb.
-
-******************************************************************
-
-subroutine cfftf(n,c,wsave)
-
-******************************************************************
-
-subroutine cfftf computes the forward complex discrete fourier
-transform (the fourier analysis). equivalently , cfftf computes
-the fourier coefficients of a complex periodic sequence.
-the transform is defined below at output parameter c.
-
-the transform is not normalized. to obtain a normalized transform
-the output must be divided by n. otherwise a call of cfftf
-followed by a call of cfftb will multiply the sequence by n.
-
-the array wsave which is used by subroutine cfftf must be
-initialized by calling subroutine cffti(n,wsave).
-
-input parameters
-
-
-n      the length of the complex sequence c. the method is
-       more efficient when n is the product of small primes. n
-
-c      a complex array of length n which contains the sequence
-
-wsave   a real work array which must be dimensioned at least 4n+15
-        in the program that calls cfftf. the wsave array must be
-        initialized by calling subroutine cffti(n,wsave) and a
-        different wsave array must be used for each different
-        value of n. this initialization does not have to be
-        repeated so long as n remains unchanged thus subsequent
-        transforms can be obtained faster than the first.
-        the same wsave array can be used by cfftf and cfftb.
-
-output parameters
-
-c      for j=1,...,n
-
-           c(j)=the sum from k=1,...,n of
-
-                 c(k)*exp(-i*(j-1)*(k-1)*2*pi/n)
-
-                       where i=sqrt(-1)
-
-wsave   contains initialization calculations which must not be
-        destroyed between calls of subroutine cfftf or cfftb
-
-******************************************************************
-
-subroutine cfftb(n,c,wsave)
-
-******************************************************************
-
-subroutine cfftb computes the backward complex discrete fourier
-transform (the fourier synthesis). equivalently , cfftb computes
-a complex periodic sequence from its fourier coefficients.
-the transform is defined below at output parameter c.
-
-a call of cfftf followed by a call of cfftb will multiply the
-sequence by n.
-
-the array wsave which is used by subroutine cfftb must be
-initialized by calling subroutine cffti(n,wsave).
-
-input parameters
-
-
-n      the length of the complex sequence c. the method is
-       more efficient when n is the product of small primes.
-
-c      a complex array of length n which contains the sequence
-
-wsave   a real work array which must be dimensioned at least 4n+15
-        in the program that calls cfftb. the wsave array must be
-        initialized by calling subroutine cffti(n,wsave) and a
-        different wsave array must be used for each different
-        value of n. this initialization does not have to be
-        repeated so long as n remains unchanged thus subsequent
-        transforms can be obtained faster than the first.
-        the same wsave array can be used by cfftf and cfftb.
-
-output parameters
-
-c      for j=1,...,n
-
-           c(j)=the sum from k=1,...,n of
-
-                 c(k)*exp(i*(j-1)*(k-1)*2*pi/n)
-
-                       where i=sqrt(-1)
-
-wsave   contains initialization calculations which must not be
-        destroyed between calls of subroutine cfftf or cfftb
-
-
-
-["send index for vfftpk" describes a vectorized version of fftpack]
--- a/liboctave/external/fftpack/module.mk	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-FFTPACK_SRC = \
-  %reldir%/cfftb.f \
-  %reldir%/cfftb1.f \
-  %reldir%/cfftf.f \
-  %reldir%/cfftf1.f \
-  %reldir%/cffti.f \
-  %reldir%/cffti1.f \
-  %reldir%/passb.f \
-  %reldir%/passb2.f \
-  %reldir%/passb3.f \
-  %reldir%/passb4.f \
-  %reldir%/passb5.f \
-  %reldir%/passf.f \
-  %reldir%/passf2.f \
-  %reldir%/passf3.f \
-  %reldir%/passf4.f \
-  %reldir%/passf5.f \
-  %reldir%/zfftb.f \
-  %reldir%/zfftb1.f \
-  %reldir%/zfftf.f \
-  %reldir%/zfftf1.f \
-  %reldir%/zffti.f \
-  %reldir%/zffti1.f \
-  %reldir%/zpassb.f \
-  %reldir%/zpassb2.f \
-  %reldir%/zpassb3.f \
-  %reldir%/zpassb4.f \
-  %reldir%/zpassb5.f \
-  %reldir%/zpassf.f \
-  %reldir%/zpassf2.f \
-  %reldir%/zpassf3.f \
-  %reldir%/zpassf4.f \
-  %reldir%/zpassf5.f
-
-if AMCOND_HAVE_FFTW
-  liboctave_EXTRA_DIST += $(FFTPACK_SRC)
-else
-  EXTERNAL_SOURCES += $(FFTPACK_SRC)
-endif
-
-liboctave_EXTRA_DIST += \
-  %reldir%/fftpack.doc
--- a/liboctave/external/fftpack/passb.f	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,116 +0,0 @@
-      subroutine passb (nac,ido,ip,l1,idl1,cc,c1,c2,ch,ch2,wa)
-      dimension       ch(ido,l1,ip)          ,cc(ido,ip,l1)          ,
-     1                c1(ido,l1,ip)          ,wa(1)      ,c2(idl1,ip),
-     2                ch2(idl1,ip)
-      idot = ido/2
-      nt = ip*idl1
-      ipp2 = ip+2
-      ipph = (ip+1)/2
-      idp = ip*ido
-c
-      if (ido .lt. l1) go to 106
-      do 103 j=2,ipph
-         jc = ipp2-j
-         do 102 k=1,l1
-            do 101 i=1,ido
-               ch(i,k,j) = cc(i,j,k)+cc(i,jc,k)
-               ch(i,k,jc) = cc(i,j,k)-cc(i,jc,k)
-  101       continue
-  102    continue
-  103 continue
-      do 105 k=1,l1
-         do 104 i=1,ido
-            ch(i,k,1) = cc(i,1,k)
-  104    continue
-  105 continue
-      go to 112
-  106 do 109 j=2,ipph
-         jc = ipp2-j
-         do 108 i=1,ido
-            do 107 k=1,l1
-               ch(i,k,j) = cc(i,j,k)+cc(i,jc,k)
-               ch(i,k,jc) = cc(i,j,k)-cc(i,jc,k)
-  107       continue
-  108    continue
-  109 continue
-      do 111 i=1,ido
-         do 110 k=1,l1
-            ch(i,k,1) = cc(i,1,k)
-  110    continue
-  111 continue
-  112 idl = 2-ido
-      inc = 0
-      do 116 l=2,ipph
-         lc = ipp2-l
-         idl = idl+ido
-         do 113 ik=1,idl1
-            c2(ik,l) = ch2(ik,1)+wa(idl-1)*ch2(ik,2)
-            c2(ik,lc) = wa(idl)*ch2(ik,ip)
-  113    continue
-         idlj = idl
-         inc = inc+ido
-         do 115 j=3,ipph
-            jc = ipp2-j
-            idlj = idlj+inc
-            if (idlj .gt. idp) idlj = idlj-idp
-            war = wa(idlj-1)
-            wai = wa(idlj)
-            do 114 ik=1,idl1
-               c2(ik,l) = c2(ik,l)+war*ch2(ik,j)
-               c2(ik,lc) = c2(ik,lc)+wai*ch2(ik,jc)
-  114       continue
-  115    continue
-  116 continue
-      do 118 j=2,ipph
-         do 117 ik=1,idl1
-            ch2(ik,1) = ch2(ik,1)+ch2(ik,j)
-  117    continue
-  118 continue
-      do 120 j=2,ipph
-         jc = ipp2-j
-         do 119 ik=2,idl1,2
-            ch2(ik-1,j) = c2(ik-1,j)-c2(ik,jc)
-            ch2(ik-1,jc) = c2(ik-1,j)+c2(ik,jc)
-            ch2(ik,j) = c2(ik,j)+c2(ik-1,jc)
-            ch2(ik,jc) = c2(ik,j)-c2(ik-1,jc)
-  119    continue
-  120 continue
-      nac = 1
-      if (ido .eq. 2) return
-      nac = 0
-      do 121 ik=1,idl1
-         c2(ik,1) = ch2(ik,1)
-  121 continue
-      do 123 j=2,ip
-         do 122 k=1,l1
-            c1(1,k,j) = ch(1,k,j)
-            c1(2,k,j) = ch(2,k,j)
-  122    continue
-  123 continue
-      if (idot .gt. l1) go to 127
-      idij = 0
-      do 126 j=2,ip
-         idij = idij+2
-         do 125 i=4,ido,2
-            idij = idij+2
-            do 124 k=1,l1
-               c1(i-1,k,j) = wa(idij-1)*ch(i-1,k,j)-wa(idij)*ch(i,k,j)
-               c1(i,k,j) = wa(idij-1)*ch(i,k,j)+wa(idij)*ch(i-1,k,j)
-  124       continue
-  125    continue
-  126 continue
-      return
-  127 idj = 2-ido
-      do 130 j=2,ip
-         idj = idj+ido
-         do 129 k=1,l1
-            idij = idj
-            do 128 i=4,ido,2
-               idij = idij+2
-               c1(i-1,k,j) = wa(idij-1)*ch(i-1,k,j)-wa(idij)*ch(i,k,j)
-               c1(i,k,j) = wa(idij-1)*ch(i,k,j)+wa(idij)*ch(i-1,k,j)
-  128       continue
-  129    continue
-  130 continue
-      return
-      end
--- a/liboctave/external/fftpack/passb2.f	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-      subroutine passb2 (ido,l1,cc,ch,wa1)
-      dimension       cc(ido,2,l1)           ,ch(ido,l1,2)           ,
-     1                wa1(1)
-      if (ido .gt. 2) go to 102
-      do 101 k=1,l1
-         ch(1,k,1) = cc(1,1,k)+cc(1,2,k)
-         ch(1,k,2) = cc(1,1,k)-cc(1,2,k)
-         ch(2,k,1) = cc(2,1,k)+cc(2,2,k)
-         ch(2,k,2) = cc(2,1,k)-cc(2,2,k)
-  101 continue
-      return
-  102 do 104 k=1,l1
-         do 103 i=2,ido,2
-            ch(i-1,k,1) = cc(i-1,1,k)+cc(i-1,2,k)
-            tr2 = cc(i-1,1,k)-cc(i-1,2,k)
-            ch(i,k,1) = cc(i,1,k)+cc(i,2,k)
-            ti2 = cc(i,1,k)-cc(i,2,k)
-            ch(i,k,2) = wa1(i-1)*ti2+wa1(i)*tr2
-            ch(i-1,k,2) = wa1(i-1)*tr2-wa1(i)*ti2
-  103    continue
-  104 continue
-      return
-      end
--- a/liboctave/external/fftpack/passb3.f	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-      subroutine passb3 (ido,l1,cc,ch,wa1,wa2)
-      dimension       cc(ido,3,l1)           ,ch(ido,l1,3)           ,
-     1                wa1(1)     ,wa2(1)
-      data taur,taui /-.5,.866025403784439/
-      if (ido .ne. 2) go to 102
-      do 101 k=1,l1
-         tr2 = cc(1,2,k)+cc(1,3,k)
-         cr2 = cc(1,1,k)+taur*tr2
-         ch(1,k,1) = cc(1,1,k)+tr2
-         ti2 = cc(2,2,k)+cc(2,3,k)
-         ci2 = cc(2,1,k)+taur*ti2
-         ch(2,k,1) = cc(2,1,k)+ti2
-         cr3 = taui*(cc(1,2,k)-cc(1,3,k))
-         ci3 = taui*(cc(2,2,k)-cc(2,3,k))
-         ch(1,k,2) = cr2-ci3
-         ch(1,k,3) = cr2+ci3
-         ch(2,k,2) = ci2+cr3
-         ch(2,k,3) = ci2-cr3
-  101 continue
-      return
-  102 do 104 k=1,l1
-         do 103 i=2,ido,2
-            tr2 = cc(i-1,2,k)+cc(i-1,3,k)
-            cr2 = cc(i-1,1,k)+taur*tr2
-            ch(i-1,k,1) = cc(i-1,1,k)+tr2
-            ti2 = cc(i,2,k)+cc(i,3,k)
-            ci2 = cc(i,1,k)+taur*ti2
-            ch(i,k,1) = cc(i,1,k)+ti2
-            cr3 = taui*(cc(i-1,2,k)-cc(i-1,3,k))
-            ci3 = taui*(cc(i,2,k)-cc(i,3,k))
-            dr2 = cr2-ci3
-            dr3 = cr2+ci3
-            di2 = ci2+cr3
-            di3 = ci2-cr3
-            ch(i,k,2) = wa1(i-1)*di2+wa1(i)*dr2
-            ch(i-1,k,2) = wa1(i-1)*dr2-wa1(i)*di2
-            ch(i,k,3) = wa2(i-1)*di3+wa2(i)*dr3
-            ch(i-1,k,3) = wa2(i-1)*dr3-wa2(i)*di3
-  103    continue
-  104 continue
-      return
-      end
--- a/liboctave/external/fftpack/passb4.f	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-      subroutine passb4 (ido,l1,cc,ch,wa1,wa2,wa3)
-      dimension       cc(ido,4,l1)           ,ch(ido,l1,4)           ,
-     1                wa1(1)     ,wa2(1)     ,wa3(1)
-      if (ido .ne. 2) go to 102
-      do 101 k=1,l1
-         ti1 = cc(2,1,k)-cc(2,3,k)
-         ti2 = cc(2,1,k)+cc(2,3,k)
-         tr4 = cc(2,4,k)-cc(2,2,k)
-         ti3 = cc(2,2,k)+cc(2,4,k)
-         tr1 = cc(1,1,k)-cc(1,3,k)
-         tr2 = cc(1,1,k)+cc(1,3,k)
-         ti4 = cc(1,2,k)-cc(1,4,k)
-         tr3 = cc(1,2,k)+cc(1,4,k)
-         ch(1,k,1) = tr2+tr3
-         ch(1,k,3) = tr2-tr3
-         ch(2,k,1) = ti2+ti3
-         ch(2,k,3) = ti2-ti3
-         ch(1,k,2) = tr1+tr4
-         ch(1,k,4) = tr1-tr4
-         ch(2,k,2) = ti1+ti4
-         ch(2,k,4) = ti1-ti4
-  101 continue
-      return
-  102 do 104 k=1,l1
-         do 103 i=2,ido,2
-            ti1 = cc(i,1,k)-cc(i,3,k)
-            ti2 = cc(i,1,k)+cc(i,3,k)
-            ti3 = cc(i,2,k)+cc(i,4,k)
-            tr4 = cc(i,4,k)-cc(i,2,k)
-            tr1 = cc(i-1,1,k)-cc(i-1,3,k)
-            tr2 = cc(i-1,1,k)+cc(i-1,3,k)
-            ti4 = cc(i-1,2,k)-cc(i-1,4,k)
-            tr3 = cc(i-1,2,k)+cc(i-1,4,k)
-            ch(i-1,k,1) = tr2+tr3
-            cr3 = tr2-tr3
-            ch(i,k,1) = ti2+ti3
-            ci3 = ti2-ti3
-            cr2 = tr1+tr4
-            cr4 = tr1-tr4
-            ci2 = ti1+ti4
-            ci4 = ti1-ti4
-            ch(i-1,k,2) = wa1(i-1)*cr2-wa1(i)*ci2
-            ch(i,k,2) = wa1(i-1)*ci2+wa1(i)*cr2
-            ch(i-1,k,3) = wa2(i-1)*cr3-wa2(i)*ci3
-            ch(i,k,3) = wa2(i-1)*ci3+wa2(i)*cr3
-            ch(i-1,k,4) = wa3(i-1)*cr4-wa3(i)*ci4
-            ch(i,k,4) = wa3(i-1)*ci4+wa3(i)*cr4
-  103    continue
-  104 continue
-      return
-      end
--- a/liboctave/external/fftpack/passb5.f	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-      subroutine passb5 (ido,l1,cc,ch,wa1,wa2,wa3,wa4)
-      dimension       cc(ido,5,l1)           ,ch(ido,l1,5)           ,
-     1                wa1(1)     ,wa2(1)     ,wa3(1)     ,wa4(1)
-      data tr11,ti11,tr12,ti12 /.309016994374947,.951056516295154,
-     1-.809016994374947,.587785252292473/
-      if (ido .ne. 2) go to 102
-      do 101 k=1,l1
-         ti5 = cc(2,2,k)-cc(2,5,k)
-         ti2 = cc(2,2,k)+cc(2,5,k)
-         ti4 = cc(2,3,k)-cc(2,4,k)
-         ti3 = cc(2,3,k)+cc(2,4,k)
-         tr5 = cc(1,2,k)-cc(1,5,k)
-         tr2 = cc(1,2,k)+cc(1,5,k)
-         tr4 = cc(1,3,k)-cc(1,4,k)
-         tr3 = cc(1,3,k)+cc(1,4,k)
-         ch(1,k,1) = cc(1,1,k)+tr2+tr3
-         ch(2,k,1) = cc(2,1,k)+ti2+ti3
-         cr2 = cc(1,1,k)+tr11*tr2+tr12*tr3
-         ci2 = cc(2,1,k)+tr11*ti2+tr12*ti3
-         cr3 = cc(1,1,k)+tr12*tr2+tr11*tr3
-         ci3 = cc(2,1,k)+tr12*ti2+tr11*ti3
-         cr5 = ti11*tr5+ti12*tr4
-         ci5 = ti11*ti5+ti12*ti4
-         cr4 = ti12*tr5-ti11*tr4
-         ci4 = ti12*ti5-ti11*ti4
-         ch(1,k,2) = cr2-ci5
-         ch(1,k,5) = cr2+ci5
-         ch(2,k,2) = ci2+cr5
-         ch(2,k,3) = ci3+cr4
-         ch(1,k,3) = cr3-ci4
-         ch(1,k,4) = cr3+ci4
-         ch(2,k,4) = ci3-cr4
-         ch(2,k,5) = ci2-cr5
-  101 continue
-      return
-  102 do 104 k=1,l1
-         do 103 i=2,ido,2
-            ti5 = cc(i,2,k)-cc(i,5,k)
-            ti2 = cc(i,2,k)+cc(i,5,k)
-            ti4 = cc(i,3,k)-cc(i,4,k)
-            ti3 = cc(i,3,k)+cc(i,4,k)
-            tr5 = cc(i-1,2,k)-cc(i-1,5,k)
-            tr2 = cc(i-1,2,k)+cc(i-1,5,k)
-            tr4 = cc(i-1,3,k)-cc(i-1,4,k)
-            tr3 = cc(i-1,3,k)+cc(i-1,4,k)
-            ch(i-1,k,1) = cc(i-1,1,k)+tr2+tr3
-            ch(i,k,1) = cc(i,1,k)+ti2+ti3
-            cr2 = cc(i-1,1,k)+tr11*tr2+tr12*tr3
-            ci2 = cc(i,1,k)+tr11*ti2+tr12*ti3
-            cr3 = cc(i-1,1,k)+tr12*tr2+tr11*tr3
-            ci3 = cc(i,1,k)+tr12*ti2+tr11*ti3
-            cr5 = ti11*tr5+ti12*tr4
-            ci5 = ti11*ti5+ti12*ti4
-            cr4 = ti12*tr5-ti11*tr4
-            ci4 = ti12*ti5-ti11*ti4
-            dr3 = cr3-ci4
-            dr4 = cr3+ci4
-            di3 = ci3+cr4
-            di4 = ci3-cr4
-            dr5 = cr2+ci5
-            dr2 = cr2-ci5
-            di5 = ci2-cr5
-            di2 = ci2+cr5
-            ch(i-1,k,2) = wa1(i-1)*dr2-wa1(i)*di2
-            ch(i,k,2) = wa1(i-1)*di2+wa1(i)*dr2
-            ch(i-1,k,3) = wa2(i-1)*dr3-wa2(i)*di3
-            ch(i,k,3) = wa2(i-1)*di3+wa2(i)*dr3
-            ch(i-1,k,4) = wa3(i-1)*dr4-wa3(i)*di4
-            ch(i,k,4) = wa3(i-1)*di4+wa3(i)*dr4
-            ch(i-1,k,5) = wa4(i-1)*dr5-wa4(i)*di5
-            ch(i,k,5) = wa4(i-1)*di5+wa4(i)*dr5
-  103    continue
-  104 continue
-      return
-      end
--- a/liboctave/external/fftpack/passf.f	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,116 +0,0 @@
-      subroutine passf (nac,ido,ip,l1,idl1,cc,c1,c2,ch,ch2,wa)
-      dimension       ch(ido,l1,ip)          ,cc(ido,ip,l1)          ,
-     1                c1(ido,l1,ip)          ,wa(1)      ,c2(idl1,ip),
-     2                ch2(idl1,ip)
-      idot = ido/2
-      nt = ip*idl1
-      ipp2 = ip+2
-      ipph = (ip+1)/2
-      idp = ip*ido
-c
-      if (ido .lt. l1) go to 106
-      do 103 j=2,ipph
-         jc = ipp2-j
-         do 102 k=1,l1
-            do 101 i=1,ido
-               ch(i,k,j) = cc(i,j,k)+cc(i,jc,k)
-               ch(i,k,jc) = cc(i,j,k)-cc(i,jc,k)
-  101       continue
-  102    continue
-  103 continue
-      do 105 k=1,l1
-         do 104 i=1,ido
-            ch(i,k,1) = cc(i,1,k)
-  104    continue
-  105 continue
-      go to 112
-  106 do 109 j=2,ipph
-         jc = ipp2-j
-         do 108 i=1,ido
-            do 107 k=1,l1
-               ch(i,k,j) = cc(i,j,k)+cc(i,jc,k)
-               ch(i,k,jc) = cc(i,j,k)-cc(i,jc,k)
-  107       continue
-  108    continue
-  109 continue
-      do 111 i=1,ido
-         do 110 k=1,l1
-            ch(i,k,1) = cc(i,1,k)
-  110    continue
-  111 continue
-  112 idl = 2-ido
-      inc = 0
-      do 116 l=2,ipph
-         lc = ipp2-l
-         idl = idl+ido
-         do 113 ik=1,idl1
-            c2(ik,l) = ch2(ik,1)+wa(idl-1)*ch2(ik,2)
-            c2(ik,lc) = -wa(idl)*ch2(ik,ip)
-  113    continue
-         idlj = idl
-         inc = inc+ido
-         do 115 j=3,ipph
-            jc = ipp2-j
-            idlj = idlj+inc
-            if (idlj .gt. idp) idlj = idlj-idp
-            war = wa(idlj-1)
-            wai = wa(idlj)
-            do 114 ik=1,idl1
-               c2(ik,l) = c2(ik,l)+war*ch2(ik,j)
-               c2(ik,lc) = c2(ik,lc)-wai*ch2(ik,jc)
-  114       continue
-  115    continue
-  116 continue
-      do 118 j=2,ipph
-         do 117 ik=1,idl1
-            ch2(ik,1) = ch2(ik,1)+ch2(ik,j)
-  117    continue
-  118 continue
-      do 120 j=2,ipph
-         jc = ipp2-j
-         do 119 ik=2,idl1,2
-            ch2(ik-1,j) = c2(ik-1,j)-c2(ik,jc)
-            ch2(ik-1,jc) = c2(ik-1,j)+c2(ik,jc)
-            ch2(ik,j) = c2(ik,j)+c2(ik-1,jc)
-            ch2(ik,jc) = c2(ik,j)-c2(ik-1,jc)
-  119    continue
-  120 continue
-      nac = 1
-      if (ido .eq. 2) return
-      nac = 0
-      do 121 ik=1,idl1
-         c2(ik,1) = ch2(ik,1)
-  121 continue
-      do 123 j=2,ip
-         do 122 k=1,l1
-            c1(1,k,j) = ch(1,k,j)
-            c1(2,k,j) = ch(2,k,j)
-  122    continue
-  123 continue
-      if (idot .gt. l1) go to 127
-      idij = 0
-      do 126 j=2,ip
-         idij = idij+2
-         do 125 i=4,ido,2
-            idij = idij+2
-            do 124 k=1,l1
-               c1(i-1,k,j) = wa(idij-1)*ch(i-1,k,j)+wa(idij)*ch(i,k,j)
-               c1(i,k,j) = wa(idij-1)*ch(i,k,j)-wa(idij)*ch(i-1,k,j)
-  124       continue
-  125    continue
-  126 continue
-      return
-  127 idj = 2-ido
-      do 130 j=2,ip
-         idj = idj+ido
-         do 129 k=1,l1
-            idij = idj
-            do 128 i=4,ido,2
-               idij = idij+2
-               c1(i-1,k,j) = wa(idij-1)*ch(i-1,k,j)+wa(idij)*ch(i,k,j)
-               c1(i,k,j) = wa(idij-1)*ch(i,k,j)-wa(idij)*ch(i-1,k,j)
-  128       continue
-  129    continue
-  130 continue
-      return
-      end
--- a/liboctave/external/fftpack/passf2.f	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-      subroutine passf2 (ido,l1,cc,ch,wa1)
-      dimension       cc(ido,2,l1)           ,ch(ido,l1,2)           ,
-     1                wa1(1)
-      if (ido .gt. 2) go to 102
-      do 101 k=1,l1
-         ch(1,k,1) = cc(1,1,k)+cc(1,2,k)
-         ch(1,k,2) = cc(1,1,k)-cc(1,2,k)
-         ch(2,k,1) = cc(2,1,k)+cc(2,2,k)
-         ch(2,k,2) = cc(2,1,k)-cc(2,2,k)
-  101 continue
-      return
-  102 do 104 k=1,l1
-         do 103 i=2,ido,2
-            ch(i-1,k,1) = cc(i-1,1,k)+cc(i-1,2,k)
-            tr2 = cc(i-1,1,k)-cc(i-1,2,k)
-            ch(i,k,1) = cc(i,1,k)+cc(i,2,k)
-            ti2 = cc(i,1,k)-cc(i,2,k)
-            ch(i,k,2) = wa1(i-1)*ti2-wa1(i)*tr2
-            ch(i-1,k,2) = wa1(i-1)*tr2+wa1(i)*ti2
-  103    continue
-  104 continue
-      return
-      end
--- a/liboctave/external/fftpack/passf3.f	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-      subroutine passf3 (ido,l1,cc,ch,wa1,wa2)
-      dimension       cc(ido,3,l1)           ,ch(ido,l1,3)           ,
-     1                wa1(1)     ,wa2(1)
-      data taur,taui /-.5,-.866025403784439/
-      if (ido .ne. 2) go to 102
-      do 101 k=1,l1
-         tr2 = cc(1,2,k)+cc(1,3,k)
-         cr2 = cc(1,1,k)+taur*tr2
-         ch(1,k,1) = cc(1,1,k)+tr2
-         ti2 = cc(2,2,k)+cc(2,3,k)
-         ci2 = cc(2,1,k)+taur*ti2
-         ch(2,k,1) = cc(2,1,k)+ti2
-         cr3 = taui*(cc(1,2,k)-cc(1,3,k))
-         ci3 = taui*(cc(2,2,k)-cc(2,3,k))
-         ch(1,k,2) = cr2-ci3
-         ch(1,k,3) = cr2+ci3
-         ch(2,k,2) = ci2+cr3
-         ch(2,k,3) = ci2-cr3
-  101 continue
-      return
-  102 do 104 k=1,l1
-         do 103 i=2,ido,2
-            tr2 = cc(i-1,2,k)+cc(i-1,3,k)
-            cr2 = cc(i-1,1,k)+taur*tr2
-            ch(i-1,k,1) = cc(i-1,1,k)+tr2
-            ti2 = cc(i,2,k)+cc(i,3,k)
-            ci2 = cc(i,1,k)+taur*ti2
-            ch(i,k,1) = cc(i,1,k)+ti2
-            cr3 = taui*(cc(i-1,2,k)-cc(i-1,3,k))
-            ci3 = taui*(cc(i,2,k)-cc(i,3,k))
-            dr2 = cr2-ci3
-            dr3 = cr2+ci3
-            di2 = ci2+cr3
-            di3 = ci2-cr3
-            ch(i,k,2) = wa1(i-1)*di2-wa1(i)*dr2
-            ch(i-1,k,2) = wa1(i-1)*dr2+wa1(i)*di2
-            ch(i,k,3) = wa2(i-1)*di3-wa2(i)*dr3
-            ch(i-1,k,3) = wa2(i-1)*dr3+wa2(i)*di3
-  103    continue
-  104 continue
-      return
-      end
--- a/liboctave/external/fftpack/passf4.f	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-      subroutine passf4 (ido,l1,cc,ch,wa1,wa2,wa3)
-      dimension       cc(ido,4,l1)           ,ch(ido,l1,4)           ,
-     1                wa1(1)     ,wa2(1)     ,wa3(1)
-      if (ido .ne. 2) go to 102
-      do 101 k=1,l1
-         ti1 = cc(2,1,k)-cc(2,3,k)
-         ti2 = cc(2,1,k)+cc(2,3,k)
-         tr4 = cc(2,2,k)-cc(2,4,k)
-         ti3 = cc(2,2,k)+cc(2,4,k)
-         tr1 = cc(1,1,k)-cc(1,3,k)
-         tr2 = cc(1,1,k)+cc(1,3,k)
-         ti4 = cc(1,4,k)-cc(1,2,k)
-         tr3 = cc(1,2,k)+cc(1,4,k)
-         ch(1,k,1) = tr2+tr3
-         ch(1,k,3) = tr2-tr3
-         ch(2,k,1) = ti2+ti3
-         ch(2,k,3) = ti2-ti3
-         ch(1,k,2) = tr1+tr4
-         ch(1,k,4) = tr1-tr4
-         ch(2,k,2) = ti1+ti4
-         ch(2,k,4) = ti1-ti4
-  101 continue
-      return
-  102 do 104 k=1,l1
-         do 103 i=2,ido,2
-            ti1 = cc(i,1,k)-cc(i,3,k)
-            ti2 = cc(i,1,k)+cc(i,3,k)
-            ti3 = cc(i,2,k)+cc(i,4,k)
-            tr4 = cc(i,2,k)-cc(i,4,k)
-            tr1 = cc(i-1,1,k)-cc(i-1,3,k)
-            tr2 = cc(i-1,1,k)+cc(i-1,3,k)
-            ti4 = cc(i-1,4,k)-cc(i-1,2,k)
-            tr3 = cc(i-1,2,k)+cc(i-1,4,k)
-            ch(i-1,k,1) = tr2+tr3
-            cr3 = tr2-tr3
-            ch(i,k,1) = ti2+ti3
-            ci3 = ti2-ti3
-            cr2 = tr1+tr4
-            cr4 = tr1-tr4
-            ci2 = ti1+ti4
-            ci4 = ti1-ti4
-            ch(i-1,k,2) = wa1(i-1)*cr2+wa1(i)*ci2
-            ch(i,k,2) = wa1(i-1)*ci2-wa1(i)*cr2
-            ch(i-1,k,3) = wa2(i-1)*cr3+wa2(i)*ci3
-            ch(i,k,3) = wa2(i-1)*ci3-wa2(i)*cr3
-            ch(i-1,k,4) = wa3(i-1)*cr4+wa3(i)*ci4
-            ch(i,k,4) = wa3(i-1)*ci4-wa3(i)*cr4
-  103    continue
-  104 continue
-      return
-      end
--- a/liboctave/external/fftpack/passf5.f	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-      subroutine passf5 (ido,l1,cc,ch,wa1,wa2,wa3,wa4)
-      dimension       cc(ido,5,l1)           ,ch(ido,l1,5)           ,
-     1                wa1(1)     ,wa2(1)     ,wa3(1)     ,wa4(1)
-      data tr11,ti11,tr12,ti12 /.309016994374947,-.951056516295154,
-     1-.809016994374947,-.587785252292473/
-      if (ido .ne. 2) go to 102
-      do 101 k=1,l1
-         ti5 = cc(2,2,k)-cc(2,5,k)
-         ti2 = cc(2,2,k)+cc(2,5,k)
-         ti4 = cc(2,3,k)-cc(2,4,k)
-         ti3 = cc(2,3,k)+cc(2,4,k)
-         tr5 = cc(1,2,k)-cc(1,5,k)
-         tr2 = cc(1,2,k)+cc(1,5,k)
-         tr4 = cc(1,3,k)-cc(1,4,k)
-         tr3 = cc(1,3,k)+cc(1,4,k)
-         ch(1,k,1) = cc(1,1,k)+tr2+tr3
-         ch(2,k,1) = cc(2,1,k)+ti2+ti3
-         cr2 = cc(1,1,k)+tr11*tr2+tr12*tr3
-         ci2 = cc(2,1,k)+tr11*ti2+tr12*ti3
-         cr3 = cc(1,1,k)+tr12*tr2+tr11*tr3
-         ci3 = cc(2,1,k)+tr12*ti2+tr11*ti3
-         cr5 = ti11*tr5+ti12*tr4
-         ci5 = ti11*ti5+ti12*ti4
-         cr4 = ti12*tr5-ti11*tr4
-         ci4 = ti12*ti5-ti11*ti4
-         ch(1,k,2) = cr2-ci5
-         ch(1,k,5) = cr2+ci5
-         ch(2,k,2) = ci2+cr5
-         ch(2,k,3) = ci3+cr4
-         ch(1,k,3) = cr3-ci4
-         ch(1,k,4) = cr3+ci4
-         ch(2,k,4) = ci3-cr4
-         ch(2,k,5) = ci2-cr5
-  101 continue
-      return
-  102 do 104 k=1,l1
-         do 103 i=2,ido,2
-            ti5 = cc(i,2,k)-cc(i,5,k)
-            ti2 = cc(i,2,k)+cc(i,5,k)
-            ti4 = cc(i,3,k)-cc(i,4,k)
-            ti3 = cc(i,3,k)+cc(i,4,k)
-            tr5 = cc(i-1,2,k)-cc(i-1,5,k)
-            tr2 = cc(i-1,2,k)+cc(i-1,5,k)
-            tr4 = cc(i-1,3,k)-cc(i-1,4,k)
-            tr3 = cc(i-1,3,k)+cc(i-1,4,k)
-            ch(i-1,k,1) = cc(i-1,1,k)+tr2+tr3
-            ch(i,k,1) = cc(i,1,k)+ti2+ti3
-            cr2 = cc(i-1,1,k)+tr11*tr2+tr12*tr3
-            ci2 = cc(i,1,k)+tr11*ti2+tr12*ti3
-            cr3 = cc(i-1,1,k)+tr12*tr2+tr11*tr3
-            ci3 = cc(i,1,k)+tr12*ti2+tr11*ti3
-            cr5 = ti11*tr5+ti12*tr4
-            ci5 = ti11*ti5+ti12*ti4
-            cr4 = ti12*tr5-ti11*tr4
-            ci4 = ti12*ti5-ti11*ti4
-            dr3 = cr3-ci4
-            dr4 = cr3+ci4
-            di3 = ci3+cr4
-            di4 = ci3-cr4
-            dr5 = cr2+ci5
-            dr2 = cr2-ci5
-            di5 = ci2-cr5
-            di2 = ci2+cr5
-            ch(i-1,k,2) = wa1(i-1)*dr2+wa1(i)*di2
-            ch(i,k,2) = wa1(i-1)*di2-wa1(i)*dr2
-            ch(i-1,k,3) = wa2(i-1)*dr3+wa2(i)*di3
-            ch(i,k,3) = wa2(i-1)*di3-wa2(i)*dr3
-            ch(i-1,k,4) = wa3(i-1)*dr4+wa3(i)*di4
-            ch(i,k,4) = wa3(i-1)*di4-wa3(i)*dr4
-            ch(i-1,k,5) = wa4(i-1)*dr5+wa4(i)*di5
-            ch(i,k,5) = wa4(i-1)*di5-wa4(i)*dr5
-  103    continue
-  104 continue
-      return
-      end
--- a/liboctave/external/fftpack/zfftb.f	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-      subroutine zfftb (n,c,wsave)
-      implicit double precision (a-h,o-z)
-      dimension       c(*)       ,wsave(*)
-      if (n .eq. 1) return
-      iw1 = n+n+1
-      iw2 = iw1+n+n
-      call zfftb1 (n,c,wsave,wsave(iw1),wsave(iw2))
-      return
-      end
--- a/liboctave/external/fftpack/zfftb1.f	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-      subroutine zfftb1 (n,c,ch,wa,ifac)
-      implicit double precision (a-h,o-z)
-      dimension       ch(*)      ,c(*)       ,wa(*)      ,ifac(*)
-      nf = ifac(2)
-      na = 0
-      l1 = 1
-      iw = 1
-      do 116 k1=1,nf
-         ip = ifac(k1+2)
-         l2 = ip*l1
-         ido = n/l2
-         idot = ido+ido
-         idl1 = idot*l1
-         if (ip .ne. 4) go to 103
-         ix2 = iw+idot
-         ix3 = ix2+idot
-         if (na .ne. 0) go to 101
-         call zpassb4 (idot,l1,c,ch,wa(iw),wa(ix2),wa(ix3))
-         go to 102
-  101    call zpassb4 (idot,l1,ch,c,wa(iw),wa(ix2),wa(ix3))
-  102    na = 1-na
-         go to 115
-  103    if (ip .ne. 2) go to 106
-         if (na .ne. 0) go to 104
-         call zpassb2 (idot,l1,c,ch,wa(iw))
-         go to 105
-  104    call zpassb2 (idot,l1,ch,c,wa(iw))
-  105    na = 1-na
-         go to 115
-  106    if (ip .ne. 3) go to 109
-         ix2 = iw+idot
-         if (na .ne. 0) go to 107
-         call zpassb3 (idot,l1,c,ch,wa(iw),wa(ix2))
-         go to 108
-  107    call zpassb3 (idot,l1,ch,c,wa(iw),wa(ix2))
-  108    na = 1-na
-         go to 115
-  109    if (ip .ne. 5) go to 112
-         ix2 = iw+idot
-         ix3 = ix2+idot
-         ix4 = ix3+idot
-         if (na .ne. 0) go to 110
-         call zpassb5 (idot,l1,c,ch,wa(iw),wa(ix2),wa(ix3),wa(ix4))
-         go to 111
-  110    call zpassb5 (idot,l1,ch,c,wa(iw),wa(ix2),wa(ix3),wa(ix4))
-  111    na = 1-na
-         go to 115
-  112    if (na .ne. 0) go to 113
-         call zpassb (nac,idot,ip,l1,idl1,c,c,c,ch,ch,wa(iw))
-         go to 114
-  113    call zpassb (nac,idot,ip,l1,idl1,ch,ch,ch,c,c,wa(iw))
-  114    if (nac .ne. 0) na = 1-na
-  115    l1 = l2
-         iw = iw+(ip-1)*idot
-  116 continue
-      if (na .eq. 0) return
-      n2 = n+n
-      do 117 i=1,n2
-         c(i) = ch(i)
-  117 continue
-      return
-      end
--- a/liboctave/external/fftpack/zfftf.f	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-      subroutine zfftf (n,c,wsave)
-      implicit double precision (a-h,o-z)
-      dimension       c(*)       ,wsave(*)
-      if (n .eq. 1) return
-      iw1 = n+n+1
-      iw2 = iw1+n+n
-      call zfftf1 (n,c,wsave,wsave(iw1),wsave(iw2))
-      return
-      end
--- a/liboctave/external/fftpack/zfftf1.f	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-      subroutine zfftf1 (n,c,ch,wa,ifac)
-      implicit double precision (a-h,o-z)
-      dimension       ch(*)      ,c(*)       ,wa(*)      ,ifac(*)
-      nf = ifac(2)
-      na = 0
-      l1 = 1
-      iw = 1
-      do 116 k1=1,nf
-         ip = ifac(k1+2)
-         l2 = ip*l1
-         ido = n/l2
-         idot = ido+ido
-         idl1 = idot*l1
-         if (ip .ne. 4) go to 103
-         ix2 = iw+idot
-         ix3 = ix2+idot
-         if (na .ne. 0) go to 101
-         call zpassf4 (idot,l1,c,ch,wa(iw),wa(ix2),wa(ix3))
-         go to 102
-  101    call zpassf4 (idot,l1,ch,c,wa(iw),wa(ix2),wa(ix3))
-  102    na = 1-na
-         go to 115
-  103    if (ip .ne. 2) go to 106
-         if (na .ne. 0) go to 104
-         call zpassf2 (idot,l1,c,ch,wa(iw))
-         go to 105
-  104    call zpassf2 (idot,l1,ch,c,wa(iw))
-  105    na = 1-na
-         go to 115
-  106    if (ip .ne. 3) go to 109
-         ix2 = iw+idot
-         if (na .ne. 0) go to 107
-         call zpassf3 (idot,l1,c,ch,wa(iw),wa(ix2))
-         go to 108
-  107    call zpassf3 (idot,l1,ch,c,wa(iw),wa(ix2))
-  108    na = 1-na
-         go to 115
-  109    if (ip .ne. 5) go to 112
-         ix2 = iw+idot
-         ix3 = ix2+idot
-         ix4 = ix3+idot
-         if (na .ne. 0) go to 110
-         call zpassf5 (idot,l1,c,ch,wa(iw),wa(ix2),wa(ix3),wa(ix4))
-         go to 111
-  110    call zpassf5 (idot,l1,ch,c,wa(iw),wa(ix2),wa(ix3),wa(ix4))
-  111    na = 1-na
-         go to 115
-  112    if (na .ne. 0) go to 113
-         call zpassf (nac,idot,ip,l1,idl1,c,c,c,ch,ch,wa(iw))
-         go to 114
-  113    call zpassf (nac,idot,ip,l1,idl1,ch,ch,ch,c,c,wa(iw))
-  114    if (nac .ne. 0) na = 1-na
-  115    l1 = l2
-         iw = iw+(ip-1)*idot
-  116 continue
-      if (na .eq. 0) return
-      n2 = n+n
-      do 117 i=1,n2
-         c(i) = ch(i)
-  117 continue
-      return
-      end
--- a/liboctave/external/fftpack/zffti.f	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-      subroutine zffti (n,wsave)
-      implicit double precision (a-h,o-z)
-      dimension       wsave(*)
-      if (n .eq. 1) return
-      iw1 = n+n+1
-      iw2 = iw1+n+n
-      call zffti1 (n,wsave(iw1),wsave(iw2))
-      return
-      end
--- a/liboctave/external/fftpack/zffti1.f	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-      subroutine zffti1 (n,wa,ifac)
-      implicit double precision (a-h,o-z)
-      dimension       wa(*)      ,ifac(*)    ,ntryh(4)
-      data ntryh(1),ntryh(2),ntryh(3),ntryh(4)/3,4,2,5/
-      nl = n
-      nf = 0
-      j = 0
-  101 j = j+1
-      if (j-4) 102,102,103
-  102 ntry = ntryh(j)
-      go to 104
-  103 ntry = ntry+2
-  104 nq = nl/ntry
-      nr = nl-ntry*nq
-      if (nr) 101,105,101
-  105 nf = nf+1
-      ifac(nf+2) = ntry
-      nl = nq
-      if (ntry .ne. 2) go to 107
-      if (nf .eq. 1) go to 107
-      do 106 i=2,nf
-         ib = nf-i+2
-         ifac(ib+2) = ifac(ib+1)
-  106 continue
-      ifac(3) = 2
-  107 if (nl .ne. 1) go to 104
-      ifac(1) = n
-      ifac(2) = nf
-      tpi = 6.28318530717959d0
-      argh = tpi/dble(n)
-      i = 2
-      l1 = 1
-      do 110 k1=1,nf
-         ip = ifac(k1+2)
-         ld = 0
-         l2 = l1*ip
-         ido = n/l2
-         idot = ido+ido+2
-         ipm = ip-1
-         do 109 j=1,ipm
-            i1 = i
-            wa(i-1) = 1.
-            wa(i) = 0.
-            ld = ld+l1
-            fi = 0.
-            argld = dble(ld)*argh
-            do 108 ii=4,idot,2
-               i = i+2
-               fi = fi+1.
-               arg = fi*argld
-               wa(i-1) = cos(arg)
-               wa(i) = sin(arg)
-  108       continue
-            if (ip .le. 5) go to 109
-            wa(i1-1) = wa(i-1)
-            wa(i1) = wa(i)
-  109    continue
-         l1 = l2
-  110 continue
-      return
-      end
--- a/liboctave/external/fftpack/zpassb.f	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-      subroutine zpassb (nac,ido,ip,l1,idl1,cc,c1,c2,ch,ch2,wa)
-      implicit double precision (a-h,o-z)
-      dimension       ch(ido,l1,ip)          ,cc(ido,ip,l1)          ,
-     1                c1(ido,l1,ip)          ,wa(1)      ,c2(idl1,ip),
-     2                ch2(idl1,ip)
-      idot = ido/2
-      nt = ip*idl1
-      ipp2 = ip+2
-      ipph = (ip+1)/2
-      idp = ip*ido
-c
-      if (ido .lt. l1) go to 106
-      do 103 j=2,ipph
-         jc = ipp2-j
-         do 102 k=1,l1
-            do 101 i=1,ido
-               ch(i,k,j) = cc(i,j,k)+cc(i,jc,k)
-               ch(i,k,jc) = cc(i,j,k)-cc(i,jc,k)
-  101       continue
-  102    continue
-  103 continue
-      do 105 k=1,l1
-         do 104 i=1,ido
-            ch(i,k,1) = cc(i,1,k)
-  104    continue
-  105 continue
-      go to 112
-  106 do 109 j=2,ipph
-         jc = ipp2-j
-         do 108 i=1,ido
-            do 107 k=1,l1
-               ch(i,k,j) = cc(i,j,k)+cc(i,jc,k)
-               ch(i,k,jc) = cc(i,j,k)-cc(i,jc,k)
-  107       continue
-  108    continue
-  109 continue
-      do 111 i=1,ido
-         do 110 k=1,l1
-            ch(i,k,1) = cc(i,1,k)
-  110    continue
-  111 continue
-  112 idl = 2-ido
-      inc = 0
-      do 116 l=2,ipph
-         lc = ipp2-l
-         idl = idl+ido
-         do 113 ik=1,idl1
-            c2(ik,l) = ch2(ik,1)+wa(idl-1)*ch2(ik,2)
-            c2(ik,lc) = wa(idl)*ch2(ik,ip)
-  113    continue
-         idlj = idl
-         inc = inc+ido
-         do 115 j=3,ipph
-            jc = ipp2-j
-            idlj = idlj+inc
-            if (idlj .gt. idp) idlj = idlj-idp
-            war = wa(idlj-1)
-            wai = wa(idlj)
-            do 114 ik=1,idl1
-               c2(ik,l) = c2(ik,l)+war*ch2(ik,j)
-               c2(ik,lc) = c2(ik,lc)+wai*ch2(ik,jc)
-  114       continue
-  115    continue
-  116 continue
-      do 118 j=2,ipph
-         do 117 ik=1,idl1
-            ch2(ik,1) = ch2(ik,1)+ch2(ik,j)
-  117    continue
-  118 continue
-      do 120 j=2,ipph
-         jc = ipp2-j
-         do 119 ik=2,idl1,2
-            ch2(ik-1,j) = c2(ik-1,j)-c2(ik,jc)
-            ch2(ik-1,jc) = c2(ik-1,j)+c2(ik,jc)
-            ch2(ik,j) = c2(ik,j)+c2(ik-1,jc)
-            ch2(ik,jc) = c2(ik,j)-c2(ik-1,jc)
-  119    continue
-  120 continue
-      nac = 1
-      if (ido .eq. 2) return
-      nac = 0
-      do 121 ik=1,idl1
-         c2(ik,1) = ch2(ik,1)
-  121 continue
-      do 123 j=2,ip
-         do 122 k=1,l1
-            c1(1,k,j) = ch(1,k,j)
-            c1(2,k,j) = ch(2,k,j)
-  122    continue
-  123 continue
-      if (idot .gt. l1) go to 127
-      idij = 0
-      do 126 j=2,ip
-         idij = idij+2
-         do 125 i=4,ido,2
-            idij = idij+2
-            do 124 k=1,l1
-               c1(i-1,k,j) = wa(idij-1)*ch(i-1,k,j)-wa(idij)*ch(i,k,j)
-               c1(i,k,j) = wa(idij-1)*ch(i,k,j)+wa(idij)*ch(i-1,k,j)
-  124       continue
-  125    continue
-  126 continue
-      return
-  127 idj = 2-ido
-      do 130 j=2,ip
-         idj = idj+ido
-         do 129 k=1,l1
-            idij = idj
-            do 128 i=4,ido,2
-               idij = idij+2
-               c1(i-1,k,j) = wa(idij-1)*ch(i-1,k,j)-wa(idij)*ch(i,k,j)
-               c1(i,k,j) = wa(idij-1)*ch(i,k,j)+wa(idij)*ch(i-1,k,j)
-  128       continue
-  129    continue
-  130 continue
-      return
-      end
--- a/liboctave/external/fftpack/zpassb2.f	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,24 +0,0 @@
-      subroutine zpassb2 (ido,l1,cc,ch,wa1)
-      implicit double precision (a-h,o-z)
-      dimension       cc(ido,2,l1)           ,ch(ido,l1,2)           ,
-     1                wa1(1)
-      if (ido .gt. 2) go to 102
-      do 101 k=1,l1
-         ch(1,k,1) = cc(1,1,k)+cc(1,2,k)
-         ch(1,k,2) = cc(1,1,k)-cc(1,2,k)
-         ch(2,k,1) = cc(2,1,k)+cc(2,2,k)
-         ch(2,k,2) = cc(2,1,k)-cc(2,2,k)
-  101 continue
-      return
-  102 do 104 k=1,l1
-         do 103 i=2,ido,2
-            ch(i-1,k,1) = cc(i-1,1,k)+cc(i-1,2,k)
-            tr2 = cc(i-1,1,k)-cc(i-1,2,k)
-            ch(i,k,1) = cc(i,1,k)+cc(i,2,k)
-            ti2 = cc(i,1,k)-cc(i,2,k)
-            ch(i,k,2) = wa1(i-1)*ti2+wa1(i)*tr2
-            ch(i-1,k,2) = wa1(i-1)*tr2-wa1(i)*ti2
-  103    continue
-  104 continue
-      return
-      end
--- a/liboctave/external/fftpack/zpassb3.f	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-      subroutine zpassb3 (ido,l1,cc,ch,wa1,wa2)
-      implicit double precision (a-h,o-z)
-      dimension       cc(ido,3,l1)           ,ch(ido,l1,3)           ,
-     1                wa1(1)     ,wa2(1)
-      data taur,taui /-.5,.866025403784439d0/
-      if (ido .ne. 2) go to 102
-      do 101 k=1,l1
-         tr2 = cc(1,2,k)+cc(1,3,k)
-         cr2 = cc(1,1,k)+taur*tr2
-         ch(1,k,1) = cc(1,1,k)+tr2
-         ti2 = cc(2,2,k)+cc(2,3,k)
-         ci2 = cc(2,1,k)+taur*ti2
-         ch(2,k,1) = cc(2,1,k)+ti2
-         cr3 = taui*(cc(1,2,k)-cc(1,3,k))
-         ci3 = taui*(cc(2,2,k)-cc(2,3,k))
-         ch(1,k,2) = cr2-ci3
-         ch(1,k,3) = cr2+ci3
-         ch(2,k,2) = ci2+cr3
-         ch(2,k,3) = ci2-cr3
-  101 continue
-      return
-  102 do 104 k=1,l1
-         do 103 i=2,ido,2
-            tr2 = cc(i-1,2,k)+cc(i-1,3,k)
-            cr2 = cc(i-1,1,k)+taur*tr2
-            ch(i-1,k,1) = cc(i-1,1,k)+tr2
-            ti2 = cc(i,2,k)+cc(i,3,k)
-            ci2 = cc(i,1,k)+taur*ti2
-            ch(i,k,1) = cc(i,1,k)+ti2
-            cr3 = taui*(cc(i-1,2,k)-cc(i-1,3,k))
-            ci3 = taui*(cc(i,2,k)-cc(i,3,k))
-            dr2 = cr2-ci3
-            dr3 = cr2+ci3
-            di2 = ci2+cr3
-            di3 = ci2-cr3
-            ch(i,k,2) = wa1(i-1)*di2+wa1(i)*dr2
-            ch(i-1,k,2) = wa1(i-1)*dr2-wa1(i)*di2
-            ch(i,k,3) = wa2(i-1)*di3+wa2(i)*dr3
-            ch(i-1,k,3) = wa2(i-1)*dr3-wa2(i)*di3
-  103    continue
-  104 continue
-      return
-      end
--- a/liboctave/external/fftpack/zpassb4.f	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-      subroutine zpassb4 (ido,l1,cc,ch,wa1,wa2,wa3)
-      implicit double precision (a-h,o-z)
-      dimension       cc(ido,4,l1)           ,ch(ido,l1,4)           ,
-     1                wa1(1)     ,wa2(1)     ,wa3(1)
-      if (ido .ne. 2) go to 102
-      do 101 k=1,l1
-         ti1 = cc(2,1,k)-cc(2,3,k)
-         ti2 = cc(2,1,k)+cc(2,3,k)
-         tr4 = cc(2,4,k)-cc(2,2,k)
-         ti3 = cc(2,2,k)+cc(2,4,k)
-         tr1 = cc(1,1,k)-cc(1,3,k)
-         tr2 = cc(1,1,k)+cc(1,3,k)
-         ti4 = cc(1,2,k)-cc(1,4,k)
-         tr3 = cc(1,2,k)+cc(1,4,k)
-         ch(1,k,1) = tr2+tr3
-         ch(1,k,3) = tr2-tr3
-         ch(2,k,1) = ti2+ti3
-         ch(2,k,3) = ti2-ti3
-         ch(1,k,2) = tr1+tr4
-         ch(1,k,4) = tr1-tr4
-         ch(2,k,2) = ti1+ti4
-         ch(2,k,4) = ti1-ti4
-  101 continue
-      return
-  102 do 104 k=1,l1
-         do 103 i=2,ido,2
-            ti1 = cc(i,1,k)-cc(i,3,k)
-            ti2 = cc(i,1,k)+cc(i,3,k)
-            ti3 = cc(i,2,k)+cc(i,4,k)
-            tr4 = cc(i,4,k)-cc(i,2,k)
-            tr1 = cc(i-1,1,k)-cc(i-1,3,k)
-            tr2 = cc(i-1,1,k)+cc(i-1,3,k)
-            ti4 = cc(i-1,2,k)-cc(i-1,4,k)
-            tr3 = cc(i-1,2,k)+cc(i-1,4,k)
-            ch(i-1,k,1) = tr2+tr3
-            cr3 = tr2-tr3
-            ch(i,k,1) = ti2+ti3
-            ci3 = ti2-ti3
-            cr2 = tr1+tr4
-            cr4 = tr1-tr4
-            ci2 = ti1+ti4
-            ci4 = ti1-ti4
-            ch(i-1,k,2) = wa1(i-1)*cr2-wa1(i)*ci2
-            ch(i,k,2) = wa1(i-1)*ci2+wa1(i)*cr2
-            ch(i-1,k,3) = wa2(i-1)*cr3-wa2(i)*ci3
-            ch(i,k,3) = wa2(i-1)*ci3+wa2(i)*cr3
-            ch(i-1,k,4) = wa3(i-1)*cr4-wa3(i)*ci4
-            ch(i,k,4) = wa3(i-1)*ci4+wa3(i)*cr4
-  103    continue
-  104 continue
-      return
-      end
--- a/liboctave/external/fftpack/zpassb5.f	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-      subroutine zpassb5 (ido,l1,cc,ch,wa1,wa2,wa3,wa4)
-      implicit double precision (a-h,o-z)
-      dimension       cc(ido,5,l1)           ,ch(ido,l1,5)           ,
-     1                wa1(1)     ,wa2(1)     ,wa3(1)     ,wa4(1)
-      data tr11,ti11,tr12,ti12 /.309016994374947d0,.951056516295154d0,
-     1-.809016994374947d0,.587785252292473d0/
-      if (ido .ne. 2) go to 102
-      do 101 k=1,l1
-         ti5 = cc(2,2,k)-cc(2,5,k)
-         ti2 = cc(2,2,k)+cc(2,5,k)
-         ti4 = cc(2,3,k)-cc(2,4,k)
-         ti3 = cc(2,3,k)+cc(2,4,k)
-         tr5 = cc(1,2,k)-cc(1,5,k)
-         tr2 = cc(1,2,k)+cc(1,5,k)
-         tr4 = cc(1,3,k)-cc(1,4,k)
-         tr3 = cc(1,3,k)+cc(1,4,k)
-         ch(1,k,1) = cc(1,1,k)+tr2+tr3
-         ch(2,k,1) = cc(2,1,k)+ti2+ti3
-         cr2 = cc(1,1,k)+tr11*tr2+tr12*tr3
-         ci2 = cc(2,1,k)+tr11*ti2+tr12*ti3
-         cr3 = cc(1,1,k)+tr12*tr2+tr11*tr3
-         ci3 = cc(2,1,k)+tr12*ti2+tr11*ti3
-         cr5 = ti11*tr5+ti12*tr4
-         ci5 = ti11*ti5+ti12*ti4
-         cr4 = ti12*tr5-ti11*tr4
-         ci4 = ti12*ti5-ti11*ti4
-         ch(1,k,2) = cr2-ci5
-         ch(1,k,5) = cr2+ci5
-         ch(2,k,2) = ci2+cr5
-         ch(2,k,3) = ci3+cr4
-         ch(1,k,3) = cr3-ci4
-         ch(1,k,4) = cr3+ci4
-         ch(2,k,4) = ci3-cr4
-         ch(2,k,5) = ci2-cr5
-  101 continue
-      return
-  102 do 104 k=1,l1
-         do 103 i=2,ido,2
-            ti5 = cc(i,2,k)-cc(i,5,k)
-            ti2 = cc(i,2,k)+cc(i,5,k)
-            ti4 = cc(i,3,k)-cc(i,4,k)
-            ti3 = cc(i,3,k)+cc(i,4,k)
-            tr5 = cc(i-1,2,k)-cc(i-1,5,k)
-            tr2 = cc(i-1,2,k)+cc(i-1,5,k)
-            tr4 = cc(i-1,3,k)-cc(i-1,4,k)
-            tr3 = cc(i-1,3,k)+cc(i-1,4,k)
-            ch(i-1,k,1) = cc(i-1,1,k)+tr2+tr3
-            ch(i,k,1) = cc(i,1,k)+ti2+ti3
-            cr2 = cc(i-1,1,k)+tr11*tr2+tr12*tr3
-            ci2 = cc(i,1,k)+tr11*ti2+tr12*ti3
-            cr3 = cc(i-1,1,k)+tr12*tr2+tr11*tr3
-            ci3 = cc(i,1,k)+tr12*ti2+tr11*ti3
-            cr5 = ti11*tr5+ti12*tr4
-            ci5 = ti11*ti5+ti12*ti4
-            cr4 = ti12*tr5-ti11*tr4
-            ci4 = ti12*ti5-ti11*ti4
-            dr3 = cr3-ci4
-            dr4 = cr3+ci4
-            di3 = ci3+cr4
-            di4 = ci3-cr4
-            dr5 = cr2+ci5
-            dr2 = cr2-ci5
-            di5 = ci2-cr5
-            di2 = ci2+cr5
-            ch(i-1,k,2) = wa1(i-1)*dr2-wa1(i)*di2
-            ch(i,k,2) = wa1(i-1)*di2+wa1(i)*dr2
-            ch(i-1,k,3) = wa2(i-1)*dr3-wa2(i)*di3
-            ch(i,k,3) = wa2(i-1)*di3+wa2(i)*dr3
-            ch(i-1,k,4) = wa3(i-1)*dr4-wa3(i)*di4
-            ch(i,k,4) = wa3(i-1)*di4+wa3(i)*dr4
-            ch(i-1,k,5) = wa4(i-1)*dr5-wa4(i)*di5
-            ch(i,k,5) = wa4(i-1)*di5+wa4(i)*dr5
-  103    continue
-  104 continue
-      return
-      end
--- a/liboctave/external/fftpack/zpassf.f	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-      subroutine zpassf (nac,ido,ip,l1,idl1,cc,c1,c2,ch,ch2,wa)
-      implicit double precision (a-h,o-z)
-      dimension       ch(ido,l1,ip)          ,cc(ido,ip,l1)          ,
-     1                c1(ido,l1,ip)          ,wa(1)      ,c2(idl1,ip),
-     2                ch2(idl1,ip)
-      idot = ido/2
-      nt = ip*idl1
-      ipp2 = ip+2
-      ipph = (ip+1)/2
-      idp = ip*ido
-c
-      if (ido .lt. l1) go to 106
-      do 103 j=2,ipph
-         jc = ipp2-j
-         do 102 k=1,l1
-            do 101 i=1,ido
-               ch(i,k,j) = cc(i,j,k)+cc(i,jc,k)
-               ch(i,k,jc) = cc(i,j,k)-cc(i,jc,k)
-  101       continue
-  102    continue
-  103 continue
-      do 105 k=1,l1
-         do 104 i=1,ido
-            ch(i,k,1) = cc(i,1,k)
-  104    continue
-  105 continue
-      go to 112
-  106 do 109 j=2,ipph
-         jc = ipp2-j
-         do 108 i=1,ido
-            do 107 k=1,l1
-               ch(i,k,j) = cc(i,j,k)+cc(i,jc,k)
-               ch(i,k,jc) = cc(i,j,k)-cc(i,jc,k)
-  107       continue
-  108    continue
-  109 continue
-      do 111 i=1,ido
-         do 110 k=1,l1
-            ch(i,k,1) = cc(i,1,k)
-  110    continue
-  111 continue
-  112 idl = 2-ido
-      inc = 0
-      do 116 l=2,ipph
-         lc = ipp2-l
-         idl = idl+ido
-         do 113 ik=1,idl1
-            c2(ik,l) = ch2(ik,1)+wa(idl-1)*ch2(ik,2)
-            c2(ik,lc) = -wa(idl)*ch2(ik,ip)
-  113    continue
-         idlj = idl
-         inc = inc+ido
-         do 115 j=3,ipph
-            jc = ipp2-j
-            idlj = idlj+inc
-            if (idlj .gt. idp) idlj = idlj-idp
-            war = wa(idlj-1)
-            wai = wa(idlj)
-            do 114 ik=1,idl1
-               c2(ik,l) = c2(ik,l)+war*ch2(ik,j)
-               c2(ik,lc) = c2(ik,lc)-wai*ch2(ik,jc)
-  114       continue
-  115    continue
-  116 continue
-      do 118 j=2,ipph
-         do 117 ik=1,idl1
-            ch2(ik,1) = ch2(ik,1)+ch2(ik,j)
-  117    continue
-  118 continue
-      do 120 j=2,ipph
-         jc = ipp2-j
-         do 119 ik=2,idl1,2
-            ch2(ik-1,j) = c2(ik-1,j)-c2(ik,jc)
-            ch2(ik-1,jc) = c2(ik-1,j)+c2(ik,jc)
-            ch2(ik,j) = c2(ik,j)+c2(ik-1,jc)
-            ch2(ik,jc) = c2(ik,j)-c2(ik-1,jc)
-  119    continue
-  120 continue
-      nac = 1
-      if (ido .eq. 2) return
-      nac = 0
-      do 121 ik=1,idl1
-         c2(ik,1) = ch2(ik,1)
-  121 continue
-      do 123 j=2,ip
-         do 122 k=1,l1
-            c1(1,k,j) = ch(1,k,j)
-            c1(2,k,j) = ch(2,k,j)
-  122    continue
-  123 continue
-      if (idot .gt. l1) go to 127
-      idij = 0
-      do 126 j=2,ip
-         idij = idij+2
-         do 125 i=4,ido,2
-            idij = idij+2
-            do 124 k=1,l1
-               c1(i-1,k,j) = wa(idij-1)*ch(i-1,k,j)+wa(idij)*ch(i,k,j)
-               c1(i,k,j) = wa(idij-1)*ch(i,k,j)-wa(idij)*ch(i-1,k,j)
-  124       continue
-  125    continue
-  126 continue
-      return
-  127 idj = 2-ido
-      do 130 j=2,ip
-         idj = idj+ido
-         do 129 k=1,l1
-            idij = idj
-            do 128 i=4,ido,2
-               idij = idij+2
-               c1(i-1,k,j) = wa(idij-1)*ch(i-1,k,j)+wa(idij)*ch(i,k,j)
-               c1(i,k,j) = wa(idij-1)*ch(i,k,j)-wa(idij)*ch(i-1,k,j)
-  128       continue
-  129    continue
-  130 continue
-      return
-      end
--- a/liboctave/external/fftpack/zpassf2.f	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,24 +0,0 @@
-      subroutine zpassf2 (ido,l1,cc,ch,wa1)
-      implicit double precision (a-h,o-z)
-      dimension       cc(ido,2,l1)           ,ch(ido,l1,2)           ,
-     1                wa1(1)
-      if (ido .gt. 2) go to 102
-      do 101 k=1,l1
-         ch(1,k,1) = cc(1,1,k)+cc(1,2,k)
-         ch(1,k,2) = cc(1,1,k)-cc(1,2,k)
-         ch(2,k,1) = cc(2,1,k)+cc(2,2,k)
-         ch(2,k,2) = cc(2,1,k)-cc(2,2,k)
-  101 continue
-      return
-  102 do 104 k=1,l1
-         do 103 i=2,ido,2
-            ch(i-1,k,1) = cc(i-1,1,k)+cc(i-1,2,k)
-            tr2 = cc(i-1,1,k)-cc(i-1,2,k)
-            ch(i,k,1) = cc(i,1,k)+cc(i,2,k)
-            ti2 = cc(i,1,k)-cc(i,2,k)
-            ch(i,k,2) = wa1(i-1)*ti2-wa1(i)*tr2
-            ch(i-1,k,2) = wa1(i-1)*tr2+wa1(i)*ti2
-  103    continue
-  104 continue
-      return
-      end
--- a/liboctave/external/fftpack/zpassf3.f	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-      subroutine zpassf3 (ido,l1,cc,ch,wa1,wa2)
-      implicit double precision (a-h,o-z)
-      dimension       cc(ido,3,l1)           ,ch(ido,l1,3)           ,
-     1                wa1(1)     ,wa2(1)
-      data taur,taui /-.5d0,-.866025403784439d0/
-      if (ido .ne. 2) go to 102
-      do 101 k=1,l1
-         tr2 = cc(1,2,k)+cc(1,3,k)
-         cr2 = cc(1,1,k)+taur*tr2
-         ch(1,k,1) = cc(1,1,k)+tr2
-         ti2 = cc(2,2,k)+cc(2,3,k)
-         ci2 = cc(2,1,k)+taur*ti2
-         ch(2,k,1) = cc(2,1,k)+ti2
-         cr3 = taui*(cc(1,2,k)-cc(1,3,k))
-         ci3 = taui*(cc(2,2,k)-cc(2,3,k))
-         ch(1,k,2) = cr2-ci3
-         ch(1,k,3) = cr2+ci3
-         ch(2,k,2) = ci2+cr3
-         ch(2,k,3) = ci2-cr3
-  101 continue
-      return
-  102 do 104 k=1,l1
-         do 103 i=2,ido,2
-            tr2 = cc(i-1,2,k)+cc(i-1,3,k)
-            cr2 = cc(i-1,1,k)+taur*tr2
-            ch(i-1,k,1) = cc(i-1,1,k)+tr2
-            ti2 = cc(i,2,k)+cc(i,3,k)
-            ci2 = cc(i,1,k)+taur*ti2
-            ch(i,k,1) = cc(i,1,k)+ti2
-            cr3 = taui*(cc(i-1,2,k)-cc(i-1,3,k))
-            ci3 = taui*(cc(i,2,k)-cc(i,3,k))
-            dr2 = cr2-ci3
-            dr3 = cr2+ci3
-            di2 = ci2+cr3
-            di3 = ci2-cr3
-            ch(i,k,2) = wa1(i-1)*di2-wa1(i)*dr2
-            ch(i-1,k,2) = wa1(i-1)*dr2+wa1(i)*di2
-            ch(i,k,3) = wa2(i-1)*di3-wa2(i)*dr3
-            ch(i-1,k,3) = wa2(i-1)*dr3+wa2(i)*di3
-  103    continue
-  104 continue
-      return
-      end
--- a/liboctave/external/fftpack/zpassf4.f	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-      subroutine zpassf4 (ido,l1,cc,ch,wa1,wa2,wa3)
-      implicit double precision (a-h,o-z)
-      dimension       cc(ido,4,l1)           ,ch(ido,l1,4)           ,
-     1                wa1(1)     ,wa2(1)     ,wa3(1)
-      if (ido .ne. 2) go to 102
-      do 101 k=1,l1
-         ti1 = cc(2,1,k)-cc(2,3,k)
-         ti2 = cc(2,1,k)+cc(2,3,k)
-         tr4 = cc(2,2,k)-cc(2,4,k)
-         ti3 = cc(2,2,k)+cc(2,4,k)
-         tr1 = cc(1,1,k)-cc(1,3,k)
-         tr2 = cc(1,1,k)+cc(1,3,k)
-         ti4 = cc(1,4,k)-cc(1,2,k)
-         tr3 = cc(1,2,k)+cc(1,4,k)
-         ch(1,k,1) = tr2+tr3
-         ch(1,k,3) = tr2-tr3
-         ch(2,k,1) = ti2+ti3
-         ch(2,k,3) = ti2-ti3
-         ch(1,k,2) = tr1+tr4
-         ch(1,k,4) = tr1-tr4
-         ch(2,k,2) = ti1+ti4
-         ch(2,k,4) = ti1-ti4
-  101 continue
-      return
-  102 do 104 k=1,l1
-         do 103 i=2,ido,2
-            ti1 = cc(i,1,k)-cc(i,3,k)
-            ti2 = cc(i,1,k)+cc(i,3,k)
-            ti3 = cc(i,2,k)+cc(i,4,k)
-            tr4 = cc(i,2,k)-cc(i,4,k)
-            tr1 = cc(i-1,1,k)-cc(i-1,3,k)
-            tr2 = cc(i-1,1,k)+cc(i-1,3,k)
-            ti4 = cc(i-1,4,k)-cc(i-1,2,k)
-            tr3 = cc(i-1,2,k)+cc(i-1,4,k)
-            ch(i-1,k,1) = tr2+tr3
-            cr3 = tr2-tr3
-            ch(i,k,1) = ti2+ti3
-            ci3 = ti2-ti3
-            cr2 = tr1+tr4
-            cr4 = tr1-tr4
-            ci2 = ti1+ti4
-            ci4 = ti1-ti4
-            ch(i-1,k,2) = wa1(i-1)*cr2+wa1(i)*ci2
-            ch(i,k,2) = wa1(i-1)*ci2-wa1(i)*cr2
-            ch(i-1,k,3) = wa2(i-1)*cr3+wa2(i)*ci3
-            ch(i,k,3) = wa2(i-1)*ci3-wa2(i)*cr3
-            ch(i-1,k,4) = wa3(i-1)*cr4+wa3(i)*ci4
-            ch(i,k,4) = wa3(i-1)*ci4-wa3(i)*cr4
-  103    continue
-  104 continue
-      return
-      end
--- a/liboctave/external/fftpack/zpassf5.f	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-      subroutine zpassf5 (ido,l1,cc,ch,wa1,wa2,wa3,wa4)
-      implicit double precision (a-h,o-z)
-      dimension       cc(ido,5,l1)           ,ch(ido,l1,5)           ,
-     1                wa1(1)     ,wa2(1)     ,wa3(1)     ,wa4(1)
-      data tr11,ti11,tr12,ti12 /.309016994374947d0,-.951056516295154d0,
-     1-.809016994374947d0,-.587785252292473d0/
-      if (ido .ne. 2) go to 102
-      do 101 k=1,l1
-         ti5 = cc(2,2,k)-cc(2,5,k)
-         ti2 = cc(2,2,k)+cc(2,5,k)
-         ti4 = cc(2,3,k)-cc(2,4,k)
-         ti3 = cc(2,3,k)+cc(2,4,k)
-         tr5 = cc(1,2,k)-cc(1,5,k)
-         tr2 = cc(1,2,k)+cc(1,5,k)
-         tr4 = cc(1,3,k)-cc(1,4,k)
-         tr3 = cc(1,3,k)+cc(1,4,k)
-         ch(1,k,1) = cc(1,1,k)+tr2+tr3
-         ch(2,k,1) = cc(2,1,k)+ti2+ti3
-         cr2 = cc(1,1,k)+tr11*tr2+tr12*tr3
-         ci2 = cc(2,1,k)+tr11*ti2+tr12*ti3
-         cr3 = cc(1,1,k)+tr12*tr2+tr11*tr3
-         ci3 = cc(2,1,k)+tr12*ti2+tr11*ti3
-         cr5 = ti11*tr5+ti12*tr4
-         ci5 = ti11*ti5+ti12*ti4
-         cr4 = ti12*tr5-ti11*tr4
-         ci4 = ti12*ti5-ti11*ti4
-         ch(1,k,2) = cr2-ci5
-         ch(1,k,5) = cr2+ci5
-         ch(2,k,2) = ci2+cr5
-         ch(2,k,3) = ci3+cr4
-         ch(1,k,3) = cr3-ci4
-         ch(1,k,4) = cr3+ci4
-         ch(2,k,4) = ci3-cr4
-         ch(2,k,5) = ci2-cr5
-  101 continue
-      return
-  102 do 104 k=1,l1
-         do 103 i=2,ido,2
-            ti5 = cc(i,2,k)-cc(i,5,k)
-            ti2 = cc(i,2,k)+cc(i,5,k)
-            ti4 = cc(i,3,k)-cc(i,4,k)
-            ti3 = cc(i,3,k)+cc(i,4,k)
-            tr5 = cc(i-1,2,k)-cc(i-1,5,k)
-            tr2 = cc(i-1,2,k)+cc(i-1,5,k)
-            tr4 = cc(i-1,3,k)-cc(i-1,4,k)
-            tr3 = cc(i-1,3,k)+cc(i-1,4,k)
-            ch(i-1,k,1) = cc(i-1,1,k)+tr2+tr3
-            ch(i,k,1) = cc(i,1,k)+ti2+ti3
-            cr2 = cc(i-1,1,k)+tr11*tr2+tr12*tr3
-            ci2 = cc(i,1,k)+tr11*ti2+tr12*ti3
-            cr3 = cc(i-1,1,k)+tr12*tr2+tr11*tr3
-            ci3 = cc(i,1,k)+tr12*ti2+tr11*ti3
-            cr5 = ti11*tr5+ti12*tr4
-            ci5 = ti11*ti5+ti12*ti4
-            cr4 = ti12*tr5-ti11*tr4
-            ci4 = ti12*ti5-ti11*ti4
-            dr3 = cr3-ci4
-            dr4 = cr3+ci4
-            di3 = ci3+cr4
-            di4 = ci3-cr4
-            dr5 = cr2+ci5
-            dr2 = cr2-ci5
-            di5 = ci2-cr5
-            di2 = ci2+cr5
-            ch(i-1,k,2) = wa1(i-1)*dr2+wa1(i)*di2
-            ch(i,k,2) = wa1(i-1)*di2-wa1(i)*dr2
-            ch(i-1,k,3) = wa2(i-1)*dr3+wa2(i)*di3
-            ch(i,k,3) = wa2(i-1)*di3-wa2(i)*dr3
-            ch(i-1,k,4) = wa3(i-1)*dr4+wa3(i)*di4
-            ch(i,k,4) = wa3(i-1)*di4-wa3(i)*dr4
-            ch(i-1,k,5) = wa4(i-1)*dr5+wa4(i)*di5
-            ch(i,k,5) = wa4(i-1)*di5-wa4(i)*dr5
-  103    continue
-  104 continue
-      return
-      end
--- a/liboctave/external/module.mk	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/external/module.mk	Fri Aug 10 09:09:51 2018 +0200
@@ -14,7 +14,6 @@
 include %reldir%/dasrt/module.mk
 include %reldir%/dassl/module.mk
 include %reldir%/Faddeeva/module.mk
-include %reldir%/fftpack/module.mk
 include %reldir%/lapack-xtra/module.mk
 include %reldir%/odepack/module.mk
 include %reldir%/quadpack/module.mk
@@ -38,10 +37,6 @@
 
 %canon_reldir%_libexternal_la_CPPFLAGS = $(liboctave_liboctave_la_CPPFLAGS)
 
-%canon_reldir%_libexternal_la_CFLAGS = $(liboctave_liboctave_la_CFLAGS)
-
-%canon_reldir%_libexternal_la_CXXFLAGS = $(liboctave_liboctave_la_CXXFLAGS)
-
 liboctave_liboctave_la_LIBADD += %reldir%/libexternal.la
 
 liboctave_EXTRA_DIST += \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/liboctave/mk-version-h.in.sh	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,41 @@
+#! /bin/sh
+#
+# Copyright (C) 2016-2018 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
+# <https://www.gnu.org/licenses/>.
+
+: ${SED=@SED@}
+
+OCTAVE_API_VERSION="@OCTAVE_API_VERSION@"
+OCTAVE_CANONICAL_HOST_TYPE="@canonical_host_type@"
+OCTAVE_COPYRIGHT="@OCTAVE_COPYRIGHT@"
+OCTAVE_MAJOR_VERSION="@OCTAVE_MAJOR_VERSION@"
+OCTAVE_MINOR_VERSION="@OCTAVE_MINOR_VERSION@"
+OCTAVE_PATCH_VERSION="@OCTAVE_PATCH_VERSION@"
+OCTAVE_RELEASE_DATE="@OCTAVE_RELEASE_DATE@"
+OCTAVE_VERSION="@OCTAVE_VERSION@"
+
+$SED \
+  -e "s|%NO_EDIT_WARNING%|DO NOT EDIT!  Generated automatically by mk-version-h.|" \
+  -e "s|%OCTAVE_API_VERSION%|\"${OCTAVE_API_VERSION}\"|" \
+  -e "s|%OCTAVE_CANONICAL_HOST_TYPE%|\"${OCTAVE_CANONICAL_HOST_TYPE}\"|" \
+  -e "s|%OCTAVE_COPYRIGHT%|\"${OCTAVE_COPYRIGHT}\"|" \
+  -e "s|%OCTAVE_MAJOR_VERSION%|${OCTAVE_MAJOR_VERSION}|" \
+  -e "s|%OCTAVE_MINOR_VERSION%|${OCTAVE_MINOR_VERSION}|" \
+  -e "s|%OCTAVE_PATCH_VERSION%|${OCTAVE_PATCH_VERSION}|" \
+  -e "s|%OCTAVE_RELEASE_DATE%|\"${OCTAVE_RELEASE_DATE}\"|" \
+  -e "s|%OCTAVE_VERSION%|\"${OCTAVE_VERSION}\"|"
--- a/liboctave/module.mk	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/module.mk	Fri Aug 10 09:09:51 2018 +0200
@@ -1,5 +1,11 @@
 %canon_reldir%_EXTRA_DIST = \
-  %reldir%/liboctave-build-info.in.cc
+  %reldir%/liboctave-build-info.in.cc \
+  %reldir%/mk-version-h.in.sh \
+  %reldir%/version.cc \
+  %reldir%/version.in.h
+
+GEN_CONFIG_SHELL += \
+  %reldir%/mk-version-h.sh
 
 %canon_reldir%_CLEANFILES =
 %canon_reldir%_DISTCLEANFILES =
@@ -17,11 +23,9 @@
   -I$(srcdir)/%reldir%/util \
   -I$(srcdir)/%reldir%/wrappers
 
-%canon_reldir%_%canon_reldir%_la_CFLAGS = $(AM_CFLAGS) $(WARN_CFLAGS)
+octlib_LTLIBRARIES += %reldir%/liboctave.la
 
-%canon_reldir%_%canon_reldir%_la_CXXFLAGS = $(AM_CXXFLAGS) $(WARN_CXXFLAGS)
-
-octlib_LTLIBRARIES += %reldir%/liboctave.la
+%canon_reldir%_pkgconfig_DATA = %reldir%/octave.pc
 
 BUILT_INCS = \
   $(BUILT_LIBOCTAVE_OPERATORS_INC) \
@@ -29,10 +33,12 @@
 
 BUILT_SOURCES += \
   $(BUILT_INCS) \
-  $(BUILT_LIBOCTAVE_OPERATORS_SOURCES)
+  $(BUILT_LIBOCTAVE_OPERATORS_SOURCES) \
+  %reldir%/version.h
 
 LIBOCTAVE_BUILT_NODISTFILES = \
-  %reldir%/liboctave-build-info.cc
+  %reldir%/liboctave-build-info.cc \
+  %reldir%/version.h
 
 octinclude_HEADERS += \
   %reldir%/liboctave-build-info.h \
@@ -45,7 +51,9 @@
   $(OTHER_INC) \
   $(LIBOCTAVE_TEMPLATE_SRC)
 
-nodist_octinclude_HEADERS += $(BUILT_INCS)
+nodist_octinclude_HEADERS += \
+  $(BUILT_INCS) \
+  %reldir%/version.h
 
 ## C++ files that are #included, not compiled
 OTHER_INC =
@@ -66,13 +74,17 @@
 include %reldir%/wrappers/module.mk
 
 nodist_%canon_reldir%_%canon_reldir%_la_SOURCES = \
-  %reldir%/liboctave-build-info.cc
+  %reldir%/liboctave-build-info.cc \
+  %reldir%/version.cc \
+  %reldir%/version.h
 
 %canon_reldir%_%canon_reldir%_la_LIBADD += \
   libgnu/libgnu.la \
   $(LIBOCTAVE_LINK_DEPS)
 
-# Increment these as needed and according to the rules in the libtool manual:
+## Increment the following version numbers as needed and according
+## to the rules in the etc/HACKING.md file:
+
 %canon_reldir%_%canon_reldir%_current = 5
 %canon_reldir%_%canon_reldir%_revision = 0
 %canon_reldir%_%canon_reldir%_age = 0
@@ -104,6 +116,9 @@
 
 nobase_liboctavetests_DATA = $(LIBOCTAVE_TST_FILES)
 
+%reldir%/version.h: %reldir%/version.in.h %reldir%/mk-version-h.sh | %reldir%/$(octave_dirstamp)
+	$(AM_V_GEN)$(call simple-filter-rule,%reldir%/mk-version-h.sh)
+
 %reldir%/liboctave-build-info.cc: %reldir%/liboctave-build-info.in.cc HG-ID | %reldir%/$(octave_dirstamp)
 	$(AM_V_GEN)$(build-info-commands)
 
@@ -112,12 +127,17 @@
 
 DIRSTAMP_FILES += %reldir%/$(octave_dirstamp)
 
+pkgconfig_DATA += $(%canon_reldir%_pkgconfig_DATA)
+
 EXTRA_DIST += $(%canon_reldir%_EXTRA_DIST)
 
 %canon_reldir%_CLEANFILES += \
   $(LIBOCTAVE_BUILT_NODISTFILES) \
   $(LIBOCTAVE_TST_FILES)
 
+%canon_reldir%_DISTCLEANFILES += \
+  $(%canon_reldir%_pkgconfig_DATA)
+
 BUILT_NODISTFILES += $(LIBOCTAVE_BUILT_NODISTFILES)
 
 CLEANFILES += $(%canon_reldir%_CLEANFILES)
--- a/liboctave/numeric/CollocWt.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/numeric/CollocWt.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -27,8 +27,8 @@
 #include <cassert>
 #include <cmath>
 
-#include <iostream>
 #include <limits>
+#include <ostream>
 
 #include "Array.h"
 #include "CollocWt.h"
--- a/liboctave/numeric/eigs-base.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/numeric/eigs-base.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -25,7 +25,8 @@
 #endif
 
 #include <cmath>
-#include <iostream>
+
+#include <ostream>
 
 #include "Array.h"
 #include "CSparse.h"
@@ -90,7 +91,7 @@
   for (octave_idx_type j = 0; j < b_nc; j++)
     {
       for (octave_idx_type i = 0; i < n; i++)
-        retval.elem (i,j) = m.elem (static_cast<octave_idx_type>(qv[i]), j);
+        retval.elem (i,j) = m.elem (static_cast<octave_idx_type> (qv[i]), j);
     }
   return L.solve (ltyp, retval, err, rcond, nullptr);
 }
@@ -115,7 +116,7 @@
       for (octave_idx_type j = 0; j < b_nc; j++)
         {
           for (octave_idx_type i = 0; i < n; i++)
-            retval.elem (static_cast<octave_idx_type>(qv[i]), j) =
+            retval.elem (static_cast<octave_idx_type> (qv[i]), j) =
               tmp.elem (i,j);
         }
     }
@@ -272,45 +273,48 @@
   // P * (R \ M) * Q = L * U
   SparseMatrix AminusSigmaB (m);
 
-  if (have_b)
+  if (sigma != 0.0)
     {
-      if (cholB)
+      if (have_b)
         {
-          if (permB.numel ())
+          if (cholB)
             {
-              SparseMatrix tmp (n,n,n);
-              for (octave_idx_type i = 0; i < n; i++)
+              if (permB.numel ())
                 {
-                  tmp.xcidx (i) = i;
-                  tmp.xridx (i) =
-                    static_cast<octave_idx_type>(permB(i));
-                  tmp.xdata (i) = 1;
+                  SparseMatrix tmp (n,n,n);
+                  for (octave_idx_type i = 0; i < n; i++)
+                    {
+                      tmp.xcidx (i) = i;
+                      tmp.xridx (i) =
+                        static_cast<octave_idx_type> (permB(i));
+                      tmp.xdata (i) = 1;
+                    }
+                  tmp.xcidx (n) = n;
+
+                  AminusSigmaB -= sigma * tmp *
+                    b.transpose () * b * tmp.transpose ();
                 }
-              tmp.xcidx (n) = n;
-
-              AminusSigmaB -= sigma * tmp *
-                              b.transpose () * b * tmp.transpose ();
+              else
+                AminusSigmaB -= sigma * b.transpose () * b;
             }
           else
-            AminusSigmaB -= sigma * b.transpose () * b;
+            AminusSigmaB -= sigma * b;
         }
       else
-        AminusSigmaB -= sigma * b;
-    }
-  else
-    {
-      SparseMatrix sigmat (n, n, n);
-
-      // Create sigma * speye (n,n)
-      sigmat.xcidx (0) = 0;
-      for (octave_idx_type i = 0; i < n; i++)
         {
-          sigmat.xdata (i) = sigma;
-          sigmat.xridx (i) = i;
-          sigmat.xcidx (i+1) = i + 1;
+          SparseMatrix sigmat (n, n, n);
+
+          // Create sigma * speye (n,n)
+          sigmat.xcidx (0) = 0;
+          for (octave_idx_type i = 0; i < n; i++)
+            {
+              sigmat.xdata (i) = sigma;
+              sigmat.xridx (i) = i;
+              sigmat.xcidx (i+1) = i + 1;
+            }
+
+          AminusSigmaB -= sigmat;
         }
-
-      AminusSigmaB -= sigmat;
     }
 
   octave::math::sparse_lu<SparseMatrix> fact (AminusSigmaB, Matrix (), true);
@@ -369,35 +373,38 @@
   // P * M = L * U
   Matrix AminusSigmaB (m);
 
-  if (have_b)
+  if (sigma != 0.0)
     {
-      if (cholB)
+      if (have_b)
         {
-          Matrix tmp = sigma * b.transpose () * b;
-          const double *pB = permB.fortran_vec ();
-          double *p = AminusSigmaB.fortran_vec ();
-
-          if (permB.numel ())
+          if (cholB)
             {
-              for (octave_idx_type j = 0;
-                   j < b.cols (); j++)
-                for (octave_idx_type i = 0;
-                     i < b.rows (); i++)
-                  *p++ -= tmp.xelem (static_cast<octave_idx_type>(pB[i]),
-                                     static_cast<octave_idx_type>(pB[j]));
+              Matrix tmp = sigma * b.transpose () * b;
+              const double *pB = permB.fortran_vec ();
+              double *p = AminusSigmaB.fortran_vec ();
+
+              if (permB.numel ())
+                {
+                  for (octave_idx_type j = 0;
+                       j < b.cols (); j++)
+                    for (octave_idx_type i = 0;
+                         i < b.rows (); i++)
+                      *p++ -= tmp.xelem (static_cast<octave_idx_type> (pB[i]),
+                                         static_cast<octave_idx_type> (pB[j]));
+                }
+              else
+                AminusSigmaB -= tmp;
             }
           else
-            AminusSigmaB -= tmp;
+            AminusSigmaB -= sigma * b;
         }
       else
-        AminusSigmaB -= sigma * b;
-    }
-  else
-    {
-      double *p = AminusSigmaB.fortran_vec ();
-
-      for (octave_idx_type i = 0; i < n; i++)
-        p[i*(n+1)] -= sigma;
+        {
+          double *p = AminusSigmaB.fortran_vec ();
+
+          for (octave_idx_type i = 0; i < n; i++)
+            p[i*(n+1)] -= sigma;
+        }
     }
 
   octave::math::lu<Matrix> fact (AminusSigmaB);
@@ -448,45 +455,48 @@
   // P * (R \ M) * Q = L * U
   SparseComplexMatrix AminusSigmaB (m);
 
-  if (have_b)
+  if (std::real (sigma) != 0.0 || std::imag (sigma) != 0.0)
     {
-      if (cholB)
+      if (have_b)
         {
-          if (permB.numel ())
+          if (cholB)
             {
-              SparseMatrix tmp (n,n,n);
-              for (octave_idx_type i = 0; i < n; i++)
+              if (permB.numel ())
                 {
-                  tmp.xcidx (i) = i;
-                  tmp.xridx (i) =
-                    static_cast<octave_idx_type>(permB(i));
-                  tmp.xdata (i) = 1;
+                  SparseMatrix tmp (n,n,n);
+                  for (octave_idx_type i = 0; i < n; i++)
+                    {
+                      tmp.xcidx (i) = i;
+                      tmp.xridx (i) =
+                        static_cast<octave_idx_type> (permB(i));
+                      tmp.xdata (i) = 1;
+                    }
+                  tmp.xcidx (n) = n;
+
+                  AminusSigmaB -= tmp * b.hermitian () * b *
+                    tmp.transpose () * sigma;
                 }
-              tmp.xcidx (n) = n;
-
-              AminusSigmaB -= tmp * b.hermitian () * b *
-                              tmp.transpose () * sigma;
+              else
+                AminusSigmaB -= sigma * b.hermitian () * b;
             }
           else
-            AminusSigmaB -= sigma * b.hermitian () * b;
+            AminusSigmaB -= sigma * b;
         }
       else
-        AminusSigmaB -= sigma * b;
-    }
-  else
-    {
-      SparseComplexMatrix sigmat (n, n, n);
-
-      // Create sigma * speye (n,n)
-      sigmat.xcidx (0) = 0;
-      for (octave_idx_type i = 0; i < n; i++)
         {
-          sigmat.xdata (i) = sigma;
-          sigmat.xridx (i) = i;
-          sigmat.xcidx (i+1) = i + 1;
+          SparseComplexMatrix sigmat (n, n, n);
+
+          // Create sigma * speye (n,n)
+          sigmat.xcidx (0) = 0;
+          for (octave_idx_type i = 0; i < n; i++)
+            {
+              sigmat.xdata (i) = sigma;
+              sigmat.xridx (i) = i;
+              sigmat.xcidx (i+1) = i + 1;
+            }
+
+          AminusSigmaB -= sigmat;
         }
-
-      AminusSigmaB -= sigmat;
     }
 
   octave::math::sparse_lu<SparseComplexMatrix> fact (AminusSigmaB, Matrix(),
@@ -546,35 +556,38 @@
   // P * M = L * U
   ComplexMatrix AminusSigmaB (m);
 
-  if (have_b)
+  if (std::real (sigma) != 0.0 || std::imag (sigma) != 0.0)
     {
-      if (cholB)
+      if (have_b)
         {
-          ComplexMatrix tmp = sigma * b.hermitian () * b;
-          const double *pB = permB.fortran_vec ();
-          Complex *p = AminusSigmaB.fortran_vec ();
-
-          if (permB.numel ())
+          if (cholB)
             {
-              for (octave_idx_type j = 0;
-                   j < b.cols (); j++)
-                for (octave_idx_type i = 0;
-                     i < b.rows (); i++)
-                  *p++ -= tmp.xelem (static_cast<octave_idx_type>(pB[i]),
-                                     static_cast<octave_idx_type>(pB[j]));
+              ComplexMatrix tmp = sigma * b.hermitian () * b;
+              const double *pB = permB.fortran_vec ();
+              Complex *p = AminusSigmaB.fortran_vec ();
+
+              if (permB.numel ())
+                {
+                  for (octave_idx_type j = 0;
+                       j < b.cols (); j++)
+                    for (octave_idx_type i = 0;
+                         i < b.rows (); i++)
+                      *p++ -= tmp.xelem (static_cast<octave_idx_type> (pB[i]),
+                                         static_cast<octave_idx_type> (pB[j]));
+                }
+              else
+                AminusSigmaB -= tmp;
             }
           else
-            AminusSigmaB -= tmp;
+            AminusSigmaB -= sigma * b;
         }
       else
-        AminusSigmaB -= sigma * b;
-    }
-  else
-    {
-      Complex *p = AminusSigmaB.fortran_vec ();
-
-      for (octave_idx_type i = 0; i < n; i++)
-        p[i*(n+1)] -= sigma;
+        {
+          Complex *p = AminusSigmaB.fortran_vec ();
+
+          for (octave_idx_type i = 0; i < n; i++)
+            p[i*(n+1)] -= sigma;
+        }
     }
 
   octave::math::lu<ComplexMatrix> fact (AminusSigmaB);
@@ -641,10 +654,10 @@
 
   if (resid.isempty ())
     {
-      std::string rand_dist = octave_rand::distribution ();
-      octave_rand::distribution ("uniform");
-      resid = ColumnVector (octave_rand::vector (n));
-      octave_rand::distribution (rand_dist);
+      std::string rand_dist = octave::rand::distribution ();
+      octave::rand::distribution ("uniform");
+      resid = ColumnVector (octave::rand::vector (n));
+      octave::rand::distribution (rand_dist);
     }
   else if (m.cols () != resid.numel ())
     (*current_liboctave_error_handler) ("eigs: opts.v0 must be n-by-1");
@@ -933,10 +946,10 @@
 
   if (resid.isempty ())
     {
-      std::string rand_dist = octave_rand::distribution ();
-      octave_rand::distribution ("uniform");
-      resid = ColumnVector (octave_rand::vector (n));
-      octave_rand::distribution (rand_dist);
+      std::string rand_dist = octave::rand::distribution ();
+      octave::rand::distribution ("uniform");
+      resid = ColumnVector (octave::rand::vector (n));
+      octave::rand::distribution (rand_dist);
     }
   else if (m.cols () != resid.numel ())
     (*current_liboctave_error_handler) ("eigs: opts.v0 must be n-by-1");
@@ -1201,30 +1214,36 @@
   return ip(4);
 }
 
+template <typename M>
 octave_idx_type
 EigsRealSymmetricFunc (EigsFunc fun, octave_idx_type n_arg,
                        const std::string& _typ, double sigma,
                        octave_idx_type k_arg, octave_idx_type p_arg,
                        octave_idx_type& info, Matrix& eig_vec,
-                       ColumnVector& eig_val, ColumnVector& resid,
+                       ColumnVector& eig_val, const M& _b,
+                       ColumnVector& permB, ColumnVector& resid,
                        std::ostream& os, double tol, bool rvec,
-                       bool /* cholB */, int disp, int maxit)
+                       bool cholB, int disp, int maxit)
 {
   F77_INT n = octave::to_f77_int (n_arg);
   F77_INT k = octave::to_f77_int (k_arg);
   F77_INT p = octave::to_f77_int (p_arg);
+  M b(_b);
   std::string typ (_typ);
   bool have_sigma = (sigma ? true : false);
+  bool have_b = ! b.isempty ();
+  bool note3 = false;
   char bmat = 'I';
   F77_INT mode = 1;
   int err = 0;
+  M bt;
 
   if (resid.isempty ())
     {
-      std::string rand_dist = octave_rand::distribution ();
-      octave_rand::distribution ("uniform");
-      resid = ColumnVector (octave_rand::vector (n));
-      octave_rand::distribution (rand_dist);
+      std::string rand_dist = octave::rand::distribution ();
+      octave::rand::distribution ("uniform");
+      resid = ColumnVector (octave::rand::vector (n));
+      octave::rand::distribution (rand_dist);
     }
   else if (n != resid.numel ())
     (*current_liboctave_error_handler) ("eigs: opts.v0 must be n-by-1");
@@ -1253,6 +1272,23 @@
     (*current_liboctave_error_handler)
       ("eigs: opts.p must be greater than k and less than or equal to n");
 
+  if (have_b && cholB && ! permB.isempty ())
+    {
+      // Check the we really have a permutation vector
+      if (permB.numel () != n)
+        (*current_liboctave_error_handler) ("eigs: permB vector invalid");
+
+      Array<bool> checked (dim_vector (n, 1), false);
+      for (F77_INT i = 0; i < n; i++)
+        {
+          octave_idx_type bidx = static_cast<octave_idx_type> (permB(i));
+
+          if (checked(bidx) || bidx < 0 || bidx >= n
+              || octave::math::x_nint (bidx) != bidx)
+            (*current_liboctave_error_handler) ("eigs: permB vector invalid");
+        }
+    }
+
   if (! have_sigma)
     {
       if (typ != "LM" && typ != "SM" && typ != "LA" && typ != "SA"
@@ -1264,19 +1300,53 @@
         (*current_liboctave_error_handler)
           ("eigs: invalid sigma value for real symmetric problem");
 
+      if (typ != "SM" && have_b)
+        note3 = true;
+
       if (typ == "SM")
         {
           typ = "LM";
           sigma = 0.;
           mode = 3;
+          if (have_b)
+            bmat = 'G';
         }
     }
   else if (! std::abs (sigma))
-    typ = "SM";
+    {
+      typ = "SM";
+      if (have_b)
+        bmat = 'G';
+    }
   else
     {
       typ = "LM";
       mode = 3;
+      if (have_b)
+        bmat = 'G';
+    }
+
+  if (mode == 1 && have_b)
+    {
+      // See Note 3 dsaupd
+      note3 = true;
+      if (cholB)
+        {
+          bt = b;
+          b = b.transpose ();
+          if (permB.isempty ())
+            {
+              permB = ColumnVector (n);
+              for (F77_INT i = 0; i < n; i++)
+                permB(i) = i;
+            }
+        }
+      else
+        {
+          if (! make_cholb (b, bt, permB))
+            (*current_liboctave_error_handler)
+              ("eigs: The matrix B is not positive definite");
+        }
     }
 
   Array<F77_INT> ip (dim_vector (11, 1));
@@ -1351,20 +1421,85 @@
 
       if (ido == -1 || ido == 1 || ido == 2)
         {
-          double *ip2 = workd + iptr(0) - 1;
-          ColumnVector x(n);
-
-          for (F77_INT i = 0; i < n; i++)
-            x(i) = *ip2++;
-
-          ColumnVector y = fun (x, err);
-
-          if (err)
-            return false;
-
-          ip2 = workd + iptr(1) - 1;
-          for (F77_INT i = 0; i < n; i++)
-            *ip2++ = y(i);
+          if (have_b)
+            {
+              if (mode == 1) // regular mode with factorized B
+                {
+                  Matrix mtmp (n,1);
+                  for (F77_INT i = 0; i < n; i++)
+                    mtmp(i,0) = workd[i + iptr(0) - 1];
+
+                  mtmp = utsolve (bt, permB, mtmp);
+                  ColumnVector y = fun (mtmp, err);
+
+                  if (err)
+                    return false;
+
+                  mtmp = ltsolve (b, permB, y);
+
+                  for (F77_INT i = 0; i < n; i++)
+                    workd[i+iptr(1)-1] = mtmp(i,0);
+                }
+              else // shift-invert mode
+                {
+                  if (ido == -1)
+                    {
+                      OCTAVE_LOCAL_BUFFER (double, dtmp, n);
+
+                      vector_product (b, workd+iptr(0)-1, dtmp);
+
+                      ColumnVector x(n);
+
+                      for (F77_INT i = 0; i < n; i++)
+                        x(i) = dtmp[i];
+
+                      ColumnVector y = fun (x, err);
+
+                      if (err)
+                        return false;
+
+                      double *ip2 = workd + iptr(1) - 1;
+                      for (F77_INT i = 0; i < n; i++)
+                        ip2[i] = y(i);
+                    }
+                  else if (ido == 2)
+                    vector_product (b, workd+iptr(0)-1, workd+iptr(1)-1);
+                  else
+                    {
+                      double *ip2 = workd+iptr(2)-1;
+                      ColumnVector x(n);
+
+                      for (F77_INT i = 0; i < n; i++)
+                        x(i) = *ip2++;
+
+                      ColumnVector y = fun (x, err);
+
+                      if (err)
+                        return false;
+
+                      ip2 = workd + iptr(1) - 1;
+                      for (F77_INT i = 0; i < n; i++)
+                        *ip2++ = y(i);
+                     }
+                }
+            }
+          else
+            {
+              double *ip2 = workd + iptr(0) - 1;
+              ColumnVector x(n);
+
+              for (F77_INT i = 0; i < n; i++)
+                x(i) = *ip2++;
+
+              ColumnVector y = fun (x, err);
+
+              if (err)
+                return false;
+
+              ip2 = workd + iptr(1) - 1;
+              for (F77_INT i = 0; i < n; i++)
+                *ip2++ = y(i);
+            }
         }
       else
         {
@@ -1407,7 +1542,7 @@
       for (F77_INT i = ip(4); i < k; i++)
         d[i] = octave::numeric_limits<double>::NaN ();
       F77_INT k2 = ip(4) / 2;
-      if (typ != "SM" && typ != "BE")
+      if (mode == 3 || (mode == 1 && typ != "SM" && typ != "BE"))
         {
           for (F77_INT i = 0; i < k2; i++)
             {
@@ -1425,7 +1560,7 @@
               for (F77_INT j = 0; j < n; j++)
                 z[off1 + j] = octave::numeric_limits<double>::NaN ();
             }
-          if (typ != "SM" && typ != "BE")
+          if (mode == 3 || (mode == 1 && typ != "SM" && typ != "BE"))
             {
               OCTAVE_LOCAL_BUFFER (double, dtmp, n);
 
@@ -1447,7 +1582,9 @@
                     z[off2 + j] = dtmp[j];
                 }
             }
-        }
+          if (note3)
+            eig_vec = utsolve (bt, permB, eig_vec);
+         }
     }
   else
     (*current_liboctave_error_handler) ("eigs: error %d in dseupd", info2);
@@ -1485,10 +1622,10 @@
 
   if (resid.isempty ())
     {
-      std::string rand_dist = octave_rand::distribution ();
-      octave_rand::distribution ("uniform");
-      resid = ColumnVector (octave_rand::vector (n));
-      octave_rand::distribution (rand_dist);
+      std::string rand_dist = octave::rand::distribution ();
+      octave::rand::distribution ("uniform");
+      resid = ColumnVector (octave::rand::vector (n));
+      octave::rand::distribution (rand_dist);
     }
   else if (m.cols () != resid.numel ())
     (*current_liboctave_error_handler) ("eigs: opts.v0 must be n-by-1");
@@ -1840,10 +1977,10 @@
 
   if (resid.isempty ())
     {
-      std::string rand_dist = octave_rand::distribution ();
-      octave_rand::distribution ("uniform");
-      resid = ColumnVector (octave_rand::vector (n));
-      octave_rand::distribution (rand_dist);
+      std::string rand_dist = octave::rand::distribution ();
+      octave::rand::distribution ("uniform");
+      resid = ColumnVector (octave::rand::vector (n));
+      octave::rand::distribution (rand_dist);
     }
   else if (m.cols () != resid.numel ())
     (*current_liboctave_error_handler) ("eigs: opts.v0 must be n-by-1");
@@ -2178,31 +2315,37 @@
   return ip(4);
 }
 
+template <typename M>
 octave_idx_type
 EigsRealNonSymmetricFunc (EigsFunc fun, octave_idx_type n_arg,
                           const std::string& _typ, double sigmar,
                           octave_idx_type k_arg, octave_idx_type p_arg,
                           octave_idx_type& info, ComplexMatrix& eig_vec,
-                          ComplexColumnVector& eig_val, ColumnVector& resid,
+                          ComplexColumnVector& eig_val, const M& _b,
+                          ColumnVector& permB, ColumnVector& resid,
                           std::ostream& os, double tol, bool rvec,
-                          bool /* cholB */, int disp, int maxit)
+                          bool cholB, int disp, int maxit)
 {
   F77_INT n = octave::to_f77_int (n_arg);
   F77_INT k = octave::to_f77_int (k_arg);
   F77_INT p = octave::to_f77_int (p_arg);
+  M b(_b);
   std::string typ (_typ);
   bool have_sigma = (sigmar ? true : false);
-  char bmat = 'I';
   double sigmai = 0.;
   F77_INT mode = 1;
+  bool have_b = ! b.isempty ();
+  bool note3 = false;
+  char bmat = 'I';
   int err = 0;
+  M bt;
 
   if (resid.isempty ())
     {
-      std::string rand_dist = octave_rand::distribution ();
-      octave_rand::distribution ("uniform");
-      resid = ColumnVector (octave_rand::vector (n));
-      octave_rand::distribution (rand_dist);
+      std::string rand_dist = octave::rand::distribution ();
+      octave::rand::distribution ("uniform");
+      resid = ColumnVector (octave::rand::vector (n));
+      octave::rand::distribution (rand_dist);
     }
   else if (n != resid.numel ())
     (*current_liboctave_error_handler) ("eigs: opts.v0 must be n-by-1");
@@ -2231,6 +2374,23 @@
     (*current_liboctave_error_handler)
       ("eigs: opts.p must be greater than k and less than or equal to n");
 
+  if (have_b && cholB && ! permB.isempty ())
+    {
+      // Check the we really have a permutation vector
+      if (permB.numel () != n)
+        (*current_liboctave_error_handler) ("eigs: permB vector invalid");
+
+      Array<bool> checked (dim_vector (n, 1), false);
+      for (F77_INT i = 0; i < n; i++)
+        {
+          octave_idx_type bidx = static_cast<octave_idx_type> (permB(i));
+
+          if (checked(bidx) || bidx < 0 || bidx >= n
+              || octave::math::x_nint (bidx) != bidx)
+            (*current_liboctave_error_handler) ("eigs: permB vector invalid");
+        }
+    }
+
   if (! have_sigma)
     {
       if (typ != "LM" && typ != "SM" && typ != "LA" && typ != "SA"
@@ -2242,19 +2402,53 @@
         (*current_liboctave_error_handler)
           ("eigs: invalid sigma value for unsymmetric problem");
 
+      if (typ != "SM" && have_b)
+        note3 = true;
+
       if (typ == "SM")
         {
           typ = "LM";
           sigmar = 0.;
           mode = 3;
+          if (have_b)
+            bmat = 'G';
         }
+   }
+  else if (! std::abs (sigmar))
+    {
+      typ = "SM";
+      if (have_b)
+        bmat = 'G';
     }
-  else if (! std::abs (sigmar))
-    typ = "SM";
   else
     {
       typ = "LM";
       mode = 3;
+      if (have_b)
+        bmat = 'G';
+    }
+
+  if (mode == 1 && have_b)
+    {
+      // See Note 3 dsaupd
+      note3 = true;
+      if (cholB)
+        {
+          bt = b;
+          b = b.transpose ();
+          if (permB.isempty ())
+            {
+              permB = ColumnVector (n);
+              for (F77_INT i = 0; i < n; i++)
+                permB(i) = i;
+            }
+        }
+      else
+        {
+          if (! make_cholb (b, bt, permB))
+            (*current_liboctave_error_handler)
+              ("eigs: The matrix B is not positive definite");
+        }
     }
 
   Array<F77_INT> ip (dim_vector (11, 1));
@@ -2333,20 +2527,85 @@
 
       if (ido == -1 || ido == 1 || ido == 2)
         {
-          double *ip2 = workd + iptr(0) - 1;
-          ColumnVector x(n);
-
-          for (F77_INT i = 0; i < n; i++)
-            x(i) = *ip2++;
-
-          ColumnVector y = fun (x, err);
-
-          if (err)
-            return false;
-
-          ip2 = workd + iptr(1) - 1;
-          for (F77_INT i = 0; i < n; i++)
-            *ip2++ = y(i);
+          if (have_b)
+            {
+              if (mode == 1) // regular mode with factorized B
+                {
+                  Matrix mtmp (n,1);
+                  for (F77_INT i = 0; i < n; i++)
+                    mtmp(i,0) = workd[i + iptr(0) - 1];
+
+                  mtmp = utsolve (bt, permB, mtmp);
+                  ColumnVector y = fun (mtmp, err);
+
+                  if (err)
+                    return false;
+
+                  mtmp = ltsolve (b, permB, y);
+
+                  for (F77_INT i = 0; i < n; i++)
+                    workd[i+iptr(1)-1] = mtmp(i,0);
+                }
+              else // shift-invert mode
+                {
+                  if (ido == -1)
+                    {
+                      OCTAVE_LOCAL_BUFFER (double, dtmp, n);
+
+                      vector_product (b, workd+iptr(0)-1, dtmp);
+
+                      ColumnVector x(n);
+
+                      for (F77_INT i = 0; i < n; i++)
+                        x(i) = dtmp[i];
+
+                      ColumnVector y = fun (x, err);
+
+                      if (err)
+                        return false;
+
+                      double *ip2 = workd + iptr(1) - 1;
+                      for (F77_INT i = 0; i < n; i++)
+                        ip2[i] = y(i);
+                    }
+                  else if (ido == 2)
+                    vector_product (b, workd+iptr(0)-1, workd+iptr(1)-1);
+                  else
+                    {
+                      double *ip2 = workd+iptr(2)-1;
+                      ColumnVector x(n);
+
+                      for (F77_INT i = 0; i < n; i++)
+                        x(i) = *ip2++;
+
+                      ColumnVector y = fun (x, err);
+
+                      if (err)
+                        return false;
+
+                      ip2 = workd + iptr(1) - 1;
+                      for (F77_INT i = 0; i < n; i++)
+                        *ip2++ = y(i);
+                     }
+                }
+            }
+          else
+            {
+              double *ip2 = workd + iptr(0) - 1;
+              ColumnVector x(n);
+
+              for (F77_INT i = 0; i < n; i++)
+                x(i) = *ip2++;
+
+              ColumnVector y = fun (x, err);
+
+              if (err)
+                return false;
+
+              ip2 = workd + iptr(1) - 1;
+              for (F77_INT i = 0; i < n; i++)
+                *ip2++ = y(i);
+            }
         }
       else
         {
@@ -2484,6 +2743,8 @@
                   eig_vec(jj,ii) =
                     Complex (octave::numeric_limits<double>::NaN (), 0.);
             }
+          if (note3)
+              eig_vec = utsolve (bt, permB, eig_vec);
         }
       if (k0 < k)
         {
@@ -2527,14 +2788,14 @@
 
   if (cresid.isempty ())
     {
-      std::string rand_dist = octave_rand::distribution ();
-      octave_rand::distribution ("uniform");
-      Array<double> rr (octave_rand::vector (n));
-      Array<double> ri (octave_rand::vector (n));
+      std::string rand_dist = octave::rand::distribution ();
+      octave::rand::distribution ("uniform");
+      Array<double> rr (octave::rand::vector (n));
+      Array<double> ri (octave::rand::vector (n));
       cresid = ComplexColumnVector (n);
       for (F77_INT i = 0; i < n; i++)
         cresid(i) = Complex (rr(i),ri(i));
-      octave_rand::distribution (rand_dist);
+      octave::rand::distribution (rand_dist);
     }
   else if (m.cols () != cresid.numel ())
     (*current_liboctave_error_handler) ("eigs: opts.v0 must be n-by-1");
@@ -2831,14 +3092,14 @@
 
   if (cresid.isempty ())
     {
-      std::string rand_dist = octave_rand::distribution ();
-      octave_rand::distribution ("uniform");
-      Array<double> rr (octave_rand::vector (n));
-      Array<double> ri (octave_rand::vector (n));
+      std::string rand_dist = octave::rand::distribution ();
+      octave::rand::distribution ("uniform");
+      Array<double> rr (octave::rand::vector (n));
+      Array<double> ri (octave::rand::vector (n));
       cresid = ComplexColumnVector (n);
       for (F77_INT i = 0; i < n; i++)
         cresid(i) = Complex (rr(i),ri(i));
-      octave_rand::distribution (rand_dist);
+      octave::rand::distribution (rand_dist);
     }
   else if (m.cols () != cresid.numel ())
     (*current_liboctave_error_handler) ("eigs: opts.v0 must be n-by-1");
@@ -3118,35 +3379,40 @@
   return ip(4);
 }
 
+template <typename M>
 octave_idx_type
 EigsComplexNonSymmetricFunc (EigsComplexFunc fun, octave_idx_type n_arg,
                              const std::string& _typ, Complex sigma,
                              octave_idx_type k_arg, octave_idx_type p_arg,
                              octave_idx_type& info, ComplexMatrix& eig_vec,
-                             ComplexColumnVector& eig_val,
-                             ComplexColumnVector& cresid, std::ostream& os,
-                             double tol, bool rvec, bool /* cholB */,
-                             int disp, int maxit)
+                             ComplexColumnVector& eig_val, const M& _b,
+                             ColumnVector& permB, ComplexColumnVector& cresid,
+                             std::ostream& os, double tol, bool rvec,
+                             bool cholB, int disp, int maxit)
 {
   F77_INT n = octave::to_f77_int (n_arg);
   F77_INT k = octave::to_f77_int (k_arg);
   F77_INT p = octave::to_f77_int (p_arg);
+  M b(_b);
   std::string typ (_typ);
   bool have_sigma = (std::abs (sigma) ? true : false);
+  F77_INT mode = 1;
+  bool have_b = ! b.isempty ();
+  bool note3 = false;
   char bmat = 'I';
-  F77_INT mode = 1;
   int err = 0;
+  M bt;
 
   if (cresid.isempty ())
     {
-      std::string rand_dist = octave_rand::distribution ();
-      octave_rand::distribution ("uniform");
-      Array<double> rr (octave_rand::vector (n));
-      Array<double> ri (octave_rand::vector (n));
+      std::string rand_dist = octave::rand::distribution ();
+      octave::rand::distribution ("uniform");
+      Array<double> rr (octave::rand::vector (n));
+      Array<double> ri (octave::rand::vector (n));
       cresid = ComplexColumnVector (n);
       for (F77_INT i = 0; i < n; i++)
         cresid(i) = Complex (rr(i),ri(i));
-      octave_rand::distribution (rand_dist);
+      octave::rand::distribution (rand_dist);
     }
   else if (n != cresid.numel ())
     (*current_liboctave_error_handler) ("eigs: opts.v0 must be n-by-1");
@@ -3175,6 +3441,23 @@
     (*current_liboctave_error_handler)
       ("eigs: opts.p must be greater than k and less than or equal to n");
 
+  if (have_b && cholB && ! permB.isempty ())
+    {
+      // Check the we really have a permutation vector
+      if (permB.numel () != n)
+        (*current_liboctave_error_handler) ("eigs: permB vector invalid");
+
+      Array<bool> checked (dim_vector (n, 1), false);
+      for (F77_INT i = 0; i < n; i++)
+        {
+          octave_idx_type bidx = static_cast<octave_idx_type> (permB(i));
+
+          if (checked(bidx) || bidx < 0 || bidx >= n
+              || octave::math::x_nint (bidx) != bidx)
+            (*current_liboctave_error_handler) ("eigs: permB vector invalid");
+        }
+    }
+
   if (! have_sigma)
     {
       if (typ != "LM" && typ != "SM" && typ != "LA" && typ != "SA"
@@ -3186,19 +3469,53 @@
         (*current_liboctave_error_handler)
           ("eigs: invalid sigma value for complex problem");
 
+      if (typ != "SM" && have_b)
+        note3 = true;
+
       if (typ == "SM")
         {
           typ = "LM";
           sigma = 0.;
           mode = 3;
+          if (have_b)
+            bmat ='G';
         }
     }
   else if (! std::abs (sigma))
-    typ = "SM";
+    {
+      typ = "SM";
+      if (have_b)
+        bmat = 'G';
+    }
   else
     {
       typ = "LM";
       mode = 3;
+      if (have_b)
+        bmat = 'G';
+    }
+
+  if (mode == 1 && have_b)
+    {
+      // See Note 3 dsaupd
+      note3 = true;
+      if (cholB)
+        {
+          bt = b;
+          b = b.hermitian ();
+          if (permB.isempty ())
+            {
+              permB = ColumnVector (n);
+              for (F77_INT i = 0; i < n; i++)
+                permB(i) = i;
+            }
+        }
+      else
+        {
+          if (! make_cholb (b, bt, permB))
+            (*current_liboctave_error_handler)
+              ("eigs: The matrix B is not positive definite");
+        }
     }
 
   Array<F77_INT> ip (dim_vector (11, 1));
@@ -3275,20 +3592,85 @@
 
       if (ido == -1 || ido == 1 || ido == 2)
         {
-          Complex *ip2 = workd + iptr(0) - 1;
-          ComplexColumnVector x(n);
-
-          for (F77_INT i = 0; i < n; i++)
-            x(i) = *ip2++;
-
-          ComplexColumnVector y = fun (x, err);
-
-          if (err)
-            return false;
-
-          ip2 = workd + iptr(1) - 1;
-          for (F77_INT i = 0; i < n; i++)
-            *ip2++ = y(i);
+          if (have_b)
+            {
+              if (mode == 1) // regular mode with factorized B
+                {
+                  ComplexMatrix mtmp (n,1);
+                  for (F77_INT i = 0; i < n; i++)
+                    mtmp(i,0) = workd[i + iptr(0) - 1];
+
+                  mtmp = utsolve (bt, permB, mtmp);
+                  ComplexColumnVector y = fun (mtmp, err);
+
+                  if (err)
+                    return false;
+
+                  mtmp = ltsolve (b, permB, y);
+
+                  for (F77_INT i = 0; i < n; i++)
+                    workd[i+iptr(1)-1] = mtmp(i,0);
+                }
+              else // shift-invert mode
+                {
+                  if (ido == -1)
+                    {
+                      OCTAVE_LOCAL_BUFFER (Complex, ctmp, n);
+
+                      vector_product (b, workd+iptr(0)-1, ctmp);
+
+                      ComplexColumnVector x(n);
+
+                      for (F77_INT i = 0; i < n; i++)
+                        x(i) = ctmp[i];
+
+                      ComplexColumnVector y = fun (x, err);
+
+                      if (err)
+                        return false;
+
+                      Complex *ip2 = workd+iptr(1)-1;
+                      for (F77_INT i = 0; i < n; i++)
+                        ip2[i] = y(i);
+                    }
+                  else if (ido == 2)
+                    vector_product (b, workd+iptr(0)-1, workd+iptr(1)-1);
+                  else
+                    {
+                      Complex *ip2 = workd+iptr(2)-1;
+                      ComplexColumnVector x(n);
+
+                      for (F77_INT i = 0; i < n; i++)
+                        x(i) = *ip2++;
+
+                      ComplexColumnVector y = fun (x, err);
+
+                      if (err)
+                        return false;
+
+                      ip2 = workd + iptr(1) - 1;
+                      for (F77_INT i = 0; i < n; i++)
+                        *ip2++ = y(i);
+                    }
+                }
+            }
+          else
+            {
+              Complex *ip2 = workd + iptr(0) - 1;
+              ComplexColumnVector x(n);
+
+              for (F77_INT i = 0; i < n; i++)
+                x(i) = *ip2++;
+
+              ComplexColumnVector y = fun (x, err);
+
+              if (err)
+                return false;
+
+              ip2 = workd + iptr(1) - 1;
+              for (F77_INT i = 0; i < n; i++)
+                *ip2++ = y(i);
+            }
         }
       else
         {
@@ -3376,6 +3758,8 @@
               for (F77_INT j = 0; j < n; j++)
                 z[off2 + j] = ctmp[j];
             }
+          if (note3)
+            eig_vec = utsolve (bt, permB, eig_vec);
         }
     }
   else
@@ -3408,6 +3792,15 @@
 
 template
 octave_idx_type
+EigsRealSymmetricFunc<Matrix>
+(EigsFunc fun, octave_idx_type n, const std::string& _typ, double sigma,
+   octave_idx_type k, octave_idx_type p, octave_idx_type& info,
+   Matrix& eig_vec, ColumnVector& eig_val, const Matrix& _b,
+   ColumnVector& permB, ColumnVector& resid, std::ostream& os, double tol,
+   bool rvec, bool cholB, int disp, int maxit);
+
+template
+octave_idx_type
 EigsRealNonSymmetricMatrix<Matrix>
   (const Matrix& m, const std::string typ, octave_idx_type k,
    octave_idx_type p, octave_idx_type& info, ComplexMatrix& eig_vec,
@@ -3424,6 +3817,15 @@
    ColumnVector& resid, std::ostream& os, double tol, bool rvec,
    bool cholB, int disp, int maxit);
 
+template
+octave_idx_type
+EigsRealNonSymmetricFunc<Matrix>
+(EigsFunc fun, octave_idx_type n, const std::string& _typ, double sigmar,
+   octave_idx_type k, octave_idx_type p, octave_idx_type& info,
+   ComplexMatrix& eig_vec, ComplexColumnVector& eig_val, const Matrix& _b,
+   ColumnVector& permB, ColumnVector& resid, std::ostream& os, double tol,
+   bool rvec, bool cholB, int disp, int maxit);
+
 // SparseMatrix
 
 template
@@ -3446,6 +3848,15 @@
 
 template
 octave_idx_type
+EigsRealSymmetricFunc<SparseMatrix>
+(EigsFunc fun, octave_idx_type n, const std::string& _typ, double sigma,
+   octave_idx_type k, octave_idx_type p, octave_idx_type& info,
+   Matrix& eig_vec, ColumnVector& eig_val, const SparseMatrix& _b,
+   ColumnVector& permB, ColumnVector& resid, std::ostream& os, double tol,
+   bool rvec, bool cholB, int disp, int maxit);
+
+template
+octave_idx_type
 EigsRealNonSymmetricMatrix<SparseMatrix>
   (const SparseMatrix& m, const std::string typ, octave_idx_type k,
    octave_idx_type p, octave_idx_type& info, ComplexMatrix& eig_vec,
@@ -3462,6 +3873,15 @@
    ColumnVector& resid, std::ostream& os, double tol, bool rvec,
    bool cholB, int disp, int maxit);
 
+template
+octave_idx_type
+EigsRealNonSymmetricFunc<SparseMatrix>
+(EigsFunc fun, octave_idx_type n, const std::string& _typ, double sigmar,
+   octave_idx_type k, octave_idx_type p, octave_idx_type& info,
+   ComplexMatrix& eig_vec, ComplexColumnVector& eig_val,
+   const SparseMatrix& _b, ColumnVector& permB, ColumnVector& resid,
+   std::ostream& os, double tol, bool rvec, bool cholB, int disp, int maxit);
+
 // ComplexMatrix
 
 template
@@ -3482,6 +3902,15 @@
    ComplexColumnVector& cresid, std::ostream& os, double tol,
    bool rvec, bool cholB, int disp, int maxit);
 
+template
+octave_idx_type
+EigsComplexNonSymmetricFunc<ComplexMatrix>
+(EigsComplexFunc fun, octave_idx_type n, const std::string& _typ, Complex sigma,
+   octave_idx_type k, octave_idx_type p, octave_idx_type& info,
+   ComplexMatrix& eig_vec, ComplexColumnVector& eig_val,
+   const ComplexMatrix& _b, ColumnVector& permB, ComplexColumnVector& cresid,
+   std::ostream& os, double tol, bool rvec, bool cholB, int disp, int maxit);
+
 // SparseComplexMatrix
 
 template
@@ -3502,4 +3931,13 @@
    ColumnVector& permB, ComplexColumnVector& cresid, std::ostream& os,
    double tol, bool rvec, bool cholB, int disp, int maxit);
 
+template
+octave_idx_type
+EigsComplexNonSymmetricFunc<SparseComplexMatrix>
+(EigsComplexFunc fun, octave_idx_type n, const std::string& _typ, Complex sigma,
+   octave_idx_type k, octave_idx_type p, octave_idx_type& info,
+   ComplexMatrix& eig_vec, ComplexColumnVector& eig_val,
+   const SparseComplexMatrix& _b, ColumnVector& permB,
+   ComplexColumnVector& cresid, std::ostream& os, double tol, bool rvec,
+   bool cholB, int disp, int maxit);
 #endif
--- a/liboctave/numeric/eigs-base.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/numeric/eigs-base.h	Fri Aug 10 09:09:51 2018 +0200
@@ -60,14 +60,16 @@
                               std::ostream& os, double tol, bool rvec,
                               bool cholB, int disp, int maxit);
 
+template <typename M>
 extern OCTAVE_API octave_idx_type
 EigsRealSymmetricFunc (EigsFunc fun, octave_idx_type n,
                        const std::string& _typ, double sigma,
                        octave_idx_type k, octave_idx_type p,
                        octave_idx_type& info, Matrix& eig_vec,
-                       ColumnVector& eig_val, ColumnVector& resid,
+                       ColumnVector& eig_val, const M& _b,
+                       ColumnVector& permB, ColumnVector& resid,
                        std::ostream& os, double tol, bool rvec,
-                       bool /* cholB */, int disp, int maxit);
+                       bool cholB, int disp, int maxit);
 
 template <typename M>
 octave_idx_type
@@ -90,14 +92,16 @@
                                  std::ostream& os, double tol, bool rvec,
                                  bool cholB, int disp, int maxit);
 
+template <typename M>
 extern OCTAVE_API octave_idx_type
 EigsRealNonSymmetricFunc (EigsFunc fun, octave_idx_type n,
                           const std::string& _typ, double sigmar,
                           octave_idx_type k, octave_idx_type p,
                           octave_idx_type& info, ComplexMatrix& eig_vec,
-                          ComplexColumnVector& eig_val, ColumnVector& resid,
+                          ComplexColumnVector& eig_val, const M& _b,
+                          ColumnVector& permB, ColumnVector& resid,
                           std::ostream& os, double tol, bool rvec,
-                          bool /* cholB */, int disp, int maxit);
+                          bool cholB, int disp, int maxit);
 
 template <typename M>
 octave_idx_type
@@ -122,14 +126,15 @@
                                     std::ostream& os, double tol, bool rvec,
                                     bool cholB, int disp, int maxit);
 
+template <typename M>
 extern OCTAVE_API octave_idx_type
 EigsComplexNonSymmetricFunc (EigsComplexFunc fun, octave_idx_type n,
                              const std::string& _typ, Complex sigma,
                              octave_idx_type k, octave_idx_type p,
                              octave_idx_type& info, ComplexMatrix& eig_vec,
-                             ComplexColumnVector& eig_val,
-                             ComplexColumnVector& cresid, std::ostream& os,
-                             double tol, bool rvec, bool /* cholB */,
-                             int disp, int maxit);
+                             ComplexColumnVector& eig_val, const M& _b,
+                             ColumnVector& permB, ComplexColumnVector& cresid,
+                             std::ostream& os, double tol, bool rvec,
+                             bool cholB, int disp, int maxit);
 
 #endif
--- a/liboctave/numeric/lo-fftpack-proto.h	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
-
-Copyright (C) 2016-2018 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
-<https://www.gnu.org/licenses/>.
-
-*/
-
-#if ! defined (octave_lo_fftpack_proto_h)
-#define octave_lo_fftpack_proto_h 1
-
-#include "octave-config.h"
-
-#include "f77-fcn.h"
-
-extern "C"
-{
-  // Note that the original complex fft routines were not written for
-  // float or double complex arguments.  They have been modified by
-  // adding an implicit float or double precision (a-h,o-z) statement
-  // at the beginning of each subroutine.
-
-  // FFTB
-
-  F77_RET_T
-  F77_FUNC (cfftb, CFFTB) (const F77_INT&, F77_CMPLX*, F77_CMPLX*);
-
-  F77_RET_T
-  F77_FUNC (zfftb, ZFFTB) (const F77_INT&, F77_DBLE_CMPLX*, F77_DBLE_CMPLX*);
-
-  // FFTF
-
-  F77_RET_T
-  F77_FUNC (cfftf, CFFTF) (const F77_INT&, F77_CMPLX*, F77_CMPLX*);
-
-  F77_RET_T
-  F77_FUNC (zfftf, ZFFTF) (const F77_INT&, F77_DBLE_CMPLX*, F77_DBLE_CMPLX*);
-
-  // FFTI
-
-  F77_RET_T
-  F77_FUNC (cffti, CFFTI) (const F77_INT&, F77_CMPLX*);
-
-  F77_RET_T
-  F77_FUNC (zffti, ZFFTI) (const F77_INT&, F77_DBLE_CMPLX*);
-}
-
-#endif
--- a/liboctave/numeric/lo-mappers.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/numeric/lo-mappers.h	Fri Aug 10 09:09:51 2018 +0200
@@ -481,248 +481,6 @@
 
 #if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
 
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::isna' instead")
-inline bool octave_is_NA (double x) { return octave::math::isna (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::isna' instead")
-inline bool octave_is_NA (float x) { return octave::math::isna (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::isna' instead")
-inline bool octave_is_NA (const Complex& x) { return octave::math::isna (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::isna' instead")
-inline bool octave_is_NA (const FloatComplex& x)
-{
-  return octave::math::isna (x);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::acos' instead")
-inline Complex acos (const Complex& x) { return octave::math::acos (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::acos' instead")
-inline FloatComplex acos (const FloatComplex& x)
-{
-  return octave::math::acos (x);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::asin' instead")
-inline Complex asin (const Complex& x) { return octave::math::asin (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::asin' instead")
-inline FloatComplex asin (const FloatComplex& x)
-{
-  return octave::math::asin (x);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::atan' instead")
-inline Complex atan (const Complex& x) { return octave::math::atan (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::atan' instead")
-inline FloatComplex atan (const FloatComplex& x)
-{
-  return octave::math::atan (x);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'std::arg' instead")
-inline double arg (double x) { return std::arg (x); }
-OCTAVE_DEPRECATED (4.2, "use 'std::arg' instead")
-inline float arg (float x) { return std::arg (x); }
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::conj' instead")
-inline double conj (double x) { return x; }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::conj' instead")
-inline float conj (float x) { return x; }
-
-OCTAVE_DEPRECATED (4.2, "use 'std::imag' instead")
-inline double imag (double x) { return std::imag (x); }
-OCTAVE_DEPRECATED (4.2, "use 'std::imag' instead")
-inline float imag (float x) { return std::imag (x); }
-
-OCTAVE_DEPRECATED (4.2, "use 'std::real' instead")
-inline double real (double x) { return std::real (x); }
-OCTAVE_DEPRECATED (4.2, "use 'std::real' instead")
-inline float real (float x) { return std::real (x); }
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::log2' instead")
-inline double xlog2 (double x) { return octave::math::log2 (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::log2' instead")
-inline float xlog2 (float x) { return octave::math::log2 (x); }
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::log2' instead")
-inline Complex xlog2 (const Complex& x) { return octave::math::log2 (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::log2' instead")
-inline FloatComplex xlog2 (const FloatComplex& x)
-{
-  return octave::math::log2 (x);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::log2' instead")
-inline double xlog2 (double x, int& exp)
-{
-  return octave::math::log2 (x, exp);
-}
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::log2' instead")
-inline float xlog2 (float x, int& exp) { return octave::math::log2 (x, exp); }
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::log2' instead")
-inline Complex xlog2 (const Complex& x, int& exp)
-{
-  return octave::math::log2 (x, exp);
-}
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::log2' instead")
-inline FloatComplex xlog2 (const FloatComplex& x, int& exp)
-{
-  return octave::math::log2 (x, exp);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::exp2' instead")
-inline double xexp2 (double x) { return octave::math::exp2 (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::exp2' instead")
-inline float xexp2 (float x) { return octave::math::exp2 (x); }
-
-OCTAVE_DEPRECATED (4.2, "use 'std::ceil' instead")
-inline double xceil (double x) { return std::ceil (x); }
-OCTAVE_DEPRECATED (4.2, "use 'std::ceil' instead")
-inline float xceil (float x) { return std::ceil (x); }
-
-template <typename T>
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::ceil' instead")
-std::complex<T>
-ceil (const std::complex<T>& x)
-{
-  return octave::math::ceil (x);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::copysign' instead")
-inline double xcopysign (double x, double y)
-{
-  return octave::math::copysign (x, y);
-}
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::copysign' instead")
-inline float xcopysign (float x, float y)
-{
-  return octave::math::copysign (x, y);
-}
-
-template <typename T>
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::signbit' instead")
-T
-xsignbit (T x)
-{
-  return octave::math::signbit (x);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::negative_sign' instead")
-inline bool xnegative_sign (double x)
-{
-  return octave::math::negative_sign (x);
-}
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::negative_sign' instead")
-inline bool xnegative_sign (float x)
-{
-  return octave::math::negative_sign (x);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::positive_sign' instead")
-inline bool xpositive_sign (double x)
-{
-  return octave::math::positive_sign (x);
-}
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::positive_sign' instead")
-inline bool xpositive_sign (float x)
-{
-  return octave::math::positive_sign (x);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::signum' instead")
-inline double signum (double x) { return octave::math::signum (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::signum' instead")
-inline float signum (float x) { return octave::math::signum (x); }
-
-template <typename T>
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::signum' instead")
-std::complex<T>
-signum (const std::complex<T>& x)
-{
-  return octave::math::signum (x);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'std::trunc' instead")
-inline double xtrunc (double x) { return std::trunc (x); }
-OCTAVE_DEPRECATED (4.2, "use 'std::trunc' instead")
-inline float xtrunc (float x) { return std::trunc (x); }
-
-template <typename T>
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::trunc' instead")
-std::complex<T>
-xtrunc (const std::complex<T>& x)
-{
-  return octave::math::trunc (x);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::fix' instead")
-inline double fix (double x) { return octave::math::fix (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::fix' instead")
-inline float fix (float x) { return octave::math::fix (x); }
-
-template <typename T>
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::fix' instead")
-std::complex<T>
-fix (const std::complex<T>& x)
-{
-  return octave::math::fix (x);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'std::floor' instead")
-inline double xfloor (double x) { return std::floor (x); }
-OCTAVE_DEPRECATED (4.2, "use 'std::floor' instead")
-inline float xfloor (float x) { return std::floor (x); }
-
-template <typename T>
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::floor' instead")
-std::complex<T>
-floor (const std::complex<T>& x)
-{
-  return octave::math::floor (x);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::round' instead")
-inline double xround (double x) { return octave::math::round (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::round' instead")
-inline float xround (float x) { return octave::math::round (x); }
-
-template <typename T>
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::round' instead")
-std::complex<T>
-xround (const std::complex<T>& x)
-{
-  return octave::math::round (x);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::roundb' instead")
-inline double xroundb (double x) { return octave::math::roundb (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::roundb' instead")
-inline float xroundb (float x) { return octave::math::roundb (x); }
-
-template <typename T>
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::roundb' instead")
-std::complex<T>
-xroundb (const std::complex<T>& x)
-{
-  return octave::math::roundb (x);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::isnan' instead")
-inline bool xisnan (bool x) { return octave::math::isnan (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::isnan' instead")
-inline bool xisnan (char x) { return octave::math::isnan (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::isnan' instead")
-inline bool xisnan (double x) { return octave::math::isnan (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::isnan' instead")
-inline bool xisnan (float x) { return octave::math::isnan (x); }
-
-template <typename T>
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::isnan' instead")
-bool
-xisnan (const std::complex<T>& x)
-{
-  return octave::math::isnan (x);
-}
-
 OCTAVE_DEPRECATED (4.4, "use 'octave::math::isfinite' instead")
 inline bool xfinite (double x) { return octave::math::isfinite (x); }
 OCTAVE_DEPRECATED (4.4, "use 'octave::math::isfinite' instead")
@@ -736,187 +494,6 @@
   return octave::math::isfinite (x);
 }
 
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::isinf' instead")
-inline bool xisinf (double x) { return octave::math::isinf (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::isinf' instead")
-inline bool xisinf (float x) { return octave::math::isinf (x); }
-
-template <typename T>
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::isinf' instead")
-bool
-xisinf (const std::complex<T>& x)
-{
-  return octave::math::isinf (x);
-}
-
-// Some useful tests, that are commonly repeated.
-// Test for a finite integer.
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::isinteger' instead")
-inline bool
-xisinteger (double x)
-{
-  return octave::math::isinteger (x);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::isinteger' instead")
-inline bool
-xisinteger (float x)
-{
-  return octave::math::isinteger (x);
-}
-
-template <typename T>
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::x_nint' instead")
-T
-X_NINT (T x)
-{
-  return octave::math::x_nint (x);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::x_nint (x)' instead")
-inline double D_NINT (double x) { return octave::math::x_nint (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::x_nint (x)' instead")
-inline float F_NINT (float x) { return octave::math::x_nint (x); }
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::nint_big' instead")
-inline octave_idx_type NINTbig (double x) { return octave::math::nint_big (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::nint_big' instead")
-inline octave_idx_type NINTbig (float x) { return octave::math::nint_big (x); }
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::nint' instead")
-inline int NINT (double x) { return octave::math::nint (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::nint' instead")
-inline int NINT (float x) { return octave::math::nint (x); }
-
-template <typename T>
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::mod' instead")
-T
-xmod (T x, T y)
-{
-  return octave::math::mod (x, y);
-}
-
-template <typename T>
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::rem' instead")
-T
-xrem (T x, T y)
-{
-  return octave::math::rem (x, y);
-}
-
-template <typename T>
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::min' instead")
-T
-xmin (T x, T y)
-{
-  return octave::math::min (x, y);
-}
-
-template <typename T>
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::max' instead")
-T
-xmax (T x, T y)
-{
-  return octave::math::max (x, y);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::min' instead")
-inline double
-xmin (double x, double y)
-{
-  return octave::math::min (x, y);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::max' instead")
-inline double
-xmax (double x, double y)
-{
-  return octave::math::max (x, y);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::min' instead")
-inline float
-xmin (float x, float y)
-{
-  return octave::math::min (x, y);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::max' instead")
-inline float
-xmax (float x, float y)
-{
-  return octave::math::max (x, y);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::min' instead")
-inline Complex
-xmin (const Complex& x, const Complex& y)
-{
-  return octave::math::min (x, y);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::max' instead")
-inline Complex
-xmax (const Complex& x, const Complex& y)
-{
-  return octave::math::max (x, y);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::min' instead")
-inline OCTAVE_API FloatComplex
-xmin (const FloatComplex& x, const FloatComplex& y)
-{
-  return octave::math::min (x, y);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::max' instead")
-inline FloatComplex
-xmax (const FloatComplex& x, const FloatComplex& y)
-{
-  return octave::math::max (x, y);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::rc_acos' instead")
-inline Complex rc_acos (double x) { return octave::math::rc_acos (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::rc_acos' instead")
-inline FloatComplex rc_acos (float x) { return octave::math::rc_acos (x); }
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::rc_acosh' instead")
-inline Complex rc_acosh (double x) { return octave::math::rc_acosh (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::rc_acosh' instead")
-inline FloatComplex rc_acosh (float x) { return octave::math::rc_acosh (x); }
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::rc_asin' instead")
-inline Complex rc_asin (double x) { return octave::math::rc_asin (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::rc_asin' instead")
-inline FloatComplex rc_asin (float x) { return octave::math::rc_asin (x); }
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::rc_atanh' instead")
-inline Complex rc_atanh (double x) { return octave::math::rc_atanh (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::rc_atanh' instead")
-inline FloatComplex rc_atanh (float x) { return octave::math::rc_atanh (x); }
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::rc_log' instead")
-inline Complex rc_log (double x) { return octave::math::rc_log (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::rc_log' instead")
-inline FloatComplex rc_log (float x) { return octave::math::rc_log (x); }
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::rc_log2' instead")
-inline Complex rc_log2 (double x) { return octave::math::rc_log2 (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::rc_log2' instead")
-inline FloatComplex rc_log2 (float x) { return octave::math::rc_log2 (x); }
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::rc_log10' instead")
-inline Complex rc_log10 (double x) { return octave::math::rc_log10 (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::rc_log10' instead")
-inline FloatComplex rc_log10 (float x) { return octave::math::rc_log10 (x); }
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::rc_sqrt' instead")
-inline Complex rc_sqrt (double x) { return octave::math::rc_sqrt (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::rc_sqrt' instead")
-inline FloatComplex rc_sqrt (float x) { return octave::math::rc_sqrt (x); }
-
 #endif
 
 #endif
--- a/liboctave/numeric/lo-specfun.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/numeric/lo-specfun.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -2260,145 +2260,3 @@
     }
   }
 }
-
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-ComplexMatrix besselj (double alpha, const ComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselj (alpha, x, scaled, ierr); }
-ComplexMatrix bessely (double alpha, const ComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::bessely (alpha, x, scaled, ierr); }
-ComplexMatrix besseli (double alpha, const ComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besseli (alpha, x, scaled, ierr); }
-ComplexMatrix besselk (double alpha, const ComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselk (alpha, x, scaled, ierr); }
-ComplexMatrix besselh1 (double alpha, const ComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselh1 (alpha, x, scaled, ierr); }
-ComplexMatrix besselh2 (double alpha, const ComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselh2 (alpha, x, scaled, ierr); }
-
-ComplexMatrix besselj (const Matrix& alpha, const Complex& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselj (alpha, x, scaled, ierr); }
-ComplexMatrix bessely (const Matrix& alpha, const Complex& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::bessely (alpha, x, scaled, ierr); }
-ComplexMatrix besseli (const Matrix& alpha, const Complex& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besseli (alpha, x, scaled, ierr); }
-ComplexMatrix besselk (const Matrix& alpha, const Complex& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselk (alpha, x, scaled, ierr); }
-ComplexMatrix besselh1 (const Matrix& alpha, const Complex& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselh1 (alpha, x, scaled, ierr); }
-ComplexMatrix besselh2 (const Matrix& alpha, const Complex& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselh2 (alpha, x, scaled, ierr); }
-
-ComplexMatrix besselj (const Matrix& alpha, const ComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselj (alpha, x, scaled, ierr); }
-ComplexMatrix bessely (const Matrix& alpha, const ComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::bessely (alpha, x, scaled, ierr); }
-ComplexMatrix besseli (const Matrix& alpha, const ComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besseli (alpha, x, scaled, ierr); }
-ComplexMatrix besselk (const Matrix& alpha, const ComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselk (alpha, x, scaled, ierr); }
-ComplexMatrix besselh1 (const Matrix& alpha, const ComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselh1 (alpha, x, scaled, ierr); }
-ComplexMatrix besselh2 (const Matrix& alpha, const ComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselh2 (alpha, x, scaled, ierr); }
-
-ComplexNDArray besselj (double alpha, const ComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselj (alpha, x, scaled, ierr); }
-ComplexNDArray bessely (double alpha, const ComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::bessely (alpha, x, scaled, ierr); }
-ComplexNDArray besseli (double alpha, const ComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besseli (alpha, x, scaled, ierr); }
-ComplexNDArray besselk (double alpha, const ComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselk (alpha, x, scaled, ierr); }
-ComplexNDArray besselh1 (double alpha, const ComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselh1 (alpha, x, scaled, ierr); }
-ComplexNDArray besselh2 (double alpha, const ComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselh2 (alpha, x, scaled, ierr); }
-
-ComplexNDArray besselj (const NDArray& alpha, const Complex& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselj (alpha, x, scaled, ierr); }
-ComplexNDArray bessely (const NDArray& alpha, const Complex& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::bessely (alpha, x, scaled, ierr); }
-ComplexNDArray besseli (const NDArray& alpha, const Complex& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besseli (alpha, x, scaled, ierr); }
-ComplexNDArray besselk (const NDArray& alpha, const Complex& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselk (alpha, x, scaled, ierr); }
-ComplexNDArray besselh1 (const NDArray& alpha, const Complex& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselh1 (alpha, x, scaled, ierr); }
-ComplexNDArray besselh2 (const NDArray& alpha, const Complex& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselh2 (alpha, x, scaled, ierr); }
-
-ComplexNDArray besselj (const NDArray& alpha, const ComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselj (alpha, x, scaled, ierr); }
-ComplexNDArray bessely (const NDArray& alpha, const ComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::bessely (alpha, x, scaled, ierr); }
-ComplexNDArray besseli (const NDArray& alpha, const ComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besseli (alpha, x, scaled, ierr); }
-ComplexNDArray besselk (const NDArray& alpha, const ComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselk (alpha, x, scaled, ierr); }
-ComplexNDArray besselh1 (const NDArray& alpha, const ComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselh1 (alpha, x, scaled, ierr); }
-ComplexNDArray besselh2 (const NDArray& alpha, const ComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselh2 (alpha, x, scaled, ierr); }
-
-ComplexMatrix besselj (const RowVector& alpha, const ComplexColumnVector& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselj (alpha, x, scaled, ierr); }
-ComplexMatrix bessely (const RowVector& alpha, const ComplexColumnVector& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::bessely (alpha, x, scaled, ierr); }
-ComplexMatrix besseli (const RowVector& alpha, const ComplexColumnVector& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besseli (alpha, x, scaled, ierr); }
-ComplexMatrix besselk (const RowVector& alpha, const ComplexColumnVector& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselk (alpha, x, scaled, ierr); }
-ComplexMatrix besselh1 (const RowVector& alpha, const ComplexColumnVector& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselh1 (alpha, x, scaled, ierr); }
-ComplexMatrix besselh2 (const RowVector& alpha, const ComplexColumnVector& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselh2 (alpha, x, scaled, ierr); }
-
-FloatComplexMatrix besselj (float alpha, const FloatComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselj (alpha, x, scaled, ierr); }
-FloatComplexMatrix bessely (float alpha, const FloatComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::bessely (alpha, x, scaled, ierr); }
-FloatComplexMatrix besseli (float alpha, const FloatComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besseli (alpha, x, scaled, ierr); }
-FloatComplexMatrix besselk (float alpha, const FloatComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselk (alpha, x, scaled, ierr); }
-FloatComplexMatrix besselh1 (float alpha, const FloatComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselh1 (alpha, x, scaled, ierr); }
-FloatComplexMatrix besselh2 (float alpha, const FloatComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselh2 (alpha, x, scaled, ierr); }
-
-FloatComplexMatrix besselj (const FloatMatrix& alpha, const FloatComplex& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselj (alpha, x, scaled, ierr); }
-FloatComplexMatrix bessely (const FloatMatrix& alpha, const FloatComplex& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::bessely (alpha, x, scaled, ierr); }
-FloatComplexMatrix besseli (const FloatMatrix& alpha, const FloatComplex& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besseli (alpha, x, scaled, ierr); }
-FloatComplexMatrix besselk (const FloatMatrix& alpha, const FloatComplex& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselk (alpha, x, scaled, ierr); }
-FloatComplexMatrix besselh1 (const FloatMatrix& alpha, const FloatComplex& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselh1 (alpha, x, scaled, ierr); }
-FloatComplexMatrix besselh2 (const FloatMatrix& alpha, const FloatComplex& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselh2 (alpha, x, scaled, ierr); }
-
-FloatComplexMatrix besselj (const FloatMatrix& alpha, const FloatComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselj (alpha, x, scaled, ierr); }
-FloatComplexMatrix bessely (const FloatMatrix& alpha, const FloatComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::bessely (alpha, x, scaled, ierr); }
-FloatComplexMatrix besseli (const FloatMatrix& alpha, const FloatComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besseli (alpha, x, scaled, ierr); }
-FloatComplexMatrix besselk (const FloatMatrix& alpha, const FloatComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselk (alpha, x, scaled, ierr); }
-FloatComplexMatrix besselh1 (const FloatMatrix& alpha, const FloatComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselh1 (alpha, x, scaled, ierr); }
-FloatComplexMatrix besselh2 (const FloatMatrix& alpha, const FloatComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselh2 (alpha, x, scaled, ierr); }
-
-FloatComplexNDArray besselj (float alpha, const FloatComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselj (alpha, x, scaled, ierr); }
-FloatComplexNDArray bessely (float alpha, const FloatComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::bessely (alpha, x, scaled, ierr); }
-FloatComplexNDArray besseli (float alpha, const FloatComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besseli (alpha, x, scaled, ierr); }
-FloatComplexNDArray besselk (float alpha, const FloatComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselk (alpha, x, scaled, ierr); }
-FloatComplexNDArray besselh1 (float alpha, const FloatComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselh1 (alpha, x, scaled, ierr); }
-FloatComplexNDArray besselh2 (float alpha, const FloatComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselh2 (alpha, x, scaled, ierr); }
-
-FloatComplexNDArray besselj (const FloatNDArray& alpha, const FloatComplex& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselj (alpha, x, scaled, ierr); }
-FloatComplexNDArray bessely (const FloatNDArray& alpha, const FloatComplex& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::bessely (alpha, x, scaled, ierr); }
-FloatComplexNDArray besseli (const FloatNDArray& alpha, const FloatComplex& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besseli (alpha, x, scaled, ierr); }
-FloatComplexNDArray besselk (const FloatNDArray& alpha, const FloatComplex& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselk (alpha, x, scaled, ierr); }
-FloatComplexNDArray besselh1 (const FloatNDArray& alpha, const FloatComplex& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselh1 (alpha, x, scaled, ierr); }
-FloatComplexNDArray besselh2 (const FloatNDArray& alpha, const FloatComplex& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselh2 (alpha, x, scaled, ierr); }
-
-FloatComplexNDArray besselj (const FloatNDArray& alpha, const FloatComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselj (alpha, x, scaled, ierr); }
-FloatComplexNDArray bessely (const FloatNDArray& alpha, const FloatComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::bessely (alpha, x, scaled, ierr); }
-FloatComplexNDArray besseli (const FloatNDArray& alpha, const FloatComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besseli (alpha, x, scaled, ierr); }
-FloatComplexNDArray besselk (const FloatNDArray& alpha, const FloatComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselk (alpha, x, scaled, ierr); }
-FloatComplexNDArray besselh1 (const FloatNDArray& alpha, const FloatComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselh1 (alpha, x, scaled, ierr); }
-FloatComplexNDArray besselh2 (const FloatNDArray& alpha, const FloatComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselh2 (alpha, x, scaled, ierr); }
-
-FloatComplexMatrix besselj (const FloatRowVector& alpha, const FloatComplexColumnVector& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselj (alpha, x, scaled, ierr); }
-FloatComplexMatrix bessely (const FloatRowVector& alpha, const FloatComplexColumnVector& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::bessely (alpha, x, scaled, ierr); }
-FloatComplexMatrix besseli (const FloatRowVector& alpha, const FloatComplexColumnVector& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besseli (alpha, x, scaled, ierr); }
-FloatComplexMatrix besselk (const FloatRowVector& alpha, const FloatComplexColumnVector& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselk (alpha, x, scaled, ierr); }
-FloatComplexMatrix besselh1 (const FloatRowVector& alpha, const FloatComplexColumnVector& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselh1 (alpha, x, scaled, ierr); }
-FloatComplexMatrix besselh2 (const FloatRowVector& alpha, const FloatComplexColumnVector& x, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::besselh2 (alpha, x, scaled, ierr); }
-
-ComplexMatrix airy (const ComplexMatrix& z, bool deriv, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::airy (z, deriv, scaled, ierr); }
-ComplexMatrix biry (const ComplexMatrix& z, bool deriv, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::biry (z, deriv, scaled, ierr); }
-
-ComplexNDArray airy (const ComplexNDArray& z, bool deriv, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::airy (z, deriv, scaled, ierr); }
-ComplexNDArray biry (const ComplexNDArray& z, bool deriv, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::biry (z, deriv, scaled, ierr); }
-
-FloatComplexMatrix airy (const FloatComplexMatrix& z, bool deriv, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::airy (z, deriv, scaled, ierr); }
-FloatComplexMatrix biry (const FloatComplexMatrix& z, bool deriv, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::biry (z, deriv, scaled, ierr); }
-
-FloatComplexNDArray airy (const FloatComplexNDArray& z, bool deriv, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::airy (z, deriv, scaled, ierr); }
-FloatComplexNDArray biry (const FloatComplexNDArray& z, bool deriv, bool scaled, Array<octave_idx_type>& ierr) { return octave::math::biry (z, deriv, scaled, ierr); }
-
-<<<<<<< dest
-Array<double> betainc (double x, double a, const Array<double>& b) { return octave::math::betainc (x, a, b); }
-Array<double> betainc (double x, const Array<double>& a, double b) { return octave::math::betainc (x, a, b); }
-Array<double> betainc (double x, const Array<double>& a, const Array<double>& b) { return octave::math::betainc (x, a, b); }
-
-Array<double> betainc (const Array<double>& x, double a, double b) { return octave::math::betainc (x, a, b); }
-Array<double> betainc (const Array<double>& x, double a, const Array<double>& b) { return octave::math::betainc (x, a, b); }
-Array<double> betainc (const Array<double>& x, const Array<double>& a, double b) { return octave::math::betainc (x, a, b); }
-Array<double> betainc (const Array<double>& x, const Array<double>& a, const Array<double>& b) { return octave::math::betainc (x, a, b); }
-
-Array<float> betainc (float x, float a, const Array<float>& b) { return octave::math::betainc (x, a, b); }
-Array<float> betainc (float x, const Array<float>& a, float b) { return octave::math::betainc (x, a, b); }
-Array<float> betainc (float x, const Array<float>& a, const Array<float>& b) { return octave::math::betainc (x, a, b); }
-
-Array<float> betainc (const Array<float>& x, float a, float b) { return octave::math::betainc (x, a, b); }
-Array<float> betainc (const Array<float>& x, float a, const Array<float>& b) { return octave::math::betainc (x, a, b); }
-Array<float> betainc (const Array<float>& x, const Array<float>& a, float b) { return octave::math::betainc (x, a, b); }
-Array<float> betainc (const Array<float>& x, const Array<float>& a, const Array<float>& b) { return octave::math::betainc (x, a, b); }
-
-Array<double> betaincinv (double x, double a, const Array<double>& b) { return octave::math::betaincinv (x, a, b); }
-Array<double> betaincinv (double x, const Array<double>& a, double b) { return octave::math::betaincinv (x, a, b); }
-Array<double> betaincinv (double x, const Array<double>& a, const Array<double>& b) { return octave::math::betaincinv (x, a, b); }
-
-Array<double> betaincinv (const Array<double>& x, double a, double b) { return octave::math::betaincinv (x, a, b); }
-Array<double> betaincinv (const Array<double>& x, double a, const Array<double>& b) { return octave::math::betaincinv (x, a, b); }
-Array<double> betaincinv (const Array<double>& x, const Array<double>& a, double b) { return octave::math::betaincinv (x, a, b); }
-Array<double> betaincinv (const Array<double>& x, const Array<double>& a, const Array<double>& b) { return octave::math::betaincinv (x, a, b); }
-
-#endif
--- a/liboctave/numeric/lo-specfun.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/numeric/lo-specfun.h	Fri Aug 10 09:09:51 2018 +0200
@@ -397,484 +397,4 @@
   }
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::acosh' instead")
-inline double xacosh (double x) { return octave::math::acosh (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::acosh' instead")
-inline float xacosh (float x) { return octave::math::acosh (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::acosh' instead")
-inline Complex xacosh (const Complex& x) { return octave::math::acosh (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::acosh' instead")
-inline FloatComplex xacosh (const FloatComplex& x) { return octave::math::acosh (x); }
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::asinh' instead")
-inline double xasinh (double x) { return octave::math::asinh (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::asinh' instead")
-inline float xasinh (float x) { return octave::math::asinh (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::asinh' instead")
-inline Complex xasinh (const Complex& x) { return octave::math::asinh (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::asinh' instead")
-inline FloatComplex xasinh (const FloatComplex& x) { return octave::math::asinh (x); }
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::atanh' instead")
-inline double xatanh (double x) { return octave::math::atanh (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::atanh' instead")
-inline float xatanh (float x) { return octave::math::atanh (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::atanh' instead")
-inline Complex xatanh (const Complex& x) { return octave::math::atanh (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::atanh' instead")
-inline FloatComplex xatanh (const FloatComplex& x) { return octave::math::atanh (x); }
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::erf' instead")
-inline double xerf (double x) { return octave::math::erf (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::erf' instead")
-inline float xerf (float x) { return octave::math::erf (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::erf' instead")
-inline Complex xerf (const Complex& x) { return octave::math::erf (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::erf' instead")
-inline FloatComplex xerf (const FloatComplex& x) { return octave::math::erf (x); }
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::erfc' instead")
-inline double xerfc (double x) { return octave::math::erfc (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::erfc' instead")
-inline float xerfc (float x) { return octave::math::erfc (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::erfc' instead")
-inline Complex xerfc (const Complex& x) { return octave::math::erfc (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::erfc' instead")
-inline FloatComplex xerfc (const FloatComplex& x) { return octave::math::erfc (x); }
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::expm1' instead")
-inline double xexpm1 (double x) { return octave::math::expm1 (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::expm1' instead")
-inline Complex xexpm1 (const Complex& x) { return octave::math::expm1 (x); }
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::expm1' instead")
-inline float xexpm1 (float x) { return octave::math::expm1 (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::expm1' instead")
-inline FloatComplex xexpm1 (const FloatComplex& x) { return octave::math::expm1 (x); }
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::log1p' instead")
-inline double xlog1p (double x) { return octave::math::log1p (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::log1p' instead")
-inline Complex xlog1p (const Complex& x) { return octave::math::log1p (x); }
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::log1p' instead")
-inline float xlog1p (float x) { return octave::math::log1p (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::log1p' instead")
-inline FloatComplex xlog1p (const FloatComplex& x) { return octave::math::log1p (x); }
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::cbrt' instead")
-inline double xcbrt (double x) { return octave::math::cbrt (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::cbrt' instead")
-inline float xcbrt (float x) { return octave::math::cbrt (x); }
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::gamma' instead")
-inline double xgamma (double x) { return octave::math::gamma (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::lgamma' instead")
-inline double xlgamma (double x) { return octave::math::lgamma (x); }
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::rc_lgamma' instead")
-inline Complex rc_lgamma (double x) { return octave::math::rc_lgamma (x); }
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::gamma' instead")
-inline float xgamma (float x) { return octave::math::gamma (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::lgamma' instead")
-inline float xlgamma (float x) { return octave::math::lgamma (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::rc_lgamma' instead")
-inline FloatComplex rc_lgamma (float x) { return octave::math::rc_lgamma (x); }
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselj' instead")
-inline Complex besselj (double alpha, const Complex& x, bool scaled, octave_idx_type& ierr) { return octave::math::besselj (alpha, x, scaled, ierr); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::bessely' instead")
-inline Complex bessely (double alpha, const Complex& x, bool scaled, octave_idx_type& ierr) { return octave::math::bessely (alpha, x, scaled, ierr); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besseli' instead")
-inline Complex besseli (double alpha, const Complex& x, bool scaled, octave_idx_type& ierr) { return octave::math::besseli (alpha, x, scaled, ierr); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselk' instead")
-inline Complex besselk (double alpha, const Complex& x, bool scaled, octave_idx_type& ierr) { return octave::math::besselk (alpha, x, scaled, ierr); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselh1' instead")
-inline Complex besselh1 (double alpha, const Complex& x, bool scaled, octave_idx_type& ierr) { return octave::math::besselh1 (alpha, x, scaled, ierr); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselh2' instead")
-inline Complex besselh2 (double alpha, const Complex& x, bool scaled, octave_idx_type& ierr) { return octave::math::besselh2 (alpha, x, scaled, ierr); }
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselj' instead")
-extern OCTAVE_API ComplexMatrix besselj (double alpha, const ComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::bessely' instead")
-extern OCTAVE_API ComplexMatrix bessely (double alpha, const ComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besseli' instead")
-extern OCTAVE_API ComplexMatrix besseli (double alpha, const ComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselk' instead")
-extern OCTAVE_API ComplexMatrix besselk (double alpha, const ComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselh1' instead")
-extern OCTAVE_API ComplexMatrix besselh1 (double alpha, const ComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselh2' instead")
-extern OCTAVE_API ComplexMatrix besselh2 (double alpha, const ComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr);
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselj' instead")
-extern OCTAVE_API ComplexMatrix besselj (const Matrix& alpha, const Complex& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::bessely' instead")
-extern OCTAVE_API ComplexMatrix bessely (const Matrix& alpha, const Complex& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besseli' instead")
-extern OCTAVE_API ComplexMatrix besseli (const Matrix& alpha, const Complex& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselk' instead")
-extern OCTAVE_API ComplexMatrix besselk (const Matrix& alpha, const Complex& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselh1' instead")
-extern OCTAVE_API ComplexMatrix besselh1 (const Matrix& alpha, const Complex& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselh2' instead")
-extern OCTAVE_API ComplexMatrix besselh2 (const Matrix& alpha, const Complex& x, bool scaled, Array<octave_idx_type>& ierr);
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselj' instead")
-extern OCTAVE_API ComplexMatrix besselj (const Matrix& alpha, const ComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::bessely' instead")
-extern OCTAVE_API ComplexMatrix bessely (const Matrix& alpha, const ComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besseli' instead")
-extern OCTAVE_API ComplexMatrix besseli (const Matrix& alpha, const ComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselk' instead")
-extern OCTAVE_API ComplexMatrix besselk (const Matrix& alpha, const ComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselh1' instead")
-extern OCTAVE_API ComplexMatrix besselh1 (const Matrix& alpha, const ComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselh2' instead")
-extern OCTAVE_API ComplexMatrix besselh2 (const Matrix& alpha, const ComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr);
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselj' instead")
-extern OCTAVE_API ComplexNDArray besselj (double alpha, const ComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::bessely' instead")
-extern OCTAVE_API ComplexNDArray bessely (double alpha, const ComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besseli' instead")
-extern OCTAVE_API ComplexNDArray besseli (double alpha, const ComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselk' instead")
-extern OCTAVE_API ComplexNDArray besselk (double alpha, const ComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselh1' instead")
-extern OCTAVE_API ComplexNDArray besselh1 (double alpha, const ComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselh2' instead")
-extern OCTAVE_API ComplexNDArray besselh2 (double alpha, const ComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselj' instead")
-extern OCTAVE_API ComplexNDArray besselj (const NDArray& alpha, const Complex& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::bessely' instead")
-extern OCTAVE_API ComplexNDArray bessely (const NDArray& alpha, const Complex& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besseli' instead")
-extern OCTAVE_API ComplexNDArray besseli (const NDArray& alpha, const Complex& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselk' instead")
-extern OCTAVE_API ComplexNDArray besselk (const NDArray& alpha, const Complex& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselh1' instead")
-extern OCTAVE_API ComplexNDArray besselh1 (const NDArray& alpha, const Complex& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselh2' instead")
-extern OCTAVE_API ComplexNDArray besselh2 (const NDArray& alpha, const Complex& x, bool scaled, Array<octave_idx_type>& ierr);
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselj' instead")
-extern OCTAVE_API ComplexNDArray besselj (const NDArray& alpha, const ComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::bessely' instead")
-extern OCTAVE_API ComplexNDArray bessely (const NDArray& alpha, const ComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besseli' instead")
-extern OCTAVE_API ComplexNDArray besseli (const NDArray& alpha, const ComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselk' instead")
-extern OCTAVE_API ComplexNDArray besselk (const NDArray& alpha, const ComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselh1' instead")
-extern OCTAVE_API ComplexNDArray besselh1 (const NDArray& alpha, const ComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselh2' instead")
-extern OCTAVE_API ComplexNDArray besselh2 (const NDArray& alpha, const ComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselj' instead")
-extern OCTAVE_API ComplexMatrix besselj (const RowVector& alpha, const ComplexColumnVector& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::bessely' instead")
-extern OCTAVE_API ComplexMatrix bessely (const RowVector& alpha, const ComplexColumnVector& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besseli' instead")
-extern OCTAVE_API ComplexMatrix besseli (const RowVector& alpha, const ComplexColumnVector& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselk' instead")
-extern OCTAVE_API ComplexMatrix besselk (const RowVector& alpha, const ComplexColumnVector& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselh1' instead")
-extern OCTAVE_API ComplexMatrix besselh1 (const RowVector& alpha, const ComplexColumnVector& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselh2' instead")
-extern OCTAVE_API ComplexMatrix besselh2 (const RowVector& alpha, const ComplexColumnVector& x, bool scaled, Array<octave_idx_type>& ierr);
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselj' instead")
-inline FloatComplex besselj (float alpha, const FloatComplex& x, bool scaled, octave_idx_type& ierr) { return octave::math::besselj (alpha, x, scaled, ierr); }
-OCTAVE_DEPRECATED (4.2, "use 'octavh::bessely' instead")
-inline FloatComplex bessely (float alpha, const FloatComplex& x, bool scaled, octave_idx_type& ierr) { return octave::math::bessely (alpha, x, scaled, ierr); }
-OCTAVE_DEPRECATED (4.2, "use 'octavh::besseli' instead")
-inline FloatComplex besseli (float alpha, const FloatComplex& x, bool scaled, octave_idx_type& ierr) { return octave::math::besseli (alpha, x, scaled, ierr); }
-OCTAVE_DEPRECATED (4.2, "use 'octavh::besselk' instead")
-inline FloatComplex besselk (float alpha, const FloatComplex& x, bool scaled, octave_idx_type& ierr) { return octave::math::besselk (alpha, x, scaled, ierr); }
-OCTAVE_DEPRECATED (4.2, "use 'octavh::besselh1' instead")
-inline FloatComplex besselh1 (float alpha, const FloatComplex& x, bool scaled, octave_idx_type& ierr) { return octave::math::besselh1 (alpha, x, scaled, ierr); }
-OCTAVE_DEPRECATED (4.2, "use 'octavh::besselh2' instead")
-inline FloatComplex besselh2 (float alpha, const FloatComplex& x, bool scaled, octave_idx_type& ierr) { return octave::math::besselh2 (alpha, x, scaled, ierr); }
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselj' instead")
-extern OCTAVE_API FloatComplexMatrix besselj (float alpha, const FloatComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::bessely' instead")
-extern OCTAVE_API FloatComplexMatrix bessely (float alpha, const FloatComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besseli' instead")
-extern OCTAVE_API FloatComplexMatrix besseli (float alpha, const FloatComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselk' instead")
-extern OCTAVE_API FloatComplexMatrix besselk (float alpha, const FloatComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselh1' instead")
-extern OCTAVE_API FloatComplexMatrix besselh1 (float alpha, const FloatComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselh2' instead")
-extern OCTAVE_API FloatComplexMatrix besselh2 (float alpha, const FloatComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr);
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselj' instead")
-extern OCTAVE_API FloatComplexMatrix besselj (const FloatMatrix& alpha, const FloatComplex& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::bessely' instead")
-extern OCTAVE_API FloatComplexMatrix bessely (const FloatMatrix& alpha, const FloatComplex& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besseli' instead")
-extern OCTAVE_API FloatComplexMatrix besseli (const FloatMatrix& alpha, const FloatComplex& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselk' instead")
-extern OCTAVE_API FloatComplexMatrix besselk (const FloatMatrix& alpha, const FloatComplex& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselh1' instead")
-extern OCTAVE_API FloatComplexMatrix besselh1 (const FloatMatrix& alpha, const FloatComplex& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselh2' instead")
-extern OCTAVE_API FloatComplexMatrix besselh2 (const FloatMatrix& alpha, const FloatComplex& x, bool scaled, Array<octave_idx_type>& ierr);
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselj' instead")
-extern OCTAVE_API FloatComplexMatrix besselj (const FloatMatrix& alpha, const FloatComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::bessely' instead")
-extern OCTAVE_API FloatComplexMatrix bessely (const FloatMatrix& alpha, const FloatComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besseli' instead")
-extern OCTAVE_API FloatComplexMatrix besseli (const FloatMatrix& alpha, const FloatComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselk' instead")
-extern OCTAVE_API FloatComplexMatrix besselk (const FloatMatrix& alpha, const FloatComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselh1' instead")
-extern OCTAVE_API FloatComplexMatrix besselh1 (const FloatMatrix& alpha, const FloatComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselh2' instead")
-extern OCTAVE_API FloatComplexMatrix besselh2 (const FloatMatrix& alpha, const FloatComplexMatrix& x, bool scaled, Array<octave_idx_type>& ierr);
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselj' instead")
-extern OCTAVE_API FloatComplexNDArray besselj (float alpha, const FloatComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::bessely' instead")
-extern OCTAVE_API FloatComplexNDArray bessely (float alpha, const FloatComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besseli' instead")
-extern OCTAVE_API FloatComplexNDArray besseli (float alpha, const FloatComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselk' instead")
-extern OCTAVE_API FloatComplexNDArray besselk (float alpha, const FloatComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselh1' instead")
-extern OCTAVE_API FloatComplexNDArray besselh1 (float alpha, const FloatComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselh2' instead")
-extern OCTAVE_API FloatComplexNDArray besselh2 (float alpha, const FloatComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselj' instead")
-extern OCTAVE_API FloatComplexNDArray besselj (const FloatNDArray& alpha, const FloatComplex& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::bessely' instead")
-extern OCTAVE_API FloatComplexNDArray bessely (const FloatNDArray& alpha, const FloatComplex& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besseli' instead")
-extern OCTAVE_API FloatComplexNDArray besseli (const FloatNDArray& alpha, const FloatComplex& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselk' instead")
-extern OCTAVE_API FloatComplexNDArray besselk (const FloatNDArray& alpha, const FloatComplex& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselh1' instead")
-extern OCTAVE_API FloatComplexNDArray besselh1 (const FloatNDArray& alpha, const FloatComplex& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselh2' instead")
-extern OCTAVE_API FloatComplexNDArray besselh2 (const FloatNDArray& alpha, const FloatComplex& x, bool scaled, Array<octave_idx_type>& ierr);
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselj' instead")
-extern OCTAVE_API FloatComplexNDArray besselj (const FloatNDArray& alpha, const FloatComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::bessely' instead")
-extern OCTAVE_API FloatComplexNDArray bessely (const FloatNDArray& alpha, const FloatComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besseli' instead")
-extern OCTAVE_API FloatComplexNDArray besseli (const FloatNDArray& alpha, const FloatComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselk' instead")
-extern OCTAVE_API FloatComplexNDArray besselk (const FloatNDArray& alpha, const FloatComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselh1' instead")
-extern OCTAVE_API FloatComplexNDArray besselh1 (const FloatNDArray& alpha, const FloatComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselh2' instead")
-extern OCTAVE_API FloatComplexNDArray besselh2 (const FloatNDArray& alpha, const FloatComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr);
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselj' instead")
-extern OCTAVE_API FloatComplexMatrix besselj (const FloatRowVector& alpha, const FloatComplexColumnVector& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::bessely' instead")
-extern OCTAVE_API FloatComplexMatrix bessely (const FloatRowVector& alpha, const FloatComplexColumnVector& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besseli' instead")
-extern OCTAVE_API FloatComplexMatrix besseli (const FloatRowVector& alpha, const FloatComplexColumnVector& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselk' instead")
-extern OCTAVE_API FloatComplexMatrix besselk (const FloatRowVector& alpha, const FloatComplexColumnVector& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselh1' instead")
-extern OCTAVE_API FloatComplexMatrix besselh1 (const FloatRowVector& alpha, const FloatComplexColumnVector& x, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::besselh2' instead")
-extern OCTAVE_API FloatComplexMatrix besselh2 (const FloatRowVector& alpha, const FloatComplexColumnVector& x, bool scaled, Array<octave_idx_type>& ierr);
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::airy' instead")
-inline Complex airy (const Complex& z, bool deriv, bool scaled, octave_idx_type& ierr) { return octave::math::airy (z, deriv, scaled, ierr); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::biry' instead")
-inline Complex biry (const Complex& z, bool deriv, bool scaled, octave_idx_type& ierr) { return octave::math::biry (z, deriv, scaled, ierr); }
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::airy' instead")
-extern OCTAVE_API ComplexMatrix airy (const ComplexMatrix& z, bool deriv, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::biry' instead")
-extern OCTAVE_API ComplexMatrix biry (const ComplexMatrix& z, bool deriv, bool scaled, Array<octave_idx_type>& ierr);
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::airy' instead")
-extern OCTAVE_API ComplexNDArray airy (const ComplexNDArray& z, bool deriv, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::biry' instead")
-extern OCTAVE_API ComplexNDArray biry (const ComplexNDArray& z, bool deriv, bool scaled, Array<octave_idx_type>& ierr);
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::airy' instead")
-inline FloatComplex airy (const FloatComplex& z, bool deriv, bool scaled, octave_idx_type& ierr) { return octave::math::airy (z, deriv, scaled, ierr); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::biry' instead")
-inline FloatComplex biry (const FloatComplex& z, bool deriv, bool scaled, octave_idx_type& ierr) { return octave::math::biry (z, deriv, scaled, ierr); }
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::airy' instead")
-extern OCTAVE_API FloatComplexMatrix airy (const FloatComplexMatrix& z, bool deriv, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::biry' instead")
-extern OCTAVE_API FloatComplexMatrix biry (const FloatComplexMatrix& z, bool deriv, bool scaled, Array<octave_idx_type>& ierr);
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::airy' instead")
-extern OCTAVE_API FloatComplexNDArray airy (const FloatComplexNDArray& z, bool deriv, bool scaled, Array<octave_idx_type>& ierr);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::biry' instead")
-extern OCTAVE_API FloatComplexNDArray biry (const FloatComplexNDArray& z, bool deriv, bool scaled, Array<octave_idx_type>& ierr);
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::gammainc' instead")
-inline double gammainc (double x, double a, bool& err) { return octave::math::gammainc (x, a, err); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::gammainc' instead")
-inline double gammainc (double x, double a) { return octave::math::gammainc (x, a); }
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::gammainc' instead")
-extern OCTAVE_API Matrix gammainc (double x, const Matrix& a);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::gammainc' instead")
-extern OCTAVE_API Matrix gammainc (const Matrix& x, double a);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::gammainc' instead")
-extern OCTAVE_API Matrix gammainc (const Matrix& x, const Matrix& a);
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::gammainc' instead")
-extern OCTAVE_API NDArray gammainc (double x, const NDArray& a);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::gammainc' instead")
-extern OCTAVE_API NDArray gammainc (const NDArray& x, double a);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::rc_log1p' instead")
-extern OCTAVE_API NDArray gammainc (const NDArray& x, const NDArray& a);
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::gammainc' instead")
-inline float gammainc (float x, float a, bool& err) { return octave::math::gammainc (x, a, err); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::gammainc' instead")
-inline float gammainc (float x, float a) { return octave::math::gammainc (x, a); }
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::rc_log1p' instead")
-extern OCTAVE_API FloatMatrix gammainc (float x, const FloatMatrix& a);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::rc_log1p' instead")
-extern OCTAVE_API FloatMatrix gammainc (const FloatMatrix& x, float a);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::rc_log1p' instead")
-extern OCTAVE_API FloatMatrix gammainc (const FloatMatrix& x, const FloatMatrix& a);
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::rc_log1p' instead")
-extern OCTAVE_API FloatNDArray gammainc (float x, const FloatNDArray& a);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::rc_log1p' instead")
-extern OCTAVE_API FloatNDArray gammainc (const FloatNDArray& x, float a);
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::rc_log1p' instead")
-extern OCTAVE_API FloatNDArray gammainc (const FloatNDArray& x, const FloatNDArray& a);
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::rc_log1p' instead")
-inline Complex rc_log1p (double x) { return octave::math::rc_log1p (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::rc_log1p' instead")
-inline FloatComplex rc_log1p (float x) { return octave::math::rc_log1p (x); }
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::erfinv' instead")
-inline double erfinv (double x) { return octave::math::erfinv (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::erfinv' instead")
-inline float erfinv (float x) { return octave::math::erfinv (x); }
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::erfcinv' instead")
-inline double erfcinv (double x) { return octave::math::erfcinv (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::erfcinv' instead")
-inline float erfcinv (float x) { return octave::math::erfcinv (x); }
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::erfcx' instead")
-inline float erfcx (float x) { return octave::math::erfcx (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::erfcx' instead")
-inline double erfcx (double x) { return octave::math::erfcx (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::erfcx' instead")
-inline Complex erfcx (const Complex& x) { return octave::math::erfcx (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::erfcx' instead")
-inline FloatComplex erfcx (const FloatComplex& x) { return octave::math::erfcx (x); }
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::erfi' instead")
-inline float erfi (float x) { return octave::math::erfi (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::erfi' instead")
-inline double erfi (double x) { return octave::math::erfi (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::erfi' instead")
-inline Complex erfi (const Complex& x) { return octave::math::erfi (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::erfi' instead")
-inline FloatComplex erfi (const FloatComplex& x) { return octave::math::erfi (x); }
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::dawson' instead")
-inline float dawson (float x) { return octave::math::dawson (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::dawson' instead")
-inline double dawson (double x) { return octave::math::dawson (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::dawson' instead")
-inline Complex dawson (const Complex& x) { return octave::math::dawson (x); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::dawson' instead")
-inline FloatComplex dawson (const FloatComplex& x) { return octave::math::dawson (x); }
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::ellipj' instead")
-inline void ellipj (double u, double m, double& sn, double& cn, double& dn, double& err) { octave::math::ellipj (u, m, sn, cn, dn, err); }
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::ellipj' instead")
-inline void ellipj (const Complex& u, double m, Complex& sn, Complex& cn, Complex& dn, double& err) { octave::math::ellipj (u, m, sn, cn, dn, err); }
-
-//! Digamma function.
-//!
-//! Only defined for double and float.
-template <typename T>
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::psi' instead")
-T
-psi (T z);
-
-template <>
-inline double
-psi (double z)
-{
-  return octave::math::psi (z);
-}
-
-template <>
-inline float
-psi (float z)
-{
-  return octave::math::psi (z);
-}
-
-//! Digamma function for complex input.
-//!
-//! Only defined for double and float.
-template <typename T>
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::psi' instead")
-std::complex<T>
-psi (const std::complex<T>& z);
-
-template <>
-inline std::complex<double>
-psi (const std::complex<double>& z)
-{
-  return octave::math::psi (z);
-}
-
-template <>
-inline std::complex<float>
-psi (const std::complex<float>& z)
-{
-  return octave::math::psi (z);
-}
-
-//! Polygamma function.
-//!
-//! Only defined for double and float.
-//! @param n must be non-negative.  If zero, the digamma function is computed.
-//! @param z must be real and non-negative.
-template <typename T>
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::psi' instead")
-T
-psi (octave_idx_type n, T z);
-
-template<>
-inline double
-psi (octave_idx_type n, double z)
-{
-  return octave::math::psi (n, z);
-}
-
-template<>
-inline float
-psi (octave_idx_type n, float z)
-{
-  return octave::math::psi (n, z);
-}
-
 #endif
-
-#endif
--- a/liboctave/numeric/module.mk	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/numeric/module.mk	Fri Aug 10 09:09:51 2018 +0200
@@ -39,7 +39,6 @@
   %reldir%/lo-amos-proto.h \
   %reldir%/lo-arpack-proto.h \
   %reldir%/lo-blas-proto.h \
-  %reldir%/lo-fftpack-proto.h \
   %reldir%/lo-lapack-proto.h \
   %reldir%/lo-mappers.h \
   %reldir%/lo-qrupdate-proto.h \
@@ -121,10 +120,6 @@
   $(FFTW_XCPPFLAGS) \
   $(SPARSE_XCPPFLAGS)
 
-%canon_reldir%_libnumeric_la_CFLAGS = $(liboctave_liboctave_la_CFLAGS)
-
-%canon_reldir%_libnumeric_la_CXXFLAGS = $(liboctave_liboctave_la_CXXFLAGS)
-
 liboctave_liboctave_la_LIBADD += %reldir%/libnumeric.la
 
 liboctave_EXTRA_DIST += $(LIBOCTAVE_OPT_IN)
--- a/liboctave/numeric/oct-fftw.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/numeric/oct-fftw.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -242,7 +242,7 @@
             // Create matrix with the same size and 16-byte alignment as input
             OCTAVE_LOCAL_BUFFER (Complex, itmp, nn * howmany + 32);
             itmp = reinterpret_cast<Complex *>
-              (((reinterpret_cast<ptrdiff_t>(itmp) + 15) & ~ 0xF) +
+              (((reinterpret_cast<ptrdiff_t> (itmp) + 15) & ~ 0xF) +
                ((reinterpret_cast<ptrdiff_t> (in)) & 0xF));
 
             *cur_plan_p =
@@ -361,7 +361,7 @@
             // Create matrix with the same size and 16-byte alignment as input
             OCTAVE_LOCAL_BUFFER (double, itmp, nn + 32);
             itmp = reinterpret_cast<double *>
-              (((reinterpret_cast<ptrdiff_t>(itmp) + 15) & ~ 0xF) +
+              (((reinterpret_cast<ptrdiff_t> (itmp) + 15) & ~ 0xF) +
                ((reinterpret_cast<ptrdiff_t> (in)) & 0xF));
 
             *cur_plan_p =
@@ -598,7 +598,7 @@
             // Create matrix with the same size and 16-byte alignment as input
             OCTAVE_LOCAL_BUFFER (FloatComplex, itmp, nn * howmany + 32);
             itmp = reinterpret_cast<FloatComplex *>
-              (((reinterpret_cast<ptrdiff_t>(itmp) + 15) & ~ 0xF) +
+              (((reinterpret_cast<ptrdiff_t> (itmp) + 15) & ~ 0xF) +
                ((reinterpret_cast<ptrdiff_t> (in)) & 0xF));
 
             *cur_plan_p =
@@ -717,7 +717,7 @@
             // Create matrix with the same size and 16-byte alignment as input
             OCTAVE_LOCAL_BUFFER (float, itmp, nn + 32);
             itmp = reinterpret_cast<float *>
-              (((reinterpret_cast<ptrdiff_t>(itmp) + 15) & ~ 0xF) +
+              (((reinterpret_cast<ptrdiff_t> (itmp) + 15) & ~ 0xF) +
                ((reinterpret_cast<ptrdiff_t> (in)) & 0xF));
 
             *cur_plan_p =
--- a/liboctave/numeric/oct-rand.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/numeric/oct-rand.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -43,747 +43,752 @@
 #include "randpoisson.h"
 #include "singleton-cleanup.h"
 
-octave_rand *octave_rand::instance = nullptr;
-
-octave_rand::octave_rand (void)
-  : current_distribution (uniform_dist), use_old_generators (false),
-    rand_states ()
-{
-  initialize_ranlib_generators ();
-
-  initialize_mersenne_twister ();
-}
-
-bool
-octave_rand::instance_ok (void)
+namespace octave
 {
-  bool retval = true;
-
-  if (! instance)
-    {
-      instance = new octave_rand ();
-
-      if (instance)
-        singleton_cleanup_list::add (cleanup_instance);
-    }
-
-  if (! instance)
-    (*current_liboctave_error_handler)
-      ("unable to create octave_rand object!");
-
-  return retval;
-}
-
-double
-octave_rand::do_seed (void)
-{
-  union d2i { double d; int32_t i[2]; };
-  union d2i u;
-
-  octave::mach_info::float_format ff = octave::mach_info::native_float_format ();
+  rand *rand::instance = nullptr;
 
-  switch (ff)
-    {
-    case octave::mach_info::flt_fmt_ieee_big_endian:
-      F77_FUNC (getsd, GETSD) (u.i[1], u.i[0]);
-      break;
-
-    default:
-      F77_FUNC (getsd, GETSD) (u.i[0], u.i[1]);
-      break;
-    }
-
-  return u.d;
-}
-
-static int32_t
-force_to_fit_range (int32_t i, int32_t lo, int32_t hi)
-{
-  assert (hi > lo && lo >= 0 && hi > lo);
-
-  i = (i > 0 ? i : -i);
+  rand::rand (void)
+    : current_distribution (uniform_dist), use_old_generators (false),
+      rand_states ()
+  {
+    initialize_ranlib_generators ();
 
-  if (i < lo)
-    i = lo;
-  else if (i > hi)
-    i = i % hi;
-
-  return i;
-}
-
-void
-octave_rand::do_seed (double s)
-{
-  use_old_generators = true;
-
-  int i0, i1;
-  union d2i { double d; int32_t i[2]; };
-  union d2i u;
-  u.d = s;
-
-  octave::mach_info::float_format ff = octave::mach_info::native_float_format ();
-
-  switch (ff)
-    {
-    case octave::mach_info::flt_fmt_ieee_big_endian:
-      i1 = force_to_fit_range (u.i[0], 1, 2147483563);
-      i0 = force_to_fit_range (u.i[1], 1, 2147483399);
-      break;
+    initialize_mersenne_twister ();
+  }
 
-    default:
-      i0 = force_to_fit_range (u.i[0], 1, 2147483563);
-      i1 = force_to_fit_range (u.i[1], 1, 2147483399);
-      break;
-    }
-
-  F77_FUNC (setsd, SETSD) (i0, i1);
-}
-
-void
-octave_rand::do_reset (void)
-{
-  use_old_generators = true;
-  initialize_ranlib_generators ();
-}
-
-uint32NDArray
-octave_rand::do_state (const std::string& d)
-{
-  return rand_states[d.empty () ? current_distribution : get_dist_id (d)];
-}
-
-void
-octave_rand::do_state (const uint32NDArray& s, const std::string& d)
-{
-  use_old_generators = false;
-
-  int old_dist = current_distribution;
-
-  int new_dist = (d.empty () ? current_distribution : get_dist_id (d));
-
-  uint32NDArray saved_state;
-
-  if (old_dist != new_dist)
-    saved_state = get_internal_state ();
-
-  set_internal_state (s);
-
-  rand_states[new_dist] = get_internal_state ();
-
-  if (old_dist != new_dist)
-    rand_states[old_dist] = saved_state;
-}
+  bool rand::instance_ok (void)
+  {
+    bool retval = true;
 
-void
-octave_rand::do_reset (const std::string& d)
-{
-  use_old_generators = false;
-
-  int old_dist = current_distribution;
-
-  int new_dist = (d.empty () ? current_distribution : get_dist_id (d));
-
-  uint32NDArray saved_state;
-
-  if (old_dist != new_dist)
-    saved_state = get_internal_state ();
-
-  oct_init_by_entropy ();
-  rand_states[new_dist] = get_internal_state ();
-
-  if (old_dist != new_dist)
-    rand_states[old_dist] = saved_state;
-}
+    if (! instance)
+      {
+        instance = new rand ();
 
-std::string
-octave_rand::do_distribution (void)
-{
-  std::string retval;
-
-  switch (current_distribution)
-    {
-    case uniform_dist:
-      retval = "uniform";
-      break;
+        if (instance)
+          singleton_cleanup_list::add (cleanup_instance);
+      }
 
-    case normal_dist:
-      retval = "normal";
-      break;
-
-    case expon_dist:
-      retval = "exponential";
-      break;
-
-    case poisson_dist:
-      retval = "poisson";
-      break;
-
-    case gamma_dist:
-      retval = "gamma";
-      break;
-
-    default:
+    if (! instance)
       (*current_liboctave_error_handler)
-        ("rand: invalid distribution ID = %d", current_distribution);
-      break;
-    }
+        ("unable to create rand object!");
+
+    return retval;
+  }
 
-  return retval;
-}
+  double rand::do_seed (void)
+  {
+    union d2i { double d; int32_t i[2]; };
+    union d2i u;
+
+    mach_info::float_format ff = mach_info::native_float_format ();
+
+    switch (ff)
+      {
+      case mach_info::flt_fmt_ieee_big_endian:
+        F77_FUNC (getsd, GETSD) (u.i[1], u.i[0]);
+        break;
 
-void
-octave_rand::do_distribution (const std::string& d)
-{
-  int id = get_dist_id (d);
+      default:
+        F77_FUNC (getsd, GETSD) (u.i[0], u.i[1]);
+        break;
+      }
+
+    return u.d;
+  }
 
-  switch (id)
-    {
-    case uniform_dist:
-      octave_rand::uniform_distribution ();
-      break;
+  static int32_t
+  force_to_fit_range (int32_t i, int32_t lo, int32_t hi)
+  {
+    assert (hi > lo && lo >= 0 && hi > lo);
+
+    i = (i > 0 ? i : -i);
+
+    if (i < lo)
+      i = lo;
+    else if (i > hi)
+      i = i % hi;
+
+    return i;
+  }
 
-    case normal_dist:
-      octave_rand::normal_distribution ();
-      break;
+  void rand::do_seed (double s)
+  {
+    use_old_generators = true;
+
+    int i0, i1;
+    union d2i { double d; int32_t i[2]; };
+    union d2i u;
+    u.d = s;
 
-    case expon_dist:
-      octave_rand::exponential_distribution ();
-      break;
+    mach_info::float_format ff = mach_info::native_float_format ();
+
+    switch (ff)
+      {
+      case mach_info::flt_fmt_ieee_big_endian:
+        i1 = force_to_fit_range (u.i[0], 1, 2147483563);
+        i0 = force_to_fit_range (u.i[1], 1, 2147483399);
+        break;
 
-    case poisson_dist:
-      octave_rand::poisson_distribution ();
-      break;
+      default:
+        i0 = force_to_fit_range (u.i[0], 1, 2147483563);
+        i1 = force_to_fit_range (u.i[1], 1, 2147483399);
+        break;
+      }
+
+    F77_FUNC (setsd, SETSD) (i0, i1);
+  }
 
-    case gamma_dist:
-      octave_rand::gamma_distribution ();
-      break;
+  void rand::do_reset (void)
+  {
+    use_old_generators = true;
+    initialize_ranlib_generators ();
+  }
 
-    default:
-      (*current_liboctave_error_handler)
-        ("rand: invalid distribution ID = %d", id);
-      break;
-    }
-}
+  uint32NDArray rand::do_state (const std::string& d)
+  {
+    return rand_states[d.empty () ? current_distribution : get_dist_id (d)];
+  }
+
+  void rand::do_state (const uint32NDArray& s, const std::string& d)
+  {
+    use_old_generators = false;
+
+    int old_dist = current_distribution;
 
-void
-octave_rand::do_uniform_distribution (void)
-{
-  switch_to_generator (uniform_dist);
+    int new_dist = (d.empty () ? current_distribution : get_dist_id (d));
+
+    uint32NDArray saved_state;
+
+    if (old_dist != new_dist)
+      saved_state = get_internal_state ();
+
+    set_internal_state (s);
 
-  F77_FUNC (setcgn, SETCGN) (uniform_dist);
-}
+    rand_states[new_dist] = get_internal_state ();
+
+    if (old_dist != new_dist)
+      rand_states[old_dist] = saved_state;
+  }
+
+  void rand::do_reset (const std::string& d)
+  {
+    use_old_generators = false;
 
-void
-octave_rand::do_normal_distribution (void)
-{
-  switch_to_generator (normal_dist);
+    int old_dist = current_distribution;
+
+    int new_dist = (d.empty () ? current_distribution : get_dist_id (d));
+
+    uint32NDArray saved_state;
+
+    if (old_dist != new_dist)
+      saved_state = get_internal_state ();
 
-  F77_FUNC (setcgn, SETCGN) (normal_dist);
-}
+    init_mersenne_twister ();
+    rand_states[new_dist] = get_internal_state ();
 
-void
-octave_rand::do_exponential_distribution (void)
-{
-  switch_to_generator (expon_dist);
+    if (old_dist != new_dist)
+      rand_states[old_dist] = saved_state;
+  }
+
+  std::string rand::do_distribution (void)
+  {
+    std::string retval;
 
-  F77_FUNC (setcgn, SETCGN) (expon_dist);
-}
+    switch (current_distribution)
+      {
+      case uniform_dist:
+        retval = "uniform";
+        break;
+
+      case normal_dist:
+        retval = "normal";
+        break;
 
-void
-octave_rand::do_poisson_distribution (void)
-{
-  switch_to_generator (poisson_dist);
+      case expon_dist:
+        retval = "exponential";
+        break;
 
-  F77_FUNC (setcgn, SETCGN) (poisson_dist);
-}
+      case poisson_dist:
+        retval = "poisson";
+        break;
+
+      case gamma_dist:
+        retval = "gamma";
+        break;
 
-void
-octave_rand::do_gamma_distribution (void)
-{
-  switch_to_generator (gamma_dist);
+      default:
+        (*current_liboctave_error_handler)
+          ("rand: invalid distribution ID = %d", current_distribution);
+        break;
+      }
+
+    return retval;
+  }
+
+  void rand::do_distribution (const std::string& d)
+  {
+    int id = get_dist_id (d);
 
-  F77_FUNC (setcgn, SETCGN) (gamma_dist);
-}
+    switch (id)
+      {
+      case uniform_dist:
+        rand::uniform_distribution ();
+        break;
 
-double
-octave_rand::do_scalar (double a)
-{
-  double retval = 0.0;
+      case normal_dist:
+        rand::normal_distribution ();
+        break;
+
+      case expon_dist:
+        rand::exponential_distribution ();
+        break;
 
-  if (use_old_generators)
-    {
-      switch (current_distribution)
-        {
-        case uniform_dist:
-          F77_FUNC (dgenunf, DGENUNF) (0.0, 1.0, retval);
-          break;
+      case poisson_dist:
+        rand::poisson_distribution ();
+        break;
+
+      case gamma_dist:
+        rand::gamma_distribution ();
+        break;
+
+      default:
+        (*current_liboctave_error_handler)
+          ("rand: invalid distribution ID = %d", id);
+        break;
+      }
+  }
+
+  void rand::do_uniform_distribution (void)
+  {
+    switch_to_generator (uniform_dist);
 
-        case normal_dist:
-          F77_FUNC (dgennor, DGENNOR) (0.0, 1.0, retval);
-          break;
+    F77_FUNC (setcgn, SETCGN) (uniform_dist);
+  }
+
+  void rand::do_normal_distribution (void)
+  {
+    switch_to_generator (normal_dist);
+
+    F77_FUNC (setcgn, SETCGN) (normal_dist);
+  }
 
-        case expon_dist:
-          F77_FUNC (dgenexp, DGENEXP) (1.0, retval);
-          break;
+  void rand::do_exponential_distribution (void)
+  {
+    switch_to_generator (expon_dist);
+
+    F77_FUNC (setcgn, SETCGN) (expon_dist);
+  }
+
+  void rand::do_poisson_distribution (void)
+  {
+    switch_to_generator (poisson_dist);
+
+    F77_FUNC (setcgn, SETCGN) (poisson_dist);
+  }
 
-        case poisson_dist:
-          if (a < 0.0 || ! octave::math::isfinite (a))
-            retval = octave::numeric_limits<double>::NaN ();
-          else
-            {
-              // workaround bug in ignpoi, by calling with different Mu
-              F77_FUNC (dignpoi, DIGNPOI) (a + 1, retval);
-              F77_FUNC (dignpoi, DIGNPOI) (a, retval);
-            }
-          break;
+  void rand::do_gamma_distribution (void)
+  {
+    switch_to_generator (gamma_dist);
+
+    F77_FUNC (setcgn, SETCGN) (gamma_dist);
+  }
+
+  template <>
+  double rand::uniform<double> (void)
+  {
+    double retval;
+
+    if (use_old_generators)
+      F77_FUNC (dgenunf, DGENUNF) (0.0, 1.0, retval);
+    else
+      retval = octave::rand_uniform<double> ();
+
+    return retval;
+  }
 
-        case gamma_dist:
-          if (a <= 0.0 || ! octave::math::isfinite (a))
-            retval = octave::numeric_limits<double>::NaN ();
-          else
-            F77_FUNC (dgengam, DGENGAM) (1.0, a, retval);
-          break;
+  template <>
+  double rand::normal<double> (void)
+  {
+    double retval;
+
+    if (use_old_generators)
+      F77_FUNC (dgennor, DGENNOR) (0.0, 1.0, retval);
+    else
+      retval = octave::rand_normal<double> ();
 
-        default:
-          (*current_liboctave_error_handler)
-            ("rand: invalid distribution ID = %d", current_distribution);
-          break;
-        }
-    }
-  else
-    {
-      switch (current_distribution)
-        {
-        case uniform_dist:
-          retval = oct_randu ();
-          break;
+    return retval;
+  }
+
+  template <>
+  double rand::exponential<double> (void)
+  {
+    double retval;
+
+    if (use_old_generators)
+      F77_FUNC (dgenexp, DGENEXP) (1.0, retval);
+    else
+      retval = octave::rand_exponential<double> ();
 
-        case normal_dist:
-          retval = oct_randn ();
-          break;
+    return retval;
+  }
 
-        case expon_dist:
-          retval = oct_rande ();
-          break;
+  template <>
+  double rand::poisson<double> (double a)
+  {
+    double retval;
 
-        case poisson_dist:
-          retval = oct_randp (a);
-          break;
+    if (use_old_generators)
+      {
+        if (a < 0.0 || ! math::isfinite (a))
+          retval = numeric_limits<double>::NaN ();
+        else
+          {
+            // workaround bug in ignpoi, by calling with different Mu
+            F77_FUNC (dignpoi, DIGNPOI) (a + 1, retval);
+            F77_FUNC (dignpoi, DIGNPOI) (a, retval);
+          }
+      }
+    else
+      retval = octave::rand_poisson<double> (a);
+
+    return retval;
+  }
 
-        case gamma_dist:
-          retval = oct_randg (a);
-          break;
+  template <>
+  double rand::gamma<double> (double a)
+  {
+    double retval;
 
-        default:
-          (*current_liboctave_error_handler)
-            ("rand: invalid distribution ID = %d", current_distribution);
-          break;
-        }
+    if (use_old_generators)
+      {
+        if (a <= 0.0 || ! math::isfinite (a))
+          retval = numeric_limits<double>::NaN ();
+        else
+          F77_FUNC (dgengam, DGENGAM) (1.0, a, retval);
+      }
+    else
+      retval = octave::rand_gamma<double> (a);
+
+    return retval;
+  }
 
-      save_state ();
-    }
+  template <>
+  float rand::uniform<float> (void)
+  {
+    float retval;
 
-  return retval;
-}
+    if (use_old_generators)
+      F77_FUNC (fgenunf, FGENUNF) (0.0f, 1.0f, retval);
+    else
+      retval = octave::rand_uniform<float> ();
 
-float
-octave_rand::do_float_scalar (float a)
-{
-  float retval = 0.0;
+    return retval;
+  }
+
+  template <>
+  float rand::normal<float> (void)
+  {
+    float retval;
 
-  if (use_old_generators)
-    {
-      switch (current_distribution)
-        {
-        case uniform_dist:
-          F77_FUNC (fgenunf, FGENUNF) (0.0f, 1.0f, retval);
-          break;
+    if (use_old_generators)
+      F77_FUNC (fgennor, FGENNOR) (0.0f, 1.0f, retval);
+    else
+      retval = octave::rand_normal<float> ();
+
+    return retval;
+  }
+
+  template <>
+  float rand::exponential<float> (void)
+  {
+    float retval;
 
-        case normal_dist:
-          F77_FUNC (fgennor, FGENNOR) (0.0f, 1.0f, retval);
-          break;
+    if (use_old_generators)
+      F77_FUNC (fgenexp, FGENEXP) (1.0f, retval);
+    else
+      retval = octave::rand_exponential<float> ();
 
-        case expon_dist:
-          F77_FUNC (fgenexp, FGENEXP) (1.0f, retval);
-          break;
+    return retval;
+  }
+
+  template <>
+  float rand::poisson<float> (float a)
+  {
+    float retval;
 
-        case poisson_dist:
-          if (a < 0.0f || ! octave::math::isfinite (a))
-            retval = octave::numeric_limits<float>::NaN ();
-          else
-            {
-              // workaround bug in ignpoi, by calling with different Mu
-              F77_FUNC (fignpoi, FIGNPOI) (a + 1, retval);
-              F77_FUNC (fignpoi, FIGNPOI) (a, retval);
-            }
-          break;
+    if (use_old_generators)
+      {
+        if (a < 0.0f || ! math::isfinite (a))
+          retval = numeric_limits<float>::NaN ();
+        else
+          {
+            // workaround bug in ignpoi, by calling with different Mu
+            F77_FUNC (fignpoi, FIGNPOI) (a + 1, retval);
+            F77_FUNC (fignpoi, FIGNPOI) (a, retval);
+          }
+      }
+    else
+      {
+        // Keep poisson distribution in double precision for accuracy
+        retval = octave::rand_poisson<double> (a);
+      }
+
+    return retval;
+  }
 
-        case gamma_dist:
-          if (a <= 0.0f || ! octave::math::isfinite (a))
-            retval = octave::numeric_limits<float>::NaN ();
-          else
-            F77_FUNC (fgengam, FGENGAM) (1.0, a, retval);
-          break;
+  template <>
+  float rand::gamma<float> (float a)
+  {
+    float retval;
+
+    if (use_old_generators)
+      {
+        if (a <= 0.0f || ! math::isfinite (a))
+          retval = numeric_limits<float>::NaN ();
+        else
+          F77_FUNC (fgengam, FGENGAM) (1.0f, a, retval);
+      }
+    else
+      retval = octave::rand_gamma<float> (a);
+
+    return retval;
+  }
+
+  template <typename T>
+  T rand::do_scalar (T a)
+  {
+    T retval = 0;
 
-        default:
-          (*current_liboctave_error_handler)
-            ("rand: invalid distribution ID = %d", current_distribution);
-          break;
-        }
-    }
-  else
-    {
-      switch (current_distribution)
-        {
-        case uniform_dist:
-          retval = oct_float_randu ();
-          break;
+    switch (current_distribution)
+      {
+      case uniform_dist:
+        retval = uniform<T> ();
+        break;
+
+      case normal_dist:
+        retval = normal<T> ();
+        break;
+
+      case expon_dist:
+        retval = exponential<T> ();
+        break;
+
+      case poisson_dist:
+        retval = poisson<T> (a);
+        break;
+
+      case gamma_dist:
+        retval = gamma<T> (a);
+        break;
 
-        case normal_dist:
-          retval = oct_float_randn ();
-          break;
+      default:
+        (*current_liboctave_error_handler)
+          ("rand: invalid distribution ID = %d", current_distribution);
+        break;
+      }
+
+    if (! use_old_generators)
+      save_state ();
+
+    return retval;
+  }
 
-        case expon_dist:
-          retval = oct_float_rande ();
-          break;
+  template double rand::do_scalar<double> (double);
+  template float rand::do_scalar<float> (float);
 
-        case poisson_dist:
-          // Keep poisson distribution in double precision for accuracy
-          retval = oct_randp (a);
-          break;
+  template <typename T>
+  Array<T>
+  rand::do_vector (octave_idx_type n, T a)
+  {
+    Array<T> retval;
+
+    if (n > 0)
+      {
+        retval.clear (n, 1);
 
-        case gamma_dist:
-          retval = oct_float_randg (a);
-          break;
+        fill (retval.numel (), retval.fortran_vec (), a);
+      }
+    else if (n < 0)
+      (*current_liboctave_error_handler) ("rand: invalid negative argument");
+
+    return retval;
+  }
+
+  template Array<double> rand::do_vector<double> (octave_idx_type, double);
+  template Array<float> rand::do_vector<float> (octave_idx_type, float);
 
-        default:
-          (*current_liboctave_error_handler)
-            ("rand: invalid distribution ID = %d", current_distribution);
-          break;
-        }
+  NDArray rand::do_nd_array (const dim_vector& dims, double a)
+  {
+    NDArray retval;
+
+    if (! dims.all_zero ())
+      {
+        retval.clear (dims);
+
+        fill (retval.numel (), retval.fortran_vec (), a);
+      }
 
-      save_state ();
-    }
+    return retval;
+  }
 
-  return retval;
-}
+  FloatNDArray rand::do_float_nd_array (const dim_vector& dims, float a)
+  {
+    FloatNDArray retval;
+
+    if (! dims.all_zero ())
+      {
+        retval.clear (dims);
 
-Array<double>
-octave_rand::do_vector (octave_idx_type n, double a)
-{
-  Array<double> retval;
+        fill (retval.numel (), retval.fortran_vec (), a);
+      }
 
-  if (n > 0)
-    {
-      retval.clear (n, 1);
+    return retval;
+  }
+
+  // Make the random number generator give us a different sequence every
+  // time we start octave unless we specifically set the seed.  The
+  // technique used below will cycle monthly, but it does seem to
+  // work ok to give fairly different seeds each time Octave starts.
 
-      fill (retval.numel (), retval.fortran_vec (), a);
-    }
-  else if (n < 0)
-    (*current_liboctave_error_handler) ("rand: invalid negative argument");
+  void rand::initialize_ranlib_generators (void)
+  {
+    sys::localtime tm;
+    int stored_distribution = current_distribution;
+    F77_FUNC (setcgn, SETCGN) (uniform_dist);
+
+    int hour = tm.hour () + 1;
+    int minute = tm.min () + 1;
+    int second = tm.sec () + 1;
 
-  return retval;
-}
+    int32_t s0 = tm.mday () * hour * minute * second;
+    int32_t s1 = hour * minute * second;
+
+    s0 = force_to_fit_range (s0, 1, 2147483563);
+    s1 = force_to_fit_range (s1, 1, 2147483399);
+
+    F77_FUNC (setall, SETALL) (s0, s1);
+    F77_FUNC (setcgn, SETCGN) (stored_distribution);
+  }
+
+  void rand::initialize_mersenne_twister (void)
+  {
+    uint32NDArray s;
 
-Array<float>
-octave_rand::do_float_vector (octave_idx_type n, float a)
-{
-  Array<float> retval;
+    init_mersenne_twister ();
+    s = get_internal_state ();
+    rand_states[uniform_dist] = s;
+
+    init_mersenne_twister ();
+    s = get_internal_state ();
+    rand_states[normal_dist] = s;
+
+    init_mersenne_twister ();
+    s = get_internal_state ();
+    rand_states[expon_dist] = s;
 
-  if (n > 0)
-    {
-      retval.clear (n, 1);
+    init_mersenne_twister ();
+    s = get_internal_state ();
+    rand_states[poisson_dist] = s;
+
+    init_mersenne_twister ();
+    s = get_internal_state ();
+    rand_states[gamma_dist] = s;
 
-      fill (retval.numel (), retval.fortran_vec (), a);
-    }
-  else if (n < 0)
-    (*current_liboctave_error_handler) ("rand: invalid negative argument");
+    // All of the initializations above have messed with the internal state.
+    // Restore the state of the currently selected distribution.
+    set_internal_state (rand_states[current_distribution]);
+  }
 
-  return retval;
-}
+  uint32NDArray rand::get_internal_state (void)
+  {
+    uint32NDArray s (dim_vector (MT_N + 1, 1));
 
-NDArray
-octave_rand::do_nd_array (const dim_vector& dims, double a)
-{
-  NDArray retval;
+    get_mersenne_twister_state (reinterpret_cast<uint32_t *> (s.fortran_vec ()));
+
+    return s;
+  }
 
-  if (! dims.all_zero ())
-    {
-      retval.clear (dims);
+  void rand::save_state (void)
+  {
+    rand_states[current_distribution] = get_internal_state ();;
+  }
+
+  int rand::get_dist_id (const std::string& d)
+  {
+    int retval = unknown_dist;
 
-      fill (retval.numel (), retval.fortran_vec (), a);
-    }
+    if (d == "uniform" || d == "rand")
+      retval = uniform_dist;
+    else if (d == "normal" || d == "randn")
+      retval = normal_dist;
+    else if (d == "exponential" || d == "rande")
+      retval = expon_dist;
+    else if (d == "poisson" || d == "randp")
+      retval = poisson_dist;
+    else if (d == "gamma" || d == "randg")
+      retval = gamma_dist;
+    else
+      (*current_liboctave_error_handler)
+        ("rand: invalid distribution '%s'", d.c_str ());
 
-  return retval;
-}
+    return retval;
+  }
 
-FloatNDArray
-octave_rand::do_float_nd_array (const dim_vector& dims, float a)
-{
-  FloatNDArray retval;
+  void rand::set_internal_state (const uint32NDArray& s)
+  {
+    octave_idx_type len = s.numel ();
+
+    const uint32_t *sdata = reinterpret_cast <const uint32_t *> (s.data ());
 
-  if (! dims.all_zero ())
-    {
-      retval.clear (dims);
+    if (len == MT_N + 1 && sdata[MT_N] <= MT_N && sdata[MT_N] > 0)
+      set_mersenne_twister_state (sdata);
+    else
+      init_mersenne_twister (sdata, len);
+  }
 
-      fill (retval.numel (), retval.fortran_vec (), a);
-    }
+  void rand::switch_to_generator (int dist)
+  {
+    if (dist != current_distribution)
+      {
+        current_distribution = dist;
 
-  return retval;
-}
+        set_internal_state (rand_states[dist]);
+      }
+  }
+
+  void rand::fill (octave_idx_type len, double *v, double a)
+  {
+    if (len < 1)
+      return;
 
-// Make the random number generator give us a different sequence every
-// time we start octave unless we specifically set the seed.  The
-// technique used below will cycle monthly, but it does seem to
-// work ok to give fairly different seeds each time Octave starts.
+    switch (current_distribution)
+      {
+      case uniform_dist:
+        if (use_old_generators)
+          std::generate_n (v, len, [](void) { double x; F77_FUNC (dgenunf, DGENUNF) (0.0, 1.0, x); return x; });
+        else
+          rand_uniform<double> (len, v);
+        break;
 
-void
-octave_rand::initialize_ranlib_generators (void)
-{
-  octave::sys::localtime tm;
-  int stored_distribution = current_distribution;
-  F77_FUNC (setcgn, SETCGN) (uniform_dist);
+      case normal_dist:
+        if (use_old_generators)
+          std::generate_n (v, len, [](void) { double x; F77_FUNC (dgennor, DGENNOR) (0.0, 1.0, x); return x; });
+        else
+          rand_normal<double> (len, v);
+        break;
 
-  int hour = tm.hour () + 1;
-  int minute = tm.min () + 1;
-  int second = tm.sec () + 1;
+      case expon_dist:
+        if (use_old_generators)
+          std::generate_n (v, len, [](void) { double x; F77_FUNC (dgenexp, DGENEXP) (1.0, x); return x; });
+        else
+          rand_exponential<double> (len, v);
+        break;
 
-  int32_t s0 = tm.mday () * hour * minute * second;
-  int32_t s1 = hour * minute * second;
-
-  s0 = force_to_fit_range (s0, 1, 2147483563);
-  s1 = force_to_fit_range (s1, 1, 2147483399);
-
-  F77_FUNC (setall, SETALL) (s0, s1);
-  F77_FUNC (setcgn, SETCGN) (stored_distribution);
-}
+      case poisson_dist:
+        if (use_old_generators)
+          {
+            if (a < 0.0 || ! math::isfinite (a))
+              std::fill_n (v, len, numeric_limits<double>::NaN ());
+            else
+              {
+                // workaround bug in ignpoi, by calling with different Mu
+                double tmp;
+                F77_FUNC (dignpoi, DIGNPOI) (a + 1, tmp);
+                std::generate_n (v, len, [a](void) { double x; F77_FUNC (dignpoi, DIGNPOI) (a, x); return x; });
+              }
+          }
+        else
+          rand_poisson<double> (a, len, v);
+        break;
 
-void
-octave_rand::initialize_mersenne_twister (void)
-{
-  uint32NDArray s;
+      case gamma_dist:
+        if (use_old_generators)
+          {
+            if (a <= 0.0 || ! math::isfinite (a))
+              std::fill_n (v, len, numeric_limits<double>::NaN ());
+            else
+              std::generate_n (v, len, [a](void) { double x; F77_FUNC (dgengam, DGENGAM) (1.0, a, x); return x; });
+          }
+        else
+          rand_gamma<double> (a, len, v);
+        break;
+
+      default:
+        (*current_liboctave_error_handler)
+          ("rand: invalid distribution ID = %d", current_distribution);
+        break;
+      }
 
-  oct_init_by_entropy ();
-  s = get_internal_state ();
-  rand_states[uniform_dist] = s;
+    save_state ();
+
+    return;
+  }
 
-  oct_init_by_entropy ();
-  s = get_internal_state ();
-  rand_states[normal_dist] = s;
+  void rand::fill (octave_idx_type len, float *v, float a)
+  {
+    if (len < 1)
+      return;
+
+    switch (current_distribution)
+      {
+      case uniform_dist:
+        if (use_old_generators)
+          std::generate_n (v, len, [](void) { float x; F77_FUNC (fgenunf, FGENUNF) (0.0f, 1.0f, x); return x; });
+        else
+          octave::rand_uniform<float> (len, v);
+        break;
 
-  oct_init_by_entropy ();
-  s = get_internal_state ();
-  rand_states[expon_dist] = s;
+      case normal_dist:
+        if (use_old_generators)
+          std::generate_n (v, len, [](void) { float x; F77_FUNC (fgennor, FGENNOR) (0.0f, 1.0f, x); return x; });
+        else
+          octave::rand_normal<float> (len, v);
+        break;
 
-  oct_init_by_entropy ();
-  s = get_internal_state ();
-  rand_states[poisson_dist] = s;
-
-  oct_init_by_entropy ();
-  s = get_internal_state ();
-  rand_states[gamma_dist] = s;
+      case expon_dist:
+        if (use_old_generators)
+          std::generate_n (v, len, [](void) { float x; F77_FUNC (fgenexp, FGENEXP) (1.0f, x); return x; });
+        else
+          octave::rand_exponential<float> (len, v);
+        break;
 
-  // All of the initializations above have messed with the internal state.
-  // Restore the state of the currently selected distribution.
-  set_internal_state (rand_states[current_distribution]);
-}
+      case poisson_dist:
+        if (use_old_generators)
+          {
+            if (a < 0.0f || ! math::isfinite (a))
+              std::fill_n (v, len, numeric_limits<float>::NaN ());
+            else
+              {
+                // workaround bug in ignpoi, by calling with different Mu
+                float tmp;
+                F77_FUNC (fignpoi, FIGNPOI) (a + 1, tmp);
+                std::generate_n (v, len, [a](void) { float x; F77_FUNC (fignpoi, FIGNPOI) (a, x); return x; });
+              }
+          }
+        else
+          octave::rand_poisson<float> (a, len, v);
+        break;
 
-uint32NDArray
-octave_rand::get_internal_state (void)
-{
-  uint32NDArray s (dim_vector (MT_N + 1, 1));
+      case gamma_dist:
+        if (use_old_generators)
+          {
+            if (a <= 0.0f || ! math::isfinite (a))
+              std::fill_n (v, len, numeric_limits<float>::NaN ());
+            else
+              std::generate_n (v, len, [a](void) { float x; F77_FUNC (fgengam, FGENGAM) (1.0f, a, x); return x; });
+          }
+        else
+          octave::rand_gamma<float> (a, len, v);
+        break;
 
-  oct_get_state (reinterpret_cast<uint32_t *> (s.fortran_vec ()));
+      default:
+        (*current_liboctave_error_handler)
+          ("rand: invalid distribution ID = %d", current_distribution);
+        break;
+      }
 
-  return s;
+    save_state ();
+
+    return;
+  }
 }
-
-void
-octave_rand::save_state (void)
-{
-  rand_states[current_distribution] = get_internal_state ();;
-}
-
-int
-octave_rand::get_dist_id (const std::string& d)
-{
-  int retval = unknown_dist;
-
-  if (d == "uniform" || d == "rand")
-    retval = uniform_dist;
-  else if (d == "normal" || d == "randn")
-    retval = normal_dist;
-  else if (d == "exponential" || d == "rande")
-    retval = expon_dist;
-  else if (d == "poisson" || d == "randp")
-    retval = poisson_dist;
-  else if (d == "gamma" || d == "randg")
-    retval = gamma_dist;
-  else
-    (*current_liboctave_error_handler)
-      ("rand: invalid distribution '%s'", d.c_str ());
-
-  return retval;
-}
-
-void
-octave_rand::set_internal_state (const uint32NDArray& s)
-{
-  octave_idx_type len = s.numel ();
-
-  const uint32_t *sdata = reinterpret_cast <const uint32_t *> (s.data ());
-
-  if (len == MT_N + 1 && sdata[MT_N] <= MT_N && sdata[MT_N] > 0)
-    oct_set_state (sdata);
-  else
-    oct_init_by_array (sdata, len);
-}
-
-void
-octave_rand::switch_to_generator (int dist)
-{
-  if (dist != current_distribution)
-    {
-      current_distribution = dist;
-
-      set_internal_state (rand_states[dist]);
-    }
-}
-
-void
-octave_rand::fill (octave_idx_type len, double *v, double a)
-{
-  if (len < 1)
-    return;
-
-  switch (current_distribution)
-    {
-    case uniform_dist:
-      if (use_old_generators)
-        std::generate_n (v, len, [](void) { double x; F77_FUNC (dgenunf, DGENUNF) (0.0, 1.0, x); return x; });
-      else
-        oct_fill_randu (len, v);
-      break;
-
-    case normal_dist:
-      if (use_old_generators)
-        std::generate_n (v, len, [](void) { double x; F77_FUNC (dgennor, DGENNOR) (0.0, 1.0, x); return x; });
-      else
-        oct_fill_randn (len, v);
-      break;
-
-    case expon_dist:
-      if (use_old_generators)
-        std::generate_n (v, len, [](void) { double x; F77_FUNC (dgenexp, DGENEXP) (1.0, x); return x; });
-      else
-        oct_fill_rande (len, v);
-      break;
-
-    case poisson_dist:
-      if (use_old_generators)
-        {
-          if (a < 0.0 || ! octave::math::isfinite (a))
-            std::fill_n (v, len, octave::numeric_limits<double>::NaN ());
-          else
-            {
-              // workaround bug in ignpoi, by calling with different Mu
-              double tmp;
-              F77_FUNC (dignpoi, DIGNPOI) (a + 1, tmp);
-              std::generate_n (v, len, [a](void) { double x; F77_FUNC (dignpoi, DIGNPOI) (a, x); return x; });
-            }
-        }
-      else
-        oct_fill_randp (a, len, v);
-      break;
-
-    case gamma_dist:
-      if (use_old_generators)
-        {
-          if (a <= 0.0 || ! octave::math::isfinite (a))
-            std::fill_n (v, len, octave::numeric_limits<double>::NaN ());
-          else
-            std::generate_n (v, len, [a](void) { double x; F77_FUNC (dgengam, DGENGAM) (1.0, a, x); return x; });
-        }
-      else
-        oct_fill_randg (a, len, v);
-      break;
-
-    default:
-      (*current_liboctave_error_handler)
-        ("rand: invalid distribution ID = %d", current_distribution);
-      break;
-    }
-
-  save_state ();
-
-  return;
-}
-
-void
-octave_rand::fill (octave_idx_type len, float *v, float a)
-{
-  if (len < 1)
-    return;
-
-  switch (current_distribution)
-    {
-    case uniform_dist:
-      if (use_old_generators)
-        std::generate_n (v, len, [](void) { float x; F77_FUNC (fgenunf, FGENUNF) (0.0f, 1.0f, x); return x; });
-      else
-        oct_fill_float_randu (len, v);
-      break;
-
-    case normal_dist:
-      if (use_old_generators)
-        std::generate_n (v, len, [](void) { float x; F77_FUNC (fgennor, FGENNOR) (0.0f, 1.0f, x); return x; });
-      else
-        oct_fill_float_randn (len, v);
-      break;
-
-    case expon_dist:
-      if (use_old_generators)
-        std::generate_n (v, len, [](void) { float x; F77_FUNC (fgenexp, FGENEXP) (1.0f, x); return x; });
-      else
-        oct_fill_float_rande (len, v);
-      break;
-
-    case poisson_dist:
-      if (use_old_generators)
-        {
-          if (a < 0.0f || ! octave::math::isfinite (a))
-            std::fill_n (v, len, octave::numeric_limits<float>::NaN ());
-          else
-            {
-              // workaround bug in ignpoi, by calling with different Mu
-              float tmp;
-              F77_FUNC (fignpoi, FIGNPOI) (a + 1, tmp);
-              std::generate_n (v, len, [a](void) { float x; F77_FUNC (fignpoi, FIGNPOI) (a, x); return x; });
-            }
-        }
-      else
-        oct_fill_float_randp (a, len, v);
-      break;
-
-    case gamma_dist:
-      if (use_old_generators)
-        {
-          if (a <= 0.0f || ! octave::math::isfinite (a))
-            std::fill_n (v, len, octave::numeric_limits<float>::NaN ());
-          else
-            std::generate_n (v, len, [a](void) { float x; F77_FUNC (fgengam, FGENGAM) (1.0f, a, x); return x; });
-        }
-      else
-        oct_fill_float_randg (a, len, v);
-      break;
-
-    default:
-      (*current_liboctave_error_handler)
-        ("rand: invalid distribution ID = %d", current_distribution);
-      break;
-    }
-
-  save_state ();
-
-  return;
-}
--- a/liboctave/numeric/oct-rand.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/numeric/oct-rand.h	Fri Aug 10 09:09:51 2018 +0200
@@ -36,247 +36,262 @@
 
 //class dim_vector;
 
-class
-OCTAVE_API
-octave_rand
+namespace octave
 {
-protected:
-
-  octave_rand (void);
-
-public:
-
-  ~octave_rand (void) = default;
-
-  static bool instance_ok (void);
-
-  // Return the current seed.
-  static double seed (void)
-  {
-    return instance_ok () ? instance->do_seed ()
-                          : octave::numeric_limits<double>::NaN ();
-  }
-
-  // Set the seed.
-  static void seed (double s)
-  {
-    if (instance_ok ())
-      instance->do_seed (s);
-  }
-
-  // Reset the seed.
-  static void reset (void)
-  {
-    if (instance_ok ())
-      instance->do_reset ();
-  }
-
-  // Return the current state.
-  static uint32NDArray state (const std::string& d = "")
-  {
-    return instance_ok () ? instance->do_state (d) : uint32NDArray ();
-  }
-
-  // Set the current state/
-  static void state (const uint32NDArray& s,
-                     const std::string& d = "")
-  {
-    if (instance_ok ())
-      instance->do_state (s, d);
-  }
-
-  // Reset the current state/
-  static void reset (const std::string& d)
-  {
-    if (instance_ok ())
-      instance->do_reset (d);
-  }
-
-  // Return the current distribution.
-  static std::string distribution (void)
+  class OCTAVE_API rand
   {
-    return instance_ok () ? instance->do_distribution () : "";
-  }
+  protected:
+
+    rand (void);
+
+  public:
+
+    ~rand (void) = default;
+
+    static bool instance_ok (void);
 
-  // Set the current distribution.  May be either "uniform" (the
-  // default), "normal", "exponential", "poisson", or "gamma".
-  static void distribution (const std::string& d)
-  {
-    if (instance_ok ())
-      instance->do_distribution (d);
-  }
+    // Return the current seed.
+    static double seed (void)
+    {
+      return instance_ok () ? instance->do_seed ()
+        : octave::numeric_limits<double>::NaN ();
+    }
+
+    // Set the seed.
+    static void seed (double s)
+    {
+      if (instance_ok ())
+        instance->do_seed (s);
+    }
 
-  static void uniform_distribution (void)
-  {
-    if (instance_ok ())
-      instance->do_uniform_distribution ();
-  }
+    // Reset the seed.
+    static void reset (void)
+    {
+      if (instance_ok ())
+        instance->do_reset ();
+    }
+
+    // Return the current state.
+    static uint32NDArray state (const std::string& d = "")
+    {
+      return instance_ok () ? instance->do_state (d) : uint32NDArray ();
+    }
 
-  static void normal_distribution (void)
-  {
-    if (instance_ok ())
-      instance->do_normal_distribution ();
-  }
+    // Set the current state/
+    static void state (const uint32NDArray& s,
+                       const std::string& d = "")
+    {
+      if (instance_ok ())
+        instance->do_state (s, d);
+    }
 
-  static void exponential_distribution (void)
-  {
-    if (instance_ok ())
-      instance->do_exponential_distribution ();
-  }
+    // Reset the current state/
+    static void reset (const std::string& d)
+    {
+      if (instance_ok ())
+        instance->do_reset (d);
+    }
+
+    // Return the current distribution.
+    static std::string distribution (void)
+    {
+      return instance_ok () ? instance->do_distribution () : "";
+    }
 
-  static void poisson_distribution (void)
-  {
-    if (instance_ok ())
-      instance->do_poisson_distribution ();
-  }
+    // Set the current distribution.  May be either "uniform" (the
+    // default), "normal", "exponential", "poisson", or "gamma".
+    static void distribution (const std::string& d)
+    {
+      if (instance_ok ())
+        instance->do_distribution (d);
+    }
+
+    static void uniform_distribution (void)
+    {
+      if (instance_ok ())
+        instance->do_uniform_distribution ();
+    }
 
-  static void gamma_distribution (void)
-  {
-    if (instance_ok ())
-      instance->do_gamma_distribution ();
-  }
+    static void normal_distribution (void)
+    {
+      if (instance_ok ())
+        instance->do_normal_distribution ();
+    }
+
+    static void exponential_distribution (void)
+    {
+      if (instance_ok ())
+        instance->do_exponential_distribution ();
+    }
+
+    static void poisson_distribution (void)
+    {
+      if (instance_ok ())
+        instance->do_poisson_distribution ();
+    }
 
-  // Return the next number from the sequence.
-  static double scalar (double a = 1.0)
-  {
-    return instance_ok () ? instance->do_scalar (a)
-                          : octave::numeric_limits<double>::NaN ();
-  }
+    static void gamma_distribution (void)
+    {
+      if (instance_ok ())
+        instance->do_gamma_distribution ();
+    }
+
+    // Return the next number from the sequence.
+    static double scalar (double a = 1.0)
+    {
+      return instance_ok () ? instance->do_scalar (a)
+        : octave::numeric_limits<double>::NaN ();
+    }
 
-  // Return the next number from the sequence.
-  static float float_scalar (float a = 1.0)
-  {
-    return instance_ok () ? instance->do_float_scalar (a)
-                          : octave::numeric_limits<float>::NaN ();
-  }
+    // Return the next number from the sequence.
+    static float float_scalar (float a = 1.0)
+    {
+      return instance_ok () ? instance->do_scalar (a)
+        : octave::numeric_limits<float>::NaN ();
+    }
 
-  // Return an array of numbers from the sequence.
-  static Array<double> vector (octave_idx_type n, double a = 1.0)
-  {
-    return instance_ok () ? instance->do_vector (n, a) : Array<double> ();
-  }
+    // Return an array of numbers from the sequence.
+    static Array<double> vector (octave_idx_type n, double a = 1.0)
+    {
+      return instance_ok () ? instance->do_vector (n, a) : Array<double> ();
+    }
+
+    // Return an array of numbers from the sequence.
+    static Array<float> float_vector (octave_idx_type n, float a = 1.0)
+    {
+      return instance_ok () ? instance->do_vector (n, a) : Array<float> ();
+    }
 
-  // Return an array of numbers from the sequence.
-  static Array<float> float_vector (octave_idx_type n, float a = 1.0)
-  {
-    return instance_ok () ? instance->do_float_vector (n, a) : Array<float> ();
-  }
+    // Return an N-dimensional array of numbers from the sequence,
+    // filled in column major order.
+    static NDArray nd_array (const dim_vector& dims, double a = 1.0)
+    {
+      return instance_ok () ? instance->do_nd_array (dims, a) : NDArray ();
+    }
 
-  // Return an N-dimensional array of numbers from the sequence,
-  // filled in column major order.
-  static NDArray nd_array (const dim_vector& dims, double a = 1.0)
-  {
-    return instance_ok () ? instance->do_nd_array (dims, a) : NDArray ();
-  }
+    // Return an N-dimensional array of numbers from the sequence,
+    // filled in column major order.
+    static FloatNDArray float_nd_array (const dim_vector& dims, float a = 1.0)
+    {
+      return instance_ok () ? instance->do_float_nd_array (dims, a)
+        : FloatNDArray ();
+    }
 
-  // Return an N-dimensional array of numbers from the sequence,
-  // filled in column major order.
-  static FloatNDArray float_nd_array (const dim_vector& dims, float a = 1.0)
-  {
-    return instance_ok () ? instance->do_float_nd_array (dims, a)
-                          : FloatNDArray ();
-  }
+  private:
+
+    static rand *instance;
+
+    static void cleanup_instance (void) { delete instance; instance = nullptr; }
 
-private:
-
-  static octave_rand *instance;
-
-  static void cleanup_instance (void) { delete instance; instance = nullptr; }
+    enum
+    {
+      unknown_dist,
+      uniform_dist,
+      normal_dist,
+      expon_dist,
+      poisson_dist,
+      gamma_dist
+    };
 
-  enum
-  {
-    unknown_dist,
-    uniform_dist,
-    normal_dist,
-    expon_dist,
-    poisson_dist,
-    gamma_dist
-  };
+    // Current distribution of random numbers.
+    int current_distribution;
 
-  // Current distribution of random numbers.
-  int current_distribution;
+    // If TRUE, use old RANLIB generators.  Otherwise, use Mersenne
+    // Twister generator.
+    bool use_old_generators;
+
+    // Saved MT states.
+    std::map<int, uint32NDArray> rand_states;
+
+    // Return the current seed.
+    double do_seed (void);
 
-  // If TRUE, use old RANLIB generators.  Otherwise, use Mersenne
-  // Twister generator.
-  bool use_old_generators;
+    // Set the seed.
+    void do_seed (double s);
 
-  // Saved MT states.
-  std::map<int, uint32NDArray> rand_states;
+    // Reset the seed.
+    void do_reset ();
+
+    // Return the current state.
+    uint32NDArray do_state (const std::string& d);
 
-  // Return the current seed.
-  double do_seed (void);
-
-  // Set the seed.
-  void do_seed (double s);
+    // Set the current state/
+    void do_state (const uint32NDArray& s, const std::string& d);
 
-  // Reset the seed.
-  void do_reset ();
+    // Reset the current state/
+    void do_reset (const std::string& d);
 
-  // Return the current state.
-  uint32NDArray do_state (const std::string& d);
+    // Return the current distribution.
+    std::string do_distribution (void);
 
-  // Set the current state/
-  void do_state (const uint32NDArray& s, const std::string& d);
+    // Set the current distribution.  May be either "uniform" (the
+    // default), "normal", "exponential", "poisson", or "gamma".
+    void do_distribution (const std::string& d);
 
-  // Reset the current state/
-  void do_reset (const std::string& d);
+    void do_uniform_distribution (void);
 
-  // Return the current distribution.
-  std::string do_distribution (void);
+    void do_normal_distribution (void);
+
+    void do_exponential_distribution (void);
 
-  // Set the current distribution.  May be either "uniform" (the
-  // default), "normal", "exponential", "poisson", or "gamma".
-  void do_distribution (const std::string& d);
+    void do_poisson_distribution (void);
 
-  void do_uniform_distribution (void);
+    void do_gamma_distribution (void);
 
-  void do_normal_distribution (void);
-
-  void do_exponential_distribution (void);
+    // The following templates only make sense for double and float
+    // types.
 
-  void do_poisson_distribution (void);
+    template <typename T> T uniform (void);
 
-  void do_gamma_distribution (void);
+    template <typename T> T normal (void);
+
+    template <typename T> T exponential (void);
 
-  // Return the next number from the sequence.
-  double do_scalar (double a = 1.);
+    template <typename T> T poisson (T a);
+
+    template <typename T> T gamma (T a);
 
-  // Return the next number from the sequence.
-  float do_float_scalar (float a = 1.);
+    // Return the next number from the sequence.
+    template <typename T> T do_scalar (T a = 1);
 
-  // Return an array of numbers from the sequence.
-  Array<double> do_vector (octave_idx_type n, double a = 1.);
+    // Return an array of numbers from the sequence.
+    template <typename T> Array<T> do_vector (octave_idx_type n, T a = 1);
 
-  // Return an array of numbers from the sequence.
-  Array<float> do_float_vector (octave_idx_type n, float a = 1.);
+    // Return an N-dimensional array of numbers from the sequence,
+    // filled in column major order.
+    NDArray do_nd_array (const dim_vector& dims, double a = 1.);
 
-  // Return an N-dimensional array of numbers from the sequence,
-  // filled in column major order.
-  NDArray do_nd_array (const dim_vector& dims, double a = 1.);
+    // Return an N-dimensional array of numbers from the sequence,
+    // filled in column major order.
+    FloatNDArray do_float_nd_array (const dim_vector& dims, float a = 1.);
 
-  // Return an N-dimensional array of numbers from the sequence,
-  // filled in column major order.
-  FloatNDArray do_float_nd_array (const dim_vector& dims, float a = 1.);
+    // Some helper functions.
+
+    void initialize_ranlib_generators (void);
 
-  // Some helper functions.
+    void initialize_mersenne_twister (void);
 
-  void initialize_ranlib_generators (void);
+    uint32NDArray get_internal_state (void);
 
-  void initialize_mersenne_twister (void);
+    void save_state (void);
 
-  uint32NDArray get_internal_state (void);
+    int get_dist_id (const std::string& d);
 
-  void save_state (void);
+    void set_internal_state (const uint32NDArray& s);
 
-  int get_dist_id (const std::string& d);
+    void switch_to_generator (int dist);
 
-  void set_internal_state (const uint32NDArray& s);
-
-  void switch_to_generator (int dist);
+    void fill (octave_idx_type len, double *v, double a);
 
-  void fill (octave_idx_type len, double *v, double a);
+    void fill (octave_idx_type len, float *v, float a);
+  };
+}
 
-  void fill (octave_idx_type len, float *v, float a);
-};
+#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
+
+OCTAVE_DEPRECATED (4.4, "use 'octave::rand' instead")
+typedef octave::rand octave_rand;
 
 #endif
+
+#endif
--- a/liboctave/numeric/randgamma.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/numeric/randgamma.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -87,110 +87,47 @@
 #include "randgamma.h"
 #include "randmtzig.h"
 
-#define INFINITE lo_ieee_isinf
-#define RUNI oct_randu()
-#define RNOR oct_randn()
-#define REXP oct_rande()
-
-void
-oct_fill_randg (double a, octave_idx_type n, double *r)
+namespace octave
 {
-  octave_idx_type i;
-  /* If a < 1, start by generating gamma (1+a) */
-  const double d = (a < 1. ? 1.+a : a) - 1./3.;
-  const double c = 1./std::sqrt (9.*d);
-
-  /* Handle invalid cases */
-  if (a <= 0 || INFINITE(a))
-    {
-      for (i=0; i < n; i++)
-        r[i] = octave::numeric_limits<double>::NaN ();
-      return;
-    }
+  template <typename T> void rand_gamma (T a, octave_idx_type n, T *r)
+  {
+    octave_idx_type i;
+    /* If a < 1, start by generating gamma (1+a) */
+    const T d = (a < 1. ? 1.+a : a) - 1./3.;
+    const T c = 1./std::sqrt (9.*d);
 
-  for (i=0; i < n; i++)
-    {
-      double x, xsq, v, u;
-    restart:
-      x = RNOR;
-      v = (1+c*x);
-      v *= v*v;
-      if (v <= 0)
-        goto restart; /* rare, so don't bother moving up */
-      u = RUNI;
-      xsq = x*x;
-      if (u >= 1.-0.0331*xsq*xsq && std::log (u) >= 0.5*xsq + d*(1-v+std::log (v)))
-        goto restart;
-      r[i] = d*v;
-    }
-  if (a < 1)
-    {
-      /* Use gamma(a) = gamma(1+a)*U^(1/a) */
-      /* Given REXP = -log(U) then U^(1/a) = exp(-REXP/a) */
-      for (i = 0; i < n; i++)
-        r[i] *= exp (-REXP/a);
-    }
-}
-
-double
-oct_randg (double a)
-{
-  double ret;
-  oct_fill_randg (a,1,&ret);
-  return ret;
-}
+    /* Handle invalid cases */
+    if (a <= 0 || lo_ieee_isinf (a))
+      {
+        for (i=0; i < n; i++)
+          r[i] = numeric_limits<T>::NaN ();
+        return;
+      }
 
-#undef RUNI
-#undef RNOR
-#undef REXP
-#define RUNI oct_float_randu()
-#define RNOR oct_float_randn()
-#define REXP oct_float_rande()
-
-void
-oct_fill_float_randg (float a, octave_idx_type n, float *r)
-{
-  octave_idx_type i;
-  /* If a < 1, start by generating gamma(1+a) */
-  const float d = (a < 1. ? 1.+a : a) - 1./3.;
-  const float c = 1./std::sqrt (9.*d);
-
-  /* Handle invalid cases */
-  if (a <= 0 || INFINITE(a))
-    {
-      for (i=0; i < n; i++)
-        r[i] = octave::numeric_limits<float>::NaN ();
-      return;
-    }
+    for (i=0; i < n; i++)
+      {
+        T x, xsq, v, u;
+      restart:
+        x = rand_normal<T> ();
+        v = (1+c*x);
+        v *= v*v;
+        if (v <= 0)
+          goto restart; /* rare, so don't bother moving up */
+        u = rand_uniform<T> ();
+        xsq = x*x;
+        if (u >= 1.-0.0331*xsq*xsq && std::log (u) >= 0.5*xsq + d*(1-v+std::log (v)))
+          goto restart;
+        r[i] = d*v;
+      }
+    if (a < 1)
+      {
+        /* Use gamma(a) = gamma(1+a)*U^(1/a) */
+        /* Given REXP = -log(U) then U^(1/a) = exp(-REXP/a) */
+        for (i = 0; i < n; i++)
+          r[i] *= exp (-rand_exponential<T> () / a);
+      }
+  }
 
-  for (i=0; i < n; i++)
-    {
-      float x, xsq, v, u;
-    frestart:
-      x = RNOR;
-      v = (1+c*x);
-      v *= v*v;
-      if (v <= 0)
-        goto frestart; /* rare, so don't bother moving up */
-      u = RUNI;
-      xsq = x*x;
-      if (u >= 1.-0.0331*xsq*xsq && std::log (u) >= 0.5*xsq + d*(1-v+std::log (v)))
-        goto frestart;
-      r[i] = d*v;
-    }
-  if (a < 1)
-    {
-      /* Use gamma(a) = gamma(1+a)*U^(1/a) */
-      /* Given REXP = -log(U) then U^(1/a) = exp(-REXP/a) */
-      for (i = 0; i < n; i++)
-        r[i] *= exp (-REXP/a);
-    }
+  template void rand_gamma (double, octave_idx_type, double *);
+  template void rand_gamma (float, octave_idx_type, float *);
 }
-
-float
-oct_float_randg (float a)
-{
-  float ret;
-  oct_fill_float_randg (a,1,&ret);
-  return ret;
-}
--- a/liboctave/numeric/randgamma.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/numeric/randgamma.h	Fri Aug 10 09:09:51 2018 +0200
@@ -28,11 +28,48 @@
 
 #include "octave-config.h"
 
-extern OCTAVE_API double oct_randg (double a);
-extern OCTAVE_API void oct_fill_randg (double a, octave_idx_type n, double *p);
+namespace octave
+{
+  template <typename T>
+  void
+  rand_gamma (T a, octave_idx_type n, T *p);
+
+  template <typename T>
+  T
+  rand_gamma (T a)
+  {
+    T retval;
+    rand_gamma (a, 1, &retval);
+    return retval;
+  }
+}
 
-extern OCTAVE_API float oct_float_randg (float a);
-extern OCTAVE_API void oct_fill_float_randg (float a, octave_idx_type n,
-                                             float *p);
+OCTAVE_DEPRECATED (4.4, "use 'octave::rand_gamma<double>' instead")
+inline double
+oct_randg (double a)
+{
+  return octave::rand_gamma (a);
+}
+
+OCTAVE_DEPRECATED (4.4, "use 'octave::rand_gamma<float>' instead")
+inline float
+oct_float_randg (float a)
+{
+  return octave::rand_gamma (a);
+}
+
+OCTAVE_DEPRECATED (4.4, "use 'octave::rand_gamma<double>' instead")
+inline void
+oct_fill_randg (double a, octave_idx_type n, double *p)
+{
+  octave::rand_gamma (a, n, p);
+}
+
+OCTAVE_DEPRECATED (4.4, "use 'octave::rand_gamma<float>' instead")
+inline void
+oct_fill_float_randg (float a, octave_idx_type n, float *p)
+{
+  octave::rand_gamma (a, n, p);
+}
 
 #endif
--- a/liboctave/numeric/randmtzig.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/numeric/randmtzig.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -112,16 +112,26 @@
 
    === Usage instructions ===
    Before using any of the generators, initialize the state with one of
-   oct_init_by_int, oct_init_by_array or oct_init_by_entropy.
+   the init_mersenne_twister functions.
 
    All generators share the same state vector.
 
    === Mersenne Twister ===
-   void oct_init_by_int (uint32_t s)           32-bit initial state
-   void oct_init_by_array (uint32_t k[],int m) m*32-bit initial state
-   void oct_init_by_entropy (void)             random initial state
-   void oct_get_state (uint32_t save[MT_N+1])  saves state in array
-   void oct_set_state (uint32_t save[MT_N+1])  restores state from array
+   random initial state:
+   void init_mersenne_twister (void)
+
+   // 32-bit initial state:
+   void init_mersenne_twister (uint32_t s)
+
+   // m*32-bit initial state:
+   void init_mersenne_twister (uint32_t k[],int m)
+
+   // saves state in array:
+   void get_mersenne_twister_state (uint32_t save[MT_N+1])
+
+   // restores state from array
+   void set_mersenne_twister_state (uint32_t save[MT_N+1])
+
    static uint32_t randmt (void)               returns 32-bit unsigned int
 
    === inline generators ===
@@ -131,22 +141,14 @@
    static float randu32 (void)      returns 32-bit uniform in (0,1)
    static double randu53 (void)     returns 53-bit uniform in (0,1)
 
-   double oct_randu (void)       returns M-bit uniform in (0,1)
-   double oct_randn (void)       returns M-bit standard normal
-   double oct_rande (void)       returns N-bit standard exponential
-
-   float oct_float_randu (void)       returns M-bit uniform in (0,1)
-   float oct_float_randn (void)       returns M-bit standard normal
-   float oct_float_rande (void)       returns N-bit standard exponential
+   double rand_uniform (void)       returns M-bit uniform in (0,1)
+   double rand_normal (void)        returns M-bit standard normal
+   double rand_exponential (void)   returns N-bit standard exponential
 
    === Array generators ===
-   void oct_fill_randu (octave_idx_type, double [])
-   void oct_fill_randn (octave_idx_type, double [])
-   void oct_fill_rande (octave_idx_type, double [])
-
-   void oct_fill_float_randu (octave_idx_type, float [])
-   void oct_fill_float_randn (octave_idx_type, float [])
-   void oct_fill_float_rande (octave_idx_type, float [])
+   void rand_uniform (octave_idx_type, double [])
+   void rand_normal (octave_idx_type, double [])
+   void rand_exponential (octave_idx_type, double [])
 */
 
 #if defined (HAVE_CONFIG_H)
@@ -170,7 +172,9 @@
 #  endif
 #endif
 
-/* ===== Mersenne Twister 32-bit generator ===== */
+namespace octave
+{
+  /* ===== Mersenne Twister 32-bit generator ===== */
 
 #define MT_M 397
 #define MATRIX_A 0x9908b0dfUL   /* constant vector a */
@@ -179,240 +183,231 @@
 #define MIXBITS(u,v) ( ((u) & UMASK) | ((v) & LMASK) )
 #define TWIST(u,v) ((MIXBITS(u,v) >> 1) ^ ((v)&1UL ? MATRIX_A : 0UL))
 
-static uint32_t *next;
-static uint32_t state[MT_N]; /* the array for the state vector  */
-static int left = 1;
-static int initf = 0;
-static int initt = 1;
-static int inittf = 1;
+  static uint32_t *next;
+  static uint32_t state[MT_N]; /* the array for the state vector  */
+  static int left = 1;
+  static int initf = 0;
+  static int initt = 1;
+  static int inittf = 1;
 
-/* initializes state[MT_N] with a seed */
-void
-oct_init_by_int (const uint32_t s)
-{
-  int j;
-  state[0] = s & 0xffffffffUL;
-  for (j = 1; j < MT_N; j++)
-    {
-      state[j] = (1812433253UL * (state[j-1] ^ (state[j-1] >> 30)) + j);
-      /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
-      /* In the previous versions, MSBs of the seed affect   */
-      /* only MSBs of the array state[].                        */
-      /* 2002/01/09 modified by Makoto Matsumoto             */
-      state[j] &= 0xffffffffUL;  /* for >32 bit machines */
-    }
-  left = 1;
-  initf = 1;
-}
+  /* initializes state[MT_N] with a seed */
+  void init_mersenne_twister (const uint32_t s)
+  {
+    int j;
+    state[0] = s & 0xffffffffUL;
+    for (j = 1; j < MT_N; j++)
+      {
+        state[j] = (1812433253UL * (state[j-1] ^ (state[j-1] >> 30)) + j);
+        /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
+        /* In the previous versions, MSBs of the seed affect   */
+        /* only MSBs of the array state[].                        */
+        /* 2002/01/09 modified by Makoto Matsumoto             */
+        state[j] &= 0xffffffffUL;  /* for >32 bit machines */
+      }
+    left = 1;
+    initf = 1;
+  }
 
-/* initialize by an array with array-length */
-/* init_key is the array for initializing keys */
-/* key_length is its length */
-void
-oct_init_by_array (const uint32_t *init_key, const int key_length)
-{
-  int i, j, k;
-  oct_init_by_int (19650218UL);
-  i = 1;
-  j = 0;
-  k = (MT_N > key_length ? MT_N : key_length);
-  for (; k; k--)
-    {
-      state[i] = (state[i] ^ ((state[i-1] ^ (state[i-1] >> 30)) * 1664525UL))
-                 + init_key[j] + j; /* non linear */
-      state[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
-      i++;
-      j++;
-      if (i >= MT_N)
-        {
-          state[0] = state[MT_N-1];
-          i = 1;
-        }
-      if (j >= key_length)
-        j = 0;
-    }
-  for (k = MT_N - 1; k; k--)
-    {
-      state[i] = (state[i] ^ ((state[i-1] ^ (state[i-1] >> 30)) * 1566083941UL))
-                 - i; /* non linear */
-      state[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
-      i++;
-      if (i >= MT_N)
-        {
-          state[0] = state[MT_N-1];
-          i = 1;
-        }
-    }
+  /* initialize by an array with array-length */
+  /* init_key is the array for initializing keys */
+  /* key_length is its length */
+  void init_mersenne_twister (const uint32_t *init_key, const int key_length)
+  {
+    int i, j, k;
+    init_mersenne_twister (19650218UL);
+    i = 1;
+    j = 0;
+    k = (MT_N > key_length ? MT_N : key_length);
+    for (; k; k--)
+      {
+        state[i] = (state[i] ^ ((state[i-1] ^ (state[i-1] >> 30)) * 1664525UL))
+          + init_key[j] + j; /* non linear */
+        state[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
+        i++;
+        j++;
+        if (i >= MT_N)
+          {
+            state[0] = state[MT_N-1];
+            i = 1;
+          }
+        if (j >= key_length)
+          j = 0;
+      }
+    for (k = MT_N - 1; k; k--)
+      {
+        state[i] = (state[i] ^ ((state[i-1] ^ (state[i-1] >> 30)) * 1566083941UL))
+          - i; /* non linear */
+        state[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
+        i++;
+        if (i >= MT_N)
+          {
+            state[0] = state[MT_N-1];
+            i = 1;
+          }
+      }
 
-  state[0] = 0x80000000UL; /* MSB is 1; assuring nonzero initial array */
-  left = 1;
-  initf = 1;
-}
+    state[0] = 0x80000000UL; /* MSB is 1; assuring nonzero initial array */
+    left = 1;
+    initf = 1;
+  }
 
-void
-oct_init_by_entropy (void)
-{
-  uint32_t entropy[MT_N];
-  int n = 0;
+  void init_mersenne_twister (void)
+  {
+    uint32_t entropy[MT_N];
+    int n = 0;
 
-  /* Look for entropy in /dev/urandom */
-  FILE *urandom = std::fopen ("/dev/urandom", "rb");
-  if (urandom)
-    {
-      while (n < MT_N)
-        {
-          unsigned char word[4];
-          if (std::fread (word, 4, 1, urandom) != 1)
-            break;
-          entropy[n++] = word[0] + (word[1]<<8) + (word[2]<<16)
-                         + (static_cast<uint32_t> (word[3])<<24);
-        }
-      std::fclose (urandom);
-    }
+    /* Look for entropy in /dev/urandom */
+    FILE *urandom = std::fopen ("/dev/urandom", "rb");
+    if (urandom)
+      {
+        while (n < MT_N)
+          {
+            unsigned char word[4];
+            if (std::fread (word, 4, 1, urandom) != 1)
+              break;
+            entropy[n++] = word[0] + (word[1]<<8) + (word[2]<<16)
+              + (static_cast<uint32_t> (word[3])<<24);
+          }
+        std::fclose (urandom);
+      }
 
-  /* If there isn't enough entropy, gather some from various sources */
+    /* If there isn't enough entropy, gather some from various sources */
 
-  octave::sys::time now;
+    octave::sys::time now;
 
-  if (n < MT_N)
-    entropy[n++] = now.unix_time (); /* Current time in seconds */
+    if (n < MT_N)
+      entropy[n++] = now.unix_time (); /* Current time in seconds */
 
-  if (n < MT_N)
-    entropy[n++] = clock ();    /* CPU time used (usec) */
+    if (n < MT_N)
+      entropy[n++] = clock ();    /* CPU time used (usec) */
 
-  if (n < MT_N)
-    entropy[n++] = now.usec ();   /* Fractional part of current time */
+    if (n < MT_N)
+      entropy[n++] = now.usec ();   /* Fractional part of current time */
 
-  /* Send all the entropy into the initial state vector */
-  oct_init_by_array (entropy,n);
-}
+    /* Send all the entropy into the initial state vector */
+    init_mersenne_twister (entropy,n);
+  }
 
-void
-oct_set_state (const uint32_t *save)
-{
-  std::copy_n (save, MT_N, state);
-  left = save[MT_N];
-  next = state + (MT_N - left + 1);
-}
+  void set_mersenne_twister_state (const uint32_t *save)
+  {
+    std::copy_n (save, MT_N, state);
+    left = save[MT_N];
+    next = state + (MT_N - left + 1);
+  }
 
-void
-oct_get_state (uint32_t *save)
-{
-  std::copy_n (state, MT_N, save);
-  save[MT_N] = left;
-}
+  void get_mersenne_twister_state (uint32_t *save)
+  {
+    std::copy_n (state, MT_N, save);
+    save[MT_N] = left;
+  }
 
-static void
-next_state (void)
-{
-  uint32_t *p = state;
-  int j;
+  static void next_state (void)
+  {
+    uint32_t *p = state;
+    int j;
 
-  /* if init_by_int() has not been called, */
-  /* a default initial seed is used         */
-  /* if (initf==0) init_by_int(5489UL); */
-  /* Or better yet, a random seed! */
-  if (initf == 0)
-    oct_init_by_entropy ();
+    /* if init_by_int() has not been called, */
+    /* a default initial seed is used         */
+    /* if (initf==0) init_by_int(5489UL); */
+    /* Or better yet, a random seed! */
+    if (initf == 0)
+      init_mersenne_twister ();
 
-  left = MT_N;
-  next = state;
+    left = MT_N;
+    next = state;
 
-  for (j = MT_N - MT_M + 1; --j; p++)
-    *p = p[MT_M] ^ TWIST(p[0], p[1]);
+    for (j = MT_N - MT_M + 1; --j; p++)
+      *p = p[MT_M] ^ TWIST(p[0], p[1]);
 
-  for (j = MT_M; --j; p++)
-    *p = p[MT_M-MT_N] ^ TWIST(p[0], p[1]);
-
-  *p = p[MT_M-MT_N] ^ TWIST(p[0], state[0]);
-}
+    for (j = MT_M; --j; p++)
+      *p = p[MT_M-MT_N] ^ TWIST(p[0], p[1]);
 
-/* generates a random number on [0,0xffffffff]-interval */
-static uint32_t
-randmt (void)
-{
-  uint32_t y;
+    *p = p[MT_M-MT_N] ^ TWIST(p[0], state[0]);
+  }
+
+  /* generates a random number on [0,0xffffffff]-interval */
+  static uint32_t randmt (void)
+  {
+    uint32_t y;
 
-  if (--left == 0)
-    next_state ();
-  y = *next++;
+    if (--left == 0)
+      next_state ();
+    y = *next++;
 
-  /* Tempering */
-  y ^= (y >> 11);
-  y ^= (y << 7) & 0x9d2c5680UL;
-  y ^= (y << 15) & 0xefc60000UL;
-  return (y ^ (y >> 18));
-}
+    /* Tempering */
+    y ^= (y >> 11);
+    y ^= (y << 7) & 0x9d2c5680UL;
+    y ^= (y << 15) & 0xefc60000UL;
+    return (y ^ (y >> 18));
+  }
 
-/* ===== Uniform generators ===== */
+  /* ===== Uniform generators ===== */
 
-/* Select which 32 bit generator to use */
+  /* Select which 32 bit generator to use */
 #define randi32 randmt
 
-static uint64_t
-randi53 (void)
-{
-  const uint32_t lo = randi32 ();
-  const uint32_t hi = randi32 () & 0x1FFFFF;
+  static uint64_t randi53 (void)
+  {
+    const uint32_t lo = randi32 ();
+    const uint32_t hi = randi32 () & 0x1FFFFF;
 #if defined (HAVE_X86_32)
-  uint64_t u;
-  uint32_t *p = (uint32_t *)&u;
-  p[0] = lo;
-  p[1] = hi;
-  return u;
+    uint64_t u;
+    uint32_t *p = (uint32_t *)&u;
+    p[0] = lo;
+    p[1] = hi;
+    return u;
 #else
-  return ((static_cast<uint64_t> (hi) << 32) | lo);
+    return ((static_cast<uint64_t> (hi) << 32) | lo);
 #endif
-}
+  }
 
-static uint64_t
-randi54 (void)
-{
-  const uint32_t lo = randi32 ();
-  const uint32_t hi = randi32 () & 0x3FFFFF;
+  static uint64_t randi54 (void)
+  {
+    const uint32_t lo = randi32 ();
+    const uint32_t hi = randi32 () & 0x3FFFFF;
 #if defined (HAVE_X86_32)
-  uint64_t u;
-  uint32_t *p = static_cast<uint32_t *> (&u);
-  p[0] = lo;
-  p[1] = hi;
-  return u;
+    uint64_t u;
+    uint32_t *p = static_cast<uint32_t *> (&u);
+    p[0] = lo;
+    p[1] = hi;
+    return u;
 #else
-  return ((static_cast<uint64_t> (hi) << 32) | lo);
+    return ((static_cast<uint64_t> (hi) << 32) | lo);
 #endif
-}
+  }
 
-/* generates a random number on (0,1)-real-interval */
-static float
-randu32 (void)
-{
-  return (static_cast<float> (randi32 ()) + 0.5) * (1.0/4294967296.0);
-  /* divided by 2^32 */
-}
+  /* generates a random number on (0,1)-real-interval */
+  static float randu32 (void)
+  {
+    return (static_cast<float> (randi32 ()) + 0.5) * (1.0/4294967296.0);
+    /* divided by 2^32 */
+  }
+
+  /* generates a random number on (0,1) with 53-bit resolution */
+  static double randu53 (void)
+  {
+    const uint32_t a = randi32 () >> 5;
+    const uint32_t b = randi32 () >> 6;
+    return (a*67108864.0+b+0.4) * (1.0/9007199254740992.0);
+  }
 
-/* generates a random number on (0,1) with 53-bit resolution */
-static double
-randu53 (void)
-{
-  const uint32_t a = randi32 () >> 5;
-  const uint32_t b = randi32 () >> 6;
-  return (a*67108864.0+b+0.4) * (1.0/9007199254740992.0);
-}
+  /* Determine mantissa for uniform doubles */
+  template <>
+  double
+  rand_uniform<double> (void)
+  {
+    return randu53 ();
+  }
 
-/* Determine mantissa for uniform doubles */
-double
-oct_randu (void)
-{
-  return randu53 ();
-}
+  /* Determine mantissa for uniform floats */
+  template <>
+  float
+  rand_uniform<float> (void)
+  {
+    return randu32 ();
+  }
 
-/* Determine mantissa for uniform floats */
-float
-oct_float_randu (void)
-{
-  return randu32 ();
-}
-
-/* ===== Ziggurat normal and exponential generators ===== */
+  /* ===== Ziggurat normal and exponential generators ===== */
 
 #define ZIGGURAT_TABLE_SIZE 256
 
@@ -431,219 +426,232 @@
 #define NRANDI randi54() /* 53 bits for mantissa + 1 bit sign */
 #define RANDU randu53()
 
-static ZIGINT ki[ZIGGURAT_TABLE_SIZE];
-static double wi[ZIGGURAT_TABLE_SIZE], fi[ZIGGURAT_TABLE_SIZE];
-static ZIGINT ke[ZIGGURAT_TABLE_SIZE];
-static double we[ZIGGURAT_TABLE_SIZE], fe[ZIGGURAT_TABLE_SIZE];
+  static ZIGINT ki[ZIGGURAT_TABLE_SIZE];
+  static double wi[ZIGGURAT_TABLE_SIZE], fi[ZIGGURAT_TABLE_SIZE];
+  static ZIGINT ke[ZIGGURAT_TABLE_SIZE];
+  static double we[ZIGGURAT_TABLE_SIZE], fe[ZIGGURAT_TABLE_SIZE];
+
+  /*
+    This code is based on the paper Marsaglia and Tsang, "The ziggurat method
+    for generating random variables", Journ. Statistical Software. Code was
+    presented in this paper for a Ziggurat of 127 levels and using a 32 bit
+    integer random number generator. This version of the code, uses the
+    Mersenne Twister as the integer generator and uses 256 levels in the
+    Ziggurat. This has several advantages.
 
-/*
-This code is based on the paper Marsaglia and Tsang, "The ziggurat method
-for generating random variables", Journ. Statistical Software. Code was
-presented in this paper for a Ziggurat of 127 levels and using a 32 bit
-integer random number generator. This version of the code, uses the
-Mersenne Twister as the integer generator and uses 256 levels in the
-Ziggurat. This has several advantages.
+    1) As Marsaglia and Tsang themselves states, the more levels the few
+    times the expensive tail algorithm must be called
+    2) The cycle time of the generator is determined by the integer
+    generator, thus the use of a Mersenne Twister for the core random
+    generator makes this cycle extremely long.
+    3) The license on the original code was unclear, thus rewriting the code
+    from the article means we are free of copyright issues.
+    4) Compile flag for full 53-bit random mantissa.
 
-  1) As Marsaglia and Tsang themselves states, the more levels the few
-     times the expensive tail algorithm must be called
-  2) The cycle time of the generator is determined by the integer
-     generator, thus the use of a Mersenne Twister for the core random
-     generator makes this cycle extremely long.
-  3) The license on the original code was unclear, thus rewriting the code
-     from the article means we are free of copyright issues.
-  4) Compile flag for full 53-bit random mantissa.
+    It should be stated that the authors made my life easier, by the fact that
+    the algorithm developed in the text of the article is for a 256 level
+    ziggurat, even if the code itself isn't...
 
-It should be stated that the authors made my life easier, by the fact that
-the algorithm developed in the text of the article is for a 256 level
-ziggurat, even if the code itself isn't...
-
-One modification to the algorithm developed in the article, is that it is
-assumed that 0 <= x < Inf, and "unsigned long"s are used, thus resulting in
-terms like 2^32 in the code. As the normal distribution is defined between
--Inf < x < Inf, we effectively only have 31 bit integers plus a sign. Thus
-in Marsaglia and Tsang, terms like 2^32 become 2^31. We use NMANTISSA for
-this term.  The exponential distribution is one sided so we use the
-full 32 bits.  We use EMANTISSA for this term.
+    One modification to the algorithm developed in the article, is that it is
+    assumed that 0 <= x < Inf, and "unsigned long"s are used, thus resulting in
+    terms like 2^32 in the code. As the normal distribution is defined between
+    -Inf < x < Inf, we effectively only have 31 bit integers plus a sign. Thus
+    in Marsaglia and Tsang, terms like 2^32 become 2^31. We use NMANTISSA for
+    this term.  The exponential distribution is one sided so we use the
+    full 32 bits.  We use EMANTISSA for this term.
 
-It appears that I'm slightly slower than the code in the article, this
-is partially due to a better generator of random integers than they
-use. But might also be that the case of rapid return was optimized by
-inlining the relevant code with a #define. As the basic Mersenne
-Twister is only 25% faster than this code I suspect that the main
-reason is just the use of the Mersenne Twister and not the inlining,
-so I'm not going to try and optimize further.
-*/
+    It appears that I'm slightly slower than the code in the article, this
+    is partially due to a better generator of random integers than they
+    use. But might also be that the case of rapid return was optimized by
+    inlining the relevant code with a #define. As the basic Mersenne
+    Twister is only 25% faster than this code I suspect that the main
+    reason is just the use of the Mersenne Twister and not the inlining,
+    so I'm not going to try and optimize further.
+  */
 
-static void
-create_ziggurat_tables (void)
-{
-  int i;
-  double x, x1;
+  void create_ziggurat_tables (void)
+  {
+    int i;
+    double x, x1;
+
+    /* Ziggurat tables for the normal distribution */
+    x1 = ZIGGURAT_NOR_R;
+    wi[255] = x1 / NMANTISSA;
+    fi[255] = exp (-0.5 * x1 * x1);
 
-  /* Ziggurat tables for the normal distribution */
-  x1 = ZIGGURAT_NOR_R;
-  wi[255] = x1 / NMANTISSA;
-  fi[255] = exp (-0.5 * x1 * x1);
-
-  /* Index zero is special for tail strip, where Marsaglia and Tsang
-   * defines this as
-   * k_0 = 2^31 * r * f(r) / v, w_0 = 0.5^31 * v / f(r), f_0 = 1,
-   * where v is the area of each strip of the ziggurat.
-   */
-  ki[0] = static_cast<ZIGINT> (x1 * fi[255] / NOR_SECTION_AREA * NMANTISSA);
-  wi[0] = NOR_SECTION_AREA / fi[255] / NMANTISSA;
-  fi[0] = 1.;
+    /* Index zero is special for tail strip, where Marsaglia and Tsang
+     * defines this as
+     * k_0 = 2^31 * r * f(r) / v, w_0 = 0.5^31 * v / f(r), f_0 = 1,
+     * where v is the area of each strip of the ziggurat.
+     */
+    ki[0] = static_cast<ZIGINT> (x1 * fi[255] / NOR_SECTION_AREA * NMANTISSA);
+    wi[0] = NOR_SECTION_AREA / fi[255] / NMANTISSA;
+    fi[0] = 1.;
 
-  for (i = 254; i > 0; i--)
-    {
-      /* New x is given by x = f^{-1}(v/x_{i+1} + f(x_{i+1})), thus
-       * need inverse operator of y = exp(-0.5*x*x) -> x = sqrt(-2*ln(y))
-       */
-      x = std::sqrt (-2. * std::log (NOR_SECTION_AREA / x1 + fi[i+1]));
-      ki[i+1] = static_cast<ZIGINT> (x / x1 * NMANTISSA);
-      wi[i] = x / NMANTISSA;
-      fi[i] = exp (-0.5 * x * x);
-      x1 = x;
-    }
+    for (i = 254; i > 0; i--)
+      {
+        /* New x is given by x = f^{-1}(v/x_{i+1} + f(x_{i+1})), thus
+         * need inverse operator of y = exp(-0.5*x*x) -> x = sqrt(-2*ln(y))
+         */
+        x = std::sqrt (-2. * std::log (NOR_SECTION_AREA / x1 + fi[i+1]));
+        ki[i+1] = static_cast<ZIGINT> (x / x1 * NMANTISSA);
+        wi[i] = x / NMANTISSA;
+        fi[i] = exp (-0.5 * x * x);
+        x1 = x;
+      }
 
-  ki[1] = 0;
+    ki[1] = 0;
 
-  /* Zigurrat tables for the exponential distribution */
-  x1 = ZIGGURAT_EXP_R;
-  we[255] = x1 / EMANTISSA;
-  fe[255] = exp (-x1);
+    /* Zigurrat tables for the exponential distribution */
+    x1 = ZIGGURAT_EXP_R;
+    we[255] = x1 / EMANTISSA;
+    fe[255] = exp (-x1);
 
-  /* Index zero is special for tail strip, where Marsaglia and Tsang
-   * defines this as
-   * k_0 = 2^32 * r * f(r) / v, w_0 = 0.5^32 * v / f(r), f_0 = 1,
-   * where v is the area of each strip of the ziggurat.
-   */
-  ke[0] = static_cast<ZIGINT> (x1 * fe[255] / EXP_SECTION_AREA * EMANTISSA);
-  we[0] = EXP_SECTION_AREA / fe[255] / EMANTISSA;
-  fe[0] = 1.;
+    /* Index zero is special for tail strip, where Marsaglia and Tsang
+     * defines this as
+     * k_0 = 2^32 * r * f(r) / v, w_0 = 0.5^32 * v / f(r), f_0 = 1,
+     * where v is the area of each strip of the ziggurat.
+     */
+    ke[0] = static_cast<ZIGINT> (x1 * fe[255] / EXP_SECTION_AREA * EMANTISSA);
+    we[0] = EXP_SECTION_AREA / fe[255] / EMANTISSA;
+    fe[0] = 1.;
 
-  for (i = 254; i > 0; i--)
-    {
-      /* New x is given by x = f^{-1}(v/x_{i+1} + f(x_{i+1})), thus
-       * need inverse operator of y = exp(-x) -> x = -ln(y)
-       */
-      x = - std::log (EXP_SECTION_AREA / x1 + fe[i+1]);
-      ke[i+1] = static_cast<ZIGINT> (x / x1 * EMANTISSA);
-      we[i] = x / EMANTISSA;
-      fe[i] = exp (-x);
-      x1 = x;
-    }
-  ke[1] = 0;
+    for (i = 254; i > 0; i--)
+      {
+        /* New x is given by x = f^{-1}(v/x_{i+1} + f(x_{i+1})), thus
+         * need inverse operator of y = exp(-x) -> x = -ln(y)
+         */
+        x = - std::log (EXP_SECTION_AREA / x1 + fe[i+1]);
+        ke[i+1] = static_cast<ZIGINT> (x / x1 * EMANTISSA);
+        we[i] = x / EMANTISSA;
+        fe[i] = exp (-x);
+        x1 = x;
+      }
+    ke[1] = 0;
 
-  initt = 0;
-}
+    initt = 0;
+  }
 
-/*
- * Here is the guts of the algorithm. As Marsaglia and Tsang state the
- * algorithm in their paper
- *
- * 1) Calculate a random signed integer j and let i be the index
- *     provided by the rightmost 8-bits of j
- * 2) Set x = j * w_i. If j < k_i return x
- * 3) If i = 0, then return x from the tail
- * 4) If [f(x_{i-1}) - f(x_i)] * U < f(x) - f(x_i), return x
- * 5) goto step 1
- *
- * Where f is the functional form of the distribution, which for a normal
- * distribution is exp(-0.5*x*x)
- */
+  /*
+   * Here is the guts of the algorithm. As Marsaglia and Tsang state the
+   * algorithm in their paper
+   *
+   * 1) Calculate a random signed integer j and let i be the index
+   *     provided by the rightmost 8-bits of j
+   * 2) Set x = j * w_i. If j < k_i return x
+   * 3) If i = 0, then return x from the tail
+   * 4) If [f(x_{i-1}) - f(x_i)] * U < f(x) - f(x_i), return x
+   * 5) goto step 1
+   *
+   * Where f is the functional form of the distribution, which for a normal
+   * distribution is exp(-0.5*x*x)
+   */
 
-double
-oct_randn (void)
-{
-  if (initt)
-    create_ziggurat_tables ();
+
+  template <> double rand_normal<double> (void)
+  {
+    if (initt)
+      create_ziggurat_tables ();
 
-  while (1)
-    {
-      /* The following code is specialized for 32-bit mantissa.
-       * Compared to the arbitrary mantissa code, there is a performance
-       * gain for 32-bits:  PPC: 2%, MIPS: 8%, x86: 40%
-       * There is a bigger performance gain compared to using a full
-       * 53-bit mantissa:  PPC: 60%, MIPS: 65%, x86: 240%
-       * Of course, different compilers and operating systems may
-       * have something to do with this.
-       */
+    while (1)
+      {
+        /* The following code is specialized for 32-bit mantissa.
+         * Compared to the arbitrary mantissa code, there is a performance
+         * gain for 32-bits:  PPC: 2%, MIPS: 8%, x86: 40%
+         * There is a bigger performance gain compared to using a full
+         * 53-bit mantissa:  PPC: 60%, MIPS: 65%, x86: 240%
+         * Of course, different compilers and operating systems may
+         * have something to do with this.
+         */
 # if defined (HAVE_X86_32)
-      /* 53-bit mantissa, 1-bit sign, x86 32-bit architecture */
-      double x;
-      int si,idx;
-      uint32_t lo, hi;
-      int64_t rabs;
-      uint32_t *p = (uint32_t *)&rabs;
-      lo = randi32 ();
-      idx = lo & 0xFF;
-      hi = randi32 ();
-      si = hi & UMASK;
-      p[0] = lo;
-      p[1] = hi & 0x1FFFFF;
-      x = ( si ? -rabs : rabs ) * wi[idx];
+        /* 53-bit mantissa, 1-bit sign, x86 32-bit architecture */
+        double x;
+        int si,idx;
+        uint32_t lo, hi;
+        int64_t rabs;
+        uint32_t *p = (uint32_t *)&rabs;
+        lo = randi32 ();
+        idx = lo & 0xFF;
+        hi = randi32 ();
+        si = hi & UMASK;
+        p[0] = lo;
+        p[1] = hi & 0x1FFFFF;
+        x = ( si ? -rabs : rabs ) * wi[idx];
 # else
-      /* arbitrary mantissa (selected by NRANDI, with 1 bit for sign) */
-      const uint64_t r = NRANDI;
-      const int64_t rabs = r >> 1;
-      const int idx = static_cast<int> (rabs & 0xFF);
-      const double x = ( (r & 1) ? -rabs : rabs) * wi[idx];
+        /* arbitrary mantissa (selected by NRANDI, with 1 bit for sign) */
+        const uint64_t r = NRANDI;
+        const int64_t rabs = r >> 1;
+        const int idx = static_cast<int> (rabs & 0xFF);
+        const double x = ( (r & 1) ? -rabs : rabs) * wi[idx];
 # endif
-      if (rabs < static_cast<int64_t> (ki[idx]))
-        return x;        /* 99.3% of the time we return here 1st try */
-      else if (idx == 0)
-        {
-          /* As stated in Marsaglia and Tsang
-           *
-           * For the normal tail, the method of Marsaglia[5] provides:
-           * generate x = -ln(U_1)/r, y = -ln(U_2), until y+y > x*x,
-           * then return r+x. Except that r+x is always in the positive
-           * tail!!!! Any thing random might be used to determine the
-           * sign, but as we already have r we might as well use it
-           *
-           * [PAK] but not the bottom 8 bits, since they are all 0 here!
-           */
-          double xx, yy;
-          do
-            {
-              xx = - ZIGGURAT_NOR_INV_R * std::log (RANDU);
-              yy = - std::log (RANDU);
-            }
-          while ( yy+yy <= xx*xx);
-          return ((rabs & 0x100) ? -ZIGGURAT_NOR_R-xx : ZIGGURAT_NOR_R+xx);
-        }
-      else if ((fi[idx-1] - fi[idx]) * RANDU + fi[idx] < exp (-0.5*x*x))
-        return x;
-    }
-}
+        if (rabs < static_cast<int64_t> (ki[idx]))
+          return x;        /* 99.3% of the time we return here 1st try */
+        else if (idx == 0)
+          {
+            /* As stated in Marsaglia and Tsang
+             *
+             * For the normal tail, the method of Marsaglia[5] provides:
+             * generate x = -ln(U_1)/r, y = -ln(U_2), until y+y > x*x,
+             * then return r+x. Except that r+x is always in the positive
+             * tail!!!! Any thing random might be used to determine the
+             * sign, but as we already have r we might as well use it
+             *
+             * [PAK] but not the bottom 8 bits, since they are all 0 here!
+             */
+            double xx, yy;
+            do
+              {
+                xx = - ZIGGURAT_NOR_INV_R * std::log (RANDU);
+                yy = - std::log (RANDU);
+              }
+            while ( yy+yy <= xx*xx);
+            return ((rabs & 0x100) ? -ZIGGURAT_NOR_R-xx : ZIGGURAT_NOR_R+xx);
+          }
+        else if ((fi[idx-1] - fi[idx]) * RANDU + fi[idx] < exp (-0.5*x*x))
+          return x;
+      }
+  }
+
+  template <> double rand_exponential<double> (void)
+  {
+    if (initt)
+      create_ziggurat_tables ();
 
-double
-oct_rande (void)
-{
-  if (initt)
-    create_ziggurat_tables ();
+    while (1)
+      {
+        ZIGINT ri = ERANDI;
+        const int idx = static_cast<int> (ri & 0xFF);
+        const double x = ri * we[idx];
+        if (ri < ke[idx])
+          return x;               /* 98.9% of the time we return here 1st try */
+        else if (idx == 0)
+          {
+            /* As stated in Marsaglia and Tsang
+             *
+             * For the exponential tail, the method of Marsaglia[5] provides:
+             * x = r - ln(U);
+             */
+            return ZIGGURAT_EXP_R - std::log (RANDU);
+          }
+        else if ((fe[idx-1] - fe[idx]) * RANDU + fe[idx] < exp (-x))
+          return x;
+      }
+  }
 
-  while (1)
-    {
-      ZIGINT ri = ERANDI;
-      const int idx = static_cast<int> (ri & 0xFF);
-      const double x = ri * we[idx];
-      if (ri < ke[idx])
-        return x;               /* 98.9% of the time we return here 1st try */
-      else if (idx == 0)
-        {
-          /* As stated in Marsaglia and Tsang
-           *
-           * For the exponential tail, the method of Marsaglia[5] provides:
-           * x = r - ln(U);
-           */
-          return ZIGGURAT_EXP_R - std::log (RANDU);
-        }
-      else if ((fe[idx-1] - fe[idx]) * RANDU + fe[idx] < exp (-x))
-        return x;
-    }
-}
+  template <> void rand_uniform<double> (octave_idx_type n, double *p)
+  {
+    std::generate_n (p, n, [](void) { return rand_uniform<double> (); });
+  }
+
+  template <> void rand_normal (octave_idx_type n, double *p)
+  {
+    std::generate_n (p, n, [](void) { return rand_normal<double> (); });
+  }
+
+  template <> void rand_exponential (octave_idx_type n, double *p)
+  {
+    std::generate_n (p, n, [](void) { return rand_exponential<double> (); });
+  }
 
 #undef ZIGINT
 #undef EMANTISSA
@@ -659,191 +667,168 @@
 #define NRANDI randi32() /* 31 bits for mantissa + 1 bit sign */
 #define RANDU randu32()
 
-static ZIGINT fki[ZIGGURAT_TABLE_SIZE];
-static float fwi[ZIGGURAT_TABLE_SIZE], ffi[ZIGGURAT_TABLE_SIZE];
-static ZIGINT fke[ZIGGURAT_TABLE_SIZE];
-static float fwe[ZIGGURAT_TABLE_SIZE], ffe[ZIGGURAT_TABLE_SIZE];
+  static ZIGINT fki[ZIGGURAT_TABLE_SIZE];
+  static float fwi[ZIGGURAT_TABLE_SIZE], ffi[ZIGGURAT_TABLE_SIZE];
+  static ZIGINT fke[ZIGGURAT_TABLE_SIZE];
+  static float fwe[ZIGGURAT_TABLE_SIZE], ffe[ZIGGURAT_TABLE_SIZE];
+
+  static void create_ziggurat_float_tables (void)
+  {
+    int i;
+    float x, x1;
 
-static void
-create_ziggurat_float_tables (void)
-{
-  int i;
-  float x, x1;
+    /* Ziggurat tables for the normal distribution */
+    x1 = ZIGGURAT_NOR_R;
+    fwi[255] = x1 / NMANTISSA;
+    ffi[255] = exp (-0.5 * x1 * x1);
+
+    /* Index zero is special for tail strip, where Marsaglia and Tsang
+     * defines this as
+     * k_0 = 2^31 * r * f(r) / v, w_0 = 0.5^31 * v / f(r), f_0 = 1,
+     * where v is the area of each strip of the ziggurat.
+     */
+    fki[0] = static_cast<ZIGINT> (x1 * ffi[255] / NOR_SECTION_AREA * NMANTISSA);
+    fwi[0] = NOR_SECTION_AREA / ffi[255] / NMANTISSA;
+    ffi[0] = 1.;
 
-  /* Ziggurat tables for the normal distribution */
-  x1 = ZIGGURAT_NOR_R;
-  fwi[255] = x1 / NMANTISSA;
-  ffi[255] = exp (-0.5 * x1 * x1);
+    for (i = 254; i > 0; i--)
+      {
+        /* New x is given by x = f^{-1}(v/x_{i+1} + f(x_{i+1})), thus
+         * need inverse operator of y = exp(-0.5*x*x) -> x = sqrt(-2*ln(y))
+         */
+        x = std::sqrt (-2. * std::log (NOR_SECTION_AREA / x1 + ffi[i+1]));
+        fki[i+1] = static_cast<ZIGINT> (x / x1 * NMANTISSA);
+        fwi[i] = x / NMANTISSA;
+        ffi[i] = exp (-0.5 * x * x);
+        x1 = x;
+      }
+
+    fki[1] = 0;
+
+    /* Zigurrat tables for the exponential distribution */
+    x1 = ZIGGURAT_EXP_R;
+    fwe[255] = x1 / EMANTISSA;
+    ffe[255] = exp (-x1);
 
-  /* Index zero is special for tail strip, where Marsaglia and Tsang
-   * defines this as
-   * k_0 = 2^31 * r * f(r) / v, w_0 = 0.5^31 * v / f(r), f_0 = 1,
-   * where v is the area of each strip of the ziggurat.
-   */
-  fki[0] = static_cast<ZIGINT> (x1 * ffi[255] / NOR_SECTION_AREA * NMANTISSA);
-  fwi[0] = NOR_SECTION_AREA / ffi[255] / NMANTISSA;
-  ffi[0] = 1.;
+    /* Index zero is special for tail strip, where Marsaglia and Tsang
+     * defines this as
+     * k_0 = 2^32 * r * f(r) / v, w_0 = 0.5^32 * v / f(r), f_0 = 1,
+     * where v is the area of each strip of the ziggurat.
+     */
+    fke[0] = static_cast<ZIGINT> (x1 * ffe[255] / EXP_SECTION_AREA * EMANTISSA);
+    fwe[0] = EXP_SECTION_AREA / ffe[255] / EMANTISSA;
+    ffe[0] = 1.;
+
+    for (i = 254; i > 0; i--)
+      {
+        /* New x is given by x = f^{-1}(v/x_{i+1} + f(x_{i+1})), thus
+         * need inverse operator of y = exp(-x) -> x = -ln(y)
+         */
+        x = - std::log (EXP_SECTION_AREA / x1 + ffe[i+1]);
+        fke[i+1] = static_cast<ZIGINT> (x / x1 * EMANTISSA);
+        fwe[i] = x / EMANTISSA;
+        ffe[i] = exp (-x);
+        x1 = x;
+      }
+    fke[1] = 0;
+
+    inittf = 0;
+  }
 
-  for (i = 254; i > 0; i--)
-    {
-      /* New x is given by x = f^{-1}(v/x_{i+1} + f(x_{i+1})), thus
-       * need inverse operator of y = exp(-0.5*x*x) -> x = sqrt(-2*ln(y))
-       */
-      x = std::sqrt (-2. * std::log (NOR_SECTION_AREA / x1 + ffi[i+1]));
-      fki[i+1] = static_cast<ZIGINT> (x / x1 * NMANTISSA);
-      fwi[i] = x / NMANTISSA;
-      ffi[i] = exp (-0.5 * x * x);
-      x1 = x;
-    }
+  /*
+   * Here is the guts of the algorithm. As Marsaglia and Tsang state the
+   * algorithm in their paper
+   *
+   * 1) Calculate a random signed integer j and let i be the index
+   *     provided by the rightmost 8-bits of j
+   * 2) Set x = j * w_i. If j < k_i return x
+   * 3) If i = 0, then return x from the tail
+   * 4) If [f(x_{i-1}) - f(x_i)] * U < f(x) - f(x_i), return x
+   * 5) goto step 1
+   *
+   * Where f is the functional form of the distribution, which for a normal
+   * distribution is exp(-0.5*x*x)
+   */
 
-  fki[1] = 0;
-
-  /* Zigurrat tables for the exponential distribution */
-  x1 = ZIGGURAT_EXP_R;
-  fwe[255] = x1 / EMANTISSA;
-  ffe[255] = exp (-x1);
+  template <> float rand_normal<float> (void)
+  {
+    if (inittf)
+      create_ziggurat_float_tables ();
 
-  /* Index zero is special for tail strip, where Marsaglia and Tsang
-   * defines this as
-   * k_0 = 2^32 * r * f(r) / v, w_0 = 0.5^32 * v / f(r), f_0 = 1,
-   * where v is the area of each strip of the ziggurat.
-   */
-  fke[0] = static_cast<ZIGINT> (x1 * ffe[255] / EXP_SECTION_AREA * EMANTISSA);
-  fwe[0] = EXP_SECTION_AREA / ffe[255] / EMANTISSA;
-  ffe[0] = 1.;
+    while (1)
+      {
+        /* 32-bit mantissa */
+        const uint32_t r = randi32 ();
+        const uint32_t rabs = r & LMASK;
+        const int idx = static_cast<int> (r & 0xFF);
+        const float x = static_cast<int32_t> (r) * fwi[idx];
+        if (rabs < fki[idx])
+          return x;        /* 99.3% of the time we return here 1st try */
+        else if (idx == 0)
+          {
+            /* As stated in Marsaglia and Tsang
+             *
+             * For the normal tail, the method of Marsaglia[5] provides:
+             * generate x = -ln(U_1)/r, y = -ln(U_2), until y+y > x*x,
+             * then return r+x. Except that r+x is always in the positive
+             * tail!!!! Any thing random might be used to determine the
+             * sign, but as we already have r we might as well use it
+             *
+             * [PAK] but not the bottom 8 bits, since they are all 0 here!
+             */
+            float xx, yy;
+            do
+              {
+                xx = - ZIGGURAT_NOR_INV_R * std::log (RANDU);
+                yy = - std::log (RANDU);
+              }
+            while ( yy+yy <= xx*xx);
+            return ((rabs & 0x100) ? -ZIGGURAT_NOR_R-xx : ZIGGURAT_NOR_R+xx);
+          }
+        else if ((ffi[idx-1] - ffi[idx]) * RANDU + ffi[idx] < exp (-0.5*x*x))
+          return x;
+      }
+  }
 
-  for (i = 254; i > 0; i--)
-    {
-      /* New x is given by x = f^{-1}(v/x_{i+1} + f(x_{i+1})), thus
-       * need inverse operator of y = exp(-x) -> x = -ln(y)
-       */
-      x = - std::log (EXP_SECTION_AREA / x1 + ffe[i+1]);
-      fke[i+1] = static_cast<ZIGINT> (x / x1 * EMANTISSA);
-      fwe[i] = x / EMANTISSA;
-      ffe[i] = exp (-x);
-      x1 = x;
-    }
-  fke[1] = 0;
+  template <> float rand_exponential<float> (void)
+  {
+    if (inittf)
+      create_ziggurat_float_tables ();
 
-  inittf = 0;
+    while (1)
+      {
+        ZIGINT ri = ERANDI;
+        const int idx = static_cast<int> (ri & 0xFF);
+        const float x = ri * fwe[idx];
+        if (ri < fke[idx])
+          return x;               /* 98.9% of the time we return here 1st try */
+        else if (idx == 0)
+          {
+            /* As stated in Marsaglia and Tsang
+             *
+             * For the exponential tail, the method of Marsaglia[5] provides:
+             * x = r - ln(U);
+             */
+            return ZIGGURAT_EXP_R - std::log (RANDU);
+          }
+        else if ((ffe[idx-1] - ffe[idx]) * RANDU + ffe[idx] < exp (-x))
+          return x;
+      }
+  }
+
+  template <> void rand_uniform (octave_idx_type n, float *p)
+  {
+    std::generate_n (p, n, [](void) { return rand_uniform<float> (); });
+  }
+
+  template <> void rand_normal (octave_idx_type n, float *p)
+  {
+    std::generate_n (p, n, [](void) { return rand_normal<float> (); });
+  }
+
+  template <> void rand_exponential (octave_idx_type n, float *p)
+  {
+    std::generate_n (p, n, [](void) { return rand_exponential<float> (); });
+  }
 }
 
-/*
- * Here is the guts of the algorithm. As Marsaglia and Tsang state the
- * algorithm in their paper
- *
- * 1) Calculate a random signed integer j and let i be the index
- *     provided by the rightmost 8-bits of j
- * 2) Set x = j * w_i. If j < k_i return x
- * 3) If i = 0, then return x from the tail
- * 4) If [f(x_{i-1}) - f(x_i)] * U < f(x) - f(x_i), return x
- * 5) goto step 1
- *
- * Where f is the functional form of the distribution, which for a normal
- * distribution is exp(-0.5*x*x)
- */
-
-float
-oct_float_randn (void)
-{
-  if (inittf)
-    create_ziggurat_float_tables ();
-
-  while (1)
-    {
-      /* 32-bit mantissa */
-      const uint32_t r = randi32 ();
-      const uint32_t rabs = r & LMASK;
-      const int idx = static_cast<int> (r & 0xFF);
-      const float x = static_cast<int32_t> (r) * fwi[idx];
-      if (rabs < fki[idx])
-        return x;        /* 99.3% of the time we return here 1st try */
-      else if (idx == 0)
-        {
-          /* As stated in Marsaglia and Tsang
-           *
-           * For the normal tail, the method of Marsaglia[5] provides:
-           * generate x = -ln(U_1)/r, y = -ln(U_2), until y+y > x*x,
-           * then return r+x. Except that r+x is always in the positive
-           * tail!!!! Any thing random might be used to determine the
-           * sign, but as we already have r we might as well use it
-           *
-           * [PAK] but not the bottom 8 bits, since they are all 0 here!
-           */
-          float xx, yy;
-          do
-            {
-              xx = - ZIGGURAT_NOR_INV_R * std::log (RANDU);
-              yy = - std::log (RANDU);
-            }
-          while ( yy+yy <= xx*xx);
-          return ((rabs & 0x100) ? -ZIGGURAT_NOR_R-xx : ZIGGURAT_NOR_R+xx);
-        }
-      else if ((ffi[idx-1] - ffi[idx]) * RANDU + ffi[idx] < exp (-0.5*x*x))
-        return x;
-    }
-}
-
-float
-oct_float_rande (void)
-{
-  if (inittf)
-    create_ziggurat_float_tables ();
-
-  while (1)
-    {
-      ZIGINT ri = ERANDI;
-      const int idx = static_cast<int> (ri & 0xFF);
-      const float x = ri * fwe[idx];
-      if (ri < fke[idx])
-        return x;               /* 98.9% of the time we return here 1st try */
-      else if (idx == 0)
-        {
-          /* As stated in Marsaglia and Tsang
-           *
-           * For the exponential tail, the method of Marsaglia[5] provides:
-           * x = r - ln(U);
-           */
-          return ZIGGURAT_EXP_R - std::log (RANDU);
-        }
-      else if ((ffe[idx-1] - ffe[idx]) * RANDU + ffe[idx] < exp (-x))
-        return x;
-    }
-}
-
-/* Array generators */
-void
-oct_fill_randu (octave_idx_type n, double *p)
-{
-  std::generate_n (p, n, oct_randu);
-}
-
-void
-oct_fill_randn (octave_idx_type n, double *p)
-{
-  std::generate_n (p, n, oct_randn);
-}
-
-void
-oct_fill_rande (octave_idx_type n, double *p)
-{
-  std::generate_n (p, n, oct_rande);
-}
-
-void
-oct_fill_float_randu (octave_idx_type n, float *p)
-{
-  std::generate_n (p, n, oct_float_randu);
-}
-
-void
-oct_fill_float_randn (octave_idx_type n, float *p)
-{
-  std::generate_n (p, n, oct_float_randn);
-}
-
-void
-oct_fill_float_rande (octave_idx_type n, float *p)
-{
-  std::generate_n (p, n, oct_float_rande);
-}
--- a/liboctave/numeric/randmtzig.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/numeric/randmtzig.h	Fri Aug 10 09:09:51 2018 +0200
@@ -68,30 +68,170 @@
 
 #define MT_N 624
 
-// Mersenne Twister.
-extern OCTAVE_API void oct_init_by_int (const uint32_t s);
-extern OCTAVE_API void oct_init_by_array (const uint32_t *init_key,
-                                          const int key_length);
-extern OCTAVE_API void oct_init_by_entropy (void);
-extern OCTAVE_API void oct_set_state (const uint32_t *save);
-extern OCTAVE_API void oct_get_state (uint32_t *save);
+namespace octave
+{
+  // Mersenne Twister.
+
+  extern void init_mersenne_twister (void);
+  extern void init_mersenne_twister (const uint32_t seed);
+  extern void init_mersenne_twister (const uint32_t *init_key,
+                                     const int key_length);
+
+  extern void set_mersenne_twister_state (const uint32_t *save);
+  extern void get_mersenne_twister_state (uint32_t *save);
+
+  template <typename T> T rand_uniform (void);
+  template <typename T> T rand_normal (void);
+  template <typename T> T rand_exponential (void);
+
+  template <typename T> void rand_uniform (octave_idx_type n, T *p);
+  template <typename T> void rand_normal (octave_idx_type n, T *p);
+  template <typename T> void rand_exponential (octave_idx_type n, T *p);
+
+  template <> double rand_uniform<double> (void);
+  template <> double rand_normal<double> (void);
+  template <> double rand_exponential<double> (void);
+
+  template <> float rand_uniform<float> (void);
+  template <> float rand_normal<float> (void);
+  template <> float rand_exponential<float> (void);
+
+  template <> void
+  rand_uniform<double> (octave_idx_type n, double *p);
+
+  template <> void
+  rand_normal<double> (octave_idx_type n, double *p);
+
+  template <> void
+  rand_exponential<double> (octave_idx_type n, double *p);
+
+  template <> void
+  rand_uniform<float> (octave_idx_type n, float *p);
 
-// Array generators.
-extern OCTAVE_API double oct_randu (void);
-extern OCTAVE_API double oct_randn (void);
-extern OCTAVE_API double oct_rande (void);
+  template <> void
+  rand_normal<float> (octave_idx_type n, float *p);
+
+  template <> void
+  rand_exponential<float> (octave_idx_type n, float *p);
+}
+
+OCTAVE_DEPRECATED (4.4, "use 'octave::init_mersenne_twister' instead")
+inline void
+oct_init_by_entropy (void)
+{
+  octave::init_mersenne_twister ();
+}
+
+OCTAVE_DEPRECATED (4.4, "use 'octave::init_mersenne_twister' instead")
+inline void
+oct_init_by_int (const uint32_t seed)
+{
+  octave::init_mersenne_twister (seed);
+}
+
+OCTAVE_DEPRECATED (4.4, "use 'octave::init_mersenne_twister' instead")
+inline void
+oct_init_by_array (const uint32_t *init_key, const int key_length)
+{
+  octave::init_mersenne_twister (init_key, key_length);
+}
+
+OCTAVE_DEPRECATED (4.4, "use 'octave::set_mersenne_twister_state' instead")
+inline void
+oct_set_state (const uint32_t *save)
+{
+  octave::set_mersenne_twister_state (save);
+}
+
+OCTAVE_DEPRECATED (4.4, "use 'octave::get_mersenne_twister_state' instead")
+inline void
+oct_get_state (uint32_t *save)
+{
+  octave::get_mersenne_twister_state (save);
+}
 
-extern OCTAVE_API float oct_float_randu (void);
-extern OCTAVE_API float oct_float_randn (void);
-extern OCTAVE_API float oct_float_rande (void);
+OCTAVE_DEPRECATED (4.4, "use 'octave::rand_uniform<double>' instead")
+inline double
+oct_randu (void)
+{
+  return octave::rand_uniform<double> ();
+}
+
+OCTAVE_DEPRECATED (4.4, "use 'octave::rand_normal<double>' instead")
+inline double
+oct_randn (void)
+{
+  return octave::rand_normal<double> ();
+}
+
+OCTAVE_DEPRECATED (4.4, "use 'octave::rand_exponential<double>' instead")
+inline double
+oct_rande (void)
+{
+  return octave::rand_exponential<double> ();
+}
+
+OCTAVE_DEPRECATED (4.4, "use 'octave::rand_uniform' instead")
+inline void
+oct_fill_randu (octave_idx_type n, double *p)
+{
+  octave::rand_uniform (n, p);
+}
+
+OCTAVE_DEPRECATED (4.4, "use 'octave::rand_normal' instead")
+inline void
+oct_fill_randn (octave_idx_type n, double *p)
+{
+  octave::rand_normal (n, p);
+}
+
+OCTAVE_DEPRECATED (4.4, "use 'octave::rand_exponential' instead")
+inline void
+oct_fill_rande (octave_idx_type n, double *p)
+{
+  octave::rand_exponential (n, p);
+}
 
-// Array generators.
-extern OCTAVE_API void oct_fill_randu (octave_idx_type n, double *p);
-extern OCTAVE_API void oct_fill_randn (octave_idx_type n, double *p);
-extern OCTAVE_API void oct_fill_rande (octave_idx_type n, double *p);
+OCTAVE_DEPRECATED (4.4, "use 'octave::rand_uniform<float>' instead")
+inline float
+oct_float_randu (void)
+{
+  return octave::rand_uniform<float> ();
+}
+
+OCTAVE_DEPRECATED (4.4, "use 'octave::rand_normal<float>' instead")
+inline float
+oct_float_randn (void)
+{
+  return octave::rand_normal<float> ();
+}
+
+OCTAVE_DEPRECATED (4.4, "use 'octave::rand_exponential<float>' instead")
+inline float
+oct_float_rande (void)
+{
+  return octave::rand_exponential<float> ();
+}
 
-extern OCTAVE_API void oct_fill_float_randu (octave_idx_type n, float *p);
-extern OCTAVE_API void oct_fill_float_randn (octave_idx_type n, float *p);
-extern OCTAVE_API void oct_fill_float_rande (octave_idx_type n, float *p);
+OCTAVE_DEPRECATED (4.4, "use 'octave::rand_uniform' instead")
+inline void
+oct_fill_float_randu (octave_idx_type n, float *p)
+{
+  octave::rand_uniform (n, p);
+}
+
+OCTAVE_DEPRECATED (4.4, "use 'octave::rand_normal' instead")
+inline void
+oct_fill_float_randn (octave_idx_type n, float *p)
+{
+  octave::rand_normal (n, p);
+}
+
+OCTAVE_DEPRECATED (4.4, "use 'octave::rand_exponential' instead")
+inline void
+oct_fill_float_rande (octave_idx_type n, float *p)
+{
+  octave::rand_exponential (n, p);
+}
 
 #endif
--- a/liboctave/numeric/randpoisson.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/numeric/randpoisson.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -23,14 +23,6 @@
 /* Original version written by Paul Kienzle distributed as free
    software in the in the public domain.  */
 
-/* Needs the following defines:
- * NAN: value to return for Not-A-Number
- * RUNI: uniform generator on (0,1)
- * RNOR: normal generator
- * LGAMMA: log gamma function
- * INFINITE: function to test whether a value is infinite
- */
-
 #if defined (HAVE_CONFIG_H)
 #  include "config.h"
 #endif
@@ -44,246 +36,234 @@
 #include "randmtzig.h"
 #include "randpoisson.h"
 
-#undef INFINITE
-#define INFINITE lo_ieee_isinf
-#define RUNI oct_randu()
-#define RNOR oct_randn()
-#define LGAMMA xlgamma
-
-static double
-xlgamma (double x)
+namespace octave
 {
-  return std::lgamma (x);
-}
-
-/* ---- pprsc.c from Stadloeber's winrand --- */
+  static double xlgamma (double x)
+  {
+    return std::lgamma (x);
+  }
 
-/* flogfak(k) = ln(k!) */
-static double
-flogfak (double k)
-{
+  /* ---- pprsc.c from Stadloeber's winrand --- */
+
+  /* flogfak(k) = ln(k!) */
+  static double flogfak (double k)
+  {
 #define C0  9.18938533204672742e-01
 #define C1  8.33333333333333333e-02
 #define C3 -2.77777777777777778e-03
 #define C5  7.93650793650793651e-04
 #define C7 -5.95238095238095238e-04
 
-  static double logfak[30L] =
-  {
-    0.00000000000000000,   0.00000000000000000,   0.69314718055994531,
-    1.79175946922805500,   3.17805383034794562,   4.78749174278204599,
-    6.57925121201010100,   8.52516136106541430,  10.60460290274525023,
-    12.80182748008146961,  15.10441257307551530,  17.50230784587388584,
-    19.98721449566188615,  22.55216385312342289,  25.19122118273868150,
-    27.89927138384089157,  30.67186010608067280,  33.50507345013688888,
-    36.39544520803305358,  39.33988418719949404,  42.33561646075348503,
-    45.38013889847690803,  48.47118135183522388,  51.60667556776437357,
-    54.78472939811231919,  58.00360522298051994,  61.26170176100200198,
-    64.55753862700633106,  67.88974313718153498,  71.25703896716800901
-  };
+    static double logfak[30L] =
+      {
+        0.00000000000000000,   0.00000000000000000,   0.69314718055994531,
+        1.79175946922805500,   3.17805383034794562,   4.78749174278204599,
+        6.57925121201010100,   8.52516136106541430,  10.60460290274525023,
+        12.80182748008146961,  15.10441257307551530,  17.50230784587388584,
+        19.98721449566188615,  22.55216385312342289,  25.19122118273868150,
+        27.89927138384089157,  30.67186010608067280,  33.50507345013688888,
+        36.39544520803305358,  39.33988418719949404,  42.33561646075348503,
+        45.38013889847690803,  48.47118135183522388,  51.60667556776437357,
+        54.78472939811231919,  58.00360522298051994,  61.26170176100200198,
+        64.55753862700633106,  67.88974313718153498,  71.25703896716800901
+      };
 
-  double r, rr;
+    double r, rr;
 
-  if (k >= 30.0)
-    {
-      r  = 1.0 / k;
-      rr = r * r;
-      return ((k + 0.5)*std::log (k) - k + C0
-              + r*(C1 + rr*(C3 + rr*(C5 + rr*C7))));
-    }
-  else
-    return (logfak[static_cast<int> (k)]);
-}
+    if (k >= 30.0)
+      {
+        r  = 1.0 / k;
+        rr = r * r;
+        return ((k + 0.5)*std::log (k) - k + C0
+                + r*(C1 + rr*(C3 + rr*(C5 + rr*C7))));
+      }
+    else
+      return (logfak[static_cast<int> (k)]);
+  }
 
-/******************************************************************
- *                                                                *
- * Poisson Distribution - Patchwork Rejection/Inversion           *
- *                                                                *
- ******************************************************************
- *                                                                *
- * For parameter my < 10, Tabulated Inversion is applied.         *
- * For my >= 10, Patchwork Rejection is employed:                 *
- * The area below the histogram function f(x) is rearranged in    *
- * its body by certain point reflections. Within a large center   *
- * interval variates are sampled efficiently by rejection from    *
- * uniform hats. Rectangular immediate acceptance regions speed   *
- * up the generation. The remaining tails are covered by          *
- * exponential functions.                                         *
- *                                                                *
- ******************************************************************
- *                                                                *
- * FUNCTION :   - pprsc samples a random number from the Poisson  *
- *                distribution with parameter my > 0.             *
- * REFERENCE :  - H. Zechner (1994): Efficient sampling from      *
- *                continuous and discrete unimodal distributions, *
- *                Doctoral Dissertation, 156 pp., Technical       *
- *                University Graz, Austria.                       *
- * SUBPROGRAM : - drand(seed) ... (0,1)-Uniform generator with    *
- *                unsigned long integer *seed.                    *
- *                                                                *
- * Implemented by H. Zechner, January 1994                        *
- * Revised by F. Niederl, July 1994                               *
- *                                                                *
- ******************************************************************/
+  /******************************************************************
+   *                                                                *
+   * Poisson Distribution - Patchwork Rejection/Inversion           *
+   *                                                                *
+   ******************************************************************
+   *                                                                *
+   * For parameter my < 10, Tabulated Inversion is applied.         *
+   * For my >= 10, Patchwork Rejection is employed:                 *
+   * The area below the histogram function f(x) is rearranged in    *
+   * its body by certain point reflections. Within a large center   *
+   * interval variates are sampled efficiently by rejection from    *
+   * uniform hats. Rectangular immediate acceptance regions speed   *
+   * up the generation. The remaining tails are covered by          *
+   * exponential functions.                                         *
+   *                                                                *
+   ******************************************************************
+   *                                                                *
+   * FUNCTION :   - pprsc samples a random number from the Poisson  *
+   *                distribution with parameter my > 0.             *
+   * REFERENCE :  - H. Zechner (1994): Efficient sampling from      *
+   *                continuous and discrete unimodal distributions, *
+   *                Doctoral Dissertation, 156 pp., Technical       *
+   *                University Graz, Austria.                       *
+   * SUBPROGRAM : - drand(seed) ... (0,1)-Uniform generator with    *
+   *                unsigned long integer *seed.                    *
+   *                                                                *
+   * Implemented by H. Zechner, January 1994                        *
+   * Revised by F. Niederl, July 1994                               *
+   *                                                                *
+   ******************************************************************/
 
-static double
-f (double k, double l_nu, double c_pm)
-{
-  return exp (k * l_nu - flogfak (k) - c_pm);
-}
+  static double f (double k, double l_nu, double c_pm)
+  {
+    return exp (k * l_nu - flogfak (k) - c_pm);
+  }
 
-static double
-pprsc (double my)
-{
-  static double my_last = -1.0;
-  static double m,  k2, k4, k1, k5;
-  static double dl, dr, r1, r2, r4, r5, ll, lr, l_my, c_pm,
-                f1, f2, f4, f5, p1, p2, p3, p4, p5, p6;
-  double        Dk, X, Y;
-  double        Ds, U, V, W;
+  static double pprsc (double my)
+  {
+    static double my_last = -1.0;
+    static double m,  k2, k4, k1, k5;
+    static double dl, dr, r1, r2, r4, r5, ll, lr, l_my, c_pm,
+      f1, f2, f4, f5, p1, p2, p3, p4, p5, p6;
+    double        Dk, X, Y;
+    double        Ds, U, V, W;
 
-  if (my != my_last)
-    {                               /* set-up           */
-      my_last = my;
-      /* approximate deviation of reflection points k2, k4 from my - 1/2 */
-      Ds = std::sqrt (my + 0.25);
+    if (my != my_last)
+      {                               /* set-up           */
+        my_last = my;
+        /* approximate deviation of reflection points k2, k4 from my - 1/2 */
+        Ds = std::sqrt (my + 0.25);
 
-      /* mode m, reflection points k2 and k4, and points k1 and k5,      */
-      /* which delimit the centre region of h(x)                         */
-      m  = std::floor (my);
-      k2 = ceil (my - 0.5 - Ds);
-      k4 = std::floor (my - 0.5 + Ds);
-      k1 = k2 + k2 - m + 1L;
-      k5 = k4 + k4 - m;
+        /* mode m, reflection points k2 and k4, and points k1 and k5,      */
+        /* which delimit the centre region of h(x)                         */
+        m  = std::floor (my);
+        k2 = ceil (my - 0.5 - Ds);
+        k4 = std::floor (my - 0.5 + Ds);
+        k1 = k2 + k2 - m + 1L;
+        k5 = k4 + k4 - m;
 
-      /* range width of the critical left and right centre region        */
-      dl = (k2 - k1);
-      dr = (k5 - k4);
+        /* range width of the critical left and right centre region        */
+        dl = (k2 - k1);
+        dr = (k5 - k4);
 
-      /* recurrence constants r(k)=p(k)/p(k-1) at k = k1, k2, k4+1, k5+1 */
-      r1 = my / k1;
-      r2 = my / k2;
-      r4 = my / (k4 + 1.0);
-      r5 = my / (k5 + 1.0);
+        /* recurrence constants r(k)=p(k)/p(k-1) at k = k1, k2, k4+1, k5+1 */
+        r1 = my / k1;
+        r2 = my / k2;
+        r4 = my / (k4 + 1.0);
+        r5 = my / (k5 + 1.0);
 
-      /* reciprocal values of the scale parameters of exp. tail envelope */
-      ll =  std::log (r1);                        /* expon. tail left */
-      lr = -std::log (r5);                        /* expon. tail right*/
+        /* reciprocal values of the scale parameters of exp. tail envelope */
+        ll =  std::log (r1);                        /* expon. tail left */
+        lr = -std::log (r5);                        /* expon. tail right*/
 
-      /* Poisson constants, necessary for computing function values f(k) */
-      l_my = std::log (my);
-      c_pm = m * l_my - flogfak (m);
+        /* Poisson constants, necessary for computing function values f(k) */
+        l_my = std::log (my);
+        c_pm = m * l_my - flogfak (m);
 
-      /* function values f(k) = p(k)/p(m) at k = k2, k4, k1, k5          */
-      f2 = f (k2, l_my, c_pm);
-      f4 = f (k4, l_my, c_pm);
-      f1 = f (k1, l_my, c_pm);
-      f5 = f (k5, l_my, c_pm);
+        /* function values f(k) = p(k)/p(m) at k = k2, k4, k1, k5          */
+        f2 = f (k2, l_my, c_pm);
+        f4 = f (k4, l_my, c_pm);
+        f1 = f (k1, l_my, c_pm);
+        f5 = f (k5, l_my, c_pm);
 
-      /* area of the two centre and the two exponential tail regions     */
-      /* area of the two immediate acceptance regions between k2, k4     */
-      p1 = f2 * (dl + 1.0);                            /* immed. left    */
-      p2 = f2 * dl         + p1;                       /* centre left    */
-      p3 = f4 * (dr + 1.0) + p2;                       /* immed. right   */
-      p4 = f4 * dr         + p3;                       /* centre right   */
-      p5 = f1 / ll         + p4;                       /* exp. tail left */
-      p6 = f5 / lr         + p5;                       /* exp. tail right*/
-    }
+        /* area of the two centre and the two exponential tail regions     */
+        /* area of the two immediate acceptance regions between k2, k4     */
+        p1 = f2 * (dl + 1.0);                            /* immed. left    */
+        p2 = f2 * dl         + p1;                       /* centre left    */
+        p3 = f4 * (dr + 1.0) + p2;                       /* immed. right   */
+        p4 = f4 * dr         + p3;                       /* centre right   */
+        p5 = f1 / ll         + p4;                       /* exp. tail left */
+        p6 = f5 / lr         + p5;                       /* exp. tail right*/
+      }
 
-  for (;;)
-    {
-      /* generate uniform number U -- U(0, p6)                           */
-      /* case distinction corresponding to U                             */
-      if ((U = RUNI * p6) < p2)
-        {                                            /* centre left      */
+    for (;;)
+      {
+        /* generate uniform number U -- U(0, p6)                           */
+        /* case distinction corresponding to U                             */
+        if ((U = octave::rand_uniform<double> () * p6) < p2)
+          {                                            /* centre left      */
 
-          /* immediate acceptance region
-             R2 = [k2, m) *[0, f2),  X = k2, ... m -1 */
-          if ((V = U - p1) < 0.0)  return (k2 + std::floor (U/f2));
-          /* immediate acceptance region
-             R1 = [k1, k2)*[0, f1),  X = k1, ... k2-1 */
-          if ((W = V / dl) < f1 )  return (k1 + std::floor (V/f1));
+            /* immediate acceptance region
+               R2 = [k2, m) *[0, f2),  X = k2, ... m -1 */
+            if ((V = U - p1) < 0.0)  return (k2 + std::floor (U/f2));
+            /* immediate acceptance region
+               R1 = [k1, k2)*[0, f1),  X = k1, ... k2-1 */
+            if ((W = V / dl) < f1 )  return (k1 + std::floor (V/f1));
 
-          /* computation of candidate X < k2, and its counterpart Y > k2 */
-          /* either squeeze-acceptance of X or acceptance-rejection of Y */
-          Dk = std::floor (dl * RUNI) + 1.0;
-          if (W <= f2 - Dk * (f2 - f2/r2))
-            {                                        /* quick accept of  */
-              return (k2 - Dk);                      /* X = k2 - Dk      */
-            }
-          if ((V = f2 + f2 - W) < 1.0)
-            {                                        /* quick reject of Y*/
-              Y = k2 + Dk;
-              if (V <= f2 + Dk * (1.0 - f2)/(dl + 1.0))
-                {                                    /* quick accept of  */
-                  return (Y);                        /* Y = k2 + Dk      */
-                }
-              if (V <= f (Y, l_my, c_pm))  return (Y); /* final accept of Y*/
-            }
-          X = k2 - Dk;
-        }
-      else if (U < p4)
-        {                                            /* centre right     */
-          /*  immediate acceptance region
-              R3 = [m, k4+1)*[0, f4), X = m, ... k4    */
-          if ((V = U - p3) < 0.0)  return (k4 - std::floor ((U - p2)/f4));
-          /* immediate acceptance region
-             R4 = [k4+1, k5+1)*[0, f5)                */
-          if ((W = V / dr) < f5 )  return (k5 - std::floor (V/f5));
+            /* computation of candidate X < k2, and its counterpart Y > k2 */
+            /* either squeeze-acceptance of X or acceptance-rejection of Y */
+            Dk = std::floor (dl * octave::rand_uniform<double> ()) + 1.0;
+            if (W <= f2 - Dk * (f2 - f2/r2))
+              {                                        /* quick accept of  */
+                return (k2 - Dk);                      /* X = k2 - Dk      */
+              }
+            if ((V = f2 + f2 - W) < 1.0)
+              {                                        /* quick reject of Y*/
+                Y = k2 + Dk;
+                if (V <= f2 + Dk * (1.0 - f2)/(dl + 1.0))
+                  {                                    /* quick accept of  */
+                    return (Y);                        /* Y = k2 + Dk      */
+                  }
+                if (V <= f (Y, l_my, c_pm))  return (Y); /* final accept of Y*/
+              }
+            X = k2 - Dk;
+          }
+        else if (U < p4)
+          {                                            /* centre right     */
+            /*  immediate acceptance region
+                R3 = [m, k4+1)*[0, f4), X = m, ... k4    */
+            if ((V = U - p3) < 0.0)  return (k4 - std::floor ((U - p2)/f4));
+            /* immediate acceptance region
+               R4 = [k4+1, k5+1)*[0, f5)                */
+            if ((W = V / dr) < f5 )  return (k5 - std::floor (V/f5));
 
-          /* computation of candidate X > k4, and its counterpart Y < k4 */
-          /* either squeeze-acceptance of X or acceptance-rejection of Y */
-          Dk = std::floor (dr * RUNI) + 1.0;
-          if (W <= f4 - Dk * (f4 - f4*r4))
-            {                                        /* quick accept of  */
-              return (k4 + Dk);                      /* X = k4 + Dk      */
-            }
-          if ((V = f4 + f4 - W) < 1.0)
-            {                                        /* quick reject of Y*/
-              Y = k4 - Dk;
-              if (V <= f4 + Dk * (1.0 - f4)/ dr)
-                {                                    /* quick accept of  */
-                  return (Y);                        /* Y = k4 - Dk      */
-                }
-              if (V <= f (Y, l_my, c_pm))  return (Y); /* final accept of Y*/
-            }
-          X = k4 + Dk;
-        }
-      else
-        {
-          W = RUNI;
-          if (U < p5)
-            {                                        /* expon. tail left */
-              Dk = std::floor (1.0 - std::log (W)/ll);
-              if ((X = k1 - Dk) < 0L)  continue;     /* 0 <= X <= k1 - 1 */
-              W *= (U - p4) * ll;                    /* W -- U(0, h(x))  */
-              if (W <= f1 - Dk * (f1 - f1/r1))
-                return (X);                          /* quick accept of X*/
-            }
-          else
-            {                                        /* expon. tail right*/
-              Dk = std::floor (1.0 - std::log (W)/lr);
-              X  = k5 + Dk;                          /* X >= k5 + 1      */
-              W *= (U - p5) * lr;                    /* W -- U(0, h(x))  */
-              if (W <= f5 - Dk * (f5 - f5*r5))
-                return (X);                          /* quick accept of X*/
-            }
-        }
+            /* computation of candidate X > k4, and its counterpart Y < k4 */
+            /* either squeeze-acceptance of X or acceptance-rejection of Y */
+            Dk = std::floor (dr * octave::rand_uniform<double> ()) + 1.0;
+            if (W <= f4 - Dk * (f4 - f4*r4))
+              {                                        /* quick accept of  */
+                return (k4 + Dk);                      /* X = k4 + Dk      */
+              }
+            if ((V = f4 + f4 - W) < 1.0)
+              {                                        /* quick reject of Y*/
+                Y = k4 - Dk;
+                if (V <= f4 + Dk * (1.0 - f4)/ dr)
+                  {                                    /* quick accept of  */
+                    return (Y);                        /* Y = k4 - Dk      */
+                  }
+                if (V <= f (Y, l_my, c_pm))  return (Y); /* final accept of Y*/
+              }
+            X = k4 + Dk;
+          }
+        else
+          {
+            W = octave::rand_uniform<double> ();
+            if (U < p5)
+              {                                        /* expon. tail left */
+                Dk = std::floor (1.0 - std::log (W)/ll);
+                if ((X = k1 - Dk) < 0L)  continue;     /* 0 <= X <= k1 - 1 */
+                W *= (U - p4) * ll;                    /* W -- U(0, h(x))  */
+                if (W <= f1 - Dk * (f1 - f1/r1))
+                  return (X);                          /* quick accept of X*/
+              }
+            else
+              {                                        /* expon. tail right*/
+                Dk = std::floor (1.0 - std::log (W)/lr);
+                X  = k5 + Dk;                          /* X >= k5 + 1      */
+                W *= (U - p5) * lr;                    /* W -- U(0, h(x))  */
+                if (W <= f5 - Dk * (f5 - f5*r5))
+                  return (X);                          /* quick accept of X*/
+              }
+          }
 
-      /* acceptance-rejection test of candidate X from the original area */
-      /* test, whether  W <= f(k),    with  W = U*h(x)  and  U -- U(0, 1)*/
-      /* log f(X) = (X - m)*log(my) - log X! + log m!                    */
-      if (std::log (W) <= X * l_my - flogfak (X) - c_pm)  return (X);
-    }
-}
-/* ---- pprsc.c end ------ */
+        /* acceptance-rejection test of candidate X from the original area */
+        /* test, whether  W <= f(k),    with  W = U*h(x)  and  U -- U(0, 1)*/
+        /* log f(X) = (X - m)*log(my) - log X! + log m!                    */
+        if (std::log (W) <= X * l_my - flogfak (X) - c_pm)  return (X);
+      }
+  }
+  /* ---- pprsc.c end ------ */
 
-/* The remainder of the file is by Paul Kienzle */
+  /* The remainder of the file is by Paul Kienzle */
 
-/* Given uniform u, find x such that CDF(L,x)==u.  Return x. */
-static void
-poisson_cdf_lookup (double lambda, double *p, size_t n)
-{
   /* Table size is predicated on the maximum value of lambda
    * we want to store in the table, and the maximum value of
    * returned by the uniform random number generator on [0,1).
@@ -294,312 +274,184 @@
    * size of 46 instead.  For long doubles, the table size
    * will need to be longer still.  */
 #define TABLESIZE 46
-  double t[TABLESIZE];
 
-  /* Precompute the table for the u up to and including 0.458.
-   * We will almost certainly need it. */
-  int intlambda = static_cast<int> (std::floor (lambda));
-  double P;
-  int tableidx;
-  size_t i = n;
+  /* Given uniform u, find x such that CDF(L,x)==u.  Return x. */
 
-  t[0] = P = exp (-lambda);
-  for (tableidx = 1; tableidx <= intlambda; tableidx++)
-    {
-      P = P*lambda/static_cast<double> (tableidx);
-      t[tableidx] = t[tableidx-1] + P;
-    }
+  template <typename T>
+  static void
+  poisson_cdf_lookup (double lambda, T *p, size_t n)
+  {
+    double t[TABLESIZE];
 
-  while (i-- > 0)
-    {
-      double u = RUNI;
-
-      /* If u > 0.458 we know we can jump to floor(lambda) before
-       * comparing (this observation is based on Stadlober's winrand
-       * code). For lambda >= 1, this will be a win.  Lambda < 1
-       * is already fast, so adding an extra comparison is not a
-       * problem. */
-      int k = (u > 0.458 ? intlambda : 0);
+    /* Precompute the table for the u up to and including 0.458.
+     * We will almost certainly need it. */
+    int intlambda = static_cast<int> (std::floor (lambda));
+    double P;
+    int tableidx;
+    size_t i = n;
 
-      /* We aren't using a for loop here because when we find the
-       * right k we want to jump to the next iteration of the
-       * outer loop, and the continue statement will only work for
-       * the inner loop. */
-    nextk:
-      if (u <= t[k])
-        {
-          p[i] = static_cast<double> (k);
-          continue;
-        }
-      if (++k < tableidx)
-        goto nextk;
+    t[0] = P = exp (-lambda);
+    for (tableidx = 1; tableidx <= intlambda; tableidx++)
+      {
+        P = P*lambda/static_cast<double> (tableidx);
+        t[tableidx] = t[tableidx-1] + P;
+      }
 
-      /* We only need high values of the table very rarely so we
-       * don't automatically compute the entire table. */
-      while (tableidx < TABLESIZE)
-        {
-          P = P*lambda/static_cast<double> (tableidx);
-          t[tableidx] = t[tableidx-1] + P;
-          /* Make sure we converge to 1.0 just in case u is uniform
-           * on [0,1] rather than [0,1). */
-          if (t[tableidx] == t[tableidx-1]) t[tableidx] = 1.0;
-          tableidx++;
-          if (u <= t[tableidx-1]) break;
-        }
+    while (i-- > 0)
+      {
+        double u = octave::rand_uniform<double> ();
 
-      /* We are assuming that the table size is big enough here.
-       * This should be true even if RUNI is returning values in
-       * the range [0,1] rather than [0,1). */
-      p[i] = static_cast<double> (tableidx-1);
-    }
-}
-
-static void
-poisson_cdf_lookup_float (double lambda, float *p, size_t n)
-{
-  double t[TABLESIZE];
+        /* If u > 0.458 we know we can jump to floor(lambda) before
+         * comparing (this observation is based on Stadlober's winrand
+         * code). For lambda >= 1, this will be a win.  Lambda < 1
+         * is already fast, so adding an extra comparison is not a
+         * problem. */
+        int k = (u > 0.458 ? intlambda : 0);
 
-  /* Precompute the table for the u up to and including 0.458.
-   * We will almost certainly need it. */
-  int intlambda = static_cast<int> (std::floor (lambda));
-  double P;
-  int tableidx;
-  size_t i = n;
-
-  t[0] = P = exp (-lambda);
-  for (tableidx = 1; tableidx <= intlambda; tableidx++)
-    {
-      P = P*lambda/static_cast<double> (tableidx);
-      t[tableidx] = t[tableidx-1] + P;
-    }
-
-  while (i-- > 0)
-    {
-      double u = RUNI;
-      int k = (u > 0.458 ? intlambda : 0);
-    nextk:
-      if (u <= t[k])
-        {
-          p[i] = static_cast<float> (k);
-          continue;
-        }
-      if (++k < tableidx)
-        goto nextk;
-
-      while (tableidx < TABLESIZE)
-        {
-          P = P*lambda/static_cast<double> (tableidx);
-          t[tableidx] = t[tableidx-1] + P;
-          if (t[tableidx] == t[tableidx-1]) t[tableidx] = 1.0;
-          tableidx++;
-          if (u <= t[tableidx-1]) break;
-        }
+        /* We aren't using a for loop here because when we find the
+         * right k we want to jump to the next iteration of the
+         * outer loop, and the continue statement will only work for
+         * the inner loop. */
+      nextk:
+        if (u <= t[k])
+          {
+            p[i] = static_cast<T> (k);
+            continue;
+          }
+        if (++k < tableidx)
+          goto nextk;
 
-      p[i] = static_cast<float> (tableidx-1);
-    }
-}
-
-/* From Press, et al., Numerical Recipes */
-static void
-poisson_rejection (double lambda, double *p, size_t n)
-{
-  double sq = std::sqrt (2.0*lambda);
-  double alxm = std::log (lambda);
-  double g = lambda*alxm - LGAMMA(lambda+1.0);
-  size_t i;
+        /* We only need high values of the table very rarely so we
+         * don't automatically compute the entire table. */
+        while (tableidx < TABLESIZE)
+          {
+            P = P*lambda/static_cast<double> (tableidx);
+            t[tableidx] = t[tableidx-1] + P;
+            /* Make sure we converge to 1.0 just in case u is uniform
+             * on [0,1] rather than [0,1). */
+            if (t[tableidx] == t[tableidx-1]) t[tableidx] = 1.0;
+            tableidx++;
+            if (u <= t[tableidx-1]) break;
+          }
 
-  for (i = 0; i < n; i++)
-    {
-      double y, em, t;
-      do
-        {
-          do
-            {
-              y = tan (M_PI*RUNI);
-              em = sq * y + lambda;
-            } while (em < 0.0);
-          em = std::floor (em);
-          t = 0.9*(1.0+y*y)*exp (em*alxm-flogfak (em)-g);
-        } while (RUNI > t);
-      p[i] = em;
-    }
-}
+        /* We are assuming that the table size is big enough here.
+         * This should be true even if rand_uniform is returning values in
+         * the range [0,1] rather than [0,1). */
+        p[i] = static_cast<T> (tableidx-1);
+      }
+  }
 
-/* From Press, et al., Numerical Recipes */
-static void
-poisson_rejection_float (double lambda, float *p, size_t n)
-{
-  double sq = std::sqrt (2.0*lambda);
-  double alxm = std::log (lambda);
-  double g = lambda*alxm - LGAMMA(lambda+1.0);
-  size_t i;
+  /* From Press, et al., Numerical Recipes */
+  template <typename T>
+  static void
+  poisson_rejection (double lambda, T *p, size_t n)
+  {
+    double sq = std::sqrt (2.0*lambda);
+    double alxm = std::log (lambda);
+    double g = lambda*alxm - xlgamma (lambda+1.0);
+    size_t i;
 
-  for (i = 0; i < n; i++)
-    {
-      double y, em, t;
-      do
-        {
-          do
-            {
-              y = tan (M_PI*RUNI);
-              em = sq * y + lambda;
-            } while (em < 0.0);
-          em = std::floor (em);
-          t = 0.9*(1.0+y*y)*exp (em*alxm-flogfak (em)-g);
-        } while (RUNI > t);
-      p[i] = em;
-    }
-}
-
-/* The cutoff of L <= 1e8 in the following two functions before using
- * the normal approximation is based on:
- *   > L=1e8; x=floor(linspace(0,2*L,1000));
- *   > max(abs(normal_pdf(x,L,L)-poisson_pdf(x,L)))
- *   ans = 1.1376e-28
- * For L=1e7, the max is around 1e-9, which is within the step size of RUNI.
- * For L>1e10 the pprsc function breaks down, as I saw from the histogram
- * of a large sample, so 1e8 is both small enough and large enough. */
+    for (i = 0; i < n; i++)
+      {
+        double y, em, t;
+        do
+          {
+            do
+              {
+                y = tan (M_PI*octave::rand_uniform<double> ());
+                em = sq * y + lambda;
+              } while (em < 0.0);
+            em = std::floor (em);
+            t = 0.9*(1.0+y*y)*exp (em*alxm-flogfak (em)-g);
+          } while (octave::rand_uniform<double> () > t);
+        p[i] = em;
+      }
+  }
 
-/* Generate a set of poisson numbers with the same distribution */
-void
-oct_fill_randp (double L, octave_idx_type n, double *p)
-{
-  octave_idx_type i;
-  if (L < 0.0 || INFINITE(L))
-    {
-      for (i=0; i<n; i++)
-        p[i] = octave::numeric_limits<double>::NaN ();
-    }
-  else if (L <= 10.0)
-    {
-      poisson_cdf_lookup (L, p, n);
-    }
-  else if (L <= 1e8)
-    {
-      for (i=0; i<n; i++)
-        p[i] = pprsc (L);
-    }
-  else
-    {
-      /* normal approximation: from Phys. Rev. D (1994) v50 p1284 */
-      const double sqrtL = std::sqrt (L);
-      for (i = 0; i < n; i++)
-        {
-          p[i] = std::floor (RNOR*sqrtL + L + 0.5);
-          if (p[i] < 0.0)
-            p[i] = 0.0; /* will probably never happen */
-        }
-    }
-}
+  /* The cutoff of L <= 1e8 in the following two functions before using
+   * the normal approximation is based on:
+   *   > L=1e8; x=floor(linspace(0,2*L,1000));
+   *   > max(abs(normal_pdf(x,L,L)-poisson_pdf(x,L)))
+   *   ans = 1.1376e-28
+   * For L=1e7, the max is around 1e-9, which is within the step size of
+   * rand_uniform.  For L>1e10 the pprsc function breaks down, as I saw
+   * from the histogram of a large sample, so 1e8 is both small enough
+   * and large enough. */
 
-/* Generate one poisson variate */
-double
-oct_randp (double L)
-{
-  double ret;
-  if (L < 0.0) ret = octave::numeric_limits<double>::NaN ();
-  else if (L <= 12.0)
-    {
-      /* From Press, et al. Numerical recipes */
-      double g = exp (-L);
-      int em = -1;
-      double t = 1.0;
-      do
-        {
-          ++em;
-          t *= RUNI;
-        } while (t > g);
-      ret = em;
-    }
-  else if (L <= 1e8)
-    {
-      /* numerical recipes */
-      poisson_rejection (L, &ret, 1);
-    }
-  else if (INFINITE(L))
-    {
-      /* FIXME: R uses NaN, but the normal approximation suggests that
-       * limit should be Inf.  Which is correct? */
-      ret = octave::numeric_limits<double>::NaN ();
-    }
-  else
-    {
-      /* normal approximation: from Phys. Rev. D (1994) v50 p1284 */
-      ret = std::floor (RNOR*std::sqrt (L) + L + 0.5);
-      if (ret < 0.0) ret = 0.0; /* will probably never happen */
-    }
-  return ret;
-}
+  /* Generate a set of poisson numbers with the same distribution */
+  template <typename T> void rand_poisson (T L_arg, octave_idx_type n, T *p)
+  {
+    double L = L_arg;
+    octave_idx_type i;
+    if (L < 0.0 || lo_ieee_isinf (L))
+      {
+        for (i=0; i<n; i++)
+          p[i] = numeric_limits<T>::NaN ();
+      }
+    else if (L <= 10.0)
+      {
+        poisson_cdf_lookup<T> (L, p, n);
+      }
+    else if (L <= 1e8)
+      {
+        for (i=0; i<n; i++)
+          p[i] = pprsc (L);
+      }
+    else
+      {
+        /* normal approximation: from Phys. Rev. D (1994) v50 p1284 */
+        const double sqrtL = std::sqrt (L);
+        for (i = 0; i < n; i++)
+          {
+            p[i] = std::floor (rand_normal<T> () * sqrtL + L + 0.5);
+            if (p[i] < 0.0)
+              p[i] = 0.0; /* will probably never happen */
+          }
+      }
+  }
+
+  template void rand_poisson<double> (double, octave_idx_type, double *);
+  template void rand_poisson<float> (float, octave_idx_type, float *);
 
-/* Generate a set of poisson numbers with the same distribution */
-void
-oct_fill_float_randp (float FL, octave_idx_type n, float *p)
-{
-  double L = FL;
-  octave_idx_type i;
-  if (L < 0.0 || INFINITE(L))
-    {
-      for (i=0; i<n; i++)
-        p[i] = octave::numeric_limits<double>::NaN ();
-    }
-  else if (L <= 10.0)
-    {
-      poisson_cdf_lookup_float (L, p, n);
-    }
-  else if (L <= 1e8)
-    {
-      for (i=0; i<n; i++)
-        p[i] = pprsc (L);
-    }
-  else
-    {
-      /* normal approximation: from Phys. Rev. D (1994) v50 p1284 */
-      const double sqrtL = std::sqrt (L);
-      for (i = 0; i < n; i++)
-        {
-          p[i] = std::floor (RNOR*sqrtL + L + 0.5);
-          if (p[i] < 0.0)
-            p[i] = 0.0; /* will probably never happen */
-        }
-    }
-}
+  /* Generate one poisson variate */
+  template <typename T> T rand_poisson (T L_arg)
+  {
+    double L = L_arg;
+    T ret;
+    if (L < 0.0) ret = numeric_limits<T>::NaN ();
+    else if (L <= 12.0)
+      {
+        /* From Press, et al. Numerical recipes */
+        double g = exp (-L);
+        int em = -1;
+        double t = 1.0;
+        do
+          {
+            ++em;
+            t *= rand_uniform<T> ();
+          } while (t > g);
+        ret = em;
+      }
+    else if (L <= 1e8)
+      {
+        /* numerical recipes */
+        poisson_rejection<T> (L, &ret, 1);
+      }
+    else if (lo_ieee_isinf (L))
+      {
+        /* FIXME: R uses NaN, but the normal approximation suggests that
+         * limit should be Inf.  Which is correct? */
+        ret = numeric_limits<T>::NaN ();
+      }
+    else
+      {
+        /* normal approximation: from Phys. Rev. D (1994) v50 p1284 */
+        ret = std::floor (rand_normal<T> () * std::sqrt (L) + L + 0.5);
+        if (ret < 0.0) ret = 0.0; /* will probably never happen */
+      }
+    return ret;
+  }
 
-/* Generate one poisson variate */
-float
-oct_float_randp (float FL)
-{
-  double L = FL;
-  float ret;
-  if (L < 0.0) ret = octave::numeric_limits<float>::NaN ();
-  else if (L <= 12.0)
-    {
-      /* From Press, et al. Numerical recipes */
-      double g = exp (-L);
-      int em = -1;
-      double t = 1.0;
-      do
-        {
-          ++em;
-          t *= RUNI;
-        } while (t > g);
-      ret = em;
-    }
-  else if (L <= 1e8)
-    {
-      /* numerical recipes */
-      poisson_rejection_float (L, &ret, 1);
-    }
-  else if (INFINITE(L))
-    {
-      /* FIXME: R uses NaN, but the normal approximation suggests that
-       * limit should be Inf. Which is correct? */
-      ret = octave::numeric_limits<float>::NaN ();
-    }
-  else
-    {
-      /* normal approximation: from Phys. Rev. D (1994) v50 p1284 */
-      ret = std::floor (RNOR*std::sqrt (L) + L + 0.5);
-      if (ret < 0.0) ret = 0.0; /* will probably never happen */
-    }
-  return ret;
+  template double rand_poisson<double> (double);
+  template float rand_poisson<float> (float);
 }
--- a/liboctave/numeric/randpoisson.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/numeric/randpoisson.h	Fri Aug 10 09:09:51 2018 +0200
@@ -28,16 +28,39 @@
 
 #include "octave-config.h"
 
-extern OCTAVE_API double
-oct_randp (double L);
+namespace octave
+{
+  template <typename T> void rand_poisson (T L, octave_idx_type n, T *p);
+
+  template <typename T> T rand_poisson (T L);
+}
 
-extern OCTAVE_API void
-oct_fill_randp (double L, octave_idx_type n, double *p);
+OCTAVE_DEPRECATED (4.4, "use 'octave::rand_poisson<double>' instead")
+inline double
+oct_randp (double L)
+{
+  return octave::rand_poisson (L);
+}
 
-extern OCTAVE_API float
-oct_float_randp (float L);
+OCTAVE_DEPRECATED (4.4, "use 'octave::rand_poisson<double>' instead")
+inline void
+oct_fill_randp (double L, octave_idx_type n, double *p)
+{
+  octave::rand_poisson (L, n, p);
+}
 
-extern OCTAVE_API void
-oct_fill_float_randp (float L, octave_idx_type n, float *p);
+OCTAVE_DEPRECATED (4.4, "use 'octave::rand_poisson<float>' instead")
+inline float
+oct_float_randp (float L)
+{
+  return octave::rand_poisson (L);
+}
+
+OCTAVE_DEPRECATED (4.4, "use 'octave::rand_poisson<float>' instead")
+inline void
+oct_fill_float_randp (float L, octave_idx_type n, float *p)
+{
+  octave::rand_poisson (L, n, p);
+}
 
 #endif
--- a/liboctave/numeric/sparse-chol.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/numeric/sparse-chol.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -102,7 +102,7 @@
       octave_idx_type P (void) const
       {
 #if defined (HAVE_CHOLMOD)
-        return (minor_p == static_cast<octave_idx_type>(Lsparse->ncol) ?
+        return (minor_p == static_cast<octave_idx_type> (Lsparse->ncol) ?
                 0 : minor_p + 1);
 #else
         return 0;
@@ -374,7 +374,7 @@
       for (octave_idx_type i = 0; i < n; i++)
         {
           p.xcidx (i) = i;
-          p.xridx (i) = static_cast<octave_idx_type>(perms (i));
+          p.xridx (i) = static_cast<octave_idx_type> (perms (i));
           p.xdata (i) = 1;
         }
 
--- a/liboctave/numeric/sparse-chol.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/numeric/sparse-chol.h	Fri Aug 10 09:09:51 2018 +0200
@@ -27,6 +27,8 @@
 
 #include "octave-config.h"
 
+#include "CSparse.h"
+
 class RowVector;
 class SparseMatrix;
 class SparseComplexMatrix;
--- a/liboctave/numeric/sparse-qr.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/numeric/sparse-qr.h	Fri Aug 10 09:09:51 2018 +0200
@@ -26,6 +26,8 @@
 
 #include "octave-config.h"
 
+#include "oct-cmplx.h"
+
 class Matrix;
 class ComplexMatrix;
 class SparseComplexMatrix;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/liboctave/octave.in.pc	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,9 @@
+Name: @PACKAGE_NAME@
+Description: C++ interface to GNU Octave underlying library.
+URL: https://www.octave.org
+Version: @PACKAGE_VERSION@
+Requires:
+Requires.private:
+Libs: -L@octlibdir@ @LIBOCTAVE@
+Libs.private: @LIBOCTAVE_LINK_DEPS@
+Cflags: -I@octincludedir@/..
--- a/liboctave/operators/Sparse-op-defs.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/operators/Sparse-op-defs.h	Fri Aug 10 09:09:51 2018 +0200
@@ -77,7 +77,7 @@
   SPARSE_SMS_BIN_OP_2 (R2, operator *, *, M, S) \
   SPARSE_SMS_BIN_OP_2 (R2, operator /, /, M, S)
 
-#define SPARSE_SMS_CMP_OP(F, OP, M, MZ, MC, S, SZ, SC)                  \
+#define SPARSE_SMS_CMP_OP(F, OP, M, S)                                  \
   SparseBoolMatrix                                                      \
   F (const M& m, const S& s)                                            \
   {                                                                     \
@@ -85,12 +85,14 @@
     octave_idx_type nc = m.cols ();                                     \
     SparseBoolMatrix r;                                                 \
                                                                         \
-    if (MC (MZ) OP SC (s))                                              \
+    M::element_type m_zero = M::element_type ();                        \
+                                                                        \
+    if (m_zero OP s)                                                    \
       {                                                                 \
         r = SparseBoolMatrix (nr, nc, true);                            \
         for (octave_idx_type j = 0; j < nc; j++)                        \
           for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++)   \
-            if (! (MC (m.data (i)) OP SC (s)))                          \
+            if (! (m.data (i) OP s))                                    \
               r.data (m.ridx (i) + j * nr) = false;                     \
         r.maybe_compress (true);                                        \
       }                                                                 \
@@ -102,7 +104,7 @@
         for (octave_idx_type j = 0; j < nc; j++)                        \
           {                                                             \
             for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++) \
-              if (MC (m.data (i)) OP SC (s))                            \
+              if (m.data (i) OP s)                                      \
                 {                                                       \
                   r.ridx (nel) = m.ridx (i);                            \
                   r.data (nel++) = true;                                \
@@ -114,37 +116,33 @@
     return r;                                                           \
   }
 
-#define SPARSE_SMS_CMP_OPS(M, MZ, CM, S, SZ, CS)                \
-  SPARSE_SMS_CMP_OP (mx_el_lt, <,  M, MZ,   , S, SZ,   )        \
-  SPARSE_SMS_CMP_OP (mx_el_le, <=, M, MZ,   , S, SZ,   )        \
-  SPARSE_SMS_CMP_OP (mx_el_ge, >=, M, MZ,   , S, SZ,   )        \
-  SPARSE_SMS_CMP_OP (mx_el_gt, >,  M, MZ,   , S, SZ,   )        \
-  SPARSE_SMS_CMP_OP (mx_el_eq, ==, M, MZ,   , S, SZ,   )        \
-  SPARSE_SMS_CMP_OP (mx_el_ne, !=, M, MZ,   , S, SZ,   )
+#define SPARSE_SMS_CMP_OPS(M, S)                \
+  SPARSE_SMS_CMP_OP (mx_el_lt, <,  M, S)        \
+  SPARSE_SMS_CMP_OP (mx_el_le, <=, M, S)        \
+  SPARSE_SMS_CMP_OP (mx_el_ge, >=, M, S)        \
+  SPARSE_SMS_CMP_OP (mx_el_gt, >,  M, S)        \
+  SPARSE_SMS_CMP_OP (mx_el_eq, ==, M, S)        \
+  SPARSE_SMS_CMP_OP (mx_el_ne, !=, M, S)
 
-#define SPARSE_SMS_EQNE_OPS(M, MZ, CM, S, SZ, CS)               \
-  SPARSE_SMS_CMP_OP (mx_el_eq, ==, M, MZ,   , S, SZ,   )        \
-  SPARSE_SMS_CMP_OP (mx_el_ne, !=, M, MZ,   , S, SZ,   )
+#define SPARSE_SMS_EQNE_OPS(M, S)               \
+  SPARSE_SMS_CMP_OP (mx_el_eq, ==, M, S)        \
+  SPARSE_SMS_CMP_OP (mx_el_ne, !=, M, S)
 
-#define SPARSE_SMS_BOOL_OP(F, OP, M, S, LHS_ZERO, RHS_ZERO)             \
+#define SPARSE_SMS_BOOL_OR_OP(M, S)                                     \
   SparseBoolMatrix                                                      \
-  F (const M& m, const S& s)                                            \
+  mx_el_or (const M& m, const S& s)                                     \
   {                                                                     \
     octave_idx_type nr = m.rows ();                                     \
     octave_idx_type nc = m.cols ();                                     \
     SparseBoolMatrix r;                                                 \
                                                                         \
+    M::element_type lhs_zero = M::element_type ();                      \
+    S rhs_zero = S ();                                                  \
+                                                                        \
     if (nr > 0 && nc > 0)                                               \
       {                                                                 \
-        if (LHS_ZERO OP (s != RHS_ZERO))                                \
-          {                                                             \
-            r = SparseBoolMatrix (nr, nc, true);                        \
-            for (octave_idx_type j = 0; j < nc; j++)                    \
-              for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++) \
-                if (! ((m.data (i) != LHS_ZERO) OP (s != RHS_ZERO)))    \
-                  r.data (m.ridx (i) + j * nr) = false;                 \
-            r.maybe_compress (true);                                    \
-          }                                                             \
+        if (s != rhs_zero)                                              \
+          r = SparseBoolMatrix (nr, nc, true);                          \
         else                                                            \
           {                                                             \
             r = SparseBoolMatrix (nr, nc, m.nnz ());                    \
@@ -153,7 +151,7 @@
             for (octave_idx_type j = 0; j < nc; j++)                    \
               {                                                         \
                 for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++) \
-                  if ((m.data (i) != LHS_ZERO) OP (s != RHS_ZERO))      \
+                  if (m.data (i) != lhs_zero)                           \
                     {                                                   \
                       r.ridx (nel) = m.ridx (i);                        \
                       r.data (nel++) = true;                            \
@@ -166,12 +164,45 @@
     return r;                                                           \
   }
 
-#define SPARSE_SMS_BOOL_OPS2(M, S, LHS_ZERO, RHS_ZERO)          \
-  SPARSE_SMS_BOOL_OP (mx_el_and, &&, M, S, LHS_ZERO, RHS_ZERO)  \
-  SPARSE_SMS_BOOL_OP (mx_el_or,  ||, M, S, LHS_ZERO, RHS_ZERO)
+#define SPARSE_SMS_BOOL_AND_OP(M, S)                                    \
+  SparseBoolMatrix                                                      \
+  mx_el_and (const M& m, const S& s)                                    \
+  {                                                                     \
+    octave_idx_type nr = m.rows ();                                     \
+    octave_idx_type nc = m.cols ();                                     \
+    SparseBoolMatrix r;                                                 \
+                                                                        \
+    M::element_type lhs_zero = M::element_type ();                      \
+    S rhs_zero = S ();                                                  \
+                                                                        \
+    if (nr > 0 && nc > 0)                                               \
+      {                                                                 \
+        if (s != rhs_zero)                                              \
+          {                                                             \
+            r = SparseBoolMatrix (nr, nc, m.nnz ());                    \
+            r.cidx (0) = static_cast<octave_idx_type> (0);              \
+            octave_idx_type nel = 0;                                    \
+            for (octave_idx_type j = 0; j < nc; j++)                    \
+              {                                                         \
+                for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++) \
+                  if (m.data (i) != lhs_zero)                           \
+                    {                                                   \
+                      r.ridx (nel) = m.ridx (i);                        \
+                      r.data (nel++) = true;                            \
+                    }                                                   \
+                r.cidx (j + 1) = nel;                                   \
+              }                                                         \
+            r.maybe_compress (false);                                   \
+          }                                                             \
+        else                                                            \
+          r = SparseBoolMatrix (nr, nc);                                \
+      }                                                                 \
+    return r;                                                           \
+  }
 
-#define SPARSE_SMS_BOOL_OPS(M, S, ZERO)         \
-  SPARSE_SMS_BOOL_OPS2(M, S, ZERO, ZERO)
+#define SPARSE_SMS_BOOL_OPS(M, S)               \
+  SPARSE_SMS_BOOL_AND_OP (M, S)                 \
+  SPARSE_SMS_BOOL_OR_OP (M, S)
 
 // scalar by sparse matrix operations.
 
@@ -219,7 +250,7 @@
   SPARSE_SSM_BIN_OP_2 (R2, operator *, *, S, M) \
   SPARSE_SSM_BIN_OP_2 (R2, operator /, /, S, M)
 
-#define SPARSE_SSM_CMP_OP(F, OP, S, SZ, SC, M, MZ, MC)                  \
+#define SPARSE_SSM_CMP_OP(F, OP, S, M)                                  \
   SparseBoolMatrix                                                      \
   F (const S& s, const M& m)                                            \
   {                                                                     \
@@ -227,12 +258,14 @@
     octave_idx_type nc = m.cols ();                                     \
     SparseBoolMatrix r;                                                 \
                                                                         \
-    if (SC (s) OP SC (MZ))                                              \
+    M::element_type m_zero = M::element_type ();                        \
+                                                                        \
+    if (s OP m_zero)                                                    \
       {                                                                 \
         r = SparseBoolMatrix (nr, nc, true);                            \
         for (octave_idx_type j = 0; j < nc; j++)                        \
           for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++)   \
-            if (! (SC (s) OP MC (m.data (i))))                          \
+            if (! (s OP m.data (i)))                                    \
               r.data (m.ridx (i) + j * nr) = false;                     \
         r.maybe_compress (true);                                        \
       }                                                                 \
@@ -244,7 +277,7 @@
         for (octave_idx_type j = 0; j < nc; j++)                        \
           {                                                             \
             for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++) \
-              if (SC (s) OP MC (m.data (i)))                            \
+              if (s OP m.data (i))                                      \
                 {                                                       \
                   r.ridx (nel) = m.ridx (i);                            \
                   r.data (nel++) = true;                                \
@@ -256,37 +289,33 @@
     return r;                                                           \
   }
 
-#define SPARSE_SSM_CMP_OPS(S, SZ, SC, M, MZ, MC)                \
-  SPARSE_SSM_CMP_OP (mx_el_lt, <,  S, SZ,   , M, MZ,   )        \
-  SPARSE_SSM_CMP_OP (mx_el_le, <=, S, SZ,   , M, MZ,   )        \
-  SPARSE_SSM_CMP_OP (mx_el_ge, >=, S, SZ,   , M, MZ,   )        \
-  SPARSE_SSM_CMP_OP (mx_el_gt, >,  S, SZ,   , M, MZ,   )        \
-  SPARSE_SSM_CMP_OP (mx_el_eq, ==, S, SZ,   , M, MZ,   )        \
-  SPARSE_SSM_CMP_OP (mx_el_ne, !=, S, SZ,   , M, MZ,   )
+#define SPARSE_SSM_CMP_OPS(S, M)                \
+  SPARSE_SSM_CMP_OP (mx_el_lt, <,  S, M)        \
+  SPARSE_SSM_CMP_OP (mx_el_le, <=, S, M)        \
+  SPARSE_SSM_CMP_OP (mx_el_ge, >=, S, M)        \
+  SPARSE_SSM_CMP_OP (mx_el_gt, >,  S, M)        \
+  SPARSE_SSM_CMP_OP (mx_el_eq, ==, S, M)        \
+  SPARSE_SSM_CMP_OP (mx_el_ne, !=, S, M)
 
-#define SPARSE_SSM_EQNE_OPS(S, SZ, SC, M, MZ, MC)               \
-  SPARSE_SSM_CMP_OP (mx_el_eq, ==, S, SZ,   , M, MZ,   )        \
-  SPARSE_SSM_CMP_OP (mx_el_ne, !=, S, SZ,   , M, MZ,   )
+#define SPARSE_SSM_EQNE_OPS(S, M)               \
+  SPARSE_SSM_CMP_OP (mx_el_eq, ==, S, M)        \
+  SPARSE_SSM_CMP_OP (mx_el_ne, !=, S, M)
 
-#define SPARSE_SSM_BOOL_OP(F, OP, S, M, LHS_ZERO, RHS_ZERO)             \
+#define SPARSE_SSM_BOOL_OR_OP(S, M)                                     \
   SparseBoolMatrix                                                      \
-  F (const S& s, const M& m)                                            \
+  mx_el_or (const S& s, const M& m)                                     \
   {                                                                     \
     octave_idx_type nr = m.rows ();                                     \
     octave_idx_type nc = m.cols ();                                     \
     SparseBoolMatrix r;                                                 \
                                                                         \
+    S lhs_zero = S ();                                                  \
+    M::element_type rhs_zero = M::element_type ();                      \
+                                                                        \
     if (nr > 0 && nc > 0)                                               \
       {                                                                 \
-        if ((s != LHS_ZERO) OP RHS_ZERO)                                \
-          {                                                             \
-            r = SparseBoolMatrix (nr, nc, true);                        \
-            for (octave_idx_type j = 0; j < nc; j++)                    \
-              for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++) \
-                if (! ((s != LHS_ZERO) OP (m.data (i) != RHS_ZERO)))    \
-                  r.data (m.ridx (i) + j * nr) = false;                 \
-            r.maybe_compress (true);                                    \
-          }                                                             \
+        if (s != lhs_zero)                                              \
+          r = SparseBoolMatrix (nr, nc, true);                          \
         else                                                            \
           {                                                             \
             r = SparseBoolMatrix (nr, nc, m.nnz ());                    \
@@ -295,7 +324,7 @@
             for (octave_idx_type j = 0; j < nc; j++)                    \
               {                                                         \
                 for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++) \
-                  if ((s != LHS_ZERO) OP (m.data (i) != RHS_ZERO))      \
+                  if (m.data (i) != rhs_zero)                           \
                     {                                                   \
                       r.ridx (nel) = m.ridx (i);                        \
                       r.data (nel++) = true;                            \
@@ -308,12 +337,45 @@
     return r;                                                           \
   }
 
-#define SPARSE_SSM_BOOL_OPS2(S, M, LHS_ZERO, RHS_ZERO)          \
-  SPARSE_SSM_BOOL_OP (mx_el_and, &&, S, M, LHS_ZERO, RHS_ZERO)  \
-  SPARSE_SSM_BOOL_OP (mx_el_or,  ||, S, M, LHS_ZERO, RHS_ZERO)
+#define SPARSE_SSM_BOOL_AND_OP(S, M)                                    \
+  SparseBoolMatrix                                                      \
+  mx_el_and (const S& s, const M& m)                                    \
+  {                                                                     \
+    octave_idx_type nr = m.rows ();                                     \
+    octave_idx_type nc = m.cols ();                                     \
+    SparseBoolMatrix r;                                                 \
+                                                                        \
+    S lhs_zero = S ();                                                  \
+    M::element_type rhs_zero = M::element_type ();                      \
+                                                                        \
+    if (nr > 0 && nc > 0)                                               \
+      {                                                                 \
+        if (s != lhs_zero)                                              \
+          {                                                             \
+            r = SparseBoolMatrix (nr, nc, m.nnz ());                    \
+            r.cidx (0) = static_cast<octave_idx_type> (0);              \
+            octave_idx_type nel = 0;                                    \
+            for (octave_idx_type j = 0; j < nc; j++)                    \
+              {                                                         \
+                for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++) \
+                  if (m.data (i) != rhs_zero)                           \
+                    {                                                   \
+                      r.ridx (nel) = m.ridx (i);                        \
+                      r.data (nel++) = true;                            \
+                    }                                                   \
+                r.cidx (j + 1) = nel;                                   \
+              }                                                         \
+            r.maybe_compress (false);                                   \
+          }                                                             \
+        else                                                            \
+          r = SparseBoolMatrix (nr, nc);                                \
+      }                                                                 \
+    return r;                                                           \
+  }
 
-#define SPARSE_SSM_BOOL_OPS(S, M, ZERO)         \
-  SPARSE_SSM_BOOL_OPS2(S, M, ZERO, ZERO)
+#define SPARSE_SSM_BOOL_OPS(S, M)               \
+  SPARSE_SSM_BOOL_AND_OP (S, M)                 \
+  SPARSE_SSM_BOOL_OR_OP (S, M)
 
 // sparse matrix by sparse matrix operations.
 
@@ -660,7 +722,7 @@
 // FIXME: this macro duplicates the bodies of the template functions
 // defined in the SPARSE_SSM_CMP_OP and SPARSE_SMS_CMP_OP macros.
 
-#define SPARSE_SMSM_CMP_OP(F, OP, M1, Z1, C1, M2, Z2, C2)               \
+#define SPARSE_SMSM_CMP_OP(F, OP, M1, M2)                               \
   SparseBoolMatrix                                                      \
   F (const M1& m1, const M2& m2)                                        \
   {                                                                     \
@@ -672,14 +734,17 @@
     octave_idx_type m2_nr = m2.rows ();                                 \
     octave_idx_type m2_nc = m2.cols ();                                 \
                                                                         \
+    M1::element_type Z1 = M1::element_type ();                          \
+    M2::element_type Z2 = M2::element_type ();                          \
+                                                                        \
     if (m1_nr == 1 && m1_nc == 1)                                       \
       {                                                                 \
-        if (C1 (m1.elem (0,0)) OP C2 (Z2))                              \
+        if (m1.elem (0,0) OP Z2)                                        \
           {                                                             \
             r = SparseBoolMatrix (m2_nr, m2_nc, true);                  \
             for (octave_idx_type j = 0; j < m2_nc; j++)                 \
               for (octave_idx_type i = m2.cidx (j); i < m2.cidx (j+1); i++) \
-                if (! (C1 (m1.elem (0,0)) OP C2 (m2.data (i))))         \
+                if (! (m1.elem (0,0) OP m2.data (i)))                   \
                   r.data (m2.ridx (i) + j * m2_nr) = false;             \
             r.maybe_compress (true);                                    \
           }                                                             \
@@ -691,7 +756,7 @@
             for (octave_idx_type j = 0; j < m2_nc; j++)                 \
               {                                                         \
                 for (octave_idx_type i = m2.cidx (j); i < m2.cidx (j+1); i++) \
-                  if (C1 (m1.elem (0,0)) OP C2 (m2.data (i)))           \
+                  if (m1.elem (0,0) OP m2.data (i))                     \
                     {                                                   \
                       r.ridx (nel) = m2.ridx (i);                       \
                       r.data (nel++) = true;                            \
@@ -703,12 +768,12 @@
       }                                                                 \
     else if (m2_nr == 1 && m2_nc == 1)                                  \
       {                                                                 \
-        if (C1 (Z1) OP C2 (m2.elem (0,0)))                              \
+        if (Z1 OP m2.elem (0,0))                                        \
           {                                                             \
             r = SparseBoolMatrix (m1_nr, m1_nc, true);                  \
             for (octave_idx_type j = 0; j < m1_nc; j++)                 \
               for (octave_idx_type i = m1.cidx (j); i < m1.cidx (j+1); i++) \
-                if (! (C1 (m1.data (i)) OP C2 (m2.elem (0,0))))         \
+                if (! (m1.data (i) OP m2.elem (0,0)))                   \
                   r.data (m1.ridx (i) + j * m1_nr) = false;             \
             r.maybe_compress (true);                                    \
           }                                                             \
@@ -720,7 +785,7 @@
             for (octave_idx_type j = 0; j < m1_nc; j++)                 \
               {                                                         \
                 for (octave_idx_type i = m1.cidx (j); i < m1.cidx (j+1); i++) \
-                  if (C1 (m1.data (i)) OP C2 (m2.elem (0,0)))           \
+                  if (m1.data (i) OP m2.elem (0,0))                     \
                     {                                                   \
                       r.ridx (nel) = m1.ridx (i);                       \
                       r.data (nel++) = true;                            \
@@ -734,7 +799,7 @@
       {                                                                 \
         if (m1_nr != 0 || m1_nc != 0)                                   \
           {                                                             \
-            if (C1 (Z1) OP C2 (Z2))                                     \
+            if (Z1 OP Z2)                                               \
               {                                                         \
                 r = SparseBoolMatrix (m1_nr, m1_nc, true);              \
                 for (octave_idx_type j = 0; j < m1_nc; j++)             \
@@ -747,19 +812,19 @@
                       {                                                 \
                         if (i1 == e1 || (i2 < e2 && m1.ridx (i1) > m2.ridx (i2))) \
                           {                                             \
-                            if (! (C1 (Z1) OP C2 (m2.data (i2))))       \
+                            if (! (Z1 OP m2.data (i2)))                 \
                               r.data (m2.ridx (i2) + j * m1_nr) = false; \
                             i2++;                                       \
                           }                                             \
                         else if (i2 == e2 || m1.ridx (i1) < m2.ridx (i2)) \
                           {                                             \
-                            if (! (C1 (m1.data (i1)) OP C2 (Z2)))       \
+                            if (! (m1.data (i1) OP Z2))                 \
                               r.data (m1.ridx (i1) + j * m1_nr) = false; \
                             i1++;                                       \
                           }                                             \
                         else                                            \
                           {                                             \
-                            if (! (C1 (m1.data (i1)) OP C2 (m2.data (i2)))) \
+                            if (! (m1.data (i1) OP m2.data (i2)))       \
                               r.data (m1.ridx (i1) + j * m1_nr) = false; \
                             i1++;                                       \
                             i2++;                                       \
@@ -783,7 +848,7 @@
                       {                                                 \
                         if (i1 == e1 || (i2 < e2 && m1.ridx (i1) > m2.ridx (i2))) \
                           {                                             \
-                            if (C1 (Z1) OP C2 (m2.data (i2)))           \
+                            if (Z1 OP m2.data (i2))                     \
                               {                                         \
                                 r.ridx (nel) = m2.ridx (i2);            \
                                 r.data (nel++) = true;                  \
@@ -792,7 +857,7 @@
                           }                                             \
                         else if (i2 == e2 || m1.ridx (i1) < m2.ridx (i2)) \
                           {                                             \
-                            if (C1 (m1.data (i1)) OP C2 (Z2))           \
+                            if (m1.data (i1) OP Z2)                     \
                               {                                         \
                                 r.ridx (nel) = m1.ridx (i1);            \
                                 r.data (nel++) = true;                  \
@@ -801,7 +866,7 @@
                           }                                             \
                         else                                            \
                           {                                             \
-                            if (C1 (m1.data (i1)) OP C2 (m2.data (i2))) \
+                            if (m1.data (i1) OP m2.data (i2))           \
                               {                                         \
                                 r.ridx (nel) = m1.ridx (i1);            \
                                 r.data (nel++) = true;                  \
@@ -824,24 +889,23 @@
     return r;                                                           \
   }
 
-#define SPARSE_SMSM_CMP_OPS(M1, Z1, C1, M2, Z2, C2)             \
-  SPARSE_SMSM_CMP_OP (mx_el_lt, <,  M1, Z1,   , M2, Z2,   )     \
-  SPARSE_SMSM_CMP_OP (mx_el_le, <=, M1, Z1,   , M2, Z2,   )     \
-  SPARSE_SMSM_CMP_OP (mx_el_ge, >=, M1, Z1,   , M2, Z2,   )     \
-  SPARSE_SMSM_CMP_OP (mx_el_gt, >,  M1, Z1,   , M2, Z2,   )     \
-  SPARSE_SMSM_CMP_OP (mx_el_eq, ==, M1, Z1,   , M2, Z2,   )     \
-  SPARSE_SMSM_CMP_OP (mx_el_ne, !=, M1, Z1,   , M2, Z2,   )
+#define SPARSE_SMSM_CMP_OPS(M1, M2)             \
+  SPARSE_SMSM_CMP_OP (mx_el_lt, <,  M1, M2)     \
+  SPARSE_SMSM_CMP_OP (mx_el_le, <=, M1, M2)     \
+  SPARSE_SMSM_CMP_OP (mx_el_ge, >=, M1, M2)     \
+  SPARSE_SMSM_CMP_OP (mx_el_gt, >,  M1, M2)     \
+  SPARSE_SMSM_CMP_OP (mx_el_eq, ==, M1, M2)     \
+  SPARSE_SMSM_CMP_OP (mx_el_ne, !=, M1, M2)
 
-#define SPARSE_SMSM_EQNE_OPS(M1, Z1, C1, M2, Z2, C2)            \
-  SPARSE_SMSM_CMP_OP (mx_el_eq, ==, M1, Z1,   , M2, Z2,   )     \
-  SPARSE_SMSM_CMP_OP (mx_el_ne, !=, M1, Z1,   , M2, Z2,   )
+#define SPARSE_SMSM_EQNE_OPS(M1, M2)            \
+  SPARSE_SMSM_CMP_OP (mx_el_eq, ==, M1, M2)     \
+  SPARSE_SMSM_CMP_OP (mx_el_ne, !=, M1, M2)
 
-// FIXME: this macro duplicates the bodies of the template functions
-// defined in the SPARSE_SSM_BOOL_OP and SPARSE_SMS_BOOL_OP macros.
-
-#define SPARSE_SMSM_BOOL_OP(F, OP, M1, M2, LHS_ZERO, RHS_ZERO)          \
+#define SPARSE_SMSM_BOOL_AND_OP(M1, M2)                                 \
+  extern SparseBoolMatrix mx_el_and (const M1&, const M2::element_type&); \
+  extern SparseBoolMatrix mx_el_and (const M1::element_type&, const M2&); \
   SparseBoolMatrix                                                      \
-  F (const M1& m1, const M2& m2)                                        \
+  mx_el_and (const M1& m1, const M2& m2)                                \
   {                                                                     \
     SparseBoolMatrix r;                                                 \
                                                                         \
@@ -851,70 +915,77 @@
     octave_idx_type m2_nr = m2.rows ();                                 \
     octave_idx_type m2_nc = m2.cols ();                                 \
                                                                         \
+    M1::element_type lhs_zero = M1::element_type ();                    \
+    M2::element_type rhs_zero = M2::element_type ();                    \
+                                                                        \
     if (m1_nr == 1 && m1_nc == 1)                                       \
+      return mx_el_and (m1.elem (0,0), m2);                             \
+    else if (m2_nr == 1 && m2_nc == 1)                                  \
+      return mx_el_and (m1, m2.elem (0,0));                             \
+    else if (m1_nr == m2_nr && m1_nc == m2_nc)                          \
       {                                                                 \
-        if (m2_nr > 0 && m2_nc > 0)                                     \
+        if (m1_nr != 0 || m1_nc != 0)                                   \
           {                                                             \
-            if ((m1.elem (0,0) != LHS_ZERO) OP RHS_ZERO)                \
-              {                                                         \
-                r = SparseBoolMatrix (m2_nr, m2_nc, true);              \
-                for (octave_idx_type j = 0; j < m2_nc; j++)             \
-                  for (octave_idx_type i = m2.cidx (j); i < m2.cidx (j+1); i++) \
-                    if (! ((m1.elem (0,0) != LHS_ZERO) OP (m2.data (i) != RHS_ZERO))) \
-                      r.data (m2.ridx (i) + j * m2_nr) = false;         \
-                r.maybe_compress (true);                                \
-              }                                                         \
-            else                                                        \
+            r = SparseBoolMatrix (m1_nr, m1_nc, m1.nnz () + m2.nnz ()); \
+            r.cidx (0) = static_cast<octave_idx_type> (0);              \
+            octave_idx_type nel = 0;                                    \
+            for (octave_idx_type j = 0; j < m1_nc; j++)                 \
               {                                                         \
-                r = SparseBoolMatrix (m2_nr, m2_nc, m2.nnz ());         \
-                r.cidx (0) = static_cast<octave_idx_type> (0);          \
-                octave_idx_type nel = 0;                                \
-                for (octave_idx_type j = 0; j < m2_nc; j++)             \
+                octave_idx_type i1 = m1.cidx (j);                       \
+                octave_idx_type e1 = m1.cidx (j+1);                     \
+                octave_idx_type i2 = m2.cidx (j);                       \
+                octave_idx_type e2 = m2.cidx (j+1);                     \
+                while (i1 < e1 || i2 < e2)                              \
                   {                                                     \
-                    for (octave_idx_type i = m2.cidx (j); i < m2.cidx (j+1); i++) \
-                      if ((m1.elem (0,0) != LHS_ZERO) OP (m2.data (i) != RHS_ZERO)) \
-                        {                                               \
-                          r.ridx (nel) = m2.ridx (i);                   \
-                          r.data (nel++) = true;                        \
-                        }                                               \
-                    r.cidx (j + 1) = nel;                               \
+                    if (i1 == e1 || (i2 < e2 && m1.ridx (i1) > m2.ridx (i2))) \
+                      i2++;                                             \
+                    else if (i2 == e2 || m1.ridx (i1) < m2.ridx (i2))   \
+                      i1++;                                             \
+                    else                                                \
+                      {                                                 \
+                        if (m1.data (i1) != lhs_zero && m2.data (i2) != rhs_zero) \
+                          {                                             \
+                            r.ridx (nel) = m1.ridx (i1);                \
+                            r.data (nel++) = true;                      \
+                          }                                             \
+                        i1++;                                           \
+                        i2++;                                           \
+                      }                                                 \
                   }                                                     \
-                r.maybe_compress (false);                               \
+                r.cidx (j + 1) = nel;                                   \
               }                                                         \
+            r.maybe_compress (false);                                   \
           }                                                             \
       }                                                                 \
-    else if (m2_nr == 1 && m2_nc == 1)                                  \
+    else                                                                \
       {                                                                 \
-        if (m1_nr > 0 && m1_nc > 0)                                     \
-          {                                                             \
-            if (LHS_ZERO OP (m2.elem (0,0) != RHS_ZERO))                \
-              {                                                         \
-                r = SparseBoolMatrix (m1_nr, m1_nc, true);              \
-                for (octave_idx_type j = 0; j < m1_nc; j++)             \
-                  for (octave_idx_type i = m1.cidx (j); i < m1.cidx (j+1); i++) \
-                    if (! ((m1.data (i) != LHS_ZERO) OP (m2.elem (0,0) != RHS_ZERO))) \
-                      r.data (m1.ridx (i) + j * m1_nr) = false;         \
-                r.maybe_compress (true);                                \
-              }                                                         \
-            else                                                        \
-              {                                                         \
-                r = SparseBoolMatrix (m1_nr, m1_nc, m1.nnz ());         \
-                r.cidx (0) = static_cast<octave_idx_type> (0);          \
-                octave_idx_type nel = 0;                                \
-                for (octave_idx_type j = 0; j < m1_nc; j++)             \
-                  {                                                     \
-                    for (octave_idx_type i = m1.cidx (j); i < m1.cidx (j+1); i++) \
-                      if ((m1.data (i) != LHS_ZERO) OP (m2.elem (0,0) != RHS_ZERO)) \
-                        {                                               \
-                          r.ridx (nel) = m1.ridx (i);                   \
-                          r.data (nel++) = true;                        \
-                        }                                               \
-                    r.cidx (j + 1) = nel;                               \
-                  }                                                     \
-                r.maybe_compress (false);                               \
-              }                                                         \
-          }                                                             \
+        if ((m1_nr != 0 || m1_nc != 0) && (m2_nr != 0 || m2_nc != 0))   \
+          octave::err_nonconformant ("mx_el_and_", m1_nr, m1_nc, m2_nr, m2_nc); \
       }                                                                 \
+    return r;                                                           \
+  }
+
+#define SPARSE_SMSM_BOOL_OR_OP(M1, M2)                                  \
+  extern SparseBoolMatrix mx_el_or (const M1&, const M2::element_type&); \
+  extern SparseBoolMatrix mx_el_or (const M1::element_type&, const M2&); \
+  SparseBoolMatrix                                                      \
+  mx_el_or (const M1& m1, const M2& m2)                                 \
+  {                                                                     \
+    SparseBoolMatrix r;                                                 \
+                                                                        \
+    octave_idx_type m1_nr = m1.rows ();                                 \
+    octave_idx_type m1_nc = m1.cols ();                                 \
+                                                                        \
+    octave_idx_type m2_nr = m2.rows ();                                 \
+    octave_idx_type m2_nc = m2.cols ();                                 \
+                                                                        \
+    M1::element_type lhs_zero = M1::element_type ();                    \
+    M2::element_type rhs_zero = M2::element_type ();                    \
+                                                                        \
+    if (m1_nr == 1 && m1_nc == 1)                                       \
+      return mx_el_or (m1.elem (0,0), m2);                              \
+    else if (m2_nr == 1 && m2_nc == 1)                                  \
+      return mx_el_or (m1, m2.elem (0,0));                              \
     else if (m1_nr == m2_nr && m1_nc == m2_nc)                          \
       {                                                                 \
         if (m1_nr != 0 || m1_nc != 0)                                   \
@@ -932,7 +1003,7 @@
                   {                                                     \
                     if (i1 == e1 || (i2 < e2 && m1.ridx (i1) > m2.ridx (i2))) \
                       {                                                 \
-                        if (LHS_ZERO OP m2.data (i2) != RHS_ZERO)       \
+                        if (m2.data (i2) != rhs_zero)                   \
                           {                                             \
                             r.ridx (nel) = m2.ridx (i2);                \
                             r.data (nel++) = true;                      \
@@ -941,7 +1012,7 @@
                       }                                                 \
                     else if (i2 == e2 || m1.ridx (i1) < m2.ridx (i2))   \
                       {                                                 \
-                        if (m1.data (i1) != LHS_ZERO OP RHS_ZERO)       \
+                        if (m1.data (i1) != lhs_zero)                   \
                           {                                             \
                             r.ridx (nel) = m1.ridx (i1);                \
                             r.data (nel++) = true;                      \
@@ -950,7 +1021,7 @@
                       }                                                 \
                     else                                                \
                       {                                                 \
-                        if (m1.data (i1) != LHS_ZERO OP m2.data (i2) != RHS_ZERO) \
+                        if (m1.data (i1) != lhs_zero || m2.data (i2) != rhs_zero) \
                           {                                             \
                             r.ridx (nel) = m1.ridx (i1);                \
                             r.data (nel++) = true;                      \
@@ -967,17 +1038,14 @@
     else                                                                \
       {                                                                 \
         if ((m1_nr != 0 || m1_nc != 0) && (m2_nr != 0 || m2_nc != 0))   \
-          octave::err_nonconformant (#F, m1_nr, m1_nc, m2_nr, m2_nc);           \
+          octave::err_nonconformant ("mx_el_or", m1_nr, m1_nc, m2_nr, m2_nc); \
       }                                                                 \
     return r;                                                           \
   }
 
-#define SPARSE_SMSM_BOOL_OPS2(M1, M2, LHS_ZERO, RHS_ZERO)               \
-  SPARSE_SMSM_BOOL_OP (mx_el_and, &&, M1, M2, LHS_ZERO, RHS_ZERO)       \
-  SPARSE_SMSM_BOOL_OP (mx_el_or,  ||, M1, M2, LHS_ZERO, RHS_ZERO)
-
-#define SPARSE_SMSM_BOOL_OPS(M1, M2, ZERO)      \
-  SPARSE_SMSM_BOOL_OPS2(M1, M2, ZERO, ZERO)
+#define SPARSE_SMSM_BOOL_OPS(M1, M2)            \
+  SPARSE_SMSM_BOOL_AND_OP (M1, M2)              \
+  SPARSE_SMSM_BOOL_OR_OP (M1, M2)
 
 // matrix by sparse matrix operations.
 
@@ -1053,14 +1121,13 @@
     return r;                                                           \
   }
 
-// FIXME: Pass a specific ZERO value
 #define SPARSE_MSM_BIN_OPS(R1, R2, M1, M2)              \
   SPARSE_MSM_BIN_OP_1 (R1, operator +,  +, M1, M2)      \
   SPARSE_MSM_BIN_OP_1 (R1, operator -,  -, M1, M2)      \
   SPARSE_MSM_BIN_OP_2 (R2, product,     *, M1, M2)      \
   SPARSE_MSM_BIN_OP_1 (R2, quotient,    /, M1, M2)
 
-#define SPARSE_MSM_CMP_OP(F, OP, M1, C1, M2, C2)                        \
+#define SPARSE_MSM_CMP_OP(F, OP, M1, M2)                                \
   SparseBoolMatrix                                                      \
   F (const M1& m1, const M2& m2)                                        \
   {                                                                     \
@@ -1082,7 +1149,7 @@
             octave_idx_type nel = 0;                                    \
             for (octave_idx_type j = 0; j < m1_nc; j++)                 \
               for (octave_idx_type i = 0; i < m1_nr; i++)               \
-                if (C1 (m1.elem (i, j)) OP C2 (m2.elem (i, j)))         \
+                if (m1.elem (i, j) OP m2.elem (i, j))                   \
                   nel++;                                                \
                                                                         \
             r = SparseBoolMatrix (m1_nr, m1_nc, nel);                   \
@@ -1093,7 +1160,7 @@
               {                                                         \
                 for (octave_idx_type i = 0; i < m1_nr; i++)             \
                   {                                                     \
-                    bool el = C1 (m1.elem (i, j)) OP C2 (m2.elem (i, j)); \
+                    bool el = m1.elem (i, j) OP m2.elem (i, j);         \
                     if (el)                                             \
                       {                                                 \
                         r.data (ii) = el;                               \
@@ -1112,19 +1179,19 @@
     return r;                                                           \
   }
 
-#define SPARSE_MSM_CMP_OPS(M1, Z1, C1, M2, Z2, C2)      \
-  SPARSE_MSM_CMP_OP (mx_el_lt, <,  M1,   , M2,   )      \
-  SPARSE_MSM_CMP_OP (mx_el_le, <=, M1,   , M2,   )      \
-  SPARSE_MSM_CMP_OP (mx_el_ge, >=, M1,   , M2,   )      \
-  SPARSE_MSM_CMP_OP (mx_el_gt, >,  M1,   , M2,   )      \
-  SPARSE_MSM_CMP_OP (mx_el_eq, ==, M1,   , M2,   )      \
-  SPARSE_MSM_CMP_OP (mx_el_ne, !=, M1,   , M2,   )
+#define SPARSE_MSM_CMP_OPS(M1, M2)              \
+  SPARSE_MSM_CMP_OP (mx_el_lt, <,  M1, M2)      \
+  SPARSE_MSM_CMP_OP (mx_el_le, <=, M1, M2)      \
+  SPARSE_MSM_CMP_OP (mx_el_ge, >=, M1, M2)      \
+  SPARSE_MSM_CMP_OP (mx_el_gt, >,  M1, M2)      \
+  SPARSE_MSM_CMP_OP (mx_el_eq, ==, M1, M2)      \
+  SPARSE_MSM_CMP_OP (mx_el_ne, !=, M1, M2)
 
-#define SPARSE_MSM_EQNE_OPS(M1, Z1, C1, M2, Z2, C2)     \
-  SPARSE_MSM_CMP_OP (mx_el_eq, ==, M1,   , M2,   )      \
-  SPARSE_MSM_CMP_OP (mx_el_ne, !=, M1,   , M2,   )
+#define SPARSE_MSM_EQNE_OPS(M1, M2)             \
+  SPARSE_MSM_CMP_OP (mx_el_eq, ==, M1, M2)      \
+  SPARSE_MSM_CMP_OP (mx_el_ne, !=, M1, M2)
 
-#define SPARSE_MSM_BOOL_OP(F, OP, M1, M2, LHS_ZERO, RHS_ZERO)           \
+#define SPARSE_MSM_BOOL_OP(F, OP, M1, M2)                               \
   SparseBoolMatrix                                                      \
   F (const M1& m1, const M2& m2)                                        \
   {                                                                     \
@@ -1136,6 +1203,9 @@
     octave_idx_type m2_nr = m2.rows ();                                 \
     octave_idx_type m2_nc = m2.cols ();                                 \
                                                                         \
+    M1::element_type lhs_zero = M1::element_type ();                    \
+    M2::element_type rhs_zero = M2::element_type ();                    \
+                                                                        \
     if (m2_nr == 1 && m2_nc == 1)                                       \
       r = SparseBoolMatrix (F (m1, m2.elem (0,0)));                     \
     else if (m1_nr == m2_nr && m1_nc == m2_nc)                          \
@@ -1146,8 +1216,8 @@
             octave_idx_type nel = 0;                                    \
             for (octave_idx_type j = 0; j < m1_nc; j++)                 \
               for (octave_idx_type i = 0; i < m1_nr; i++)               \
-                if ((m1.elem (i, j) != LHS_ZERO)                        \
-                    OP (m2.elem (i, j) != RHS_ZERO))                    \
+                if ((m1.elem (i, j) != lhs_zero)                        \
+                    OP (m2.elem (i, j) != rhs_zero))                    \
                   nel++;                                                \
                                                                         \
             r = SparseBoolMatrix (m1_nr, m1_nc, nel);                   \
@@ -1158,8 +1228,8 @@
               {                                                         \
                 for (octave_idx_type i = 0; i < m1_nr; i++)             \
                   {                                                     \
-                    bool el = (m1.elem (i, j) != LHS_ZERO)              \
-                      OP (m2.elem (i, j) != RHS_ZERO);                  \
+                    bool el = (m1.elem (i, j) != lhs_zero)              \
+                      OP (m2.elem (i, j) != rhs_zero);                  \
                     if (el)                                             \
                       {                                                 \
                         r.data (ii) = el;                               \
@@ -1178,12 +1248,9 @@
     return r;                                                           \
   }
 
-#define SPARSE_MSM_BOOL_OPS2(M1, M2, LHS_ZERO, RHS_ZERO)                \
-  SPARSE_MSM_BOOL_OP (mx_el_and, &&, M1, M2, LHS_ZERO, RHS_ZERO)        \
-  SPARSE_MSM_BOOL_OP (mx_el_or,  ||, M1, M2, LHS_ZERO, RHS_ZERO)
-
-#define SPARSE_MSM_BOOL_OPS(M1, M2, ZERO)       \
-  SPARSE_MSM_BOOL_OPS2(M1, M2, ZERO, ZERO)
+#define SPARSE_MSM_BOOL_OPS(M1, M2)             \
+  SPARSE_MSM_BOOL_OP (mx_el_and, &&, M1, M2)    \
+  SPARSE_MSM_BOOL_OP (mx_el_or,  ||, M1, M2)
 
 // sparse matrix by matrix operations.
 
@@ -1273,7 +1340,7 @@
   SPARSE_SMM_BIN_OP_2 (R2, product,     *, M1, M2)      \
   SPARSE_SMM_BIN_OP_2 (R2, quotient,    /, M1, M2)
 
-#define SPARSE_SMM_CMP_OP(F, OP, M1, C1, M2, C2)                        \
+#define SPARSE_SMM_CMP_OP(F, OP, M1, M2)                                \
   SparseBoolMatrix                                                      \
   F (const M1& m1, const M2& m2)                                        \
   {                                                                     \
@@ -1295,7 +1362,7 @@
             octave_idx_type nel = 0;                                    \
             for (octave_idx_type j = 0; j < m1_nc; j++)                 \
               for (octave_idx_type i = 0; i < m1_nr; i++)               \
-                if (C1 (m1.elem (i, j)) OP C2 (m2.elem (i, j)))         \
+                if (m1.elem (i, j) OP m2.elem (i, j))                   \
                   nel++;                                                \
                                                                         \
             r = SparseBoolMatrix (m1_nr, m1_nc, nel);                   \
@@ -1306,7 +1373,7 @@
               {                                                         \
                 for (octave_idx_type i = 0; i < m1_nr; i++)             \
                   {                                                     \
-                    bool el = C1 (m1.elem (i, j)) OP C2 (m2.elem (i, j)); \
+                    bool el = m1.elem (i, j) OP m2.elem (i, j);         \
                     if (el)                                             \
                       {                                                 \
                         r.data (ii) = el;                               \
@@ -1325,19 +1392,19 @@
     return r;                                                           \
   }
 
-#define SPARSE_SMM_CMP_OPS(M1, Z1, C1, M2, Z2, C2)      \
-  SPARSE_SMM_CMP_OP (mx_el_lt, <,  M1,   , M2,   )      \
-  SPARSE_SMM_CMP_OP (mx_el_le, <=, M1,   , M2,   )      \
-  SPARSE_SMM_CMP_OP (mx_el_ge, >=, M1,   , M2,   )      \
-  SPARSE_SMM_CMP_OP (mx_el_gt, >,  M1,   , M2,   )      \
-  SPARSE_SMM_CMP_OP (mx_el_eq, ==, M1,   , M2,   )      \
-  SPARSE_SMM_CMP_OP (mx_el_ne, !=, M1,   , M2,   )
+#define SPARSE_SMM_CMP_OPS(M1, M2)              \
+  SPARSE_SMM_CMP_OP (mx_el_lt, <,  M1, M2)      \
+  SPARSE_SMM_CMP_OP (mx_el_le, <=, M1, M2)      \
+  SPARSE_SMM_CMP_OP (mx_el_ge, >=, M1, M2)      \
+  SPARSE_SMM_CMP_OP (mx_el_gt, >,  M1, M2)      \
+  SPARSE_SMM_CMP_OP (mx_el_eq, ==, M1, M2)      \
+  SPARSE_SMM_CMP_OP (mx_el_ne, !=, M1, M2)
 
-#define SPARSE_SMM_EQNE_OPS(M1, Z1, C1, M2, Z2, C2)     \
-  SPARSE_SMM_CMP_OP (mx_el_eq, ==, M1,   , M2,   )      \
-  SPARSE_SMM_CMP_OP (mx_el_ne, !=, M1,   , M2,   )
+#define SPARSE_SMM_EQNE_OPS(M1, M2)             \
+  SPARSE_SMM_CMP_OP (mx_el_eq, ==, M1, M2)      \
+  SPARSE_SMM_CMP_OP (mx_el_ne, !=, M1, M2)
 
-#define SPARSE_SMM_BOOL_OP(F, OP, M1, M2, LHS_ZERO, RHS_ZERO)           \
+#define SPARSE_SMM_BOOL_OP(F, OP, M1, M2)                               \
   SparseBoolMatrix                                                      \
   F (const M1& m1, const M2& m2)                                        \
   {                                                                     \
@@ -1349,6 +1416,9 @@
     octave_idx_type m2_nr = m2.rows ();                                 \
     octave_idx_type m2_nc = m2.cols ();                                 \
                                                                         \
+    M1::element_type lhs_zero = M1::element_type ();                    \
+    M2::element_type rhs_zero = M2::element_type ();                    \
+                                                                        \
     if (m1_nr == 1 && m1_nc == 1)                                       \
       r = SparseBoolMatrix (F (m1.elem (0,0), m2));                     \
     else if (m1_nr == m2_nr && m1_nc == m2_nc)                          \
@@ -1359,8 +1429,8 @@
             octave_idx_type nel = 0;                                    \
             for (octave_idx_type j = 0; j < m1_nc; j++)                 \
               for (octave_idx_type i = 0; i < m1_nr; i++)               \
-                if ((m1.elem (i, j) != LHS_ZERO)                        \
-                    OP (m2.elem (i, j) != RHS_ZERO))                    \
+                if ((m1.elem (i, j) != lhs_zero)                        \
+                    OP (m2.elem (i, j) != rhs_zero))                    \
                   nel++;                                                \
                                                                         \
             r = SparseBoolMatrix (m1_nr, m1_nc, nel);                   \
@@ -1371,8 +1441,8 @@
               {                                                         \
                 for (octave_idx_type i = 0; i < m1_nr; i++)             \
                   {                                                     \
-                    bool el = (m1.elem (i, j) != LHS_ZERO)              \
-                      OP (m2.elem (i, j) != RHS_ZERO);                  \
+                    bool el = (m1.elem (i, j) != lhs_zero)              \
+                      OP (m2.elem (i, j) != rhs_zero);                  \
                     if (el)                                             \
                       {                                                 \
                         r.data (ii) = el;                               \
@@ -1391,12 +1461,9 @@
     return r;                                                           \
   }
 
-#define SPARSE_SMM_BOOL_OPS2(M1, M2, LHS_ZERO, RHS_ZERO)                \
-  SPARSE_SMM_BOOL_OP (mx_el_and, &&, M1, M2, LHS_ZERO, RHS_ZERO)        \
-  SPARSE_SMM_BOOL_OP (mx_el_or,  ||, M1, M2, LHS_ZERO, RHS_ZERO)
-
-#define SPARSE_SMM_BOOL_OPS(M1, M2, ZERO)       \
-  SPARSE_SMM_BOOL_OPS2(M1, M2, ZERO, ZERO)
+#define SPARSE_SMM_BOOL_OPS(M1, M2)             \
+  SPARSE_SMM_BOOL_OP (mx_el_and, &&, M1, M2)    \
+  SPARSE_SMM_BOOL_OP (mx_el_or,  ||, M1, M2)
 
 // Avoid some code duplication.  Maybe we should use templates.
 
@@ -1858,7 +1925,7 @@
         }                                                               \
     }
 
-#define SPARSE_FULL_MUL(RET_TYPE, EL_TYPE, ZERO)                        \
+#define SPARSE_FULL_MUL(RET_TYPE, EL_TYPE)                              \
   octave_idx_type nr = m.rows ();                                       \
   octave_idx_type nc = m.cols ();                                       \
                                                                         \
@@ -1874,7 +1941,9 @@
     octave::err_nonconformant ("operator *", nr, nc, a_nr, a_nc);               \
   else                                                                  \
     {                                                                   \
-      RET_TYPE retval (nr, a_nc, ZERO);                                 \
+      RET_TYPE::element_type zero = RET_TYPE::element_type ();          \
+                                                                        \
+      RET_TYPE retval (nr, a_nc, zero);                                 \
                                                                         \
       for (octave_idx_type i = 0; i < a_nc ; i++)                       \
         {                                                               \
@@ -1890,7 +1959,7 @@
       return retval;                                                    \
     }
 
-#define SPARSE_FULL_TRANS_MUL(RET_TYPE, EL_TYPE, ZERO, CONJ_OP)         \
+#define SPARSE_FULL_TRANS_MUL(RET_TYPE, EL_TYPE, CONJ_OP)               \
   octave_idx_type nr = m.rows ();                                       \
   octave_idx_type nc = m.cols ();                                       \
                                                                         \
@@ -1914,7 +1983,7 @@
             {                                                           \
               octave_quit ();                                           \
                                                                         \
-              EL_TYPE acc = ZERO;                                       \
+              EL_TYPE acc = EL_TYPE ();                                 \
               for (octave_idx_type k = m.cidx (j) ; k < m.cidx (j+1); k++) \
                 acc += a.elem (m.ridx (k),i) * CONJ_OP (m.data (k));    \
               retval.xelem (j,i) = acc;                                 \
@@ -1923,7 +1992,7 @@
       return retval;                                                    \
     }
 
-#define FULL_SPARSE_MUL(RET_TYPE, EL_TYPE, ZERO)                        \
+#define FULL_SPARSE_MUL(RET_TYPE, EL_TYPE)                              \
   octave_idx_type nr = m.rows ();                                       \
   octave_idx_type nc = m.cols ();                                       \
                                                                         \
@@ -1939,7 +2008,9 @@
     octave::err_nonconformant ("operator *", nr, nc, a_nr, a_nc);               \
   else                                                                  \
     {                                                                   \
-      RET_TYPE retval (nr, a_nc, ZERO);                                 \
+      RET_TYPE::element_type zero = RET_TYPE::element_type ();          \
+                                                                        \
+      RET_TYPE retval (nr, a_nc, zero);                                 \
                                                                         \
       for (octave_idx_type i = 0; i < a_nc ; i++)                       \
         {                                                               \
@@ -1956,7 +2027,7 @@
       return retval;                                                    \
     }
 
-#define FULL_SPARSE_MUL_TRANS(RET_TYPE, EL_TYPE, ZERO, CONJ_OP)         \
+#define FULL_SPARSE_MUL_TRANS(RET_TYPE, EL_TYPE, CONJ_OP)               \
   octave_idx_type nr = m.rows ();                                       \
   octave_idx_type nc = m.cols ();                                       \
                                                                         \
@@ -1972,7 +2043,9 @@
     octave::err_nonconformant ("operator *", nr, nc, a_nc, a_nr);               \
   else                                                                  \
     {                                                                   \
-      RET_TYPE retval (nr, a_nr, ZERO);                                 \
+      RET_TYPE::element_type zero = RET_TYPE::element_type ();          \
+                                                                        \
+      RET_TYPE retval (nr, a_nr, zero);                                 \
                                                                         \
       for (octave_idx_type i = 0; i < a_nc ; i++)                       \
         {                                                               \
--- a/liboctave/operators/mk-ops.awk	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/operators/mk-ops.awk	Fri Aug 10 09:09:51 2018 +0200
@@ -89,12 +89,11 @@
     {
       ntypes++;
 
-      if (NF == 6 || NF == 7)
+      if (NF == 5 || NF == 6)
         {
-          if (NF == 7)
-            core_type[ntypes] = $7;
+          if (NF == 6)
+            core_type[ntypes] = $6;
 
-          scalar_zero_val[ntypes] = $6;
           fwd_decl_ok[ntypes] = $5 == "YES";
           header[ntypes] = $4 == "NONE" ? "" : $4;
           class[ntypes] = $3;
@@ -123,18 +122,6 @@
           eqne_ops = index (op_type, "E") != 0;
           bool_ops = index (op_type, "L") != 0;
 
-          if (cmp_ops)
-            {
-              lhs_conv = $(++n);
-              rhs_conv = $(++n);
-            }
-
-          if (lhs_conv == "NONE")
-            lhs_conv = "";
-
-          if (rhs_conv == "NONE")
-            rhs_conv = "";
-
           k = 0
           while (NF > n)
             bool_headers[k++] = $(++n);
@@ -180,12 +167,6 @@
           lhs_core_type = core_type[lhs_num];
           rhs_core_type = core_type[rhs_num];
 
-          result_scalar_zero_val_1 = scalar_zero_val[result_num_1];
-          if (sparse)
-            result_scalar_zero_val_2 = scalar_zero_val[result_num_2];
-          lhs_scalar_zero_val = scalar_zero_val[lhs_num];
-          rhs_scalar_zero_val = scalar_zero_val[rhs_num];
-
           result_header_1 = header[result_num_1];
           if (sparse)
             result_header_2 = header[result_num_2];
@@ -335,47 +316,23 @@
 
                   printf ("#include \"Sparse-op-defs.h\"\n");
                 }
-              else
-                printf ("#include \"mx-op-decl.h\"\n");
 
               if (bin_ops)
-                {
-                  if (sparse)
-                    printf ("SPARSE_%s%s_BIN_OP_DECLS (%s, %s, %s, %s, OCTAVE_API)\n",
-                            lhs_class, rhs_class, result_type_1, result_type_2,
-                            lhs_type, rhs_type);
-                  else
-                    printf ("%s%s_BIN_OP_DECLS (%s, %s, %s, OCTAVE_API)\n",
-                            lhs_class, rhs_class, result_type_1, lhs_type,
-                            rhs_type);
-                }
+                emit_bin_op_decls(sparse, lhs_class, rhs_class,
+                                  result_type_1, result_type_2,
+                                  lhs_type, rhs_type);
 
               if (cmp_ops)
-                {
-                  if (sparse)
-                    printf ("SPARSE_%s%s_CMP_OP_DECLS (%s, %s, OCTAVE_API)\n",
-                            lhs_class, rhs_class, lhs_type, rhs_type);
-                  else
-                    printf ("%s%s_CMP_OP_DECLS (%s, %s, OCTAVE_API)\n",
-                            lhs_class, rhs_class, lhs_type, rhs_type);
-                }
+                emit_cmp_op_decls(sparse, lhs_class, rhs_class,
+                                  lhs_type, rhs_type);
 
               if (eqne_ops)
-                {
-                  if (sparse)
-                    printf ("SPARSE_%s%s_EQNE_OP_DECLS (%s, %s, OCTAVE_API)\n",
-                            lhs_class, rhs_class, lhs_type, rhs_type);
-                }
+                emit_eqne_op_decls(sparse, lhs_class, rhs_class,
+                                   lhs_type, rhs_type);
 
               if (bool_ops)
-                {
-                  if (sparse)
-                    printf ("SPARSE_%s%s_BOOL_OP_DECLS (%s, %s, OCTAVE_API)\n",
-                            lhs_class, rhs_class, lhs_type, rhs_type);
-                  else
-                    printf ("%s%s_BOOL_OP_DECLS (%s, %s, OCTAVE_API)\n",
-                            lhs_class, rhs_class, lhs_type, rhs_type);
-                }
+                emit_bool_op_decls(sparse, lhs_class, rhs_class,
+                                   lhs_type, rhs_type);
 
               print "#endif";
 
@@ -411,61 +368,23 @@
               if (lhs_header && ! (lhs_header == result_header_1 || lhs_header == result_header_2))
                 printf ("#include \"%s\"\n", lhs_header);
 
-              if (rhs_header && ! (rhs_header == lhs_header || rhs_header == result_header_1 || rhs_heaer == result_header_2))
+              if (rhs_header && ! (rhs_header == lhs_header || rhs_header == result_header_1 || rhs_header == result_header_2))
                 printf ("#include \"%s\"\n", rhs_header);
 
               if (bin_ops)
-                {
-                  if (sparse)
-                    printf ("SPARSE_%s%s_BIN_OPS (%s, %s, %s, %s)\n",
-                            lhs_class, rhs_class, result_type_1,
-                            result_type_2, lhs_type, rhs_type);
-                  else
-                    {
-                      if ((lhs_class == "DM" && rhs_class == "M") || (lhs_class == "M" && rhs_class == "DM"))
-                        printf ("%s%s_BIN_OPS (%s, %s, %s, %s)\n",
-                                lhs_class, rhs_class, result_type_1,
-                                lhs_type, rhs_type, result_scalar_zero_val_1);
-                      else
-                        printf ("%s%s_BIN_OPS (%s, %s, %s)\n",
-                                lhs_class, rhs_class, result_type_1,
-                                lhs_type, rhs_type);
-                    }
-                }
+                emit_bin_ops(sparse, lhs_class, rhs_class,
+                             result_type_1, result_type_2, lhs_type, rhs_type);
 
               if (cmp_ops)
-                {
-                  if (sparse)
-                    printf ("SPARSE_%s%s_CMP_OPS (%s, %s, %s, %s, %s, %s)\n",
-                            lhs_class, rhs_class, lhs_type,
-                            lhs_scalar_zero_val, lhs_conv, rhs_type,
-                            rhs_scalar_zero_val, rhs_conv);
-                  else
-                    printf ("%s%s_CMP_OPS (%s, %s)\n",
-                            lhs_class, rhs_class, lhs_type, rhs_type);
-                }
+                emit_cmp_ops(sparse, lhs_class, rhs_class, lhs_type, rhs_type);
 
               if (eqne_ops)
-                {
-                  if (sparse)
-                    printf ("SPARSE_%s%s_EQNE_OPS (%s, %s, %s, %s, %s, %s)\n",
-                            lhs_class, rhs_class, lhs_type,
-                            lhs_scalar_zero_val, lhs_conv, rhs_type,
-                            rhs_scalar_zero_val, rhs_conv);
-
-                  ## No separate eqne ops for full-matrix or vector.
-                }
+                emit_eqne_ops(sparse, lhs_class, rhs_class,
+                              lhs_type, rhs_type);
 
               if (bool_ops)
-                {
-                  if (sparse)
-                    printf ("SPARSE_%s%s_BOOL_OPS2 (%s, %s, %s, %s)\n",
-                            lhs_class, rhs_class, lhs_type, rhs_type,
-                            lhs_scalar_zero_val, rhs_scalar_zero_val);
-                  else
-                    printf ("%s%s_BOOL_OPS (%s, %s)\n", lhs_class, rhs_class,
-                            lhs_type, rhs_type);
-                }
+                emit_bool_ops(sparse, lhs_class, rhs_class,
+                              lhs_type, rhs_type);
 
               exit (0);
             }
@@ -478,3 +397,272 @@
   if (make_inclusive_header)
     print "#endif";
 }
+
+function emit_bin_op_decl (result_type, operator, lhs_type, rhs_type)
+{
+  if (operator != "")
+    printf ("  extern OCTAVE_API %s %s (const %s&, const %s&);\n",
+            result_type, operator, lhs_type, rhs_type);
+}
+
+function emit_bin_op_decls_1 (result_type, lhs_type, rhs_type,
+                              add_op, sub_op, mul_op, div_op)
+{
+  emit_bin_op_decl(result_type, add_op, lhs_type, rhs_type);
+  emit_bin_op_decl(result_type, sub_op, lhs_type, rhs_type);
+  emit_bin_op_decl(result_type, mul_op, lhs_type, rhs_type);
+  emit_bin_op_decl(result_type, div_op, lhs_type, rhs_type);
+}
+
+function emit_sparse_bin_op_decls (result_type_1, result_type_2,
+                                   lhs_type, rhs_type,
+                                   add_op, sub_op, mul_op, div_op)
+{
+  emit_bin_op_decl(result_type_1, add_op, lhs_type, rhs_type);
+  emit_bin_op_decl(result_type_1, sub_op, lhs_type, rhs_type);
+  emit_bin_op_decl(result_type_2, mul_op, lhs_type, rhs_type);
+  emit_bin_op_decl(result_type_2, div_op, lhs_type, rhs_type);
+}
+
+function emit_bin_op_decls (sparse, lhs_class, rhs_class,
+                            result_type_1, result_type_2,
+                            lhs_type, rhs_type)
+{
+  if (sparse)
+    {
+      if ((lhs_class == "SM" && rhs_class == "S") \
+          || (lhs_class == "S" && rhs_class == "SM"))
+        emit_sparse_bin_op_decls(result_type_1, result_type_2,
+                                 lhs_type, rhs_type,
+                                 "operator +", "operator -",
+                                 "operator *", "operator /");
+
+      else if ((lhs_class == "M" && rhs_class == "SM")    \
+               || (lhs_class == "SM" && rhs_class == "M") \
+               || (lhs_class == "SM" && rhs_class == "SM"))
+        emit_sparse_bin_op_decls(result_type_1, result_type_2,
+                                 lhs_type, rhs_type,
+                                 "operator +", "operator -",
+                                 "product", "quotient");
+    }
+  else
+    {
+      if ((lhs_class == "M" && rhs_class == "S") \
+          || (lhs_class == "ND" && rhs_class == "S") \
+          || (lhs_class == "S" \
+              && (rhs_class == "M" || rhs_class == "ND" || rhs_class == "V")) \
+          || (lhs_class == "V" && rhs_class == "S"))
+        emit_bin_op_decls_1(result_type_1, lhs_type, rhs_type,
+                            "operator +", "operator -",
+                            "operator *", "operator /");
+
+      else if ((lhs_class == "M" && rhs_class == "M")      \
+               || (lhs_class == "ND" && rhs_class == "ND") \
+               || (lhs_class == "V" && rhs_class == "V"))
+        emit_bin_op_decls_1(result_type_1, lhs_type, rhs_type,
+                            "operator +", "operator -",
+                            "product", "quotient");
+
+      else if ((lhs_class == "DM" && rhs_class == "M")  \
+          || (lhs_class == "M" && rhs_class == "DM"))
+        emit_bin_op_decls_1(result_type_1, lhs_type, rhs_type,
+                            "operator +", "operator -", "operator *", "");
+
+      else if (lhs_class == "DM" && rhs_class == "DM")
+        emit_bin_op_decls_1(result_type_1, lhs_type, rhs_type,
+                            "operator +", "operator -", "product", "");
+
+      else if (lhs_class == "DM" && rhs_class == "S")
+        emit_bin_op_decls_1(result_type_1, lhs_type, rhs_type,
+                            "", "", "operator *", "operator /");
+
+      else if ((lhs_class == "M" && rhs_class == "PM") \
+               || (lhs_class == "PM" && rhs_class == "M") \
+               || (lhs_class == "S" && rhs_class == "DM"))
+        emit_bin_op_decls_1(result_type_1, lhs_type, rhs_type,
+                            "", "", "operator *", "");
+    }
+}
+
+function emit_cmp_op_decls_1(result_type, lhs_type, rhs_type)
+{
+  emit_bin_op_decl(result_type, "mx_el_lt", lhs_type, rhs_type);
+  emit_bin_op_decl(result_type, "mx_el_le", lhs_type, rhs_type);
+  emit_bin_op_decl(result_type, "mx_el_ge", lhs_type, rhs_type);
+  emit_bin_op_decl(result_type, "mx_el_gt", lhs_type, rhs_type);
+  emit_bin_op_decl(result_type, "mx_el_eq", lhs_type, rhs_type);
+  emit_bin_op_decl(result_type, "mx_el_ne", lhs_type, rhs_type);
+}
+
+function emit_cmp_op_decls (sparse, lhs_class, rhs_class, lhs_type, rhs_type)
+{
+  if (sparse)
+    {
+      if ((lhs_class == "M" && rhs_class == "SM") \
+          || (lhs_class == "SM" && (rhs_class == "M" || rhs_class == "S" || rhs_class == "SM")) \
+          || (lhs_class == "S" && rhs_class == "SM"))
+        emit_cmp_op_decls_1("SparseBoolMatrix", lhs_type, rhs_type);
+    }
+  else
+    {
+      if ((lhs_class == "M" && rhs_class == "M") \
+          || (lhs_class == "M" && rhs_class == "S") \
+          || (lhs_class == "S" && rhs_class == "M"))
+        emit_cmp_op_decls_1("boolMatrix", lhs_type, rhs_type);
+      else if ((lhs_class == "ND" && rhs_class == "ND") \
+               || (lhs_class == "ND" && rhs_class == "S") \
+               || (lhs_class == "S" && rhs_class == "ND"))
+        emit_cmp_op_decls_1("boolNDArray", lhs_type, rhs_type);
+    }
+}
+
+function emit_eqne_op_decls_1(result_type, lhs_type, rhs_type)
+{
+  emit_bin_op_decl(result_type, "mx_el_eq", lhs_type, rhs_type);
+  emit_bin_op_decl(result_type, "mx_el_ne", lhs_type, rhs_type);
+}
+
+function emit_eqne_op_decls (sparse, lhs_class, rhs_class, lhs_type, rhs_type)
+{
+  if (sparse)
+    {
+      if ((lhs_class == "M" && rhs_class == "SM") \
+          || (lhs_class == "SM" && rhs_class == "M"))
+        emit_eqne_op_decls_1("SparseBoolMatrix", lhs_type, rhs_type);
+    }
+
+  ## No separate eqne ops for full-matrix or vector.
+}
+
+function emit_bool_op_decls_1 (result_type, lhs_type, rhs_type)
+{
+  emit_bin_op_decl(result_type, "mx_el_and", lhs_type, rhs_type);
+  emit_bin_op_decl(result_type, "mx_el_or", lhs_type, rhs_type);
+}
+
+function emit_bool_op_decls_2 (result_type, lhs_type, rhs_type)
+{
+  emit_bin_op_decl(result_type, "mx_el_not_and", lhs_type, rhs_type);
+  emit_bin_op_decl(result_type, "mx_el_not_or", lhs_type, rhs_type);
+}
+
+function emit_bool_op_decls_3 (result_type, lhs_type, rhs_type)
+{
+  emit_bin_op_decl(result_type, "mx_el_and_not", lhs_type, rhs_type);
+  emit_bin_op_decl(result_type, "mx_el_or_not", lhs_type, rhs_type);
+}
+
+function emit_bool_op_decls (sparse, lhs_class, rhs_class, lhs_type, rhs_type)
+{
+  if (sparse)
+    {
+      if ((lhs_class == "M" && rhs_class == "SM") \
+          || (lhs_class == "SM" && (rhs_class == "M" || rhs_class == "S" || rhs_class == "SM")) \
+          || (lhs_class == "S" && rhs_class == "SM"))
+        emit_bool_op_decls_1("SparseBoolMatrix", lhs_type, rhs_type);
+    }
+  else
+    {
+      if ((lhs_class == "M" && rhs_class == "M") \
+          || (lhs_class == "M" && rhs_class == "S") \
+          || (lhs_class == "S" && rhs_class == "M"))
+        emit_bool_op_decls_1("boolMatrix", lhs_type, rhs_type);
+      else if (lhs_class == "ND" && rhs_class == "S")
+        {
+          emit_bool_op_decls_1("boolNDArray", lhs_type, rhs_type);
+          emit_bool_op_decls_2("boolNDArray", lhs_type, rhs_type);
+        }
+      else if (lhs_class == "S" && rhs_class == "ND")
+        {
+          emit_bool_op_decls_1("boolNDArray", lhs_type, rhs_type);
+          emit_bool_op_decls_3("boolNDArray", lhs_type, rhs_type);
+        }
+      else if (lhs_class == "ND" && rhs_class == "ND")
+        {
+          emit_bool_op_decls_1("boolNDArray", lhs_type, rhs_type);
+          emit_bool_op_decls_2("boolNDArray", lhs_type, rhs_type);
+          emit_bool_op_decls_3("boolNDArray", lhs_type, rhs_type);
+        }
+    }
+}
+
+function emit_sparse_bin_ops (lhs_class, rhs_class, result_type_1,
+                              result_type_2, lhs_type, rhs_type)
+{
+  printf ("SPARSE_%s%s_BIN_OPS (%s, %s, %s, %s)\n",
+          lhs_class, rhs_class, result_type_1,
+          result_type_2, lhs_type, rhs_type);
+}
+
+function emit_dm_bin_ops (lhs_class, rhs_class, result_type_1,
+                          lhs_type, rhs_type)
+{
+  printf ("%s%s_BIN_OPS (%s, %s, %s)\n",
+          lhs_class, rhs_class, result_type_1, lhs_type, rhs_type);
+}
+
+function emit_mm_bin_op (result_t, op, lhs_t, rhs_t, fcn)
+{
+  printf ("\n" \
+          "%s\n" \
+          "%s (const %s& m1, const %s& m2)\n" \
+          "{\n" \
+          "  return do_mm_binary_op<%s::element_type, %s::element_type, %s::element_type> (m1, m2, %s, %s, %s, \"%s\");\n" \
+          "}\n",
+          result_t, op, lhs_t, rhs_t, result_t, lhs_t, rhs_t,
+          fcn, fcn, fcn, op);
+}
+
+function emit_mm_bin_ops (result_t, lhs_t, rhs_t)
+{
+  emit_mm_bin_op(result_t, "operator +", lhs_t, rhs_t, "mx_inline_add");
+  emit_mm_bin_op(result_t, "operator -", lhs_t, rhs_t, "mx_inline_sub");
+  emit_mm_bin_op(result_t, "product", lhs_t, rhs_t, "mx_inline_mul");
+  emit_mm_bin_op(result_t, "quotient", lhs_t, rhs_t, "mx_inline_div");
+}
+
+function emit_bin_ops (sparse, lhs_class, rhs_class,
+                       result_type_1, result_type_2, lhs_type, rhs_type)
+{
+  if (sparse)
+    emit_sparse_bin_ops(lhs_class, rhs_class, result_type_1,
+                        result_type_2, lhs_type, rhs_type);
+ else if ((lhs_class == "DM" && rhs_class == "M") \
+          || (lhs_class == "M" && rhs_class == "DM"))
+    emit_dm_bin_ops(lhs_class, rhs_class, result_type_1,
+                    lhs_type, rhs_type);
+  else if (lhs_class == "M" && rhs_class == "M")
+    emit_mm_bin_ops(result_type_1, lhs_type, rhs_type);
+  else
+    printf ("%s%s_BIN_OPS (%s, %s, %s)\n",
+            lhs_class, rhs_class, result_type_1, lhs_type, rhs_type);
+}
+
+function emit_cmp_ops (sparse, lhs_class, rhs_class, lhs_type, rhs_type)
+{
+  if (sparse)
+    printf ("SPARSE_%s%s_CMP_OPS (%s, %s)\n",
+            lhs_class, rhs_class, lhs_type, rhs_type);
+  else
+    printf ("%s%s_CMP_OPS (%s, %s)\n",
+            lhs_class, rhs_class, lhs_type, rhs_type);
+}
+
+function emit_eqne_ops (sparse, lhs_class, rhs_class, lhs_type, rhs_type)
+{
+  if (sparse)
+    printf ("SPARSE_%s%s_EQNE_OPS (%s, %s)\n",
+            lhs_class, rhs_class, lhs_type, rhs_type);
+
+  ## No separate eqne ops for full-matrix or vector.
+}
+
+function emit_bool_ops (sparse, lhs_class, rhs_class, lhs_type, rhs_type)
+{
+  if (sparse)
+    printf ("SPARSE_%s%s_BOOL_OPS (%s, %s)\n",
+            lhs_class, rhs_class, lhs_type, rhs_type);
+  else
+    printf ("%s%s_BOOL_OPS (%s, %s)\n",
+            lhs_class, rhs_class, lhs_type, rhs_type);
+}
--- a/liboctave/operators/module.mk	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/operators/module.mk	Fri Aug 10 09:09:51 2018 +0200
@@ -6,6 +6,18 @@
 include %reldir%/mx-op-src.mk
 include %reldir%/smx-op-src.mk
 
+OP_MK_FILES := \
+  $(srcdir)/%reldir%/vx-op-inc.mk \
+  $(srcdir)/%reldir%/mx-op-inc.mk \
+  $(srcdir)/%reldir%/smx-op-inc.mk \
+  $(srcdir)/%reldir%/vx-op-src.mk \
+  $(srcdir)/%reldir%/mx-op-src.mk \
+  $(srcdir)/%reldir%/smx-op-src.mk
+
+$(OP_MK_FILES) : %.mk : $(srcdir)/%reldir%/config-ops.sh $(srcdir)/%reldir%/mk-ops.awk
+	$(AM_V_GEN)$(SHELL) $(srcdir)/%reldir%/config-ops.sh $(top_srcdir) `echo $(*F) | $(SED) 's/-op-.*//'` `echo $(*F) | $(SED) 's/.*-op-//'` 
+
+
 BUILT_LIBOCTAVE_OPERATORS_SOURCES = \
   $(MX_OP_SRC) \
   $(VX_OP_SRC) \
@@ -82,10 +94,6 @@
 
 %canon_reldir%_liboperators_la_CPPFLAGS = $(liboctave_liboctave_la_CPPFLAGS)
 
-%canon_reldir%_liboperators_la_CFLAGS = $(liboctave_liboctave_la_CFLAGS)
-
-%canon_reldir%_liboperators_la_CXXFLAGS = $(liboctave_liboctave_la_CXXFLAGS)
-
 liboctave_liboctave_la_LIBADD += %reldir%/liboperators.la
 
 liboctave_EXTRA_DIST += \
--- a/liboctave/operators/mx-op-defs.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/operators/mx-op-defs.h	Fri Aug 10 09:09:51 2018 +0200
@@ -421,12 +421,14 @@
     return r;                                                   \
   }
 
-#define MDM_MULTIPLY_OP(R, M, DM, R_ZERO)                               \
+#define MDM_MULTIPLY_OP(R, M, DM)                                       \
   R                                                                     \
   operator * (const M& m, const DM& dm)                                 \
   {                                                                     \
     R r;                                                                \
                                                                         \
+    R::element_type r_zero = R::element_type ();                        \
+                                                                        \
     octave_idx_type m_nr = m.rows ();                                   \
     octave_idx_type m_nc = m.cols ();                                   \
                                                                         \
@@ -447,15 +449,15 @@
         mx_inline_mul (m_nr, rd, md, dd[i]);                            \
         rd += m_nr; md += m_nr;                                         \
       }                                                                 \
-    mx_inline_fill (m_nr * (dm_nc - len), rd, R_ZERO);                  \
+    mx_inline_fill (m_nr * (dm_nc - len), rd, r_zero);                  \
                                                                         \
     return r;                                                           \
   }
 
-#define MDM_BIN_OPS(R, M, DM, R_ZERO)           \
+#define MDM_BIN_OPS(R, M, DM)                   \
   MDM_BIN_OP (R, operator +, M, DM, +=)         \
   MDM_BIN_OP (R, operator -, M, DM, -=)         \
-  MDM_MULTIPLY_OP (R, M, DM, R_ZERO)
+  MDM_MULTIPLY_OP (R, M, DM)
 
 // diagonal matrix by matrix operations.
 
@@ -491,12 +493,14 @@
     return r;                                                   \
   }
 
-#define DMM_MULTIPLY_OP(R, DM, M, R_ZERO)                               \
+#define DMM_MULTIPLY_OP(R, DM, M)                                       \
   R                                                                     \
   operator * (const DM& dm, const M& m)                                 \
   {                                                                     \
     R r;                                                                \
                                                                         \
+    R::element_type r_zero = R::element_type ();                        \
+                                                                        \
     octave_idx_type dm_nr = dm.rows ();                                 \
     octave_idx_type dm_nc = dm.cols ();                                 \
                                                                         \
@@ -516,17 +520,17 @@
       {                                                                 \
         mx_inline_mul (len, rd, md, dd);                                \
         rd += len; md += m_nr;                                          \
-        mx_inline_fill (dm_nr - len, rd, R_ZERO);                       \
+        mx_inline_fill (dm_nr - len, rd, r_zero);                       \
         rd += dm_nr - len;                                              \
       }                                                                 \
                                                                         \
     return r;                                                           \
   }
 
-#define DMM_BIN_OPS(R, DM, M, R_ZERO)           \
+#define DMM_BIN_OPS(R, DM, M)                   \
   DMM_BIN_OP (R, operator +, DM, M, +=, )       \
   DMM_BIN_OP (R, operator -, DM, M, +=, -)      \
-  DMM_MULTIPLY_OP (R, DM, M, R_ZERO)
+  DMM_MULTIPLY_OP (R, DM, M)
 
 // diagonal matrix by diagonal matrix operations.
 
--- a/liboctave/operators/mx-ops	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/operators/mx-ops	Fri Aug 10 09:09:51 2018 +0200
@@ -21,7 +21,7 @@
 
 # types
 #
-# key typename object-type header fwd-decl-ok scalar-zero core-type
+# key typename object-type header fwd-decl-ok core-type
 #
 # object-type is one of
 #
@@ -37,47 +37,47 @@
 # core-type is only used for the octave_int types, and is the template
 # parameter: octave_int8 is octave_int<int8_t>
 #
-x NONE NONE NONE NO 0
-b bool S NONE NO false
-bm boolMatrix ND boolMatrix.h YES false
-bnda boolNDArray ND boolNDArray.h YES false
-cdm ComplexDiagMatrix DM CDiagMatrix.h YES 0.0
-cm ComplexMatrix M CMatrix.h YES 0.0
-cnda ComplexNDArray ND CNDArray.h YES 0.0
-cs Complex S oct-cmplx.h NO 0.0
-dm DiagMatrix DM dDiagMatrix.h YES 0.0
-m Matrix M dMatrix.h YES 0.0
-nda NDArray ND dNDArray.h YES 0.0
-s double S NONE NO 0.0
-fcdm FloatComplexDiagMatrix DM fCDiagMatrix.h YES 0.0f
-fcm FloatComplexMatrix M fCMatrix.h YES 0.0f
-fcnda FloatComplexNDArray ND fCNDArray.h YES 0.0f
-fcs FloatComplex S oct-cmplx.h NO 0.0f
-fdm FloatDiagMatrix DM fDiagMatrix.h YES 0.0f
-fm FloatMatrix M fMatrix.h YES 0.0f
-fnda FloatNDArray ND fNDArray.h YES 0.0f
-fs float S NONE NO 0.0f
-i8 octave_int8 S oct-inttypes.h YES octave_int8::zero int8_t
-ui8 octave_uint8 S oct-inttypes.h YES octave_uint8::zero uint8_t
-i16 octave_int16 S oct-inttypes.h YES octave_int16::zero int16_t
-ui16 octave_uint16 S oct-inttypes.h YES octave_uint16::zero uint16_t
-i32 octave_int32 S oct-inttypes.h YES octave_int32::zero int32_t
-ui32 octave_uint32 S oct-inttypes.h YES octave_uint32::zero uint32_t
-i64 octave_int64 S oct-inttypes.h YES octave_int64::zero int64_t
-ui64 octave_uint64 S oct-inttypes.h YES octave_uint64::zero uint64_t
-i8nda int8NDArray ND int8NDArray.h YES octave_int8::zero int8_t
-ui8nda uint8NDArray ND uint8NDArray.h YES octave_uint8::zero uint8_t
-i16nda int16NDArray ND int16NDArray.h YES octave_int16::zero int16_t
-ui16nda uint16NDArray ND uint16NDArray.h YES octave_uint16::zero uint16_t
-i32nda int32NDArray ND int32NDArray.h YES octave_int32::zero int32_t
-ui32nda uint32NDArray ND uint32NDArray.h YES octave_uint32::zero uint32_t
-i64nda int64NDArray ND int64NDArray.h YES octave_int64::zero int64_t
-ui64nda uint64NDArray ND uint64NDArray.h YES octave_uint64::zero uint64_t
-pm PermMatrix PM PermMatrix.h YES static_cast<octave_idx_type>(0)
+x NONE NONE NONE NO
+b bool S NONE NO
+bm boolMatrix ND boolMatrix.h YES
+bnda boolNDArray ND boolNDArray.h YES
+cdm ComplexDiagMatrix DM CDiagMatrix.h YES
+cm ComplexMatrix M CMatrix.h YES
+cnda ComplexNDArray ND CNDArray.h YES
+cs Complex S oct-cmplx.h NO
+dm DiagMatrix DM dDiagMatrix.h YES
+m Matrix M dMatrix.h YES
+nda NDArray ND dNDArray.h YES
+s double S NONE NO
+fcdm FloatComplexDiagMatrix DM fCDiagMatrix.h YES
+fcm FloatComplexMatrix M fCMatrix.h YES
+fcnda FloatComplexNDArray ND fCNDArray.h YES
+fcs FloatComplex S oct-cmplx.h NO
+fdm FloatDiagMatrix DM fDiagMatrix.h YES
+fm FloatMatrix M fMatrix.h YES
+fnda FloatNDArray ND fNDArray.h YES
+fs float S NONE NO
+i8 octave_int8 S oct-inttypes.h YES int8_t
+ui8 octave_uint8 S oct-inttypes.h YES uint8_t
+i16 octave_int16 S oct-inttypes.h YES int16_t
+ui16 octave_uint16 S oct-inttypes.h YES uint16_t
+i32 octave_int32 S oct-inttypes.h YES int32_t
+ui32 octave_uint32 S oct-inttypes.h YES uint32_t
+i64 octave_int64 S oct-inttypes.h YES int64_t
+ui64 octave_uint64 S oct-inttypes.h YES uint64_t
+i8nda int8NDArray ND int8NDArray.h YES int8_t
+ui8nda uint8NDArray ND uint8NDArray.h YES uint8_t
+i16nda int16NDArray ND int16NDArray.h YES int16_t
+ui16nda uint16NDArray ND uint16NDArray.h YES uint16_t
+i32nda int32NDArray ND int32NDArray.h YES int32_t
+ui32nda uint32NDArray ND uint32NDArray.h YES uint32_t
+i64nda int64NDArray ND int64NDArray.h YES int64_t
+ui64nda uint64NDArray ND uint64NDArray.h YES uint64_t
+pm PermMatrix PM PermMatrix.h YES
 #
 # full-matrix operators
 #
-# result_t lhs_t rhs_t op-type lhs_conv rhs_conv headers ...
+# result_t lhs_t rhs_t op-type headers ...
 #
 # op-type is one of
 #
@@ -88,54 +88,54 @@
 cdm cdm dm B
 cdm dm cdm B
 cdm cs dm B
-cm cs m BCL real NONE boolMatrix.h
-cnda cs nda BCL real NONE boolMatrix.h boolNDArray.h
+cm cs m BCL boolMatrix.h
+cnda cs nda BCL boolMatrix.h boolNDArray.h
 cm cdm cm B
 cm cdm m B
 cdm cdm s B
 cm cm cdm B
 cm cm dm B
-cm cm m BCL real NONE boolMatrix.h
-cnda cnda nda BCL real NONE boolMatrix.h boolNDArray.h
-cm cm s BCL real NONE boolMatrix.h
-cnda cnda s BCL real NONE boolMatrix.h boolNDArray.h
+cm cm m BCL boolMatrix.h
+cnda cnda nda BCL boolMatrix.h boolNDArray.h
+cm cm s BCL boolMatrix.h
+cnda cnda s BCL boolMatrix.h boolNDArray.h
 cdm dm cs B
 cm dm cm B
-cm m cs BCL NONE real boolMatrix.h
-cnda nda cs BCL NONE real boolMatrix.h boolNDArray.h
+cm m cs BCL boolMatrix.h
+cnda nda cs BCL boolMatrix.h boolNDArray.h
 cm m cdm B
-cm m cm BCL NONE real boolMatrix.h
-cnda nda cnda BCL NONE real boolMatrix.h boolNDArray.h
+cm m cm BCL boolMatrix.h
+cnda nda cnda BCL boolMatrix.h boolNDArray.h
 cdm s cdm B
-cm s cm BCL NONE real boolMatrix.h
-cnda s cnda BCL NONE real boolMatrix.h boolNDArray.h
+cm s cm BCL boolMatrix.h
+cnda s cnda BCL boolMatrix.h boolNDArray.h
 m dm m B
 m m dm B
 #
 fcdm fcdm fdm B
 fcdm fdm fcdm B
 fcdm fcs fdm B
-fcm fcs fm BCL real NONE boolMatrix.h
-fcnda fcs fnda BCL real NONE boolMatrix.h boolNDArray.h
+fcm fcs fm BCL boolMatrix.h
+fcnda fcs fnda BCL boolMatrix.h boolNDArray.h
 fcm fcdm fcm B
 fcm fcdm fm B
 fcdm fcdm fs B
 fcm fcm fcdm B
 fcm fcm fdm B
-fcm fcm fm BCL real NONE boolMatrix.h
-fcnda fcnda fnda BCL real NONE boolMatrix.h boolNDArray.h
-fcm fcm fs BCL real NONE boolMatrix.h
-fcnda fcnda fs BCL real NONE boolMatrix.h boolNDArray.h
+fcm fcm fm BCL boolMatrix.h
+fcnda fcnda fnda BCL boolMatrix.h boolNDArray.h
+fcm fcm fs BCL boolMatrix.h
+fcnda fcnda fs BCL boolMatrix.h boolNDArray.h
 fcdm fdm fcs B
 fcm fdm fcm B
-fcm fm fcs BCL NONE real boolMatrix.h
-fcnda fnda fcs BCL NONE real boolMatrix.h boolNDArray.h
+fcm fm fcs BCL boolMatrix.h
+fcnda fnda fcs BCL boolMatrix.h boolNDArray.h
 fcm fm fcdm B
-fcm fm fcm BCL NONE real boolMatrix.h
-fcnda fnda fcnda BCL NONE real boolMatrix.h boolNDArray.h
+fcm fm fcm BCL boolMatrix.h
+fcnda fnda fcnda BCL boolMatrix.h boolNDArray.h
 fcdm fs fcdm B
-fcm fs fcm BCL NONE real boolMatrix.h
-fcnda fs fcnda BCL NONE real boolMatrix.h boolNDArray.h
+fcm fs fcm BCL boolMatrix.h
+fcnda fs fcnda BCL boolMatrix.h boolNDArray.h
 fm fdm fm B
 fm fm fdm B
 #
@@ -148,293 +148,293 @@
 fcm pm fcm B
 fcm fcm pm B
 #
-i8nda s i8nda BCL NONE NONE boolMatrix.h boolNDArray.h
-i8nda i8nda s BCL NONE NONE boolMatrix.h boolNDArray.h
-ui8nda s ui8nda BCL NONE NONE boolMatrix.h boolNDArray.h
-ui8nda ui8nda s BCL NONE NONE boolMatrix.h boolNDArray.h
-i16nda s i16nda BCL NONE NONE boolMatrix.h boolNDArray.h
-i16nda i16nda s BCL NONE NONE boolMatrix.h boolNDArray.h
-ui16nda s ui16nda BCL NONE NONE boolMatrix.h boolNDArray.h
-ui16nda ui16nda s BCL NONE NONE boolMatrix.h boolNDArray.h
-i32nda s i32nda BCL NONE NONE boolMatrix.h boolNDArray.h
-i32nda i32nda s BCL NONE NONE boolMatrix.h boolNDArray.h
-ui32nda s ui32nda BCL NONE NONE boolMatrix.h boolNDArray.h
-ui32nda ui32nda s BCL NONE NONE boolMatrix.h boolNDArray.h
-i64nda s i64nda BCL NONE NONE boolMatrix.h boolNDArray.h
-i64nda i64nda s BCL NONE NONE boolMatrix.h boolNDArray.h
-ui64nda s ui64nda BCL NONE NONE boolMatrix.h boolNDArray.h
-ui64nda ui64nda s BCL NONE NONE boolMatrix.h boolNDArray.h
-i8nda fs i8nda BCL NONE NONE boolMatrix.h boolNDArray.h
-i8nda i8nda fs BCL NONE NONE boolMatrix.h boolNDArray.h
-ui8nda fs ui8nda BCL NONE NONE boolMatrix.h boolNDArray.h
-ui8nda ui8nda fs BCL NONE NONE boolMatrix.h boolNDArray.h
-i16nda fs i16nda BCL NONE NONE boolMatrix.h boolNDArray.h
-i16nda i16nda fs BCL NONE NONE boolMatrix.h boolNDArray.h
-ui16nda fs ui16nda BCL NONE NONE boolMatrix.h boolNDArray.h
-ui16nda ui16nda fs BCL NONE NONE boolMatrix.h boolNDArray.h
-i32nda fs i32nda BCL NONE NONE boolMatrix.h boolNDArray.h
-i32nda i32nda fs BCL NONE NONE boolMatrix.h boolNDArray.h
-ui32nda fs ui32nda BCL NONE NONE boolMatrix.h boolNDArray.h
-ui32nda ui32nda fs BCL NONE NONE boolMatrix.h boolNDArray.h
-i64nda fs i64nda BCL NONE NONE boolMatrix.h boolNDArray.h
-i64nda i64nda fs BCL NONE NONE boolMatrix.h boolNDArray.h
-ui64nda fs ui64nda BCL NONE NONE boolMatrix.h boolNDArray.h
-ui64nda ui64nda fs BCL NONE NONE boolMatrix.h boolNDArray.h
+i8nda s i8nda BCL boolMatrix.h boolNDArray.h
+i8nda i8nda s BCL boolMatrix.h boolNDArray.h
+ui8nda s ui8nda BCL boolMatrix.h boolNDArray.h
+ui8nda ui8nda s BCL boolMatrix.h boolNDArray.h
+i16nda s i16nda BCL boolMatrix.h boolNDArray.h
+i16nda i16nda s BCL boolMatrix.h boolNDArray.h
+ui16nda s ui16nda BCL boolMatrix.h boolNDArray.h
+ui16nda ui16nda s BCL boolMatrix.h boolNDArray.h
+i32nda s i32nda BCL boolMatrix.h boolNDArray.h
+i32nda i32nda s BCL boolMatrix.h boolNDArray.h
+ui32nda s ui32nda BCL boolMatrix.h boolNDArray.h
+ui32nda ui32nda s BCL boolMatrix.h boolNDArray.h
+i64nda s i64nda BCL boolMatrix.h boolNDArray.h
+i64nda i64nda s BCL boolMatrix.h boolNDArray.h
+ui64nda s ui64nda BCL boolMatrix.h boolNDArray.h
+ui64nda ui64nda s BCL boolMatrix.h boolNDArray.h
+i8nda fs i8nda BCL boolMatrix.h boolNDArray.h
+i8nda i8nda fs BCL boolMatrix.h boolNDArray.h
+ui8nda fs ui8nda BCL boolMatrix.h boolNDArray.h
+ui8nda ui8nda fs BCL boolMatrix.h boolNDArray.h
+i16nda fs i16nda BCL boolMatrix.h boolNDArray.h
+i16nda i16nda fs BCL boolMatrix.h boolNDArray.h
+ui16nda fs ui16nda BCL boolMatrix.h boolNDArray.h
+ui16nda ui16nda fs BCL boolMatrix.h boolNDArray.h
+i32nda fs i32nda BCL boolMatrix.h boolNDArray.h
+i32nda i32nda fs BCL boolMatrix.h boolNDArray.h
+ui32nda fs ui32nda BCL boolMatrix.h boolNDArray.h
+ui32nda ui32nda fs BCL boolMatrix.h boolNDArray.h
+i64nda fs i64nda BCL boolMatrix.h boolNDArray.h
+i64nda i64nda fs BCL boolMatrix.h boolNDArray.h
+ui64nda fs ui64nda BCL boolMatrix.h boolNDArray.h
+ui64nda ui64nda fs BCL boolMatrix.h boolNDArray.h
 #
-i8nda nda i8 BCL NONE NONE boolMatrix.h boolNDArray.h
-i8nda i8 nda BCL NONE NONE boolMatrix.h boolNDArray.h
-ui8nda nda ui8 BCL NONE NONE boolMatrix.h boolNDArray.h
-ui8nda ui8 nda BCL NONE NONE boolMatrix.h boolNDArray.h
-i16nda nda i16 BCL NONE NONE boolMatrix.h boolNDArray.h
-i16nda i16 nda BCL NONE NONE boolMatrix.h boolNDArray.h
-ui16nda nda ui16 BCL NONE NONE boolMatrix.h boolNDArray.h
-ui16nda ui16 nda BCL NONE NONE boolMatrix.h boolNDArray.h
-i32nda nda i32 BCL NONE NONE boolMatrix.h boolNDArray.h
-i32nda i32 nda BCL NONE NONE boolMatrix.h boolNDArray.h
-ui32nda nda ui32 BCL NONE NONE boolMatrix.h boolNDArray.h
-ui32nda ui32 nda BCL NONE NONE boolMatrix.h boolNDArray.h
-i64nda nda i64 BCL NONE NONE boolMatrix.h boolNDArray.h
-i64nda i64 nda BCL NONE NONE boolMatrix.h boolNDArray.h
-ui64nda nda ui64 BCL NONE NONE boolMatrix.h boolNDArray.h
-ui64nda ui64 nda BCL NONE NONE boolMatrix.h boolNDArray.h
-i8nda fnda i8 BCL NONE NONE boolMatrix.h boolNDArray.h
-i8nda i8 fnda BCL NONE NONE boolMatrix.h boolNDArray.h
-ui8nda fnda ui8 BCL NONE NONE boolMatrix.h boolNDArray.h
-ui8nda ui8 fnda BCL NONE NONE boolMatrix.h boolNDArray.h
-i16nda fnda i16 BCL NONE NONE boolMatrix.h boolNDArray.h
-i16nda i16 fnda BCL NONE NONE boolMatrix.h boolNDArray.h
-ui16nda fnda ui16 BCL NONE NONE boolMatrix.h boolNDArray.h
-ui16nda ui16 fnda BCL NONE NONE boolMatrix.h boolNDArray.h
-i32nda fnda i32 BCL NONE NONE boolMatrix.h boolNDArray.h
-i32nda i32 fnda BCL NONE NONE boolMatrix.h boolNDArray.h
-ui32nda fnda ui32 BCL NONE NONE boolMatrix.h boolNDArray.h
-ui32nda ui32 fnda BCL NONE NONE boolMatrix.h boolNDArray.h
-i64nda fnda i64 BCL NONE NONE boolMatrix.h boolNDArray.h
-i64nda i64 fnda BCL NONE NONE boolMatrix.h boolNDArray.h
-ui64nda fnda ui64 BCL NONE NONE boolMatrix.h boolNDArray.h
-ui64nda ui64 fnda BCL NONE NONE boolMatrix.h boolNDArray.h
+i8nda nda i8 BCL boolMatrix.h boolNDArray.h
+i8nda i8 nda BCL boolMatrix.h boolNDArray.h
+ui8nda nda ui8 BCL boolMatrix.h boolNDArray.h
+ui8nda ui8 nda BCL boolMatrix.h boolNDArray.h
+i16nda nda i16 BCL boolMatrix.h boolNDArray.h
+i16nda i16 nda BCL boolMatrix.h boolNDArray.h
+ui16nda nda ui16 BCL boolMatrix.h boolNDArray.h
+ui16nda ui16 nda BCL boolMatrix.h boolNDArray.h
+i32nda nda i32 BCL boolMatrix.h boolNDArray.h
+i32nda i32 nda BCL boolMatrix.h boolNDArray.h
+ui32nda nda ui32 BCL boolMatrix.h boolNDArray.h
+ui32nda ui32 nda BCL boolMatrix.h boolNDArray.h
+i64nda nda i64 BCL boolMatrix.h boolNDArray.h
+i64nda i64 nda BCL boolMatrix.h boolNDArray.h
+ui64nda nda ui64 BCL boolMatrix.h boolNDArray.h
+ui64nda ui64 nda BCL boolMatrix.h boolNDArray.h
+i8nda fnda i8 BCL boolMatrix.h boolNDArray.h
+i8nda i8 fnda BCL boolMatrix.h boolNDArray.h
+ui8nda fnda ui8 BCL boolMatrix.h boolNDArray.h
+ui8nda ui8 fnda BCL boolMatrix.h boolNDArray.h
+i16nda fnda i16 BCL boolMatrix.h boolNDArray.h
+i16nda i16 fnda BCL boolMatrix.h boolNDArray.h
+ui16nda fnda ui16 BCL boolMatrix.h boolNDArray.h
+ui16nda ui16 fnda BCL boolMatrix.h boolNDArray.h
+i32nda fnda i32 BCL boolMatrix.h boolNDArray.h
+i32nda i32 fnda BCL boolMatrix.h boolNDArray.h
+ui32nda fnda ui32 BCL boolMatrix.h boolNDArray.h
+ui32nda ui32 fnda BCL boolMatrix.h boolNDArray.h
+i64nda fnda i64 BCL boolMatrix.h boolNDArray.h
+i64nda i64 fnda BCL boolMatrix.h boolNDArray.h
+ui64nda fnda ui64 BCL boolMatrix.h boolNDArray.h
+ui64nda ui64 fnda BCL boolMatrix.h boolNDArray.h
 #
-i8nda nda i8nda BCL NONE NONE boolMatrix.h boolNDArray.h
-i8nda i8nda nda BCL NONE NONE boolMatrix.h boolNDArray.h
-ui8nda nda ui8nda BCL NONE NONE boolMatrix.h boolNDArray.h
-ui8nda ui8nda nda BCL NONE NONE boolMatrix.h boolNDArray.h
-i16nda nda i16nda BCL NONE NONE boolMatrix.h boolNDArray.h
-i16nda i16nda nda BCL NONE NONE boolMatrix.h boolNDArray.h
-ui16nda nda ui16nda BCL NONE NONE boolMatrix.h boolNDArray.h
-ui16nda ui16nda nda BCL NONE NONE boolMatrix.h boolNDArray.h
-i32nda nda i32nda BCL NONE NONE boolMatrix.h boolNDArray.h
-i32nda i32nda nda BCL NONE NONE boolMatrix.h boolNDArray.h
-ui32nda nda ui32nda BCL NONE NONE boolMatrix.h boolNDArray.h
-ui32nda ui32nda nda BCL NONE NONE boolMatrix.h boolNDArray.h
-i64nda nda i64nda BCL NONE NONE boolMatrix.h boolNDArray.h
-i64nda i64nda nda BCL NONE NONE boolMatrix.h boolNDArray.h
-ui64nda nda ui64nda BCL NONE NONE boolMatrix.h boolNDArray.h
-ui64nda ui64nda nda BCL NONE NONE boolMatrix.h boolNDArray.h
-i8nda fnda i8nda BCL NONE NONE boolMatrix.h boolNDArray.h
-i8nda i8nda fnda BCL NONE NONE boolMatrix.h boolNDArray.h
-ui8nda fnda ui8nda BCL NONE NONE boolMatrix.h boolNDArray.h
-ui8nda ui8nda fnda BCL NONE NONE boolMatrix.h boolNDArray.h
-i16nda fnda i16nda BCL NONE NONE boolMatrix.h boolNDArray.h
-i16nda i16nda fnda BCL NONE NONE boolMatrix.h boolNDArray.h
-ui16nda fnda ui16nda BCL NONE NONE boolMatrix.h boolNDArray.h
-ui16nda ui16nda fnda BCL NONE NONE boolMatrix.h boolNDArray.h
-i32nda fnda i32nda BCL NONE NONE boolMatrix.h boolNDArray.h
-i32nda i32nda fnda BCL NONE NONE boolMatrix.h boolNDArray.h
-ui32nda fnda ui32nda BCL NONE NONE boolMatrix.h boolNDArray.h
-ui32nda ui32nda fnda BCL NONE NONE boolMatrix.h boolNDArray.h
-i64nda fnda i64nda BCL NONE NONE boolMatrix.h boolNDArray.h
-i64nda i64nda fnda BCL NONE NONE boolMatrix.h boolNDArray.h
-ui64nda fnda ui64nda BCL NONE NONE boolMatrix.h boolNDArray.h
-ui64nda ui64nda fnda BCL NONE NONE boolMatrix.h boolNDArray.h
+i8nda nda i8nda BCL boolMatrix.h boolNDArray.h
+i8nda i8nda nda BCL boolMatrix.h boolNDArray.h
+ui8nda nda ui8nda BCL boolMatrix.h boolNDArray.h
+ui8nda ui8nda nda BCL boolMatrix.h boolNDArray.h
+i16nda nda i16nda BCL boolMatrix.h boolNDArray.h
+i16nda i16nda nda BCL boolMatrix.h boolNDArray.h
+ui16nda nda ui16nda BCL boolMatrix.h boolNDArray.h
+ui16nda ui16nda nda BCL boolMatrix.h boolNDArray.h
+i32nda nda i32nda BCL boolMatrix.h boolNDArray.h
+i32nda i32nda nda BCL boolMatrix.h boolNDArray.h
+ui32nda nda ui32nda BCL boolMatrix.h boolNDArray.h
+ui32nda ui32nda nda BCL boolMatrix.h boolNDArray.h
+i64nda nda i64nda BCL boolMatrix.h boolNDArray.h
+i64nda i64nda nda BCL boolMatrix.h boolNDArray.h
+ui64nda nda ui64nda BCL boolMatrix.h boolNDArray.h
+ui64nda ui64nda nda BCL boolMatrix.h boolNDArray.h
+i8nda fnda i8nda BCL boolMatrix.h boolNDArray.h
+i8nda i8nda fnda BCL boolMatrix.h boolNDArray.h
+ui8nda fnda ui8nda BCL boolMatrix.h boolNDArray.h
+ui8nda ui8nda fnda BCL boolMatrix.h boolNDArray.h
+i16nda fnda i16nda BCL boolMatrix.h boolNDArray.h
+i16nda i16nda fnda BCL boolMatrix.h boolNDArray.h
+ui16nda fnda ui16nda BCL boolMatrix.h boolNDArray.h
+ui16nda ui16nda fnda BCL boolMatrix.h boolNDArray.h
+i32nda fnda i32nda BCL boolMatrix.h boolNDArray.h
+i32nda i32nda fnda BCL boolMatrix.h boolNDArray.h
+ui32nda fnda ui32nda BCL boolMatrix.h boolNDArray.h
+ui32nda ui32nda fnda BCL boolMatrix.h boolNDArray.h
+i64nda fnda i64nda BCL boolMatrix.h boolNDArray.h
+i64nda i64nda fnda BCL boolMatrix.h boolNDArray.h
+ui64nda fnda ui64nda BCL boolMatrix.h boolNDArray.h
+ui64nda ui64nda fnda BCL boolMatrix.h boolNDArray.h
 #
-x i8nda ui8 CL NONE NONE boolMatrix.h boolNDArray.h
-x i8nda i16 CL NONE NONE boolMatrix.h boolNDArray.h
-x i8nda ui16 CL NONE NONE boolMatrix.h boolNDArray.h
-x i8nda i32 CL NONE NONE boolMatrix.h boolNDArray.h
-x i8nda ui32 CL NONE NONE boolMatrix.h boolNDArray.h
-x i8nda i64 CL NONE NONE boolMatrix.h boolNDArray.h
-x i8nda ui64 CL NONE NONE boolMatrix.h boolNDArray.h
+x i8nda ui8 CL boolMatrix.h boolNDArray.h
+x i8nda i16 CL boolMatrix.h boolNDArray.h
+x i8nda ui16 CL boolMatrix.h boolNDArray.h
+x i8nda i32 CL boolMatrix.h boolNDArray.h
+x i8nda ui32 CL boolMatrix.h boolNDArray.h
+x i8nda i64 CL boolMatrix.h boolNDArray.h
+x i8nda ui64 CL boolMatrix.h boolNDArray.h
 #
-x i16nda i8 CL NONE NONE boolMatrix.h boolNDArray.h
-x i16nda ui8 CL NONE NONE boolMatrix.h boolNDArray.h
-x i16nda ui16 CL NONE NONE boolMatrix.h boolNDArray.h
-x i16nda i32 CL NONE NONE boolMatrix.h boolNDArray.h
-x i16nda ui32 CL NONE NONE boolMatrix.h boolNDArray.h
-x i16nda i64 CL NONE NONE boolMatrix.h boolNDArray.h
-x i16nda ui64 CL NONE NONE boolMatrix.h boolNDArray.h
+x i16nda i8 CL boolMatrix.h boolNDArray.h
+x i16nda ui8 CL boolMatrix.h boolNDArray.h
+x i16nda ui16 CL boolMatrix.h boolNDArray.h
+x i16nda i32 CL boolMatrix.h boolNDArray.h
+x i16nda ui32 CL boolMatrix.h boolNDArray.h
+x i16nda i64 CL boolMatrix.h boolNDArray.h
+x i16nda ui64 CL boolMatrix.h boolNDArray.h
 #
-x i32nda i8 CL NONE NONE boolMatrix.h boolNDArray.h
-x i32nda ui8 CL NONE NONE boolMatrix.h boolNDArray.h
-x i32nda i16 CL NONE NONE boolMatrix.h boolNDArray.h
-x i32nda ui16 CL NONE NONE boolMatrix.h boolNDArray.h
-x i32nda ui32 CL NONE NONE boolMatrix.h boolNDArray.h
-x i32nda i64 CL NONE NONE boolMatrix.h boolNDArray.h
-x i32nda ui64 CL NONE NONE boolMatrix.h boolNDArray.h
+x i32nda i8 CL boolMatrix.h boolNDArray.h
+x i32nda ui8 CL boolMatrix.h boolNDArray.h
+x i32nda i16 CL boolMatrix.h boolNDArray.h
+x i32nda ui16 CL boolMatrix.h boolNDArray.h
+x i32nda ui32 CL boolMatrix.h boolNDArray.h
+x i32nda i64 CL boolMatrix.h boolNDArray.h
+x i32nda ui64 CL boolMatrix.h boolNDArray.h
 #
-x i64nda i8 CL NONE NONE boolMatrix.h boolNDArray.h
-x i64nda ui8 CL NONE NONE boolMatrix.h boolNDArray.h
-x i64nda i16 CL NONE NONE boolMatrix.h boolNDArray.h
-x i64nda ui16 CL NONE NONE boolMatrix.h boolNDArray.h
-x i64nda i32 CL NONE NONE boolMatrix.h boolNDArray.h
-x i64nda ui32 CL NONE NONE boolMatrix.h boolNDArray.h
-x i64nda ui64 CL NONE NONE boolMatrix.h boolNDArray.h
+x i64nda i8 CL boolMatrix.h boolNDArray.h
+x i64nda ui8 CL boolMatrix.h boolNDArray.h
+x i64nda i16 CL boolMatrix.h boolNDArray.h
+x i64nda ui16 CL boolMatrix.h boolNDArray.h
+x i64nda i32 CL boolMatrix.h boolNDArray.h
+x i64nda ui32 CL boolMatrix.h boolNDArray.h
+x i64nda ui64 CL boolMatrix.h boolNDArray.h
 #
-x ui8nda i8 CL NONE NONE boolMatrix.h boolNDArray.h
-x ui8nda i16 CL NONE NONE boolMatrix.h boolNDArray.h
-x ui8nda ui16 CL NONE NONE boolMatrix.h boolNDArray.h
-x ui8nda i32 CL NONE NONE boolMatrix.h boolNDArray.h
-x ui8nda ui32 CL NONE NONE boolMatrix.h boolNDArray.h
-x ui8nda i64 CL NONE NONE boolMatrix.h boolNDArray.h
-x ui8nda ui64 CL NONE NONE boolMatrix.h boolNDArray.h
+x ui8nda i8 CL boolMatrix.h boolNDArray.h
+x ui8nda i16 CL boolMatrix.h boolNDArray.h
+x ui8nda ui16 CL boolMatrix.h boolNDArray.h
+x ui8nda i32 CL boolMatrix.h boolNDArray.h
+x ui8nda ui32 CL boolMatrix.h boolNDArray.h
+x ui8nda i64 CL boolMatrix.h boolNDArray.h
+x ui8nda ui64 CL boolMatrix.h boolNDArray.h
 #
-x ui16nda i8 CL NONE NONE boolMatrix.h boolNDArray.h
-x ui16nda ui8 CL NONE NONE boolMatrix.h boolNDArray.h
-x ui16nda i16 CL NONE NONE boolMatrix.h boolNDArray.h
-x ui16nda i32 CL NONE NONE boolMatrix.h boolNDArray.h
-x ui16nda ui32 CL NONE NONE boolMatrix.h boolNDArray.h
-x ui16nda i64 CL NONE NONE boolMatrix.h boolNDArray.h
-x ui16nda ui64 CL NONE NONE boolMatrix.h boolNDArray.h
+x ui16nda i8 CL boolMatrix.h boolNDArray.h
+x ui16nda ui8 CL boolMatrix.h boolNDArray.h
+x ui16nda i16 CL boolMatrix.h boolNDArray.h
+x ui16nda i32 CL boolMatrix.h boolNDArray.h
+x ui16nda ui32 CL boolMatrix.h boolNDArray.h
+x ui16nda i64 CL boolMatrix.h boolNDArray.h
+x ui16nda ui64 CL boolMatrix.h boolNDArray.h
 #
-x ui32nda i8 CL NONE NONE boolMatrix.h boolNDArray.h
-x ui32nda ui8 CL NONE NONE boolMatrix.h boolNDArray.h
-x ui32nda i16 CL NONE NONE boolMatrix.h boolNDArray.h
-x ui32nda ui16 CL NONE NONE boolMatrix.h boolNDArray.h
-x ui32nda i32 CL NONE NONE boolMatrix.h boolNDArray.h
-x ui32nda i64 CL NONE NONE boolMatrix.h boolNDArray.h
-x ui32nda ui64 CL NONE NONE boolMatrix.h boolNDArray.h
+x ui32nda i8 CL boolMatrix.h boolNDArray.h
+x ui32nda ui8 CL boolMatrix.h boolNDArray.h
+x ui32nda i16 CL boolMatrix.h boolNDArray.h
+x ui32nda ui16 CL boolMatrix.h boolNDArray.h
+x ui32nda i32 CL boolMatrix.h boolNDArray.h
+x ui32nda i64 CL boolMatrix.h boolNDArray.h
+x ui32nda ui64 CL boolMatrix.h boolNDArray.h
 #
-x ui64nda i8 CL NONE NONE boolMatrix.h boolNDArray.h
-x ui64nda ui8 CL NONE NONE boolMatrix.h boolNDArray.h
-x ui64nda i16 CL NONE NONE boolMatrix.h boolNDArray.h
-x ui64nda ui16 CL NONE NONE boolMatrix.h boolNDArray.h
-x ui64nda i32 CL NONE NONE boolMatrix.h boolNDArray.h
-x ui64nda ui32 CL NONE NONE boolMatrix.h boolNDArray.h
-x ui64nda i64 CL NONE NONE boolMatrix.h boolNDArray.h
+x ui64nda i8 CL boolMatrix.h boolNDArray.h
+x ui64nda ui8 CL boolMatrix.h boolNDArray.h
+x ui64nda i16 CL boolMatrix.h boolNDArray.h
+x ui64nda ui16 CL boolMatrix.h boolNDArray.h
+x ui64nda i32 CL boolMatrix.h boolNDArray.h
+x ui64nda ui32 CL boolMatrix.h boolNDArray.h
+x ui64nda i64 CL boolMatrix.h boolNDArray.h
 #
-x i8 ui8nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i8 i16nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i8 ui16nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i8 i32nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i8 ui32nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i8 i64nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i8 ui64nda CL NONE NONE boolMatrix.h boolNDArray.h
+x i8 ui8nda CL boolMatrix.h boolNDArray.h
+x i8 i16nda CL boolMatrix.h boolNDArray.h
+x i8 ui16nda CL boolMatrix.h boolNDArray.h
+x i8 i32nda CL boolMatrix.h boolNDArray.h
+x i8 ui32nda CL boolMatrix.h boolNDArray.h
+x i8 i64nda CL boolMatrix.h boolNDArray.h
+x i8 ui64nda CL boolMatrix.h boolNDArray.h
 #
-x i16 i8nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i16 ui8nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i16 ui16nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i16 i32nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i16 ui32nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i16 i64nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i16 ui64nda CL NONE NONE boolMatrix.h boolNDArray.h
+x i16 i8nda CL boolMatrix.h boolNDArray.h
+x i16 ui8nda CL boolMatrix.h boolNDArray.h
+x i16 ui16nda CL boolMatrix.h boolNDArray.h
+x i16 i32nda CL boolMatrix.h boolNDArray.h
+x i16 ui32nda CL boolMatrix.h boolNDArray.h
+x i16 i64nda CL boolMatrix.h boolNDArray.h
+x i16 ui64nda CL boolMatrix.h boolNDArray.h
 #
-x i32 i8nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i32 ui8nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i32 i16nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i32 ui16nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i32 ui32nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i32 i64nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i32 ui64nda CL NONE NONE boolMatrix.h boolNDArray.h
+x i32 i8nda CL boolMatrix.h boolNDArray.h
+x i32 ui8nda CL boolMatrix.h boolNDArray.h
+x i32 i16nda CL boolMatrix.h boolNDArray.h
+x i32 ui16nda CL boolMatrix.h boolNDArray.h
+x i32 ui32nda CL boolMatrix.h boolNDArray.h
+x i32 i64nda CL boolMatrix.h boolNDArray.h
+x i32 ui64nda CL boolMatrix.h boolNDArray.h
 #
-x i64 i8nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i64 ui8nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i64 i16nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i64 ui16nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i64 i32nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i64 ui32nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i64 ui64nda CL NONE NONE boolMatrix.h boolNDArray.h
+x i64 i8nda CL boolMatrix.h boolNDArray.h
+x i64 ui8nda CL boolMatrix.h boolNDArray.h
+x i64 i16nda CL boolMatrix.h boolNDArray.h
+x i64 ui16nda CL boolMatrix.h boolNDArray.h
+x i64 i32nda CL boolMatrix.h boolNDArray.h
+x i64 ui32nda CL boolMatrix.h boolNDArray.h
+x i64 ui64nda CL boolMatrix.h boolNDArray.h
 #
-x ui8 i8nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui8 i16nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui8 ui16nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui8 i32nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui8 ui32nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui8 i64nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui8 ui64nda CL NONE NONE boolMatrix.h boolNDArray.h
+x ui8 i8nda CL boolMatrix.h boolNDArray.h
+x ui8 i16nda CL boolMatrix.h boolNDArray.h
+x ui8 ui16nda CL boolMatrix.h boolNDArray.h
+x ui8 i32nda CL boolMatrix.h boolNDArray.h
+x ui8 ui32nda CL boolMatrix.h boolNDArray.h
+x ui8 i64nda CL boolMatrix.h boolNDArray.h
+x ui8 ui64nda CL boolMatrix.h boolNDArray.h
 #
-x ui16 i8nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui16 ui8nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui16 i16nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui16 i32nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui16 ui32nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui16 i64nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui16 ui64nda CL NONE NONE boolMatrix.h boolNDArray.h
+x ui16 i8nda CL boolMatrix.h boolNDArray.h
+x ui16 ui8nda CL boolMatrix.h boolNDArray.h
+x ui16 i16nda CL boolMatrix.h boolNDArray.h
+x ui16 i32nda CL boolMatrix.h boolNDArray.h
+x ui16 ui32nda CL boolMatrix.h boolNDArray.h
+x ui16 i64nda CL boolMatrix.h boolNDArray.h
+x ui16 ui64nda CL boolMatrix.h boolNDArray.h
 #
-x ui32 i8nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui32 ui8nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui32 i16nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui32 ui16nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui32 i32nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui32 i64nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui32 ui64nda CL NONE NONE boolMatrix.h boolNDArray.h
+x ui32 i8nda CL boolMatrix.h boolNDArray.h
+x ui32 ui8nda CL boolMatrix.h boolNDArray.h
+x ui32 i16nda CL boolMatrix.h boolNDArray.h
+x ui32 ui16nda CL boolMatrix.h boolNDArray.h
+x ui32 i32nda CL boolMatrix.h boolNDArray.h
+x ui32 i64nda CL boolMatrix.h boolNDArray.h
+x ui32 ui64nda CL boolMatrix.h boolNDArray.h
 #
-x ui64 i8nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui64 ui8nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui64 i16nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui64 ui16nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui64 i32nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui64 ui32nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui64 i64nda CL NONE NONE boolMatrix.h boolNDArray.h
+x ui64 i8nda CL boolMatrix.h boolNDArray.h
+x ui64 ui8nda CL boolMatrix.h boolNDArray.h
+x ui64 i16nda CL boolMatrix.h boolNDArray.h
+x ui64 ui16nda CL boolMatrix.h boolNDArray.h
+x ui64 i32nda CL boolMatrix.h boolNDArray.h
+x ui64 ui32nda CL boolMatrix.h boolNDArray.h
+x ui64 i64nda CL boolMatrix.h boolNDArray.h
 #
-x i8nda ui8nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i8nda i16nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i8nda ui16nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i8nda i32nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i8nda ui32nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i8nda i64nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i8nda ui64nda CL NONE NONE boolMatrix.h boolNDArray.h
+x i8nda ui8nda CL boolMatrix.h boolNDArray.h
+x i8nda i16nda CL boolMatrix.h boolNDArray.h
+x i8nda ui16nda CL boolMatrix.h boolNDArray.h
+x i8nda i32nda CL boolMatrix.h boolNDArray.h
+x i8nda ui32nda CL boolMatrix.h boolNDArray.h
+x i8nda i64nda CL boolMatrix.h boolNDArray.h
+x i8nda ui64nda CL boolMatrix.h boolNDArray.h
 #
-x i16nda i8nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i16nda ui8nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i16nda ui16nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i16nda i32nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i16nda ui32nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i16nda i64nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i16nda ui64nda CL NONE NONE boolMatrix.h boolNDArray.h
+x i16nda i8nda CL boolMatrix.h boolNDArray.h
+x i16nda ui8nda CL boolMatrix.h boolNDArray.h
+x i16nda ui16nda CL boolMatrix.h boolNDArray.h
+x i16nda i32nda CL boolMatrix.h boolNDArray.h
+x i16nda ui32nda CL boolMatrix.h boolNDArray.h
+x i16nda i64nda CL boolMatrix.h boolNDArray.h
+x i16nda ui64nda CL boolMatrix.h boolNDArray.h
 #
-x i32nda i8nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i32nda ui8nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i32nda i16nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i32nda ui16nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i32nda ui32nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i32nda i64nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i32nda ui64nda CL NONE NONE boolMatrix.h boolNDArray.h
+x i32nda i8nda CL boolMatrix.h boolNDArray.h
+x i32nda ui8nda CL boolMatrix.h boolNDArray.h
+x i32nda i16nda CL boolMatrix.h boolNDArray.h
+x i32nda ui16nda CL boolMatrix.h boolNDArray.h
+x i32nda ui32nda CL boolMatrix.h boolNDArray.h
+x i32nda i64nda CL boolMatrix.h boolNDArray.h
+x i32nda ui64nda CL boolMatrix.h boolNDArray.h
 #
-x i64nda i8nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i64nda ui8nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i64nda i16nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i64nda ui16nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i64nda i32nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i64nda ui32nda CL NONE NONE boolMatrix.h boolNDArray.h
-x i64nda ui64nda CL NONE NONE boolMatrix.h boolNDArray.h
+x i64nda i8nda CL boolMatrix.h boolNDArray.h
+x i64nda ui8nda CL boolMatrix.h boolNDArray.h
+x i64nda i16nda CL boolMatrix.h boolNDArray.h
+x i64nda ui16nda CL boolMatrix.h boolNDArray.h
+x i64nda i32nda CL boolMatrix.h boolNDArray.h
+x i64nda ui32nda CL boolMatrix.h boolNDArray.h
+x i64nda ui64nda CL boolMatrix.h boolNDArray.h
 #
-x ui8nda i8nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui8nda i16nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui8nda ui16nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui8nda i32nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui8nda ui32nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui8nda i64nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui8nda ui64nda CL NONE NONE boolMatrix.h boolNDArray.h
+x ui8nda i8nda CL boolMatrix.h boolNDArray.h
+x ui8nda i16nda CL boolMatrix.h boolNDArray.h
+x ui8nda ui16nda CL boolMatrix.h boolNDArray.h
+x ui8nda i32nda CL boolMatrix.h boolNDArray.h
+x ui8nda ui32nda CL boolMatrix.h boolNDArray.h
+x ui8nda i64nda CL boolMatrix.h boolNDArray.h
+x ui8nda ui64nda CL boolMatrix.h boolNDArray.h
 #
-x ui16nda i8nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui16nda ui8nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui16nda i16nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui16nda i32nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui16nda ui32nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui16nda i64nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui16nda ui64nda CL NONE NONE boolMatrix.h boolNDArray.h
+x ui16nda i8nda CL boolMatrix.h boolNDArray.h
+x ui16nda ui8nda CL boolMatrix.h boolNDArray.h
+x ui16nda i16nda CL boolMatrix.h boolNDArray.h
+x ui16nda i32nda CL boolMatrix.h boolNDArray.h
+x ui16nda ui32nda CL boolMatrix.h boolNDArray.h
+x ui16nda i64nda CL boolMatrix.h boolNDArray.h
+x ui16nda ui64nda CL boolMatrix.h boolNDArray.h
 #
-x ui32nda i8nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui32nda ui8nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui32nda i16nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui32nda ui16nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui32nda i32nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui32nda i64nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui32nda ui64nda CL NONE NONE boolMatrix.h boolNDArray.h
+x ui32nda i8nda CL boolMatrix.h boolNDArray.h
+x ui32nda ui8nda CL boolMatrix.h boolNDArray.h
+x ui32nda i16nda CL boolMatrix.h boolNDArray.h
+x ui32nda ui16nda CL boolMatrix.h boolNDArray.h
+x ui32nda i32nda CL boolMatrix.h boolNDArray.h
+x ui32nda i64nda CL boolMatrix.h boolNDArray.h
+x ui32nda ui64nda CL boolMatrix.h boolNDArray.h
 #
-x ui64nda i8nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui64nda ui8nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui64nda i16nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui64nda ui16nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui64nda i32nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui64nda ui32nda CL NONE NONE boolMatrix.h boolNDArray.h
-x ui64nda i64nda CL NONE NONE boolMatrix.h boolNDArray.h
+x ui64nda i8nda CL boolMatrix.h boolNDArray.h
+x ui64nda ui8nda CL boolMatrix.h boolNDArray.h
+x ui64nda i16nda CL boolMatrix.h boolNDArray.h
+x ui64nda ui16nda CL boolMatrix.h boolNDArray.h
+x ui64nda i32nda CL boolMatrix.h boolNDArray.h
+x ui64nda ui32nda CL boolMatrix.h boolNDArray.h
+x ui64nda i64nda CL boolMatrix.h boolNDArray.h
--- a/liboctave/operators/smx-ops	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/operators/smx-ops	Fri Aug 10 09:09:51 2018 +0200
@@ -21,7 +21,7 @@
 
 # types
 #
-# key typename object-type header fwd-decl-ok scalar-zero
+# key typename object-type header fwd-decl-ok
 #
 #   S:  scalar
 #   M:  matrix
@@ -29,19 +29,19 @@
 #   ND: N-d array
 #   SM: sparse matrix
 #
-sm SparseMatrix SM dSparse.h YES 0.0
-scm SparseComplexMatrix SM CSparse.h YES 0.0
-sbm SparseBoolMatrix SM boolSparse.h YES false
-b bool S NONE NO false
-bm boolMatrix M boolMatrix.h YES false
-s double S NONE NO 0.0
-cs Complex S oct-cmplx.h NO 0.0
-m Matrix M dMatrix.h YES 0.0
-cm ComplexMatrix M CMatrix.h YES 0.0
+sm SparseMatrix SM dSparse.h YES
+scm SparseComplexMatrix SM CSparse.h YES
+sbm SparseBoolMatrix SM boolSparse.h YES
+b bool S NONE NO
+bm boolMatrix M boolMatrix.h YES
+s double S NONE NO
+cs Complex S oct-cmplx.h NO
+m Matrix M dMatrix.h YES
+cm ComplexMatrix M CMatrix.h YES
 #
 # sparse-matrix operators
 #
-# result_t_1 result_t_2 lhs_t rhs_t op-type lhs_conv rhs_conv headers ...
+# result_t_1 result_t_2 lhs_t rhs_t op-type headers ...
 #
 # op-type is one of
 #
@@ -50,19 +50,19 @@
 #   E: == != (Only one of C or E can be used!!)
 #   L: logical ops, & |
 #
-cm scm sm cs BCL NONE real boolSparse.h
-cm scm cs sm BCL real NONE boolSparse.h
-cm scm scm s BCL real NONE boolSparse.h
-cm scm s scm BCL NONE real boolSparse.h
-scm scm scm sm BCL real NONE boolSparse.h
-scm scm sm scm BCL NONE real boolSparse.h
-m sm m sm BCL NONE NONE boolSparse.h
-cm scm m scm BCL NONE real boolSparse.h
-cm scm cm sm BCL real NONE boolSparse.h
-cm scm cm scm BCL real real boolSparse.h
-m sm sm m BCL NONE NONE boolSparse.h
-cm scm scm m BCL real NONE boolSparse.h
-cm scm sm cm BCL NONE real boolSparse.h
-cm scm scm cm BCL real real boolSparse.h
+cm scm sm cs BCL boolSparse.h
+cm scm cs sm BCL boolSparse.h
+cm scm scm s BCL boolSparse.h
+cm scm s scm BCL boolSparse.h
+scm scm scm sm BCL boolSparse.h
+scm scm sm scm BCL boolSparse.h
+m sm m sm BCL boolSparse.h
+cm scm m scm BCL boolSparse.h
+cm scm cm sm BCL boolSparse.h
+cm scm cm scm BCL boolSparse.h
+m sm sm m BCL boolSparse.h
+cm scm scm m BCL boolSparse.h
+cm scm sm cm BCL boolSparse.h
+cm scm scm cm BCL boolSparse.h
 bm sbm bm sbm EL
 bm sbm sbm bm EL
--- a/liboctave/system/dir-ops.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/system/dir-ops.h	Fri Aug 10 09:09:51 2018 +0200
@@ -97,11 +97,4 @@
   }
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sys::dir_entry' instead")
-typedef octave::sys::dir_entry dir_entry;
-
 #endif
-
-#endif
--- a/liboctave/system/file-ops.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/system/file-ops.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -33,7 +33,6 @@
 #  include <algorithm>
 #endif
 
-#include <iostream>
 #include <vector>
 
 #include "areadlink-wrapper.h"
@@ -42,6 +41,7 @@
 #include "file-ops.h"
 #include "file-stat.h"
 #include "gen-tempname-wrapper.h"
+#include "lo-sysdep.h"
 #include "oct-env.h"
 #include "oct-locbuf.h"
 #include "oct-passwd.h"
@@ -501,13 +501,19 @@
       return rename (from, to, msg);
     }
 
-    int rename (const std::string& from, const std::string& to, std::string& msg)
+    int rename (const std::string& from, const std::string& to,
+                std::string& msg)
     {
       int status = -1;
 
       msg = "";
 
+#if defined (OCTAVE_USE_WINDOWS_API)
+      status = _wrename (u8_to_wstring (from).c_str (),
+                         u8_to_wstring (to).c_str ());
+#else
       status = std::rename (from.c_str (), to.c_str ());
+#endif
 
       if (status < 0)
         msg = std::strerror (errno);
@@ -549,12 +555,10 @@
 
       int status = 0;
 
-      dir_entry dir (name);
+      string_vector dirlist;
 
-      if (dir)
+      if (get_dirlist (name, dirlist, msg))
         {
-          string_vector dirlist = dir.read ();
-
           for (octave_idx_type i = 0; i < dirlist.numel (); i++)
             {
               octave_quit ();
@@ -595,17 +599,10 @@
             }
 
           if (status >= 0)
-            {
-              dir.close ();
-              status = rmdir (name, msg);
-            }
+            status = rmdir (name, msg);
         }
       else
-        {
-          status = -1;
-
-          msg = dir.error ();
-        }
+        status = -1;
 
       return status;
     }
--- a/liboctave/system/file-ops.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/system/file-ops.h	Fri Aug 10 09:09:51 2018 +0200
@@ -181,172 +181,4 @@
   }
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sys::mkdir' instead")
-inline int
-octave_mkdir (const std::string& nm, mode_t md)
-{
-  return octave::sys::mkdir (nm, md);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sys::mkdir' instead")
-inline int
-octave_mkdir (const std::string& nm, mode_t md, std::string& msg)
-{
-  return octave::sys::mkdir (nm, md, msg);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sys::mkfifo' instead")
-inline int
-octave_mkfifo (const std::string& nm, mode_t md)
-{
-  return octave::sys::mkfifo (nm, md);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sys::mkfifo' instead")
-inline int
-octave_mkfifo (const std::string& nm, mode_t md, std::string& msg)
-{
-  return octave::sys::mkfifo (nm, md, msg);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sys::link' instead")
-inline int
-octave_link (const std::string& old_name, const std::string& new_name)
-{
-  return octave::sys::link (old_name, new_name);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sys::link' instead")
-inline int
-octave_link (const std::string& old_name, const std::string& new_name,
-             std::string& msg)
-{
-  return octave::sys::link (old_name, new_name, msg);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sys::symlink' instead")
-inline int
-octave_symlink (const std::string& old_name, const std::string& new_name)
-{
-  return octave::sys::symlink (old_name, new_name);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sys::symlink' instead")
-inline int
-octave_symlink (const std::string& old_name, const std::string& new_name,
-                std::string& msg)
-{
-  return octave::sys::symlink (old_name, new_name, msg);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sys::readlink' instead")
-inline int
-octave_readlink (const std::string& path, std::string& result)
-{
-  return octave::sys::readlink (path, result);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sys::readlink' instead")
-inline int
-octave_readlink (const std::string& path, std::string& result, std::string& msg)
-{
-  return octave::sys::readlink (path, result, msg);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sys::rename' instead")
-inline int
-octave_rename (const std::string& from, const std::string& to)
-{
-  return octave::sys::rename (from, to);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sys::rename' instead")
-inline int
-octave_rename (const std::string& from, const std::string& to, std::string& msg)
-{
-  return octave::sys::rename (from, to, msg);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sys::rmdir' instead")
-inline int
-octave_rmdir (const std::string& nm)
-{
-  return octave::sys::rmdir (nm);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sys::rmdir' instead")
-inline int
-octave_rmdir (const std::string& nm, std::string& msg)
-{
-  return octave::sys::rmdir (nm, msg);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sys::recursive_rmdir' instead")
-inline int
-octave_recursive_rmdir (const std::string& nm)
-{
-  return octave::sys::recursive_rmdir (nm);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sys::recursive_rmdir' instead")
-inline int
-octave_recursive_rmdir (const std::string& nm, std::string& msg)
-{
-  return octave::sys::recursive_rmdir (nm, msg);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sys::umask' instead")
-inline int
-octave_umask (mode_t md)
-{
-  return octave::sys::umask (md);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sys::unlink' instead")
-inline int
-octave_unlink (const std::string& nm)
-{
-  return octave::sys::unlink (nm);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sys::unlink' instead")
-inline int
-octave_unlink (const std::string& nm, std::string& msg)
-{
-  return octave::sys::unlink (nm, msg);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sys::tempnam' instead")
-inline std::string
-octave_tempnam (const std::string& dir, const std::string& pfx)
-{
-  return octave::sys::tempnam (dir, pfx);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sys::tempnam' instead")
-inline std::string
-octave_tempnam (const std::string& dir, const std::string& pfx,
-                std::string& msg)
-{
-  return octave::sys::tempnam (dir, pfx, msg);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sys::canonicalize_file_name' instead")
-inline std::string
-octave_canonicalize_file_name (const std::string& nm)
-{
-  return octave::sys::canonicalize_file_name (nm);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sys::canonicalize_file_name' instead")
-inline std::string
-octave_canonicalize_file_name (const std::string& nm, std::string& msg)
-{
-  return octave::sys::canonicalize_file_name (nm, msg);
-}
-
 #endif
-
-#endif
--- a/liboctave/system/file-stat.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/system/file-stat.h	Fri Aug 10 09:09:51 2018 +0200
@@ -322,17 +322,4 @@
   }
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sys::base_file_stat' instead")
-typedef octave::sys::base_file_stat base_file_stat;
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sys::file_stat' instead")
-typedef octave::sys::file_stat file_stat;
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sys::file_fstat' instead")
-typedef octave::sys::file_fstat file_fstat;
-
 #endif
-
-#endif
--- a/liboctave/system/lo-sysdep.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/system/lo-sysdep.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -26,11 +26,20 @@
 
 #include <string>
 
+#include "dir-ops.h"
 #include "file-ops.h"
 #include "lo-error.h"
 #include "lo-sysdep.h"
+#include "uniconv-wrappers.h"
 #include "unistd-wrappers.h"
 
+#if defined (OCTAVE_USE_WINDOWS_API)
+#  include <windows.h>
+#  include <wchar.h>
+
+#  include "lo-hash.h"
+#endif
+
 namespace octave
 {
   namespace sys
@@ -67,5 +76,273 @@
 
       return octave_chdir_wrapper (path.c_str ());
     }
+
+    bool
+    get_dirlist (const std::string& dirname, string_vector& dirlist, std::string& msg)
+    {
+      dirlist = "";
+      msg = "";
+#if defined (OCTAVE_USE_WINDOWS_API)
+      _WIN32_FIND_DATAW ffd;
+
+      std::string path_name (dirname);
+      if (path_name.empty ())
+        return true;
+
+      if (path_name.back () == '\\' || path_name.back () == '/')
+        path_name.push_back ('*');
+      else
+        path_name.append (R"(\*)");
+
+      // Find first file in directory.
+      HANDLE hFind = FindFirstFileW (u8_to_wstring (path_name).c_str (),
+                              &ffd);
+      if (INVALID_HANDLE_VALUE == hFind)
+        {
+          DWORD errCode = GetLastError ();
+          char *errorText;
+          FormatMessageA (FORMAT_MESSAGE_FROM_SYSTEM |
+                         FORMAT_MESSAGE_ALLOCATE_BUFFER |
+                         FORMAT_MESSAGE_IGNORE_INSERTS,
+                         NULL, errCode,
+                         MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
+                         errorText, 0, NULL);
+          if (errorText != NULL)
+            {
+              msg = std::string (errorText);
+              LocalFree (errorText);
+            }
+          return false;
+        }
+
+      std::list<std::string> dirlist_str;
+      do
+        dirlist_str.push_back (u8_from_wstring (ffd.cFileName));
+      while (FindNextFileW (hFind, &ffd) != 0);
+
+      FindClose(hFind);
+
+      dirlist = string_vector (dirlist_str);
+
+#else
+
+      dir_entry dir (dirname);
+
+      if (! dir)
+        {
+          msg = dir.error ();
+          return false;
+        }
+
+      dirlist = dir.read ();
+
+      dir.close ();
+#endif
+
+      return true;
+    }
+
+    std::FILE *
+    fopen (const std::string& filename, const std::string& mode)
+    {
+#if defined (OCTAVE_USE_WINDOWS_API)
+      return _wfopen (u8_to_wstring (filename).c_str (),
+                      u8_to_wstring (mode).c_str ());
+#else
+      return std::fopen (filename.c_str (), mode.c_str ());
+#endif
+    }
+
+    std::wstring
+    u8_to_wstring (const std::string& utf8_string)
+    {
+      size_t srclen = utf8_string.length ();
+      const uint8_t *src = reinterpret_cast<const uint8_t *>
+                           (utf8_string.c_str ());
+
+      size_t length = 0;
+      wchar_t *wchar = reinterpret_cast<wchar_t *>
+                       (octave_u8_conv_to_encoding ("wchar_t", src, srclen,
+                                                    &length));
+
+      std::wstring retval = L"";
+      if (wchar != nullptr)
+        {
+          retval = std::wstring (wchar, length / sizeof (wchar_t));
+          free (static_cast<void *> (wchar));
+        }
+
+      return retval;
+    }
+
+    std::string
+    u8_from_wstring (const std::wstring& wchar_string)
+    {
+      size_t srclen = wchar_string.length () * sizeof (wchar_t);
+      const char *src = reinterpret_cast<const char *> (wchar_string.c_str ());
+
+      size_t length = 0;
+      char *mbchar = reinterpret_cast<char *>
+                     (octave_u8_conv_from_encoding ("wchar_t", src, srclen,
+                                                    &length));
+
+      std::string retval = "";
+      if (mbchar != nullptr)
+        {
+          retval = std::string (mbchar, length);
+          free (static_cast<void *> (mbchar));
+        }
+
+      return retval;
+    }
+
+    // At quite a few places in the code we are passing file names as
+    // char arrays to external library functions.
+
+    // When these functions try to locate the corresponding file on the
+    // disc, they need to use the wide character API on Windows to
+    // correctly open files with non-ASCII characters.
+
+    // But they have no way of knowing which encoding we are using for
+    // the passed string.  So they have no way of reliably converting to
+    // a wchar_t array.  (I.e. there is no possible fix for these
+    // functions with current C or C++.)
+
+    // To solve the dilemma, the function "get_ASCII_filename" first
+    // checks whether there are any non-ASCII characters in the passed
+    // file name.  If there are not, it returns the original name.
+
+    // Otherwise, it tries to obtain the short file name (8.3 naming
+    // scheme) which only consists of ASCII characters and are safe to
+    // pass.  However, short file names can be disabled for performance
+    // reasons on the file system level with NTFS.  So there is no
+    // guarantee that these exist.
+
+    // If short file names are not stored, a hard link to the file is
+    // created.  For this the path to the file is split at the deepest
+    // possible level that doesn't contain non-ASCII characters.  At
+    // that level a hidden folder is created that holds the hard links.
+    // That means we need to have write access on that location.  A path
+    // to that hard link is returned.
+
+    // If the file system is FAT32, there are no hard links.  But FAT32
+    // always stores short file names.  So we are safe.
+
+    // ExFAT that is occasionally used on USB sticks and SD cards stores
+    // neither short file names nor does it support hard links.  So for
+    // exFAT with this function, there is (currently) no way to generate
+    // a file name that is stripped from non-ASCII characters but still
+    // is valid.
+
+    // For Unixy systems, this function does nothing.
+
+    std::string
+    get_ASCII_filename (const std::string& orig_file_name)
+    {
+#if defined (OCTAVE_USE_WINDOWS_API)
+
+      // Return file name that only contains ASCII characters that can
+      // be used to access the file orig_file_name.  The original file
+      // must exist in the file system before calling this function.
+      // This is useful for passing file names to functions that are not
+      // aware of the character encoding we are using.
+
+      // 1. Check whether filename contains non-ASCII (UTF-8) characters.
+
+      std::string::const_iterator first_non_ASCII
+        = std::find_if (orig_file_name.begin (), orig_file_name.end (),
+                        [](char c) { return (c < 0 || c >= 128); });
+
+      if (first_non_ASCII == orig_file_name.end ())
+        return orig_file_name;
+
+      // 2. Check if file system stores short filenames (always
+      // ASCII-only).
+
+      std::wstring w_orig_file_name_str = u8_to_wstring (orig_file_name);
+      const wchar_t *w_orig_file_name = w_orig_file_name_str.c_str ();
+
+      // Get full path to file
+      wchar_t w_full_file_name[_MAX_PATH];
+      if (_wfullpath (w_full_file_name, w_orig_file_name, _MAX_PATH) == nullptr)
+        return orig_file_name;
+
+      std::wstring w_full_file_name_str = w_full_file_name;
+
+      // Get short filename (8.3) from UTF-16 filename.
+
+      long length = GetShortPathNameW (w_full_file_name, nullptr, 0);
+
+      if (length > 0)
+        {
+          // Dynamically allocate the correct size (terminating null char
+          // was included in length).
+
+          wchar_t *w_short_file_name = new wchar_t[length];
+          GetShortPathNameW (w_full_file_name, w_short_file_name, length);
+
+          std::wstring w_short_file_name_str
+            = std::wstring (w_short_file_name, length);
+          std::string short_file_name = u8_from_wstring (w_short_file_name_str);
+
+          if (w_short_file_name_str.compare (0, length-1, w_full_file_name_str) != 0)
+            return short_file_name;
+        }
+
+      // 3. Create hard link with only-ASCII characters.
+      // Get longest possible part of path that only contains ASCII chars.
+
+      std::wstring::iterator w_first_non_ASCII
+        = std::find_if (w_full_file_name_str.begin (), w_full_file_name_str.end (),
+                        [](wchar_t c) { return (c < 0 || c >= 128); });
+      std::wstring tmp_substr
+        = std::wstring (w_full_file_name_str.begin (), w_first_non_ASCII);
+
+      size_t pos
+        = tmp_substr.find_last_of (u8_to_wstring (file_ops::dir_sep_chars ()));
+
+      std::string par_dir
+        = u8_from_wstring (w_full_file_name_str.substr (0, pos+1));
+
+      // Create .oct_ascii directory.
+      // FIXME: We need to have write permission in this location.
+
+      std::string oct_ascii_dir = par_dir + ".oct_ascii";
+      std::string test_dir = canonicalize_file_name (oct_ascii_dir);
+
+      if (test_dir.empty ())
+      {
+        std::string msg;
+        int status = octave::sys::mkdir (oct_ascii_dir, 0777, msg);
+
+        if (status < 0)
+          return orig_file_name;
+
+        // Set hidden property.
+        SetFileAttributesA (oct_ascii_dir.c_str (), FILE_ATTRIBUTE_HIDDEN);
+      }
+
+      // Create file from hash of full filename.
+      std::string filename_hash
+        = (oct_ascii_dir + file_ops::dir_sep_str ()
+           + octave::crypto::hash ("SHA1", orig_file_name));
+
+      std::string abs_filename_hash = canonicalize_file_name (filename_hash);
+
+      if (! abs_filename_hash.empty ())
+        octave::sys::unlink (filename_hash);
+
+      wchar_t w_filename_hash[filename_hash.length ()+1] = {0};
+
+      for (size_t i=0; i < filename_hash.length (); i++)
+        w_filename_hash[i] = filename_hash.at (i);
+
+      if (CreateHardLinkW (w_filename_hash, w_orig_file_name, nullptr))
+        return filename_hash;
+
+#endif
+
+      return orig_file_name;
+    }
   }
 }
--- a/liboctave/system/lo-sysdep.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/system/lo-sysdep.h	Fri Aug 10 09:09:51 2018 +0200
@@ -40,17 +40,18 @@
     extern std::string getcwd (void);
 
     extern int chdir (const std::string&);
+
+    extern bool get_dirlist (const std::string& dirname, string_vector& dirlist,
+                             std::string& msg);
+
+    extern std::FILE * fopen (const std::string& name, const std::string& mode);
+
+    extern std::wstring u8_to_wstring (const std::string&);
+
+    extern std::string u8_from_wstring (const std::wstring&);
+
+    extern std::string get_ASCII_filename (const std::string& long_file_name);
   }
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sys::getcwd' instead")
-const auto octave_getcwd = octave::sys::getcwd;
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sys::chdir' instead")
-const auto octave_chdir = octave::sys::chdir;
-
 #endif
-
-#endif
--- a/liboctave/system/module.mk	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/system/module.mk	Fri Aug 10 09:09:51 2018 +0200
@@ -38,8 +38,4 @@
 
 %canon_reldir%_libsystem_la_CPPFLAGS = $(liboctave_liboctave_la_CPPFLAGS)
 
-%canon_reldir%_libsystem_la_CFLAGS = $(liboctave_liboctave_la_CFLAGS)
-
-%canon_reldir%_libsystem_la_CXXFLAGS = $(liboctave_liboctave_la_CXXFLAGS)
-
 liboctave_liboctave_la_LIBADD += %reldir%/libsystem.la
--- a/liboctave/system/oct-env.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/system/oct-env.h	Fri Aug 10 09:09:51 2018 +0200
@@ -150,11 +150,4 @@
   }
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sys::env' instead")
-typedef octave::sys::env octave_env;
-
 #endif
-
-#endif
--- a/liboctave/system/oct-group.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/system/oct-group.h	Fri Aug 10 09:09:51 2018 +0200
@@ -115,11 +115,4 @@
   }
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sys::group' instead")
-typedef octave::sys::group octave_group;
-
 #endif
-
-#endif
--- a/liboctave/system/oct-passwd.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/system/oct-passwd.h	Fri Aug 10 09:09:51 2018 +0200
@@ -135,11 +135,4 @@
   }
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sys::password' instead")
-typedef octave::sys::password octave_passwd;
-
 #endif
-
-#endif
--- a/liboctave/system/oct-syscalls.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/system/oct-syscalls.h	Fri Aug 10 09:09:51 2018 +0200
@@ -103,33 +103,4 @@
   }
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sys::popen2' instead")
-inline pid_t
-octave_popen2 (const std::string& cmd, const string_vector& args,
-               bool sync_mode, int *filedes)
-{
-  return octave::sys::popen2 (cmd, args, sync_mode, filedes);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sys::popen2' instead")
-inline pid_t
-popen2 (const std::string& cmd, const string_vector& args,
-        bool sync_mode, int *filedes, std::string& msg)
-{
-  return octave::sys::popen2 (cmd, args, sync_mode, filedes, msg);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sys::popen2' instead")
-inline pid_t
-popen2 (const std::string& cmd, const string_vector& args,
-        bool sync_mode, int *filedes, std::string& msg,
-        bool &/*interactive*/)
-{
-  return octave::sys::popen2 (cmd, args, sync_mode, filedes, msg);
-}
-
 #endif
-
-#endif
--- a/liboctave/system/oct-time.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/system/oct-time.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -28,8 +28,8 @@
 #include <ctime>
 
 #include <iomanip>
-#include <iostream>
 #include <limits>
+#include <ostream>
 
 #include "lo-error.h"
 #include "lo-utils.h"
--- a/liboctave/system/oct-time.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/system/oct-time.h	Fri Aug 10 09:09:51 2018 +0200
@@ -536,23 +536,4 @@
   }
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sys::time' instead")
-typedef octave::sys::time octave_time;
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sys::base_tm' instead")
-typedef octave::sys::base_tm octave_base_tm;
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sys::localtime' instead")
-typedef octave::sys::localtime octave_localtime;
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sys::gmtime' instead")
-typedef octave::sys::gmtime octave_gmtime;
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sys::strptime' instead")
-typedef octave::sys::strptime octave_strptime;
-
 #endif
-
-#endif
--- a/liboctave/system/oct-uname.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/system/oct-uname.h	Fri Aug 10 09:09:51 2018 +0200
@@ -94,11 +94,4 @@
   }
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sys::uname' instead")
-typedef octave::sys::uname octave_uname;
-
 #endif
-
-#endif
--- a/liboctave/util/action-container.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/util/action-container.h	Fri Aug 10 09:09:51 2018 +0200
@@ -26,7 +26,7 @@
 
 #include "octave-config.h"
 
-#include <cstddef>
+#include <functional>
 
 // This class allows registering actions in a list for later
 // execution, either explicitly or when the container goes out of
@@ -34,9 +34,6 @@
 
 // FIXME: is there a better name for this class?
 
-// FIXME: we should probably be using std::function, std::bind, and
-// related c++11 features to implement this functionality.
-
 namespace octave
 {
   class
@@ -71,238 +68,16 @@
     {
     public:
 
-      fcn_elem (void (*fptr) (void))
-        : e_fptr (fptr) { }
-
-      void run (void) { e_fptr (); }
-
-    private:
-
-      void (*e_fptr) (void);
-    };
-
-    // An element that stores a variable of type T along with a void (*) (T)
-    // function pointer, and calls the function with the parameter.
-
-    template <typename T>
-    class fcn_arg_elem : public elem
-    {
-    public:
-
-      fcn_arg_elem (void (*fcn) (T), T arg)
-        : e_fcn (fcn), e_arg (arg) { }
-
-      // No copying!
-
-      fcn_arg_elem (const fcn_arg_elem&) = delete;
-
-      fcn_arg_elem& operator = (const fcn_arg_elem&) = delete;
-
-      void run (void) { e_fcn (e_arg); }
-
-    private:
-
-      void (*e_fcn) (T);
-
-      T e_arg;
-    };
-
-    // An element that stores a variable of type T along with a
-    // void (*) (const T&) function pointer, and calls the function with
-    // the parameter.
-
-    template <typename T>
-    class fcn_crefarg_elem : public elem
-    {
-    public:
-
-      fcn_crefarg_elem (void (*fcn) (const T&), const T& arg)
-        : e_fcn (fcn), e_arg (arg) { }
-
-      void run (void) { e_fcn (e_arg); }
-
-    private:
+      template <typename F, typename... Args>
+      fcn_elem (F&& fcn, Args&&... args)
+        : m_fcn (std::bind (fcn, args...))
+      { }
 
-      void (*e_fcn) (const T&);
-
-      T e_arg;
-    };
-
-    // An element for calling a member function.
-
-    template <typename T>
-    class method_elem : public elem
-    {
-    public:
-
-      method_elem (T *obj, void (T::*method) (void))
-        : e_obj (obj), e_method (method) { }
-
-      method_elem (T& obj, void (T::*method) (void))
-        : e_obj (&obj), e_method (method) { }
-
-      // No copying!
-
-      method_elem (const method_elem&) = delete;
-
-      method_elem operator = (const method_elem&) = delete;
-
-      void run (void) { (e_obj->*e_method) (); }
-
-    private:
-
-      T *e_obj;
-
-      void (T::*e_method) (void);
-    };
-
-    // An element for calling a member function with a single argument
-
-    template <typename T, typename A>
-    class method_arg_elem : public elem
-    {
-    public:
-
-      method_arg_elem (T *obj, void (T::*method) (A), A arg)
-        : e_obj (obj), e_method (method), e_arg (arg) { }
-
-      method_arg_elem (T& obj, void (T::*method) (A), A arg)
-        : e_obj (&obj), e_method (method), e_arg (arg) { }
-
-      // No copying!
-
-      method_arg_elem (const method_arg_elem&) = delete;
-
-      method_arg_elem operator = (const method_arg_elem&) = delete;
-
-      void run (void) { (e_obj->*e_method) (e_arg); }
+      void run (void) { m_fcn (); }
 
     private:
 
-      T *e_obj;
-
-      void (T::*e_method) (A);
-
-      A e_arg;
-    };
-
-    // An element for calling a member function with a single argument
-
-    template <typename T, typename A>
-    class method_crefarg_elem : public elem
-    {
-    public:
-
-      method_crefarg_elem (T *obj, void (T::*method) (const A&), const A& arg)
-        : e_obj (obj), e_method (method), e_arg (arg) { }
-
-      method_crefarg_elem (T& obj, void (T::*method) (const A&), const A& arg)
-        : e_obj (&obj), e_method (method), e_arg (arg) { }
-
-      // No copying!
-
-      method_crefarg_elem (const method_crefarg_elem&) = delete;
-
-      method_crefarg_elem operator = (const method_crefarg_elem&) = delete;
-
-      void run (void) { (e_obj->*e_method) (e_arg); }
-
-    private:
-
-      T *e_obj;
-
-      void (T::*e_method) (const A&);
-
-      A e_arg;
-    };
-
-    /// An element for calling a member function with two arguments
-    template <class T, class A, class B>
-    class method_arg2_elem : public elem
-    {
-    public:
-      method_arg2_elem (T *obj, void (T::*method) (const A&, const B&),
-                        const A& arg_a, const B& arg_b)
-        : e_obj (obj), e_method (method),
-          e_arg_a (arg_a), e_arg_b (arg_b) { }
-
-      void run (void) { (e_obj->*e_method) (e_arg_a, e_arg_b); }
-
-    private:
-
-      T *e_obj;
-      void (T::*e_method) (const A&, const B&);
-      A e_arg_a;
-      B e_arg_b;
-
-      // No copying!
-
-      method_arg2_elem (const method_arg2_elem&);
-
-      method_arg2_elem operator = (const method_arg2_elem&);
-    };
-
-    /// An element for calling a member function with three arguments
-    template <class T, class A, class B, class C>
-    class method_arg3_elem : public elem
-    {
-    public:
-      method_arg3_elem (T *obj,
-                        void (T::*method) (const A&, const B&, const C&),
-                        const A& arg_a, const B& arg_b, const C& arg_c)
-        : e_obj (obj), e_method (method),
-          e_arg_a (arg_a), e_arg_b (arg_b), e_arg_c (arg_c)
-      { }
-
-      void run (void) { (e_obj->*e_method) (e_arg_a, e_arg_b, e_arg_c); }
-
-    private:
-
-      T *e_obj;
-      void (T::*e_method) (const A&, const B&, const C&);
-      A e_arg_a;
-      B e_arg_b;
-      C e_arg_c;
-
-      // No copying!
-
-      method_arg3_elem (const method_arg3_elem&);
-
-      method_arg3_elem operator = (const method_arg3_elem&);
-    };
-
-    /// An element for calling a member function with three arguments
-    template <class T, class A, class B, class C, class D>
-    class method_arg4_elem : public elem
-    {
-    public:
-      method_arg4_elem (T *obj,
-                        void (T::*method) (const A&, const B&, const C&, const D&),
-                        const A& arg_a, const B& arg_b, const C& arg_c,
-                        const D& arg_d)
-        : e_obj (obj), e_method (method),
-          e_arg_a (arg_a), e_arg_b (arg_b), e_arg_c (arg_c), e_arg_d (arg_d)
-      { }
-
-      void run (void)
-      {
-        (e_obj->*e_method) (e_arg_a, e_arg_b, e_arg_c, e_arg_d);
-      }
-
-    private:
-
-      T *e_obj;
-      void (T::*e_method) (const A&, const B&, const C&, const D&);
-      A e_arg_a;
-      B e_arg_b;
-      C e_arg_c;
-      D e_arg_d;
-
-      // No copying!
-
-      method_arg4_elem (const method_arg4_elem&);
-
-      method_arg4_elem operator = (const method_arg4_elem&);
+      std::function<void (void)> m_fcn;
     };
 
     // An element that stores arbitrary variable, and restores it.
@@ -361,94 +136,33 @@
 
     virtual ~action_container (void) = default;
 
-    virtual void add (elem *new_elem) = 0;
-
-    // Call to void func (void).
-    void add_fcn (void (*fcn) (void))
-    {
-      add (new fcn_elem (fcn));
-    }
-
-    // Call to void func (T).
-    template <typename T>
-    void add_fcn (void (*action) (T), T val)
-    {
-      add (new fcn_arg_elem<T> (action, val));
-    }
-
-    // Call to void func (const T&).
-    template <typename T>
-    void add_fcn (void (*action) (const T&), const T& val)
+    template <typename F, typename... Args>
+    void add (F&& fcn, Args&&... args)
     {
-      add (new fcn_crefarg_elem<T> (action, val));
-    }
-
-    // Call to T::method (void).
-    template <typename T>
-    void add_method (T *obj, void (T::*method) (void))
-    {
-      add (new method_elem<T> (obj, method));
-    }
-
-    template <typename T>
-    void add_method (T& obj, void (T::*method) (void))
-    {
-      add (new method_elem<T> (obj, method));
-    }
-
-    // Call to T::method (A).
-    template <typename T, typename A>
-    void add_method (T *obj, void (T::*method) (A), A arg)
-    {
-      add (new method_arg_elem<T, A> (obj, method, arg));
+      add_action (new fcn_elem (std::forward<F> (fcn),
+                                std::forward<Args> (args)...));
     }
 
-    template <typename T, typename A>
-    void add_method (T& obj, void (T::*method) (A), A arg)
-    {
-      add (new method_arg_elem<T, A> (obj, method, arg));
-    }
+    // Use separate template types for function pointer parameter
+    // declarations and captured arguments so that differences in
+    // const are handled properly.
 
-    // Call to T::method (const A&).
-    template <typename T, typename A>
-    void add_method (T *obj, void (T::*method) (const A&), const A& arg)
+    template <typename... Params, typename... Args>
+    void add_fcn (void (*fcn) (Params...), Args&&... args)
     {
-      add (new method_crefarg_elem<T, A> (obj, method, arg));
-    }
-
-    template <typename T, typename A>
-    void add_method (T& obj, void (T::*method) (const A&), const A& arg)
-    {
-      add (new method_crefarg_elem<T, A> (obj, method, arg));
+      add_action (new fcn_elem (fcn, std::forward<Args> (args)...));
     }
 
-    // Call to T::method (A, B).
-    template <class T, class A, class B>
-    void add_method (T *obj, void (T::*method) (const A&, const B&),
-                     const A& arg_a, const B& arg_b)
+    template <typename T, typename... Params, typename... Args>
+    void add_method (T *obj, void (T::*method) (Params...), Args&&... args)
     {
-      add (new method_arg2_elem<T, A, B> (obj, method, arg_a, arg_b));
+      add_action (new fcn_elem (method, obj, std::forward<Args> (args)...));
     }
 
-    // Call to T::method (A, B, C).
-    template <class T, class A, class B, class C>
-    void add_method (T *obj,
-                     void (T::*method) (const A&, const B&, const C&),
-                     const A& arg_a, const B& arg_b, const C& arg_c)
+    template <typename T, typename... Params, typename... Args>
+    void add_method (T& obj, void (T::*method) (Params...), Args&&... args)
     {
-      add (new method_arg3_elem<T, A, B, C> (obj, method, arg_a,
-                                             arg_b, arg_c));
-    }
-
-    // Call to T::method (A, B, C, D).
-    template <class T, class A, class B, class C, class D>
-    void add_method (T *obj,
-                     void (T::*method) (const A&, const B&, const C&, const D&),
-                     const A& arg_a, const B& arg_b,
-                     const C& arg_c, const D& arg_d)
-    {
-      add (new method_arg4_elem<T, A, B, C, D> (obj, method, arg_a,
-                                                arg_b, arg_c, arg_d));
+      add_action (new fcn_elem (method, &obj, std::forward<Args> (args)...));
     }
 
     // Call to delete (T*).
@@ -456,21 +170,21 @@
     template <typename T>
     void add_delete (T *obj)
     {
-      add (new delete_ptr_elem<T> (obj));
+      add_action (new delete_ptr_elem<T> (obj));
     }
 
     // Protect any variable.
     template <typename T>
     void protect_var (T& var)
     {
-      add (new restore_var_elem<T> (var, var));
+      add_action (new restore_var_elem<T> (var, var));
     }
 
     // Protect any variable, value given.
     template <typename T>
     void protect_var (T& var, const T& val)
     {
-      add (new restore_var_elem<T> (var, val));
+      add_action (new restore_var_elem<T> (var, val));
     }
 
     operator bool (void) const { return ! empty (); }
@@ -504,6 +218,10 @@
     virtual size_t size (void) const = 0;
 
     bool empty (void) const { return size () == 0; }
+
+  protected:
+
+    virtual void add_action (elem *new_elem) = 0;
   };
 }
 
--- a/liboctave/util/caseless-str.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/util/caseless-str.h	Fri Aug 10 09:09:51 2018 +0200
@@ -49,8 +49,8 @@
 
   bool operator < (const std::string& s) const
   {
-    const_iterator p1 = begin ();
-    const_iterator p2 = s.begin ();
+    auto p1 = begin ();
+    auto p2 = s.begin ();
 
     while (p1 != end () && p2 != s.end ())
       {
@@ -75,8 +75,8 @@
   // Case-insensitive comparison.
   bool compare (const std::string& s, size_t limit = std::string::npos) const
   {
-    const_iterator p1 = begin ();
-    const_iterator p2 = s.begin ();
+    auto p1 = begin ();
+    auto p2 = s.begin ();
 
     size_t k = 0;
 
--- a/liboctave/util/cmd-edit.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/util/cmd-edit.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -788,7 +788,7 @@
 
     ::octave_rl_recover_from_interrupt ();
 
-    throw octave::interrupt_exception ();
+    throw interrupt_exception ();
   }
 
   int
--- a/liboctave/util/cmd-edit.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/util/cmd-edit.h	Fri Aug 10 09:09:51 2018 +0200
@@ -371,11 +371,4 @@
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::command_editor' instead")
-typedef octave::command_editor command_editor;
-
 #endif
-
-#endif
--- a/liboctave/util/cmd-hist.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/util/cmd-hist.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -27,7 +27,6 @@
 #include <cstring>
 
 #include <fstream>
-#include <iostream>
 #include <sstream>
 #include <string>
 
--- a/liboctave/util/cmd-hist.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/util/cmd-hist.h	Fri Aug 10 09:09:51 2018 +0200
@@ -233,11 +233,4 @@
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::command_history' instead")
-typedef octave::command_history command_history;
-
 #endif
-
-#endif
--- a/liboctave/util/data-conv.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/util/data-conv.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -27,8 +27,9 @@
 #include <cctype>
 #include <cstdlib>
 
-#include <iostream>
+#include <istream>
 #include <limits>
+#include <ostream>
 #include <vector>
 
 #include "byte-swap.h"
--- a/liboctave/util/data-conv.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/util/data-conv.h	Fri Aug 10 09:09:51 2018 +0200
@@ -25,8 +25,6 @@
 
 #include "octave-config.h"
 
-#include <limits>
-
 #include "mach-info.h"
 #include "oct-inttypes-fwd.h"
 
--- a/liboctave/util/file-info.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/util/file-info.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -27,11 +27,11 @@
 
 #include <deque>
 #include <fstream>
-#include <iostream>
 
 #include "file-info.h"
 #include "file-stat.h"
 #include "lo-error.h"
+#include "lo-sysdep.h"
 
 namespace octave
 {
@@ -81,7 +81,9 @@
 
     size_t sz = fs.size ();
 
-    std::ifstream file (fname.c_str (), std::ios::in | std::ios::binary);
+    std::string ascii_fname = octave::sys::get_ASCII_filename (fname);
+
+    std::ifstream file (ascii_fname.c_str (), std::ios::in | std::ios::binary);
 
     if (file)
       {
--- a/liboctave/util/lo-array-errwarn.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/util/lo-array-errwarn.h	Fri Aug 10 09:09:51 2018 +0200
@@ -157,111 +157,4 @@
   warn_singular_matrix (double rcond = 0.0);
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::err_nan_to_logical_conversion' instead")
-OCTAVE_NORETURN inline void
-err_nan_to_logical_conversion (void)
-{
-  octave::err_nan_to_logical_conversion ();
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::err_nan_to_character_conversion' instead")
-OCTAVE_NORETURN inline void
-err_nan_to_character_conversion (void)
-{
-  octave::err_nan_to_character_conversion ();
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::err_nonconformant' instead")
-OCTAVE_NORETURN inline void
-err_nonconformant (const char *op, octave_idx_type op1_len,
-                   octave_idx_type op2_len)
-{
-  octave::err_nonconformant (op, op1_len, op2_len);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::err_nonconformant' instead")
-OCTAVE_NORETURN inline void
-err_nonconformant (const char *op,
-                   octave_idx_type op1_nr, octave_idx_type op1_nc,
-                   octave_idx_type op2_nr, octave_idx_type op2_nc)
-{
-  octave::err_nonconformant (op, op1_nr, op1_nc, op2_nr, op2_nc);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::err_nonconformant' instead")
-OCTAVE_NORETURN inline void
-err_nonconformant (const char *op,
-                   const dim_vector& op1_dims, const dim_vector& op2_dims)
-{
-  octave::err_nonconformant (op, op1_dims, op2_dims);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::err_index_out_of_range' instead")
-OCTAVE_NORETURN inline void
-err_index_out_of_range (int nd, int dim, octave_idx_type iext,
-                        octave_idx_type ext, const dim_vector& d)
-{
-  octave::err_index_out_of_range (nd, dim, iext, ext, d);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::err_index_out_of_range' instead")
-OCTAVE_NORETURN inline void
-err_index_out_of_range (int nd, int dim, octave_idx_type iext,
-                        octave_idx_type ext)
-{
-  octave::err_index_out_of_range (nd, dim, iext, ext);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::err_del_index_out_of_range' instead")
-OCTAVE_NORETURN inline void
-err_del_index_out_of_range (bool is1d, octave_idx_type iext,
-                            octave_idx_type ext)
-{
-  octave::err_del_index_out_of_range (is1d, iext, ext);
-}
-
-OCTAVE_NORETURN inline void
-err_invalid_index (double n, octave_idx_type nd = 0,
-                   octave_idx_type dim = 0,
-                   const std::string& var = "")
-{
-  octave::err_invalid_index (n, nd, dim, var);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::err_invalid_index' instead")
-OCTAVE_NORETURN inline void
-err_invalid_index (octave_idx_type n, octave_idx_type nd = 0,
-                   octave_idx_type dim = 0,
-                   const std::string& var = "")
-{
-  octave::err_invalid_index (n, nd, dim, var);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::err_invalid_index' instead")
-OCTAVE_NORETURN inline void
-err_invalid_index (const std::string& idx, octave_idx_type nd = 0,
-                   octave_idx_type dim = 0,
-                   const std::string& var = "")
-{
-  octave::err_invalid_index (idx, nd, dim, var);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::err_invalid_resize' instead")
-OCTAVE_NORETURN inline void
-err_invalid_resize (void)
-{
-  octave::err_invalid_resize ();
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::warn_singular_matrix' instead")
-inline void
-warn_singular_matrix (double rcond = 0.0)
-{
-  return octave::warn_singular_matrix (rcond);
-}
-
 #endif
-
-#endif
--- a/liboctave/util/lo-array-gripes.cc	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,299 +0,0 @@
-/*
-
-Copyright (C) 2003-2018 John W. Eaton
-Copyright (C) 2009 VZLU Prague
-
-This file is part of Octave.
-
-Octave is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-Octave is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Octave; see the file COPYING.  If not, see
-<https://www.gnu.org/licenses/>.
-
-*/
-
-// FIXME: All gripe_XXX functions deprecated in 4.2.  Remove file in
-// version 5.
-
-#if defined (HAVE_CONFIG_H)
-#  include "config.h"
-#endif
-
-#include <sstream>
-
-#include "lo-array-gripes.h"
-#include "lo-error.h"
-
-// Text constants used to shorten code below.
-static const char *error_id_nonconformant_args = "Octave:nonconformant-args";
-
-static const char *error_id_index_out_of_bounds = "Octave:index-out-of-bounds";
-
-static const char *error_id_invalid_index = "Octave:invalid-index";
-
-static const char *warning_id_nearly_singular_matrix =
-  "Octave:nearly-singular-matrix";
-
-static const char *warning_id_singular_matrix = "Octave:singular-matrix";
-
-void
-gripe_nan_to_logical_conversion (void)
-{
-  (*current_liboctave_error_handler)
-    ("invalid conversion from NaN to logical");
-}
-
-void
-gripe_nan_to_character_conversion (void)
-{
-  (*current_liboctave_error_handler)
-    ("invalid conversion from NaN to character");
-}
-
-void
-gripe_nonconformant (const char *op, octave_idx_type op1_len,
-                     octave_idx_type op2_len)
-{
-  const char *err_id = error_id_nonconformant_args;
-
-  (*current_liboctave_error_with_id_handler)
-    (err_id, "%s: nonconformant arguments (op1 len: %d, op2 len: %d)",
-     op, op1_len, op2_len);
-}
-
-void
-gripe_nonconformant (const char *op,
-                     octave_idx_type op1_nr, octave_idx_type op1_nc,
-                     octave_idx_type op2_nr, octave_idx_type op2_nc)
-{
-  const char *err_id = error_id_nonconformant_args;
-
-  (*current_liboctave_error_with_id_handler)
-    (err_id, "%s: nonconformant arguments (op1 is %dx%d, op2 is %dx%d)",
-     op, op1_nr, op1_nc, op2_nr, op2_nc);
-}
-
-void
-gripe_nonconformant (const char *op, const dim_vector& op1_dims,
-                     const dim_vector& op2_dims)
-{
-  const char *err_id = error_id_nonconformant_args;
-
-  std::string op1_dims_str = op1_dims.str ();
-  std::string op2_dims_str = op2_dims.str ();
-
-  (*current_liboctave_error_with_id_handler)
-    (err_id, "%s: nonconformant arguments (op1 is %s, op2 is %s)",
-     op, op1_dims_str.c_str (), op2_dims_str.c_str ());
-}
-
-void
-gripe_del_index_out_of_range (bool is1d, octave_idx_type idx,
-                              octave_idx_type ext)
-{
-  const char *err_id = error_id_index_out_of_bounds;
-
-  (*current_liboctave_error_with_id_handler)
-    (err_id, "A(%s) = []: index out of bounds: value %d out of bound %d",
-     is1d ? "I" : "..,I,..", idx, ext);
-}
-
-namespace octave
-{
-  class invalid_index : public index_exception
-  {
-  public:
-
-    invalid_index (const std::string& value, octave_idx_type ndim,
-                   octave_idx_type dimen)
-      : index_exception (value, ndim, dimen)
-    { }
-
-    std::string details (void) const
-    {
-#if defined (OCTAVE_ENABLE_64)
-      return "subscripts must be either integers 1 to (2^63)-1 or logicals";
-#else
-      return "subscripts must be either integers 1 to (2^31)-1 or logicals";
-#endif
-    }
-
-    // ID of error to throw
-    const char * err_id (void) const
-    {
-      return error_id_invalid_index;
-    }
-  };
-}
-
-// Complain if an index is negative, fractional, or too big.
-
-void
-gripe_invalid_index (const std::string& idx, octave_idx_type nd,
-                     octave_idx_type dim, const std::string&)
-{
-  octave::invalid_index e (idx, nd, dim);
-
-  throw e;
-}
-
-void
-gripe_invalid_index (octave_idx_type n, octave_idx_type nd,
-                     octave_idx_type dim, const std::string& var)
-{
-  std::ostringstream buf;
-  buf << n + 1;
-
-#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
-#  pragma GCC diagnostic push
-#  pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-
-  gripe_invalid_index (buf.str (), nd, dim, var);
-
-#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
-#  pragma GCC diagnostic pop
-#endif
-}
-
-void
-gripe_invalid_index (double n, octave_idx_type nd, octave_idx_type dim,
-                     const std::string& var)
-{
-  std::ostringstream buf;
-  buf << n + 1;
-
-#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
-#  pragma GCC diagnostic push
-#  pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-
-  gripe_invalid_index (buf.str (), nd, dim, var);
-
-#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
-#  pragma GCC diagnostic pop
-#endif
-}
-
-namespace octave
-{
-  // Gripe and exception for read access beyond the bounds of an array.
-
-  class out_of_range : public index_exception
-  {
-  public:
-
-    out_of_range (const std::string& value, octave_idx_type nd_in,
-                  octave_idx_type dim_in)
-      : index_exception (value, nd_in, dim_in), extent (0)
-    { }
-
-    std::string details (void) const
-    {
-      std::string expl;
-
-      if (nd >= size.ndims ())   // if not an index slice
-        {
-          if (var != "")
-            expl = "but " + var + " has size ";
-          else
-            expl = "but object has size ";
-
-          expl = expl + size.str ('x');
-        }
-      else
-        {
-          std::ostringstream buf;
-          buf << extent;
-          expl = "out of bound " + buf.str ();
-        }
-
-      return expl;
-    }
-
-    // ID of error to throw.
-    const char * err_id (void) const
-    {
-      return error_id_index_out_of_bounds;
-    }
-
-    void set_size (const dim_vector& size_in) { size = size_in; }
-
-    void set_extent (octave_idx_type ext) { extent = ext; }
-
-  private:
-
-    // Dimension of object being accessed.
-    dim_vector size;
-
-    // Length of dimension being accessed.
-    octave_idx_type extent;
-  };
-}
-
-// Complain of an index that is out of range, but we don't know matrix size
-void
-gripe_index_out_of_range (int nd, int dim, octave_idx_type idx,
-                          octave_idx_type ext)
-{
-  std::ostringstream buf;
-  buf << idx;
-  octave::out_of_range e (buf.str (), nd, dim);
-
-  e.set_extent (ext);
-  // ??? Make details method give extent not size.
-  e.set_size (dim_vector (1, 1, 1, 1, 1, 1,1));
-
-  throw e;
-}
-
-// Complain of an index that is out of range
-void
-gripe_index_out_of_range (int nd, int dim, octave_idx_type idx,
-                          octave_idx_type ext, const dim_vector& d)
-{
-  std::ostringstream buf;
-  buf << idx;
-  octave::out_of_range e (buf.str (), nd, dim);
-
-  e.set_extent (ext);
-  e.set_size (d);
-
-  throw e;
-}
-
-void
-gripe_invalid_resize (void)
-{
-  (*current_liboctave_error_with_id_handler)
-    ("Octave:invalid-resize",
-     "Invalid resizing operation or ambiguous assignment to an out-of-bounds array element");
-}
-
-void
-gripe_singular_matrix (double rcond)
-{
-  if (rcond == 0.0)
-    {
-      (*current_liboctave_warning_with_id_handler)
-        (warning_id_singular_matrix,
-         "matrix singular to machine precision");
-    }
-  else
-    {
-      (*current_liboctave_warning_with_id_handler)
-        (warning_id_nearly_singular_matrix,
-         "matrix singular to machine precision, rcond = %g", rcond);
-    }
-}
-
-/* Tests in test/index.tst */
--- a/liboctave/util/lo-array-gripes.h	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +0,0 @@
-/*
-
-Copyright (C) 2000-2018 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
-<https://www.gnu.org/licenses/>.
-
-*/
-
-// FIXME: All gripe_XXX functions deprecated in 4.2.  Remove file in
-// version 5.
-
-#if ! defined (octave_lo_array_gripes_h)
-#define octave_lo_array_gripes_h 1
-
-#include "octave-config.h"
-
-#include "lo-array-errwarn.h"
-#include "dim-vector.h"
-#include "quit.h"
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::err_nan_to_logical_conversion' instead")
-OCTAVE_NORETURN OCTAVE_API extern void
-gripe_nan_to_logical_conversion (void);
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::err_nan_to_character_conversion' instead")
-OCTAVE_NORETURN OCTAVE_API extern void
-gripe_nan_to_character_conversion (void);
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::err_nonconformant' instead")
-OCTAVE_NORETURN OCTAVE_API extern void
-gripe_nonconformant (const char *op,
-                     octave_idx_type op1_len,
-                     octave_idx_type op2_len);
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::err_nonconformant' instead")
-OCTAVE_NORETURN OCTAVE_API extern void
-gripe_nonconformant (const char *op,
-                     octave_idx_type op1_nr, octave_idx_type op1_nc,
-                     octave_idx_type op2_nr, octave_idx_type op2_nc);
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::err_nonconformant' instead")
-OCTAVE_NORETURN OCTAVE_API extern void
-gripe_nonconformant (const char *op, const dim_vector& op1_dims,
-                     const dim_vector& op2_dims);
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::err_index_out_of_range' instead")
-OCTAVE_NORETURN OCTAVE_API extern void
-gripe_index_out_of_range (int nd, int dim,
-                          octave_idx_type iext, octave_idx_type ext,
-                          const dim_vector& d);
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::err_index_out_of_range' instead")
-OCTAVE_NORETURN OCTAVE_API extern void
-gripe_index_out_of_range (int nd, int dim,
-                          octave_idx_type iext, octave_idx_type ext);
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::err_del_index_out_of_range' instead")
-OCTAVE_NORETURN OCTAVE_API extern void
-gripe_del_index_out_of_range (bool is1d, octave_idx_type iext,
-                              octave_idx_type ext);
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::err_invalid_index' instead")
-OCTAVE_NORETURN OCTAVE_API extern void
-gripe_invalid_index (double, octave_idx_type nd = 0,
-                     octave_idx_type dim = 0,
-                     const std::string& var = "");
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::err_invalid_index' instead")
-OCTAVE_NORETURN OCTAVE_API extern void
-gripe_invalid_index (octave_idx_type n, octave_idx_type nd = 0,
-                     octave_idx_type dim = 0,
-                     const std::string& var = "");
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::err_invalid_index' instead")
-OCTAVE_NORETURN OCTAVE_API extern void
-gripe_invalid_index (const std::string& idx, octave_idx_type nd = 0,
-                     octave_idx_type dim = 0,
-                     const std::string& var = "");
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::err_invalid_resize' instead")
-OCTAVE_NORETURN OCTAVE_API extern void
-gripe_invalid_resize (void);
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::err_singular_matrix' instead")
-OCTAVE_API extern void
-gripe_singular_matrix (double rcond = 0.0);
-
-#endif
--- a/liboctave/util/lo-regexp.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/util/lo-regexp.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -459,7 +459,7 @@
   {
     std::string retval;
 
-    regexp::match_data rx_lst = match (buffer);
+    const regexp::match_data rx_lst = match (buffer);
 
     size_t num_matches = rx_lst.size ();
 
@@ -518,7 +518,7 @@
         // Determine replacement length
         const size_t replen = repstr.size () - 2*num_tokens;
         int delta = 0;
-        regexp::match_data::const_iterator p = rx_lst.begin ();
+        auto p = rx_lst.begin ();
         for (size_t i = 0; i < num_matches; i++)
           {
             octave_quit ();
@@ -595,7 +595,7 @@
         // Determine repstr length
         const size_t replen = repstr.size ();
         int delta = 0;
-        regexp::match_data::const_iterator p = rx_lst.begin ();
+        auto p = rx_lst.begin ();
         for (size_t i = 0; i < num_matches; i++)
           {
             octave_quit ();
--- a/liboctave/util/lo-regexp.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/util/lo-regexp.h	Fri Aug 10 09:09:51 2018 +0200
@@ -258,7 +258,7 @@
 
       ~match_data (void) = default;
 
-      string_vector named_patterns (void) { return named_pats; }
+      string_vector named_patterns (void) const { return named_pats; }
 
     private:
 
@@ -287,52 +287,4 @@
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::regexp' instead")
-typedef octave::regexp regexp;
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::regexp::match' instead")
-inline regexp::match_data
-regexp_match (const std::string& pat,
-              const std::string& buffer,
-              const regexp::opts& opt = regexp::opts (),
-              const std::string& who = "regexp")
-{
-  return octave::regexp::match (pat, buffer, opt, who);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::regexp::is_match' instead")
-inline bool
-is_regexp_match (const std::string& pat,
-                 const std::string& buffer,
-                 const regexp::opts& opt = regexp::opts (),
-                 const std::string& who = "regexp")
-{
-  return octave::regexp::is_match (pat, buffer, opt, who);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::regexp::is_match' instead")
-inline Array<bool>
-is_regexp_match (const std::string& pat,
-                 const string_vector& buffer,
-                 const regexp::opts& opt = regexp::opts (),
-                 const std::string& who = "regexp")
-{
-  return octave::regexp::is_match (pat, buffer, opt, who);
-}
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::regexp::replace' instead")
-inline std::string
-regexp_replace (const std::string& pat,
-                const std::string& buffer,
-                const std::string& replacement,
-                const regexp::opts& opt = regexp::opts (),
-                const std::string& who = "regexp")
-{
-  return octave::regexp::replace (pat, buffer, replacement, opt, who);
-}
-
 #endif
-
-#endif
--- a/liboctave/util/lo-utils.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/util/lo-utils.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -28,7 +28,9 @@
 #include <cstring>
 
 #include <complex>
+#include <istream>
 #include <limits>
+#include <ostream>
 #include <string>
 
 #include "quit.h"
@@ -237,6 +239,8 @@
                 val = octave::numeric_limits<T>::NA ();
                 if (c2 != std::istream::traits_type::eof ())
                   is.putback (c2);
+                else
+                  is.clear (is.rdstate () & ~std::ios::failbit);
               }
           }
         else
--- a/liboctave/util/lo-utils.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/util/lo-utils.h	Fri Aug 10 09:09:51 2018 +0200
@@ -27,7 +27,7 @@
 
 #include <cstdio>
 
-#include <iostream>
+#include <iosfwd>
 #include <string>
 
 #include "lo-cutils.h"
--- a/liboctave/util/module.mk	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/util/module.mk	Fri Aug 10 09:09:51 2018 +0200
@@ -10,7 +10,6 @@
   %reldir%/functor.h \
   %reldir%/glob-match.h \
   %reldir%/lo-array-errwarn.h \
-  %reldir%/lo-array-gripes.h \
   %reldir%/lo-cutils.h \
   %reldir%/lo-hash.h \
   %reldir%/lo-ieee.h \
@@ -70,7 +69,6 @@
   %reldir%/glob-match.cc \
   %reldir%/kpse.cc \
   %reldir%/lo-array-errwarn.cc \
-  %reldir%/lo-array-gripes.cc \
   %reldir%/lo-hash.cc \
   %reldir%/lo-ieee.cc \
   %reldir%/lo-regexp.cc \
@@ -110,10 +108,6 @@
   $(PCRE_CPPFLAGS) \
   $(SPARSE_XCPPFLAGS)
 
-%canon_reldir%_libutil_la_CFLAGS = $(liboctave_liboctave_la_CFLAGS)
-
-%canon_reldir%_libutil_la_CXXFLAGS = $(liboctave_liboctave_la_CXXFLAGS)
-
 %canon_reldir%_libutil_la_FFLAGS = $(F77_INTEGER_8_FLAG)
 
 liboctave_liboctave_la_LIBADD += %reldir%/libutil.la
--- a/liboctave/util/oct-base64.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/util/oct-base64.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -93,7 +93,11 @@
   }
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
+// Always define these functions.  The macro is intended to allow the
+// declarations to be hidden, not so that Octave will not provide the
+// functions if they are requested.
+
+// #if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
 
 bool
 octave_base64_encode (const char *inc, const size_t inlen, char **out)
@@ -107,4 +111,4 @@
   return octave::base64_decode (str);
 }
 
-#endif
+// #endif
--- a/liboctave/util/oct-glob.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/util/oct-glob.h	Fri Aug 10 09:09:51 2018 +0200
@@ -43,14 +43,4 @@
   }
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sys::fnmatch' instead")
-const auto octave_fnmatch = octave::sys::fnmatch;
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::sys::glob' instead")
-const auto octave_glob = octave::sys::glob;
-
 #endif
-
-#endif
--- a/liboctave/util/oct-inttypes.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/util/oct-inttypes.h	Fri Aug 10 09:09:51 2018 +0200
@@ -59,16 +59,6 @@
   }
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::round' instead")
-inline long double xround (long double x) { return octave::math::round (x); }
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::isnan' instead")
-inline bool xisnan (long double x) { return octave::math::isnan (x); }
-
-#endif
-
 #endif
 
 // FIXME: we define this by our own because some compilers, such as
@@ -994,18 +984,6 @@
   }
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-template <typename T>
-OCTAVE_DEPRECATED (4.2, "use 'octave::math::isnan' instead")
-bool
-xisnan (const octave_int<T>& x)
-{
-  return octave::math::isnan (x);
-}
-
-#endif
-
 // FIXME: can/should any of these be inline?
 
 template <typename T>
--- a/liboctave/util/oct-shlib.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/util/oct-shlib.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -62,6 +62,10 @@
 #include "oct-shlib.h"
 #include "str-vec.h"
 
+#if defined (HAVE_LOADLIBRARY_API)
+#  include "lo-sysdep.h"
+#endif
+
 namespace octave
 {
   dynamic_library::dynlib_rep::dynlib_rep (const std::string& f)
@@ -371,7 +375,8 @@
   static void
   set_dll_directory (const std::string& dir = "")
   {
-    SetDllDirectory (dir.empty () ? nullptr : dir.c_str ());
+    SetDllDirectoryW (dir.empty () ? nullptr
+                                   : sys::u8_to_wstring (dir).c_str ());
   }
 
   octave_w32_shlib::octave_w32_shlib (const std::string& f)
@@ -387,7 +392,7 @@
 
     set_dll_directory (dir);
 
-    handle = LoadLibrary (file.c_str ());
+    handle = LoadLibraryW (sys::u8_to_wstring (file).c_str ());
 
     set_dll_directory ();
 
--- a/liboctave/util/oct-shlib.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/util/oct-shlib.h	Fri Aug 10 09:09:51 2018 +0200
@@ -202,11 +202,4 @@
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::dynamic_library' instead")
-typedef octave::dynamic_library octave_shlib;
-
 #endif
-
-#endif
--- a/liboctave/util/oct-sort.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/util/oct-sort.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -111,6 +111,7 @@
 #include <cstring>
 #include <stack>
 
+#include "lo-error.h"
 #include "lo-mappers.h"
 #include "quit.h"
 #include "oct-sort.h"
@@ -493,10 +494,10 @@
 }
 
 static inline octave_idx_type
-roundupsize (octave_idx_type n)
+roundupsize (size_t n)
 {
   unsigned int nbits = 3;
-  octave_idx_type n2 = static_cast<octave_idx_type> (n) >> 8;
+  size_t n2 = n >> 8;
 
   /* Round up:
    * If n <       256, to a multiple of        8.
@@ -526,7 +527,13 @@
       nbits += 3;
     }
 
-  return ((n >> nbits) + 1) << nbits;
+  size_t new_size = ((n >> nbits) + 1) << nbits;
+
+  if (new_size == 0 || new_size > std::numeric_limits<octave_idx_type>::max ())
+    (*current_liboctave_error_handler)
+      ("unable to allocate sufficient memory for sort");
+
+  return static_cast<octave_idx_type> (new_size);
 }
 
 /* Ensure enough temp memory for 'need' array slots is available.
--- a/liboctave/util/oct-string.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/util/oct-string.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -146,8 +146,13 @@
 octave::string::strncmp (const T& str_a, const T& str_b,
                          const typename T::size_type n)
 {
-  return (numel (str_a) >= n && numel (str_b) >= n
-          && str_data_cmp<T> (str_a.data (), str_b.data (), n));
+  typename T::size_type neff;
+  auto len_a = numel (str_a);
+  auto len_b = numel (str_b);
+  neff = std::min (std::max (len_a, len_b), n); 
+
+  return (len_a >= neff && len_b >= neff
+          && str_data_cmp<T> (str_a.data (), str_b.data (), neff));
 }
 
 template<typename T>
@@ -155,8 +160,13 @@
 octave::string::strncmp (const T& str_a, const typename T::value_type *str_b,
                          const typename T::size_type n)
 {
-  return (numel (str_a) >= n && strlen<T> (str_b) >= n
-          && str_data_cmp<T> (str_a.data (), str_b, n));
+  typename T::size_type neff;
+  auto len_a = numel (str_a);
+  auto len_b = strlen<T> (str_b);
+  neff = std::min (std::max (len_a, len_b), n); 
+
+  return (len_a >= neff && len_b >= neff
+          && str_data_cmp<T> (str_a.data (), str_b, neff));
 }
 
 
@@ -165,8 +175,13 @@
 octave::string::strncmpi (const T& str_a, const T& str_b,
                           const typename T::size_type n)
 {
-  return (numel (str_a) >= n && numel (str_b) >= n
-          && str_data_cmpi<T> (str_a.data (), str_b.data (), n));
+  typename T::size_type neff;
+  auto len_a = numel (str_a);
+  auto len_b = numel (str_b);
+  neff = std::min (std::max (len_a, len_b), n); 
+
+  return (len_a >= neff && len_b >= neff
+          && str_data_cmpi<T> (str_a.data (), str_b.data (), neff));
 }
 
 template<typename T>
@@ -174,8 +189,13 @@
 octave::string::strncmpi (const T& str_a, const typename T::value_type *str_b,
                           const typename T::size_type n)
 {
-  return (numel (str_a) >= n && strlen<T> (str_b) >= n
-          && str_data_cmpi<T> (str_a.data (), str_b, n));
+  typename T::size_type neff;
+  auto len_a = numel (str_a);
+  auto len_b = strlen<T> (str_b);
+  neff = std::min (std::max (len_a, len_b), n); 
+
+  return (len_a >= neff && len_b >= neff
+          && str_data_cmpi<T> (str_a.data (), str_b, neff));
 }
 
 
--- a/liboctave/util/pathsearch.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/util/pathsearch.h	Fri Aug 10 09:09:51 2018 +0200
@@ -103,11 +103,4 @@
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::directory_path' instead")
-typedef octave::directory_path dir_path;
-
 #endif
-
-#endif
--- a/liboctave/util/quit.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/util/quit.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -26,7 +26,6 @@
 
 #include <cstring>
 
-#include <iostream>
 #include <new>
 
 #include "quit.h"
@@ -94,7 +93,7 @@
 #  pragma GCC diagnostic ignored "-Wdeprecated-declarations"
 #endif
 
-  throw octave_exit_exception (exit_status, safe_to_return);
+  throw octave::exit_exception (exit_status, safe_to_return);
 
 #if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
 #  pragma GCC diagnostic pop
--- a/liboctave/util/quit.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/util/quit.h	Fri Aug 10 09:09:51 2018 +0200
@@ -121,15 +121,6 @@
   };
 }
 
-OCTAVE_DEPRECATED (4.2, "use 'octave::execution_exception' instead")
-typedef octave::execution_exception octave_execution_exception;
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::exit_exception' instead")
-typedef octave::exit_exception octave_exit_exception;
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::interrupt_exception' instead")
-typedef octave::interrupt_exception octave_interrupt_exception;
-
 #endif
 
 enum octave_exception
--- a/liboctave/util/str-vec.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/util/str-vec.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -32,7 +32,7 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <ostream>
 #include <string>
 
 #include "cmd-edit.h"
--- a/liboctave/util/unwind-prot.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/util/unwind-prot.h	Fri Aug 10 09:09:51 2018 +0200
@@ -55,11 +55,6 @@
 
     ~unwind_protect (void) { run (); }
 
-    virtual void add (elem *new_elem)
-    {
-      lifo.push (new_elem);
-    }
-
     operator bool (void) const { return ! empty (); }
 
     void run_first (void)
@@ -87,6 +82,11 @@
 
   protected:
 
+    virtual void add_action (elem *new_elem)
+    {
+      lifo.push (new_elem);
+    }
+
     std::stack<elem *> lifo;
   };
 
@@ -129,14 +129,4 @@
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::unwind_protect' instead")
-typedef octave::unwind_protect unwind_protect;
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::unwind_protect_safe' instead")
-typedef octave::unwind_protect_safe unwind_protect_safe;
-
 #endif
-
-#endif
--- a/liboctave/util/url-transfer.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/util/url-transfer.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -36,6 +36,7 @@
 #include "dir-ops.h"
 #include "file-ops.h"
 #include "file-stat.h"
+#include "lo-sysdep.h"
 #include "oct-env.h"
 #include "unwind-prot.h"
 #include "url-transfer.h"
@@ -48,6 +49,25 @@
 
 namespace octave
 {
+  base_url_transfer::base_url_transfer (void)
+    : host_or_url (), valid (false), ftp (false),
+      ascii_mode (false), ok (true), errmsg (),
+      curr_istream (&std::cin), curr_ostream (&std::cout) { }
+
+  base_url_transfer::base_url_transfer (const std::string& host,
+                                        const std::string& /* user_arg */,
+                                        const std::string& /* passwd */,
+                                        std::ostream& os)
+    : host_or_url (host), valid (false), ftp (true),
+      ascii_mode (false), ok (true), errmsg (), curr_istream (&std::cin),
+      curr_ostream (&os) { }
+
+  base_url_transfer::base_url_transfer (const std::string& url,
+                                        std::ostream& os)
+    : host_or_url (url), valid (false), ftp (false),
+      ascii_mode (false), ok (true), errmsg (),
+      curr_istream (&std::cin), curr_ostream (&os) { }
+
   void
   base_url_transfer::delete_file (const std::string& file)
   {
@@ -150,62 +170,62 @@
 
         frame.add_fcn (reset_path, this);
 
-        sys::dir_entry dirlist (realdir);
-
-        if (dirlist)
-          {
-            string_vector files = dirlist.read ();
+        string_vector files;
+        std::string msg;
 
-            for (octave_idx_type i = 0; i < files.numel (); i++)
-              {
-                std::string file = files (i);
+        if (sys::get_dirlist (realdir, files, msg))
+          for (octave_idx_type i = 0; i < files.numel (); i++)
+            {
+              std::string file = files (i);
 
-                if (file == "." || file == "..")
-                  continue;
+              if (file == "." || file == "..")
+                continue;
 
-                std::string realfile = realdir + sys::file_ops::dir_sep_str () + file;
-                sys::file_stat fs (realfile);
+              std::string realfile = realdir + sys::file_ops::dir_sep_str () + file;
+              sys::file_stat fs (realfile);
 
-                if (! fs.exists ())
-                  {
-                    ok = false;
-                    errmsg = "__ftp__mput: file '" + realfile
-                             + "' does not exist";
-                    break;
-                  }
+              if (! fs.exists ())
+                {
+                  ok = false;
+                  errmsg = "__ftp__mput: file '" + realfile
+                           + "' does not exist";
+                  break;
+                }
 
-                if (fs.is_dir ())
-                  {
-                    file_list.append (mput_directory (realdir, file));
+              if (fs.is_dir ())
+                {
+                  file_list.append (mput_directory (realdir, file));
 
-                    if (! good ())
-                      break;
-                  }
-                else
-                  {
-                    // FIXME: Does ascii mode need to be flagged here?
-                    std::ifstream ifile (realfile.c_str (), std::ios::in |
-                                         std::ios::binary);
+                  if (! good ())
+                    break;
+                }
+              else
+                {
+                  // FIXME: Does ascii mode need to be flagged here?
+                  std::string ascii_fname
+                    = octave::sys::get_ASCII_filename (realfile);
+
+                  std::ifstream ifile (ascii_fname.c_str (),
+                                       std::ios::in | std::ios::binary);
 
-                    if (! ifile.is_open ())
-                      {
-                        ok = false;
-                        errmsg = "__ftp_mput__: unable to open file '"
-                                 + realfile + "'";
-                        break;
-                      }
-
-                    put (file, ifile);
+                  if (! ifile.is_open ())
+                    {
+                      ok = false;
+                      errmsg = "__ftp_mput__: unable to open file '"
+                               + realfile + "'";
+                      break;
+                    }
 
-                    ifile.close ();
+                  put (file, ifile);
 
-                    if (! good ())
-                      break;
+                  ifile.close ();
 
-                    file_list.append (realfile);
-                  }
-              }
-          }
+                  if (! good ())
+                    break;
+
+                  file_list.append (realfile);
+                }
+            }
         else
           {
             ok = false;
@@ -241,7 +261,7 @@
   static size_t
   throw_away (void *, size_t size, size_t nmemb, void *)
   {
-    return static_cast<size_t>(size * nmemb);
+    return static_cast<size_t> (size * nmemb);
   }
 
   // I'd love to rewrite this as a private method of the url_transfer
--- a/liboctave/util/url-transfer.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/util/url-transfer.h	Fri Aug 10 09:09:51 2018 +0200
@@ -30,8 +30,9 @@
 
 #include "octave-config.h"
 
-#include <iosfwd>
+#include <istream>
 #include <memory>
+#include <ostream>
 #include <string>
 
 #include "str-vec.h"
@@ -57,23 +58,14 @@
 
     friend class url_transfer;
 
-    base_url_transfer (void)
-      : host_or_url (), valid (false), ftp (false),
-        ascii_mode (false), ok (true), errmsg (),
-        curr_istream (&std::cin), curr_ostream (&std::cout) { }
+    base_url_transfer (void);
 
     base_url_transfer (const std::string& host,
                        const std::string& /* user_arg */,
                        const std::string& /* passwd */,
-                       std::ostream& os)
-      : host_or_url (host), valid (false), ftp (true),
-        ascii_mode (false), ok (true), errmsg (), curr_istream (&std::cin),
-        curr_ostream (&os) { }
+                       std::ostream& os);
 
-    base_url_transfer (const std::string& url, std::ostream& os)
-      : host_or_url (url), valid (false), ftp (false),
-        ascii_mode (false), ok (true), errmsg (),
-        curr_istream (&std::cin), curr_ostream (&os) { }
+    base_url_transfer (const std::string& url, std::ostream& os);
 
     // No copying!
 
@@ -269,14 +261,4 @@
   };
 }
 
-#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::base_url_transfer' instead")
-typedef octave::base_url_transfer base_url_transfer;
-
-OCTAVE_DEPRECATED (4.2, "use 'octave::url_transfer' instead")
-typedef octave::url_transfer url_transfer;
-
 #endif
-
-#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/liboctave/version.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,132 @@
+/*
+
+Copyright (C) 2013-2018 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
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include <string>
+
+#include "version.h"
+
+static std::string
+octave_warranty_statement (const std::string& extra_info = "")
+{
+  return "There is ABSOLUTELY NO WARRANTY; not even for MERCHANTABILITY or\n\
+FITNESS FOR A PARTICULAR PURPOSE."
+         + extra_info;
+}
+
+static std::string
+format_url (bool html, const std::string& url)
+{
+  return html ? R"(<a href=")" + url + R"(">)" + url + "</a>" : url;
+}
+
+std::string
+octave_www_statement (bool html)
+{
+  return "Additional information about Octave is available at "
+         + format_url (html, "https://www.octave.org") + ".";
+}
+
+std::string
+octave_contrib_statement (bool html)
+{
+  return "Please contribute if you find this software useful.\n\
+For more information, visit "
+         + format_url (html, "https://www.octave.org/get-involved.html");
+}
+
+std::string
+octave_bugs_statement (bool html)
+{
+  return "Read " + format_url (html, "https://www.octave.org/bugs.html")
+         + " to learn how to submit bug reports.";
+}
+
+std::string
+octave_name_version_and_copyright (void)
+{
+  // The GNU coding standards say that on the first line printed by
+  // --version, the version number should follow the last space on the
+  // line.
+
+  return "GNU Octave, version " OCTAVE_VERSION "\n" OCTAVE_COPYRIGHT;
+}
+
+std::string
+octave_name_version_copyright_copying_and_warranty
+  (bool html, const std::string& extra_info)
+{
+  std::string br = (html ? "<br>\n" : "\n");
+  std::string sep = (html ? "\n</p>\n<p>\n" : "\n\n");
+
+  return octave_name_version_and_copyright ()
+         + br
+         + "This is free software; see the source code for copying conditions."
+         + br
+         + octave_warranty_statement (extra_info)
+         + sep
+         + R"(Octave was configured for ")"
+         + OCTAVE_CANONICAL_HOST_TYPE
+         + R"(".)";
+}
+
+std::string
+octave_name_version_copyright_copying_warranty_and_bugs
+  (bool html, const std::string& extra_info)
+{
+  std::string sep = (html ? "\n</p>\n<p>\n" : "\n\n");
+
+  std::string msg;
+
+  if (html)
+    msg = "<p>\n";
+
+  msg += octave_name_version_copyright_copying_and_warranty (html, extra_info)
+         + sep
+         + octave_www_statement (html)
+         + sep
+         + octave_contrib_statement (html)
+         + sep
+         + octave_bugs_statement (html)
+         + (html ? "\n</p>" : "");
+
+  return msg;
+}
+
+std::string
+octave_startup_message (bool html)
+{
+  std::string msg
+    = octave_name_version_copyright_copying_warranty_and_bugs
+        (html, "  For details, type 'warranty'.");
+
+  msg += (html ? "<p>\n" : "\n");
+
+  msg += "For information about changes from previous versions, type 'news'.";
+
+  msg += (html ? "\n</p>" : "");
+
+  return msg;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/liboctave/version.in.h	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,73 @@
+// %NO_EDIT_WARNING%
+/*
+
+Copyright (C) 1992-2018 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
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if ! defined (octave_version_h)
+#define octave_version_h 1
+
+#include "octave-config.h"
+
+#define OCTAVE_VERSION %OCTAVE_VERSION%
+
+#define OCTAVE_MAJOR_VERSION %OCTAVE_MAJOR_VERSION%
+
+#define OCTAVE_MINOR_VERSION %OCTAVE_MINOR_VERSION%
+
+#define OCTAVE_PATCH_VERSION %OCTAVE_PATCH_VERSION%
+
+// The "API version" is used as a way of checking that interfaces in the
+// liboctave and libinterp libraries haven't changed in a backwardly
+// incompatible way when loading .oct files.  A better way to do that is
+// with library versioning, but not all systems support that.
+// NOTE: This macro will be removed in a future version of Octave.  If
+// you insist on checking for features using a version number, use the
+// OCTAVE_MAJOR_VERSION, OCTAVE_MINOR_VERSION, and
+// OCTAVE_PATCH_VERSION macros instead.
+#define OCTAVE_API_VERSION %OCTAVE_API_VERSION%
+
+#define OCTAVE_RELEASE_DATE %OCTAVE_RELEASE_DATE%
+
+#define OCTAVE_CANONICAL_HOST_TYPE %OCTAVE_CANONICAL_HOST_TYPE%
+
+#define OCTAVE_COPYRIGHT %OCTAVE_COPYRIGHT%
+
+#include <string>
+
+extern OCTINTERP_API std::string octave_www_statement (bool html = false);
+
+extern OCTINTERP_API std::string octave_contrib_statement (bool html = false);
+
+extern OCTINTERP_API std::string octave_bugs_statement (bool html = false);
+
+extern OCTINTERP_API std::string octave_name_version_and_copyright (void);
+
+extern OCTINTERP_API std::string
+octave_name_version_copyright_copying_and_warranty
+  (bool html = false, const std::string& extra_info = "");
+
+extern OCTINTERP_API std::string
+octave_name_version_copyright_copying_warranty_and_bugs
+  (bool html = false, const std::string& extra_info = "");
+
+extern OCTINTERP_API std::string octave_startup_message (bool html = false);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/liboctave/wrappers/iconv-wrappers.c	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,41 @@
+/*
+
+Copyright (C) 2018 Markus Mützel
+
+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
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include "iconv.h"
+
+#include "iconv-wrappers.h"
+
+iconv_t
+octave_iconv_open_wrapper (const char *tocode, const char *fromcode)
+{
+  return iconv_open (tocode, fromcode);
+}
+
+int
+octave_iconv_close_wrapper (iconv_t cd)
+{
+  return iconv_close (cd);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/liboctave/wrappers/iconv-wrappers.h	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,40 @@
+/*
+
+Copyright (C) 2018 Markus Mützel
+
+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
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if ! defined (octave_iconv_wrappers_h)
+#define octave_iconv_wrappers_h 1
+
+#if defined __cplusplus
+extern "C" {
+#endif
+
+extern void *
+octave_iconv_open_wrapper (const char *tocode, const char *fromcode);
+
+extern int
+octave_iconv_close_wrapper (void *cd);
+
+#if defined __cplusplus
+}
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/liboctave/wrappers/mkostemps-wrapper.c	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,40 @@
+/*
+
+Copyright (C) 2016-2018 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
+<https://www.gnu.org/licenses/>.
+
+*/
+
+// mkostemp may be provided by gnulib.  We don't include gnulib headers
+// directly in Octave's C++ source files to avoid problems that may be
+// caused by the way that gnulib overrides standard library functions.
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include <fcntl.h>
+#include <stdlib.h>
+
+#include "mkostemps-wrapper.h"
+
+int
+octave_mkostemps_wrapper (char *tmpl, int suffixlen)
+{
+  return mkostemps (tmpl, suffixlen, O_BINARY);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/liboctave/wrappers/mkostemps-wrapper.h	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,36 @@
+/*
+
+Copyright (C) 2016-2018 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
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if ! defined (octave_mkostemps_wrapper_h)
+#define octave_mkostemps_wrapper_h 1
+
+#if defined __cplusplus
+extern "C" {
+#endif
+
+extern int octave_mkostemps_wrapper (char *tmpl, int suffixlen);
+
+#if defined __cplusplus
+}
+#endif
+
+#endif
--- a/liboctave/wrappers/module.mk	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/wrappers/module.mk	Fri Aug 10 09:09:51 2018 +0200
@@ -11,9 +11,11 @@
   %reldir%/getopt-wrapper.h \
   %reldir%/glob-wrappers.h \
   %reldir%/hash-wrappers.h \
+  %reldir%/iconv-wrappers.h \
   %reldir%/localcharset-wrapper.h \
   %reldir%/math-wrappers.h \
   %reldir%/mkostemp-wrapper.h \
+  %reldir%/mkostemps-wrapper.h \
   %reldir%/nanosleep-wrapper.h \
   %reldir%/nproc-wrapper.h \
   %reldir%/octave-popen2.h \
@@ -28,8 +30,11 @@
   %reldir%/time-wrappers.h \
   %reldir%/tmpfile-wrapper.h \
   %reldir%/uname-wrapper.h \
+  %reldir%/unicase-wrappers.h \
   %reldir%/uniconv-wrappers.h \
+  %reldir%/unictype-wrappers.h \
   %reldir%/unistd-wrappers.h \
+  %reldir%/unistr-wrappers.h \
   %reldir%/unsetenv-wrapper.h \
   %reldir%/vasprintf-wrapper.h \
   %reldir%/wait-for-input.h \
@@ -48,9 +53,11 @@
   %reldir%/getopt-wrapper.c \
   %reldir%/glob-wrappers.c \
   %reldir%/hash-wrappers.c \
+  %reldir%/iconv-wrappers.c \
   %reldir%/localcharset-wrapper.c \
   %reldir%/math-wrappers.c \
   %reldir%/mkostemp-wrapper.c \
+  %reldir%/mkostemps-wrapper.c \
   %reldir%/nanosleep-wrapper.c \
   %reldir%/nproc-wrapper.c \
   %reldir%/octave-popen2.c \
@@ -65,8 +72,11 @@
   %reldir%/time-wrappers.c \
   %reldir%/tmpfile-wrapper.c \
   %reldir%/uname-wrapper.c \
+  %reldir%/unicase-wrappers.c \
   %reldir%/uniconv-wrappers.c \
+  %reldir%/unictype-wrappers.c \
   %reldir%/unistd-wrappers.c \
+  %reldir%/unistr-wrappers.c \
   %reldir%/unsetenv-wrapper.c \
   %reldir%/vasprintf-wrapper.c \
   %reldir%/wait-for-input.c \
@@ -80,6 +90,4 @@
 %canon_reldir%_libwrappers_la_CPPFLAGS = \
   -Ilibgnu -I$(srcdir)/libgnu
 
-%canon_reldir%_libwrappers_la_CFLAGS = $(liboctave_liboctave_la_CFLAGS)
-
 liboctave_liboctave_la_LIBADD += %reldir%/libwrappers.la
--- a/liboctave/wrappers/stat-wrappers.c	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/wrappers/stat-wrappers.c	Fri Aug 10 09:09:51 2018 +0200
@@ -35,11 +35,25 @@
 #include <sys/stat.h>
 
 #include "stat-wrappers.h"
+#include "uniconv-wrappers.h"
+
+#if defined (OCTAVE_USE_WINDOWS_API)
+#  include <windows.h>
+#  include <wchar.h>
+#endif
 
 int
 octave_mkdir_wrapper (const char *name, mode_t mode)
 {
+#if defined (OCTAVE_USE_WINDOWS_API)
+  wchar_t *wname = u8_to_wchar (name);
+  int status = _wmkdir (wname);
+  free ((void *) wname);
+  octave_unused_parameter (mode);
+  return status;
+#else
   return mkdir (name, mode);
+#endif
 }
 
 int
@@ -100,7 +114,13 @@
 {
   struct stat buf;
 
+#if defined (OCTAVE_USE_WINDOWS_API)
+  wchar_t *wfname = u8_to_wchar (fname);
+  int status = _wstati64 (wfname, &buf);
+  free ((void *) wfname);
+#else
   int status = stat (fname, &buf);
+#endif
 
   assign_stat_fields (&buf, mode, ino, dev, nlink, uid, gid, size,
                       atime, mtime, ctime, rdev, blksize, blocks);
@@ -117,7 +137,14 @@
 {
   struct stat buf;
 
+#if defined (OCTAVE_USE_WINDOWS_API)
+  // Windows doesn't have an lstat. Use stat instead
+  wchar_t *wlname = u8_to_wchar (lname);
+  int status = _wstati64 (wlname, &buf);
+  free ((void *) wlname);
+#else
   int status = lstat (lname, &buf);
+#endif
 
   assign_stat_fields (&buf, mode, ino, dev, nlink, uid, gid, size,
                       atime, mtime, ctime, rdev, blksize, blocks);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/liboctave/wrappers/unicase-wrappers.c	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,45 @@
+/*
+
+Copyright (C) 2018 Markus Mützel
+
+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
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include "unicase.h"
+
+#include "unicase-wrappers.h"
+
+uint8_t *
+octave_u8_tolower_wrapper (const uint8_t *s, size_t n,
+                           const char *iso639_language,
+                           uint8_t *resultbuf, size_t *lengthp)
+{
+  return u8_tolower (s, n, iso639_language, NULL, resultbuf, lengthp);
+}
+
+uint8_t *
+octave_u8_toupper_wrapper (const uint8_t *s, size_t n,
+                           const char *iso639_language,
+                           uint8_t *resultbuf, size_t *lengthp)
+{
+  return u8_toupper (s, n, iso639_language, NULL, resultbuf, lengthp);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/liboctave/wrappers/unicase-wrappers.h	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,44 @@
+/*
+
+Copyright (C) 2018 Markus Mützel
+
+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
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if ! defined (octave_unicase_wrappers_h)
+#define octave_unicase_wrappers_h 1
+
+#if defined __cplusplus
+extern "C" {
+#endif
+
+extern uint8_t *
+octave_u8_tolower_wrapper (const uint8_t *s, size_t n,
+                           const char *iso639_language,
+                           uint8_t *resultbuf, size_t *lengthp);
+
+extern uint8_t *
+octave_u8_toupper_wrapper (const uint8_t *s, size_t n,
+                           const char *iso639_language,
+                           uint8_t *resultbuf, size_t *lengthp);
+
+#if defined __cplusplus
+}
+#endif
+
+#endif
--- a/liboctave/wrappers/uniconv-wrappers.c	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/wrappers/uniconv-wrappers.c	Fri Aug 10 09:09:51 2018 +0200
@@ -29,6 +29,10 @@
 #  include "config.h"
 #endif
 
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
 #include "uniconv.h"
 
 #include "uniconv-wrappers.h"
@@ -41,10 +45,54 @@
                                 src, srclen, NULL, NULL, lengthp);
 }
 
-extern char *
+char *
 octave_u8_conv_to_encoding (const char *tocode, const uint8_t *src,
                             size_t srclen, size_t *lengthp)
 {
   return u8_conv_to_encoding (tocode, iconveh_question_mark,
                               src, srclen, NULL, NULL, lengthp);
 }
+
+char *
+u8_from_wchar (const wchar_t *wc)
+{
+  // Convert wide char array to multibyte UTF-8 char array
+  // The memory at the returned pointer must be freed after use.
+
+  size_t srclen = wcslen (wc) * sizeof (wchar_t);
+  const char *src = (const char *) wc;
+
+  size_t length = 0;
+  uint8_t *mbchar = u8_conv_from_encoding ("wchar_t", iconveh_question_mark,
+                                           src, srclen, NULL, NULL, &length);
+
+  // result might not be 0 terminated
+  char *retval = malloc (length + 1);
+  memcpy (retval, mbchar, length);
+  free ((void *) mbchar);
+  retval[length] = 0; // 0 terminate string
+
+  return retval;
+}
+
+wchar_t *
+u8_to_wchar (const char *u8)
+{
+  // Convert multibyte UTF-8 char array to wide char array
+  // The memory at the returned pointer must be freed after use.
+
+  size_t srclen = strlen (u8);
+  const uint8_t *src = (const uint8_t *) u8;
+
+  size_t length = 0;
+
+  char *wchar = u8_conv_to_encoding ("wchar_t", iconveh_question_mark,
+                                     src, srclen, NULL, NULL, &length);
+  // result might not be 0 terminated
+  wchar_t *retval = malloc (length + 1 * sizeof (wchar_t));
+  memcpy (retval, wchar, length);
+  free ((void *) wchar);
+  retval[length / sizeof (wchar_t)] = 0; // 0 terminate string
+
+  return retval;
+}
--- a/liboctave/wrappers/uniconv-wrappers.h	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/wrappers/uniconv-wrappers.h	Fri Aug 10 09:09:51 2018 +0200
@@ -46,6 +46,12 @@
 octave_u8_conv_to_encoding (const char *tocode, const uint8_t *src,
                             size_t srclen, size_t *lengthp);
 
+extern char *
+u8_from_wchar (const wchar_t *wc);
+
+extern wchar_t *
+u8_to_wchar (const char *u8_char);
+
 #if defined __cplusplus
 }
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/liboctave/wrappers/unictype-wrappers.c	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,101 @@
+/*
+
+Copyright (C) 2018 Markus Mützel
+
+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
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include "unictype.h"
+
+#include "unictype-wrappers.h"
+
+bool
+octave_uc_is_alnum_wrapper (ucs4_t uc)
+{
+  return uc_is_alnum (uc);
+}
+
+bool
+octave_uc_is_alpha_wrapper (ucs4_t uc)
+{
+  return uc_is_alpha (uc);
+}
+
+bool
+octave_uc_is_blank_wrapper (ucs4_t uc)
+{
+  return uc_is_blank (uc);
+}
+
+bool
+octave_uc_is_cntrl_wrapper (ucs4_t uc)
+{
+  return uc_is_cntrl (uc);
+}
+
+bool
+octave_uc_is_digit_wrapper (ucs4_t uc)
+{
+  return uc_is_digit (uc);
+}
+
+bool
+octave_uc_is_graph_wrapper (ucs4_t uc)
+{
+  return uc_is_graph (uc);
+}
+
+bool
+octave_uc_is_lower_wrapper (ucs4_t uc)
+{
+  return uc_is_lower (uc);
+}
+
+bool
+octave_uc_is_print_wrapper (ucs4_t uc)
+{
+  return uc_is_print (uc);
+}
+
+bool
+octave_uc_is_punct_wrapper (ucs4_t uc)
+{
+  return uc_is_punct (uc);
+}
+
+bool
+octave_uc_is_space_wrapper (ucs4_t uc)
+{
+  return uc_is_space (uc);
+}
+
+bool
+octave_uc_is_upper_wrapper (ucs4_t uc)
+{
+  return uc_is_upper (uc);
+}
+
+bool
+octave_uc_is_xdigit_wrapper (ucs4_t uc)
+{
+  return uc_is_xdigit (uc);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/liboctave/wrappers/unictype-wrappers.h	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,72 @@
+/*
+
+Copyright (C) 2018 Markus Mützel
+
+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
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if ! defined (octave_unictype_wrappers_h)
+#define octave_unictype_wrappers_h 1
+
+typedef uint32_t ucs4_t;
+
+#if defined __cplusplus
+extern "C" {
+#endif
+
+extern bool
+octave_uc_is_alnum_wrapper (ucs4_t uc);
+
+extern bool
+octave_uc_is_alpha_wrapper (ucs4_t uc);
+
+extern bool
+octave_uc_is_blank_wrapper (ucs4_t uc);
+
+extern bool
+octave_uc_is_cntrl_wrapper (ucs4_t uc);
+
+extern bool
+octave_uc_is_digit_wrapper (ucs4_t uc);
+
+extern bool
+octave_uc_is_graph_wrapper (ucs4_t uc);
+
+extern bool
+octave_uc_is_lower_wrapper (ucs4_t uc);
+
+extern bool
+octave_uc_is_print_wrapper (ucs4_t uc);
+
+extern bool
+octave_uc_is_punct_wrapper (ucs4_t uc);
+
+extern bool
+octave_uc_is_space_wrapper (ucs4_t uc);
+
+extern bool
+octave_uc_is_upper_wrapper (ucs4_t uc);
+
+extern bool
+octave_uc_is_xdigit_wrapper (ucs4_t uc);
+
+#if defined __cplusplus
+}
+#endif
+
+#endif
--- a/liboctave/wrappers/unistd-wrappers.c	Fri Aug 10 09:08:33 2018 +0200
+++ b/liboctave/wrappers/unistd-wrappers.c	Fri Aug 10 09:09:51 2018 +0200
@@ -31,8 +31,6 @@
 
 #include <stdio.h>
 
-#include <stdio.h>
-
 #include <sys/types.h>
 #include <unistd.h>
 
@@ -40,6 +38,12 @@
 #  include <process.h>
 #endif
 
+#if defined (OCTAVE_USE_WINDOWS_API)
+#  include <windows.h>
+#  include <wchar.h>
+#endif
+
+#include "uniconv-wrappers.h"
 #include "unistd-wrappers.h"
 
 int
@@ -75,7 +79,14 @@
 int
 octave_chdir_wrapper (const char *nm)
 {
+#if defined (OCTAVE_USE_WINDOWS_API)
+  wchar_t *wnm = u8_to_wchar (nm);
+  int status = _wchdir (wnm);
+  free ((void *) wnm);
+  return status;
+#else
   return chdir (nm);
+#endif
 }
 
 int
@@ -281,7 +292,28 @@
 char *
 octave_getcwd_wrapper (char *nm, size_t len)
 {
+#if defined (OCTAVE_USE_WINDOWS_API)
+  wchar_t *tmp = _wgetcwd (NULL, 0);
+  char *retval = NULL;
+
+  if (! tmp)
+    return retval;
+
+  retval = u8_from_wchar (tmp);
+  if (! nm)
+    return retval;
+  else
+    {
+      if (strlen (retval) > len)
+        return NULL;
+
+      memcpy (nm, retval, len);
+      free (retval);
+      return nm;
+    }
+#else
   return getcwd (nm, len);
+#endif
 }
 
 gid_t
@@ -381,7 +413,14 @@
 int
 octave_rmdir_wrapper (const char *nm)
 {
+#if defined (OCTAVE_USE_WINDOWS_API)
+  wchar_t *wnm = u8_to_wchar (nm);
+  int status = _wrmdir (wnm);
+  free ((void *) wnm);
+  return status;
+#else
   return rmdir (nm);
+#endif
 }
 
 pid_t
@@ -415,7 +454,14 @@
 int
 octave_unlink_wrapper (const char *nm)
 {
+#if defined (OCTAVE_USE_WINDOWS_API)
+  wchar_t *wnm = u8_to_wchar (nm);
+  int status = _wunlink (wnm);
+  free ((void *) wnm);
+  return status;
+#else
   return unlink (nm);
+#endif
 }
 
 pid_t
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/liboctave/wrappers/unistr-wrappers.c	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,48 @@
+/*
+
+Copyright (C) 2018 Markus Mützel
+
+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
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include "unistr.h"
+
+#include "unistr-wrappers.h"
+
+int
+octave_u8_strmblen_wrapper (const uint8_t *src)
+{
+  return u8_strmblen (src);
+}
+
+int
+octave_u8_strmbtouc_wrapper (uint32_t *puc, const uint8_t *src)
+{
+  return u8_strmbtouc (puc, src);
+}
+
+uint32_t *
+octave_u8_to_u32_wrapper (const uint8_t *src, size_t src_len,
+                          uint32_t *result_buf, size_t *lengthp)
+{
+  return u8_to_u32 (src, src_len, result_buf, lengthp);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/liboctave/wrappers/unistr-wrappers.h	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,44 @@
+/*
+
+Copyright (C) 2018 Markus Mützel
+
+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
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if ! defined (octave_unistr_wrappers_h)
+#define octave_unistr_wrappers_h 1
+
+#if defined __cplusplus
+extern "C" {
+#endif
+
+extern int
+octave_u8_strmblen_wrapper (const uint8_t *src);
+
+extern int
+octave_u8_strmbtouc_wrapper (uint32_t *puc, const uint8_t *src);
+
+extern uint32_t *
+octave_u8_to_u32_wrapper (const uint8_t *src, size_t src_len,
+                          uint32_t *result_buf, size_t *lengthp);
+
+#if defined __cplusplus
+}
+#endif
+
+#endif
--- a/m4/acinclude.m4	Fri Aug 10 09:08:33 2018 +0200
+++ b/m4/acinclude.m4	Fri Aug 10 09:09:51 2018 +0200
@@ -3183,72 +3183,18 @@
       ])
   fi
 
-  AC_SUBST(BISON_API_PREFIX_DECL_STYLE, $octave_cv_bison_api_prefix_decl_style)
-
-  if test -z "$octave_cv_bison_api_prefix_decl_style"; then
+  if test -z "$octave_cv_bison_api_prefix_decl_style" \
+    || test "$octave_cv_bison_api_prefix_decl_style" != "api brace"; then
     tmp_have_bison=no
     warn_bison_api_prefix_decl_style="
 
 I wasn't able to find a suitable style for declaring the api prefix
-in a bison input file so I'm disabling bison.
+in a bison input file so I'm disabling bison.  We expect bison to
+understand the '%define api.prefix { PREFIX }' syntax.
 "
     OCTAVE_CONFIGURE_WARNING([warn_bison_api_prefix_decl_style])
   fi
 
-  if test $tmp_have_bison = yes; then
-    AC_CACHE_CHECK([syntax of bison push/pull declaration],
-                   [octave_cv_bison_push_pull_decl_style], [
-      style="dash underscore"
-      quote="noquote quote"
-      for s in $style; do
-        for q in $quote; do
-          if test $s = "dash"; then
-            def="%define api.push-pull"
-          else
-            def="%define api.push_pull"
-          fi
-          if test $q = "quote"; then
-            def="$def \"both\""
-          else
-            def="$def both"
-          fi
-          cat << EOF > conftest.yy
-$def
-%start input
-%%
-input:;
-%%
-EOF
-          octave_bison_output=`$YACC conftest.yy 2>&1`
-          ac_status=$?
-          if test $ac_status -eq 0 && test -z "$octave_bison_output"; then
-            if test $q = noquote; then
-              q=
-            fi
-            octave_cv_bison_push_pull_decl_style="$s $q"
-            break
-          fi
-        done
-        if test -n "$octave_cv_bison_push_pull_decl_style"; then
-          break
-        fi
-      done
-      rm -f conftest.yy y.tab.h y.tab.c
-      ])
-  fi
-
-  AC_SUBST(BISON_PUSH_PULL_DECL_STYLE, $octave_cv_bison_push_pull_decl_style)
-
-  if test -z "$octave_cv_bison_push_pull_decl_style"; then
-    tmp_have_bison=no
-    warn_bison_push_pull_decl_style="
-
-I wasn't able to find a suitable style for declaring a push-pull
-parser in a bison input file so I'm disabling bison.
-"
-    OCTAVE_CONFIGURE_WARNING([warn_bison_push_pull_decl_style])
-  fi
-
   if test $tmp_have_bison = no; then
     YACC='${top_srcdir}/build-aux/missing bison'
     warn_bison="
--- a/m4/pkg.m4	Fri Aug 10 09:08:33 2018 +0200
+++ b/m4/pkg.m4	Fri Aug 10 09:09:51 2018 +0200
@@ -1,32 +1,68 @@
-# pkg.m4 - Macros to locate and utilise pkg-config.            -*- Autoconf -*-
-#
-# Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# 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, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-#
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
+# pkg.m4 - Macros to locate and utilise pkg-config.   -*- Autoconf -*-
+# serial 12 (pkg-config-0.29.2)
+
+dnl Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
+dnl Copyright © 2012-2015 Dan Nicholson <dbn.lists@gmail.com>
+dnl
+dnl This program is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2 of the License, or
+dnl (at your option) any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful, but
+dnl WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+dnl General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+dnl 02111-1307, USA.
+dnl
+dnl As a special exception to the GNU General Public License, if you
+dnl distribute this file as part of a program that contains a
+dnl configuration script generated by Autoconf, you may include it under
+dnl the same distribution terms that you use for the rest of that
+dnl program.
 
-# PKG_PROG_PKG_CONFIG([MIN-VERSION])
-# ----------------------------------
+dnl PKG_PREREQ(MIN-VERSION)
+dnl -----------------------
+dnl Since: 0.29
+dnl
+dnl Verify that the version of the pkg-config macros are at least
+dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's
+dnl installed version of pkg-config, this checks the developer's version
+dnl of pkg.m4 when generating configure.
+dnl
+dnl To ensure that this macro is defined, also add:
+dnl m4_ifndef([PKG_PREREQ],
+dnl     [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])])
+dnl
+dnl See the "Since" comment for each macro you use to see what version
+dnl of the macros you require.
+m4_defun([PKG_PREREQ],
+[m4_define([PKG_MACROS_VERSION], [0.29.2])
+m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1,
+    [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])])
+])dnl PKG_PREREQ
+
+dnl PKG_PROG_PKG_CONFIG([MIN-VERSION])
+dnl ----------------------------------
+dnl Since: 0.16
+dnl
+dnl Search for the pkg-config tool and set the PKG_CONFIG variable to
+dnl first found in the path. Checks that the version of pkg-config found
+dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is
+dnl used since that's the first version where most current features of
+dnl pkg-config existed.
 AC_DEFUN([PKG_PROG_PKG_CONFIG],
 [m4_pattern_forbid([^_?PKG_[A-Z_]+$])
-m4_pattern_allow([^PKG_CONFIG(_PATH)?$])
-AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl
+m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
+m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$])
+AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])
+AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path])
+AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path])
+
 if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
 	AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
 fi
@@ -39,48 +75,49 @@
 		AC_MSG_RESULT([no])
 		PKG_CONFIG=""
 	fi
-		
 fi[]dnl
-])# PKG_PROG_PKG_CONFIG
+])dnl PKG_PROG_PKG_CONFIG
 
-# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
-#
-# Check to see whether a particular set of modules exists.  Similar
-# to PKG_CHECK_MODULES(), but does not set variables or print errors.
-#
-#
-# Similar to PKG_CHECK_MODULES, make sure that the first instance of
-# this or PKG_CHECK_MODULES is called, or make sure to call
-# PKG_CHECK_EXISTS manually
-# --------------------------------------------------------------
+dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+dnl -------------------------------------------------------------------
+dnl Since: 0.18
+dnl
+dnl Check to see whether a particular set of modules exists. Similar to
+dnl PKG_CHECK_MODULES(), but does not set variables or print errors.
+dnl
+dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+dnl only at the first occurence in configure.ac, so if the first place
+dnl it's called might be skipped (such as if it is within an "if", you
+dnl have to call PKG_CHECK_EXISTS manually
 AC_DEFUN([PKG_CHECK_EXISTS],
 [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
 if test -n "$PKG_CONFIG" && \
     AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
-  m4_ifval([$2], [$2], [:])
+  m4_default([$2], [:])
 m4_ifvaln([$3], [else
   $3])dnl
 fi])
 
-
-# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
-# ---------------------------------------------
+dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
+dnl ---------------------------------------------
+dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting
+dnl pkg_failed based on the result.
 m4_define([_PKG_CONFIG],
-[if test -n "$PKG_CONFIG"; then
-    if test -n "$$1"; then
-        pkg_cv_[]$1="$$1"
-    else
-        PKG_CHECK_EXISTS([$3],
-                         [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`],
-			 [pkg_failed=yes])
-    fi
-else
-	pkg_failed=untried
+[if test -n "$$1"; then
+    pkg_cv_[]$1="$$1"
+ elif test -n "$PKG_CONFIG"; then
+    PKG_CHECK_EXISTS([$3],
+                     [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes ],
+		     [pkg_failed=yes])
+ else
+    pkg_failed=untried
 fi[]dnl
-])# _PKG_CONFIG
+])dnl _PKG_CONFIG
 
-# _PKG_SHORT_ERRORS_SUPPORTED
-# -----------------------------
+dnl _PKG_SHORT_ERRORS_SUPPORTED
+dnl ---------------------------
+dnl Internal check to see if pkg-config supports short errors.
 AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
 [AC_REQUIRE([PKG_PROG_PKG_CONFIG])
 if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
@@ -88,26 +125,24 @@
 else
         _pkg_short_errors_supported=no
 fi[]dnl
-])# _PKG_SHORT_ERRORS_SUPPORTED
+])dnl _PKG_SHORT_ERRORS_SUPPORTED
 
 
-# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
-# [ACTION-IF-NOT-FOUND])
-#
-#
-# Note that if there is a possibility the first call to
-# PKG_CHECK_MODULES might not happen, you should be sure to include an
-# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
-#
-#
-# --------------------------------------------------------------
+dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+dnl   [ACTION-IF-NOT-FOUND])
+dnl --------------------------------------------------------------
+dnl Since: 0.4.0
+dnl
+dnl Note that if there is a possibility the first call to
+dnl PKG_CHECK_MODULES might not happen, you should be sure to include an
+dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
 AC_DEFUN([PKG_CHECK_MODULES],
 [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
 AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
 AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
 
 pkg_failed=no
-AC_MSG_CHECKING([for $1])
+AC_MSG_CHECKING([for $2])
 
 _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
 _PKG_CONFIG([$1][_LIBS], [libs], [$2])
@@ -117,16 +152,17 @@
 See the pkg-config man page for more details.])
 
 if test $pkg_failed = yes; then
+        AC_MSG_RESULT([no])
         _PKG_SHORT_ERRORS_SUPPORTED
         if test $_pkg_short_errors_supported = yes; then
-	        $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$2"`
+	        $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1`
         else
-	        $1[]_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"`
+	        $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1`
         fi
 	# Put the nasty error message in config.log where it belongs
 	echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
 
-	ifelse([$4], , [AC_MSG_ERROR(dnl
+	m4_default([$4], [AC_MSG_ERROR(
 [Package requirements ($2) were not met:
 
 $$1_PKG_ERRORS
@@ -134,24 +170,106 @@
 Consider adjusting the PKG_CONFIG_PATH environment variable if you
 installed software in a non-standard prefix.
 
-_PKG_TEXT
-])],
-		[AC_MSG_RESULT([no])
-                $4])
+_PKG_TEXT])[]dnl
+        ])
 elif test $pkg_failed = untried; then
-	ifelse([$4], , [AC_MSG_FAILURE(dnl
+        AC_MSG_RESULT([no])
+	m4_default([$4], [AC_MSG_FAILURE(
 [The pkg-config script could not be found or is too old.  Make sure it
 is in your PATH or set the PKG_CONFIG environment variable to the full
 path to pkg-config.
 
 _PKG_TEXT
 
-To get pkg-config, see <http://pkg-config.freedesktop.org/>.])],
-		[$4])
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.])[]dnl
+        ])
 else
 	$1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
 	$1[]_LIBS=$pkg_cv_[]$1[]_LIBS
         AC_MSG_RESULT([yes])
-	ifelse([$3], , :, [$3])
+	$3
 fi[]dnl
-])# PKG_CHECK_MODULES
+])dnl PKG_CHECK_MODULES
+
+
+dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+dnl   [ACTION-IF-NOT-FOUND])
+dnl ---------------------------------------------------------------------
+dnl Since: 0.29
+dnl
+dnl Checks for existence of MODULES and gathers its build flags with
+dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags
+dnl and VARIABLE-PREFIX_LIBS from --libs.
+dnl
+dnl Note that if there is a possibility the first call to
+dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to
+dnl include an explicit call to PKG_PROG_PKG_CONFIG in your
+dnl configure.ac.
+AC_DEFUN([PKG_CHECK_MODULES_STATIC],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+_save_PKG_CONFIG=$PKG_CONFIG
+PKG_CONFIG="$PKG_CONFIG --static"
+PKG_CHECK_MODULES($@)
+PKG_CONFIG=$_save_PKG_CONFIG[]dnl
+])dnl PKG_CHECK_MODULES_STATIC
+
+
+dnl PKG_INSTALLDIR([DIRECTORY])
+dnl -------------------------
+dnl Since: 0.27
+dnl
+dnl Substitutes the variable pkgconfigdir as the location where a module
+dnl should install pkg-config .pc files. By default the directory is
+dnl $libdir/pkgconfig, but the default can be changed by passing
+dnl DIRECTORY. The user can override through the --with-pkgconfigdir
+dnl parameter.
+AC_DEFUN([PKG_INSTALLDIR],
+[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])])
+m4_pushdef([pkg_description],
+    [pkg-config installation directory @<:@]pkg_default[@:>@])
+AC_ARG_WITH([pkgconfigdir],
+    [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],,
+    [with_pkgconfigdir=]pkg_default)
+AC_SUBST([pkgconfigdir], [$with_pkgconfigdir])
+m4_popdef([pkg_default])
+m4_popdef([pkg_description])
+])dnl PKG_INSTALLDIR
+
+
+dnl PKG_NOARCH_INSTALLDIR([DIRECTORY])
+dnl --------------------------------
+dnl Since: 0.27
+dnl
+dnl Substitutes the variable noarch_pkgconfigdir as the location where a
+dnl module should install arch-independent pkg-config .pc files. By
+dnl default the directory is $datadir/pkgconfig, but the default can be
+dnl changed by passing DIRECTORY. The user can override through the
+dnl --with-noarch-pkgconfigdir parameter.
+AC_DEFUN([PKG_NOARCH_INSTALLDIR],
+[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])])
+m4_pushdef([pkg_description],
+    [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@])
+AC_ARG_WITH([noarch-pkgconfigdir],
+    [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],,
+    [with_noarch_pkgconfigdir=]pkg_default)
+AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir])
+m4_popdef([pkg_default])
+m4_popdef([pkg_description])
+])dnl PKG_NOARCH_INSTALLDIR
+
+
+dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
+dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+dnl -------------------------------------------
+dnl Since: 0.28
+dnl
+dnl Retrieves the value of the pkg-config variable for the given module.
+AC_DEFUN([PKG_CHECK_VAR],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
+
+_PKG_CONFIG([$1], [variable="][$3]["], [$2])
+AS_VAR_COPY([$1], [pkg_cv_][$1])
+
+AS_VAR_IF([$1], [""], [$5], [$4])dnl
+])dnl PKG_CHECK_VAR
--- a/scripts/deprecated/bitmax.m	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-## Copyright (C) 2004-2018 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
-## <https://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {} {@var{r} =} bitmax (@var{precision})
-##
-## @code{bitmax} is deprecated and will be removed in Octave version 5.
-## Use @code{flintmax (precision) - 1} for the equivalent functionality.
-##
-## Return the largest integer @var{r} that can be represented within a
-## floating point value.
-##
-## The default class is @qcode{"double"}, but @qcode{"single"} is a valid
-## option.  On IEEE 754 compatible systems, @code{bitmax} is
-## @w{@math{2^{53} - 1}} for @qcode{"double"} and @w{@math{2^{24} - 1}} for
-## @qcode{"single"}.
-##
-## @seealso{flintmax, intmax, realmax, realmin}
-## @end deftypefn
-
-## Deprecated in version 4.2
-
-function r = bitmax (precision)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "bitmax is obsolete and will be removed from a future version of Octave, please use flintmax instead");
-  endif
-
-  if (nargin == 0)
-    precision = "double";
-  endif
-  r = flintmax (precision) - 1;
-
-endfunction
--- a/scripts/deprecated/chop.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/deprecated/chop.m	Fri Aug 10 09:09:51 2018 +0200
@@ -82,6 +82,11 @@
 endfunction
 
 
+## First test is necessary to provoke 1-time legacy warning
+%!test
+%! warning ("off", "Octave:deprecated-function", "local");
+%! chop (0, 1);
+
 %!assert (chop (e, 3), 2.72)
 %!assert (chop (e, 4), 2.718)
 %!assert (chop (e, 4, 5), 2.72)
--- a/scripts/deprecated/isstr.m	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-## Copyright (C) 2003-2018 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
-## <https://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {} {} isstr (@var{a})
-## This function has been deprecated.  Use ischar instead.
-## @end deftypefn
-
-## Author: jwe
-
-## Deprecated in version 3.0
-## Matlab still has this function, so don't remove just yet.
-
-function retval = isstr (varargin)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "isstr is obsolete and will be removed from a future version of Octave, please use ischar instead");
-  endif
-
-  retval = ischar (varargin{:});
-
-endfunction
--- a/scripts/deprecated/mahalanobis.m	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-## Copyright (C) 1996-2018 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
-## <https://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {} {} mahalanobis (@var{x}, @var{y})
-##
-## @code{mahalanobis} is deprecated and will be removed in Octave version 5.
-## See the @code{mahal} function in the statistics package from Octave-Forge
-## for equivalent functionality.
-##
-## Return the Mahalanobis' D-square distance between the multivariate
-## samples @var{x} and @var{y}.
-##
-## The data @var{x} and @var{y} must have the same number of components
-## (columns), but may have a different number of observations (rows).
-## @end deftypefn
-
-## Author: Friedrich Leisch <leisch@ci.tuwien.ac.at>
-## Created: July 1993
-## Adapted-By: jwe
-
-function retval = mahalanobis (x, y)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "mahalanobis is obsolete and will be removed from a future version of Octave, please use mahal from the statistics package in Octave-Forge instead");
-  endif
-
-  if (nargin != 2)
-    print_usage ();
-  endif
-
-  if (   ! (isnumeric (x) || islogical (x))
-      || ! (isnumeric (y) || islogical (y)))
-    error ("mahalanobis: X and Y must be numeric matrices or vectors");
-  endif
-
-  if (ndims (x) != 2 || ndims (y) != 2)
-    error ("mahalanobis: X and Y must be 2-D matrices or vectors");
-  endif
-
-  [xr, xc] = size (x);
-  [yr, yc] = size (y);
-
-  if (xc != yc)
-    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);
-
-  ## Center data by subtracting means
-  x = bsxfun (@minus, x, xm);
-  y = bsxfun (@minus, y, ym);
-
-  w = (x' * x + y' * y) / (xr + yr - 2);
-
-  retval = sumsq ((xm - ym) / chol (w));
-
-endfunction
-
-## Test input validation
-%!error mahalanobis ()
-%!error mahalanobis (1, 2, 3)
-%!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/deprecated/md5sum.m	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-## Copyright (C) 2007-2018 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
-## <https://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn  {} {} md5sum (@var{file})
-## @deftypefnx {} {} md5sum (@var{str}, @var{opt})
-##
-## @code{md5sum} is deprecated and will be removed in Octave version 5.
-## For equivalent functionality replace calls like @code{md5sum (@var{file})}
-## with:
-##
-## @example
-## hash ("md5", fileread (@var{file}))
-## @end example
-##
-## And calls like @code{md5sum (@var{str}, true)} with:
-##
-## @example
-## hash ("md5", @var{str})
-## @end example
-##
-## Calculate the MD5 sum of the file @var{file}.
-##
-## If the second parameter @var{opt} exists and is true, then calculate the MD5
-## sum of the string @var{str}.
-##
-## @seealso{hash, fileread}
-## @end deftypefn
-
-function r = md5sum (str, opt)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "md5sum is obsolete and will be removed from a future version of Octave, please use hash instead");
-  endif
-
-  if (nargin == 1)
-    r = hash ("md5", fileread (str));
-  elseif ((nargin == 2) && isbool (opt) && isscalar (opt) && (opt == true))
-    r = hash ("md5", str);
-  else
-    print_usage ();
-  endif
-
-endfunction
-
-
-%!assert (md5sum ("abc\0", true), "147a664a2ca9410911e61986d3f0d52a")
-
-%!test
-%! tfile = tempname ();
-%! fid = fopen (tfile, "wb");
-%! fwrite (fid, "abc\0");
-%! fclose (fid);
-%! assert (md5sum (tfile), "147a664a2ca9410911e61986d3f0d52a");
-%! unlink (tfile);
-
-%!error md5sum ()
--- a/scripts/deprecated/module.mk	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/deprecated/module.mk	Fri Aug 10 09:09:51 2018 +0200
@@ -1,25 +1,14 @@
 FCN_FILE_DIRS += scripts/deprecated
 
 %canon_reldir%_FCN_FILES = \
-  %reldir%/bitmax.m \
   %reldir%/chop.m \
   %reldir%/comma.m \
   %reldir%/desktop.m \
-  %reldir%/isstr.m \
   %reldir%/java2mat.m \
-  %reldir%/mahalanobis.m \
-  %reldir%/md5sum.m \
-  %reldir%/octave_config_info.m \
-  %reldir%/onenormest.m \
   %reldir%/paren.m \
   %reldir%/semicolon.m \
-  %reldir%/setstr.m \
-  %reldir%/sleep.m \
   %reldir%/tmpnam.m \
-  %reldir%/toascii.m \
-  %reldir%/usleep.m \
-  %reldir%/wavread.m \
-  %reldir%/wavwrite.m
+  %reldir%/toascii.m
 
 %canon_reldir%dir = $(fcnfiledir)/deprecated
 
--- a/scripts/deprecated/octave_config_info.m	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-## Copyright (C) 2016-2018 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
-## <https://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn  {} {} octave_config_info ()
-## @deftypefnx {} {} octave_config_info (@var{option})
-##
-## @code{octave_config_info} is deprecated and will be removed in
-## Octave version 5.  Use @code{__have_feature__ (@var{option})} or
-## @code{__octave_config_info__} as a replacement.
-##
-## Return a structure containing configuration and installation
-## information for Octave.
-##
-## If @var{option} is a string, return the configuration information for
-## the specified option.
-##
-## @seealso{computer}
-## @end deftypefn
-
-## Deprecated in version 4.2
-
-function [retval, build_env_cell] = octave_config_info (option)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "octave_config_info is obsolete and will be removed from a future version of Octave, please use __have_feature__ or __octave_config_info__ instead.");
-  endif
-
-  if (nargin > 1)
-    print_usage ();
-  endif
-
-  if (nargin == 0)
-    info = __octave_config_info__ ();
-    ## Structure layout has changed.
-
-    dld = info.dld;
-    float_format = info.float_format;
-    words_big_endian = info.words_big_endian;
-    words_little_endian = info.words_little_endian;
-
-    features = info.build_features;
-
-    env = info.build_environment;
-    env_fields = fieldnames (env);
-    env_vals = struct2cell (env);
-    env_cell = [env_fields, env_vals]';
-
-    info = rmfield (info, {"dld", "float_format", "words_big_endian", ...
-                           "words_little_endian", "build_features", ...
-                           "build_environment"});
-
-    other_fields = fieldnames (info);
-    other_vals = struct2cell (info);
-    other_cell = [other_fields, other_vals]';
-
-    retval = struct ("dld", dld,
-                     "float_format", float_format,
-                     "words_big_endian", words_big_endian,
-                     "words_little_endian", words_little_endian,
-                     "features", features,
-                     env_cell{:}, other_cell{:});
-  else
-    if (strcmp (option, "features"))
-      option = "build_features";
-    endif
-    retval = __octave_config_info__ (option);
-  endif
-
-endfunction
--- a/scripts/deprecated/onenormest.m	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,307 +0,0 @@
-## Copyright (C) 2007-2018 Regents of the University of California
-##
-## 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
-## <https://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn  {} {[@var{est}, @var{v}, @var{w}, @var{iter}] =} onenormest (@var{A}, @var{t})
-## @deftypefnx {} {[@var{est}, @var{v}, @var{w}, @var{iter}] =} onenormest (@var{apply}, @var{apply_t}, @var{n}, @var{t})
-##
-## @code{onenormest} is deprecated and will be removed in Octave version 5.
-## Use @code{normest1} for the equivalent functionality.
-##
-## Apply @nospell{Higham and Tisseur's} randomized block 1-norm estimator to
-## matrix @var{A} using @var{t} test vectors.
-##
-## If @var{t} exceeds 5, then only 5 test vectors are used.
-##
-## If the matrix is not explicit, e.g., when estimating the norm of
-## @code{inv (@var{A})} given an LU@tie{}factorization, @code{onenormest}
-## applies @var{A} and its conjugate transpose through a pair of functions
-## @var{apply} and @var{apply_t}, respectively, to a dense matrix of size
-## @var{n} by @var{t}.  The implicit version requires an explicit dimension
-## @var{n}.
-##
-## Returns the norm estimate @var{est}, two vectors @var{v} and @var{w} related
-## by norm @code{(@var{w}, 1) = @var{est} * norm (@var{v}, 1)}, and the number
-## of iterations @var{iter}.  The number of iterations is limited to 10 and is
-## at least 2.
-##
-## References:
-##
-## @itemize
-## @item
-## @nospell{N.J. Higham and F. Tisseur}, @cite{A Block Algorithm
-## for Matrix 1-Norm Estimation, with an Application to 1-Norm
-## Pseudospectra}. SIMAX vol 21, no 4, pp 1185-1201.
-## @url{http://dx.doi.org/10.1137/S0895479899356080}
-##
-## @item
-## @nospell{N.J. Higham and F. Tisseur}, @cite{A Block Algorithm
-## for Matrix 1-Norm Estimation, with an Application to 1-Norm
-## Pseudospectra}. @url{http://citeseer.ist.psu.edu/223007.html}
-## @end itemize
-##
-## @seealso{condest, norm, cond}
-## @end deftypefn
-
-## Code originally licensed under:
-##
-## Copyright (c) 2007, Regents of the University of California
-## All rights reserved.
-##
-## Redistribution and use in source and binary forms, with or without
-## modification, are permitted provided that the following conditions
-## are met:
-##
-##    * Redistributions of source code must retain the above copyright
-##      notice, this list of conditions and the following disclaimer.
-##
-##    * Redistributions in binary form must reproduce the above
-##      copyright notice, this list of conditions and the following
-##      disclaimer in the documentation and/or other materials provided
-##      with the distribution.
-##
-##    * Neither the name of the University of California, Berkeley nor
-##      the names of its contributors may be used to endorse or promote
-##      products derived from this software without specific prior
-##      written permission.
-##
-## THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS''
-## AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-## TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-## PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND
-## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-## USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
-## OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-## SUCH DAMAGE.
-
-## Author: Jason Riedy <ejr@cs.berkeley.edu>
-## Keywords: linear-algebra norm estimation
-## Version: 0.2
-
-function [est, v, w, iter] = onenormest (varargin)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "onenormest is obsolete and will be removed from a future version of Octave, please use normest1 instead");
-  endif
-
-
-  if (nargin < 1 || nargin > 4)
-    print_usage ();
-  endif
-
-  default_t = 5;
-  itmax = 10;
-
-  if (isnumeric (varargin{1}))
-    [n, nc] = size (varargin{1});
-    if (n != nc)
-      error ("onenormest: matrix must be square");
-    endif
-    apply = @(x) varargin{1} * x;
-    apply_t = @(x) varargin{1}' * x;
-    if (nargin > 1)
-      t = varargin{2};
-    else
-      t = min (n, default_t);
-    endif
-    issing = isa (varargin{1}, "single");
-  else
-    if (nargin < 3)
-      print_usage ();
-    endif
-    apply = varargin{1};
-    apply_t = varargin{2};
-    n = varargin{3};
-    if (nargin > 3)
-      t = varargin{4};
-    else
-      t = default_t;
-    endif
-    issing = isa (n, "single");
-  endif
-
-  ## Initial test vectors X.
-  X = rand (n, t);
-  X ./= ones (n,1) * sum (abs (X), 1);
-
-  ## Track if a vertex has been visited.
-  been_there = zeros (n, 1);
-
-  ## To check if the estimate has increased.
-  est_old = 0;
-
-  ## Normalized vector of signs.
-  S = zeros (n, t);
-
-  if (issing)
-    myeps = eps ("single");
-    X = single (X);
-  else
-    myeps = eps;
-  endif
-
-  for iter = 1 : itmax + 1
-    Y = feval (apply, X);
-
-    ## Find the initial estimate as the largest A*x.
-    [est, ind_best] = max (sum (abs (Y), 1));
-    if (est > est_old || iter == 2)
-      w = Y(:,ind_best);
-    endif
-    if (iter >= 2 && est < est_old)
-      ## No improvement, so stop.
-      est = est_old;
-      break;
-    endif
-
-    est_old = est;
-    S_old = S;
-    if (iter > itmax),
-      ## Gone too far.  Stop.
-      break;
-    endif
-
-    S = sign (Y);
-
-    ## Test if any of S are approximately parallel to previous S
-    ## vectors or current S vectors.  If everything is parallel,
-    ## stop.  Otherwise, replace any parallel vectors with
-    ## rand{-1,+1}.
-    partest = any (abs (S_old' * S - n) < 4*eps*n);
-    if (all (partest))
-      ## All the current vectors are parallel to old vectors.
-      ## We've hit a cycle, so stop.
-      break;
-    endif
-    if (any (partest))
-      ## Some vectors are parallel to old ones and are cycling,
-      ## but not all of them.  Replace the parallel vectors with
-      ## rand{-1,+1}.
-      numpar = sum (partest);
-      replacements = 2*(rand (n,numpar) < 0.5) - 1;
-      S(:,partest) = replacements;
-    endif
-    ## Now test for parallel vectors within S.
-    partest = any ((S' * S - eye (t)) == n);
-    if (any (partest))
-      numpar = sum (partest);
-      replacements = 2*(rand (n,numpar) < 0.5) - 1;
-      S(:,partest) = replacements;
-    endif
-
-    Z = feval (apply_t, S);
-
-    ## Now find the largest non-previously-visted index per vector.
-    h = max (abs (Z),2);
-    [mh, mhi] = max (h);
-    if (iter >= 2 && mhi == ind_best)
-      ## Hit a cycle, stop.
-      break;
-    endif
-    [h, ind] = sort (h, 'descend');
-    if (t > 1)
-      firstind = ind(1:t);
-      if (all (been_there(firstind)))
-        ## Visited all these before, so stop.
-        break;
-      endif
-      ind = ind(! been_there(ind));
-      if (length (ind) < t)
-        ## There aren't enough new vectors, so we're practically
-        ## in a cycle.  Stop.
-        break;
-      endif
-    endif
-
-    ## Visit the new indices.
-    X = zeros (n, t);
-    for zz = 1 : t
-      X(ind(zz),zz) = 1;
-    endfor
-    been_there(ind(1 : t)) = 1;
-  endfor
-
-  ## The estimate est and vector w are set in the loop above.
-  ## The vector v selects the ind_best column of A.
-  v = zeros (n, 1);
-  v(ind_best) = 1;
-
-endfunction
-
-
-%!demo
-%! N = 100;
-%! A = randn (N) + eye (N);
-%! [L,U,P] = lu (A);
-%! nm1inv = onenormest (@(x) U\(L\(P*x)), @(x) P'*(L'\(U'\x)), N, 30)
-%! norm (inv (A), 1)
-
-%!test
-%! warning ("off", "Octave:deprecated-function", "local");
-%! N = 10;
-%! A = ones (N);
-%! [nm1, v1, w1] = onenormest (A);
-%! [nminf, vinf, winf] = onenormest (A', 6);
-%! assert (nm1, N, -2*eps);
-%! assert (nminf, N, -2*eps);
-%! assert (norm (w1, 1), nm1 * norm (v1, 1), -2*eps);
-%! assert (norm (winf, 1), nminf * norm (vinf, 1), -2*eps);
-
-%!test
-%! warning ("off", "Octave:deprecated-function", "local");
-%! N = 10;
-%! A = ones (N);
-%! [nm1, v1, w1] = onenormest (@(x) A*x, @(x) A'*x, N, 3);
-%! [nminf, vinf, winf] = onenormest (@(x) A'*x, @(x) A*x, N, 3);
-%! assert (nm1, N, -2*eps);
-%! assert (nminf, N, -2*eps);
-%! assert (norm (w1, 1), nm1 * norm (v1, 1), -2*eps);
-%! assert (norm (winf, 1), nminf * norm (vinf, 1), -2*eps);
-
-%!test
-%! warning ("off", "Octave:deprecated-function", "local");
-%! N = 5;
-%! A = hilb (N);
-%! [nm1, v1, w1] = onenormest (A);
-%! [nminf, vinf, winf] = onenormest (A', 6);
-%! assert (nm1, norm (A, 1), -2*eps);
-%! assert (nminf, norm (A, inf), -2*eps);
-%! assert (norm (w1, 1), nm1 * norm (v1, 1), -2*eps);
-%! assert (norm (winf, 1), nminf * norm (vinf, 1), -2*eps);
-
-## Only likely to be within a factor of 10.
-%!test
-%! warning ("off", "Octave:deprecated-function", "local");
-%! old_state = rand ("state");
-%! restore_state = onCleanup (@() rand ("state", old_state));
-%! rand ("state", 42);  # Initialize to guarantee reproducible results
-%! N = 100;
-%! A = rand (N);
-%! [nm1, v1, w1] = onenormest (A);
-%! [nminf, vinf, winf] = onenormest (A', 6);
-%! assert (nm1, norm (A, 1), -.1);
-%! assert (nminf, norm (A, inf), -.1);
-%! assert (norm (w1, 1), nm1 * norm (v1, 1), -2*eps);
-%! assert (norm (winf, 1), nminf * norm (vinf, 1), -2*eps);
--- a/scripts/deprecated/setstr.m	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-## Copyright (C) 2003-2018 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} {} setstr (@var{s})
-## This function has been deprecated.  Use char instead.
-## @end deftypefn
-
-## Author: jwe
-
-## Deprecated in version 3.0
-## Matlab still has this function, so don't remove just yet.
-
-function retval = setstr (varargin)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "setstr is obsolete and will be removed from a future version of Octave; please use char instead");
-  endif
-
-  retval = char (varargin{:});
-
-endfunction
--- a/scripts/deprecated/sleep.m	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-## Copyright (C) 1993-2018 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
-## <https://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {} {} sleep (@var{seconds})
-##
-## @code{sleep} is deprecated and will be removed in Octave version 5.
-## Use @code{pause} instead.
-##
-## Suspend the execution of the program for the given number of seconds.
-##
-## @seealso{pause}
-## @end deftypefn
-
-function sleep (seconds)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "sleep is obsolete and will be removed from a future version of Octave, please use pause instead");
-  endif
-
-  if (nargin == 1)
-    pause (seconds);
-  else
-    print_usage ();
-  endif
-
-endfunction
-
-
-%!test
-%! sleep (1);
-
-%!error (sleep ())
-%!error (sleep (1, 2))
--- a/scripts/deprecated/toascii.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/deprecated/toascii.m	Fri Aug 10 09:09:51 2018 +0200
@@ -60,6 +60,11 @@
 endfunction
 
 
+## First test is necessary to provoke 1-time legacy warning
+%!test
+%! warning ("off", "Octave:deprecated-function", "local");
+%! toascii ("");
+
 %!assert (toascii (char (0:127)), 0:127)
 %!assert (toascii (" ":"@"), 32:64)
 %!assert (toascii ("A":"Z"), 65:90)
--- a/scripts/deprecated/usleep.m	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-## Copyright (C) 1993-2018 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
-## <https://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {} {} usleep (@var{microseconds})
-##
-## @code{usleep} is deprecated and will be removed in Octave version 5.
-## Use @code{pause} instead.
-##
-## Suspend the execution of the program for the given number of
-## microseconds (1e-6 seconds).
-##
-## @seealso{pause}
-## @end deftypefn
-
-function usleep (microseconds)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "usleep is obsolete and will be removed from a future version of Octave, please use pause instead");
-  endif
-
-  if (nargin == 1)
-    pause (microseconds / 1e6);
-  else
-    print_usage ();
-  endif
-
-endfunction
-
-
-%!test
-%! usleep (1000);
-
-%!error (usleep ())
-%!error (usleep (1, 2))
--- a/scripts/deprecated/wavread.m	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,128 +0,0 @@
-## Copyright (C) 2016-2018 Mike Miller
-## Copyright (C) 2005-2018 Michael Zeising
-##
-## 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
-## <https://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn  {} {@var{y} =} wavread (@var{filename})
-## @deftypefnx {} {[@var{y}, @var{fs}, @var{nbits}] =} wavread (@var{filename})
-## @deftypefnx {} {[@dots{}] =} wavread (@var{filename}, @var{n})
-## @deftypefnx {} {[@dots{}] =} wavread (@var{filename}, [@var{n1} @var{n2}])
-## @deftypefnx {} {[@dots{}] =} wavread (@dots{}, @var{datatype})
-## @deftypefnx {} {@var{sz} =} wavread (@var{filename}, "size")
-## @deftypefnx {} {[@var{n_samp}, @var{n_chan}] =} wavread (@var{filename}, "size")
-##
-## @code{wavread} is deprecated and will be removed in Octave version 5.
-## Use @code{audioread} for the equivalent functionality.
-##
-## Read the audio signal @var{y} from the RIFF/WAVE sound file @var{filename}.
-##
-## If the file contains multichannel data, then @var{y} is a matrix with the
-## channels represented as columns.
-##
-## If @var{n} is specified, only the first @var{n} samples of the file are
-## returned.  If [@var{n1} @var{n2}] is specified, only the range of samples
-## from @var{n1} to @var{n2} is returned.  A value of @code{Inf} can be used
-## to represent the total number of samples in the file.
-##
-## If the option @qcode{"size"} is given, then the size of the audio signal
-## is returned instead of the data.  The size is returned in a row vector of
-## the form [@var{samples} @var{channels}].  If there are two output arguments,
-## the number of samples is assigned to the first and the number of channels
-## is assigned to the second.
-##
-## The optional return value @var{fs} is the sample rate of the audio file in
-## Hz.  The optional return value @var{nbits} is the number of bits per sample
-## as encoded in the file.
-##
-## @seealso{audioread, audiowrite, wavwrite}
-## @end deftypefn
-
-## Deprecated in 4.2
-
-function [y, fs, nbits] = wavread (filename, varargin)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "wavread is obsolete and will be removed from a future version of Octave, please use audioread instead");
-  endif
-
-  if (nargin < 1 || nargin > 3)
-    print_usage ();
-  endif
-
-  if (! ischar (filename))
-    error ("wavread: FILENAME must be a character string");
-  endif
-
-  datatype = "double";
-  samples = [1, Inf];
-  do_file_size = false;
-
-  if (nargin == 3)
-    samples = varargin{1};
-    datatype = varargin{2};
-  elseif (nargin == 2)
-    if (strcmp (varargin{1}, "size"))
-      do_file_size = true;
-    elseif (ischar (varargin{1}))
-      datatype = varargin{1};
-    else
-      samples = varargin{1};
-    endif
-  endif
-
-  if (isscalar (samples))
-    samples = [1, samples];
-  endif
-
-  if (! (isrow (samples) && numel (samples) == 2 && all (samples > 0)
-         && all (fix (samples) == samples)))
-    error ("wavread: SAMPLES must be a 1- or 2-element integer row vector");
-  endif
-
-  if (! (ischar (datatype) && any (strcmp (datatype, {"double", "native"}))))
-    error ('wavread: DATATYPE must be either "double" or "native"');
-  endif
-
-  info = audioinfo (filename);
-
-  if (do_file_size)
-    if (nargout > 1)
-      [y, fs] = deal (info.TotalSamples, info.NumChannels);
-    else
-      y = [info.TotalSamples, info.NumChannels];
-    endif
-  else
-    [y, fs] = audioread (filename, samples, datatype);
-    nbits = info.BitsPerSample;
-  endif
-
-endfunction
-
-
-## Functional tests for wavread/wavwrite pair are in wavwrite.m.
-
-## Test input validation
-%!error wavread ()
-%!error wavread (1)
-%!error wavread ("foo.wav", 2, 3, 4)
-%!error wavread ("foo.wav", "foo")
-%!error wavread ("foo.wav", -1)
-%!error wavread ("foo.wav", [1, Inf], "foo")
--- a/scripts/deprecated/wavwrite.m	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,193 +0,0 @@
-## Copyright (C) 2016-2018 Mike Miller
-## Copyright (C) 2005-2018 Michael Zeising
-##
-## 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
-## <https://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn  {} {} wavwrite (@var{y}, @var{filename})
-## @deftypefnx {} {} wavwrite (@var{y}, @var{fs}, @var{filename})
-## @deftypefnx {} {} wavwrite (@var{y}, @var{fs}, @var{nbits}, @var{filename})
-##
-## @code{wavwrite} is deprecated and will be removed in Octave version 5.
-## Use @code{audiowrite} for the equivalent functionality.
-##
-## Write the audio signal @var{y} to the RIFF/WAVE sound file @var{filename}.
-##
-## If @var{y} is a matrix, the columns represent multiple audio channels.
-##
-## The optional argument @var{fs} specifies the sample rate of the audio signal
-## in Hz.
-##
-## The optional argument @var{nbits} specifies the number of bits per sample
-## to write to @var{filename}.
-##
-## The default sample rate is 8000 Hz and the default bit depth is 16 bits
-## per sample.
-##
-## @seealso{audiowrite, audioread, wavread}
-## @end deftypefn
-
-## Deprecated in 4.2
-
-function wavwrite (y, varargin)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "wavwrite is obsolete and will be removed from a future version of Octave, please use audiowrite instead");
-  endif
-
-  if (nargin < 2 || nargin > 4)
-    print_usage ();
-  endif
-
-  ## Defaults.
-  fs = 8000;
-  nbits = 16;
-
-  filename = varargin{end};
-  if (nargin > 2)
-    fs = varargin{1};
-    if (nargin > 3)
-      nbits = varargin{2};
-    endif
-  endif
-
-  ## calculate filesize
-  [n, channels] = size (y);
-
-  ## allow y to be a row vector
-  if (n == 1)
-    y = y(:);
-    n = channels;
-    channels = 1;
-  endif
-
-  ## test arguments
-  if (channels < 1)
-    error ("wavwrite: Y must have at least one column");
-  endif
-
-  if (channels > 0x7FFF)
-    error ("wavwrite: Y must have no more than 32767 columns");
-  endif
-
-  if (! (isscalar (fs) && (fs > 0)))
-    error ("wavwrite: sample rate FS must be a positive number");
-  endif
-
-  if (! isscalar (nbits) || isempty (find (nbits == [8, 16, 24, 32])))
-    error ("wavwrite: bit depth NBITS must be 8, 16, 24, or 32");
-  endif
-
-  audiowrite (filename, y, fs, "BitsPerSample", nbits);
-
-endfunction
-
-
-%!shared fname
-%! fname = [tempname() ".wav"];
-
-%!testif HAVE_SNDFILE
-%! A = [-1:0.1:1; -1:0.1:1]';
-%! unwind_protect
-%!   wavwrite (A, fname);
-%!   [B, samples_per_sec, bits_per_sample] = wavread (fname);
-%!   assert (B, A, 2^-14);
-%!   assert (samples_per_sec, 8000);
-%!   assert (bits_per_sample, 16);
-%! unwind_protect_cleanup
-%!   unlink (fname);
-%! end_unwind_protect
-
-%!testif HAVE_SNDFILE
-%! A = [-1:0.1:1; -1:0.1:1]';
-%! unwind_protect
-%!   wavwrite (A, 4000, fname);
-%!   [B, samples_per_sec, bits_per_sample] = wavread (fname);
-%!   assert (B, A, 2^-14);
-%!   assert (samples_per_sec, 4000);
-%!   assert (bits_per_sample, 16);
-%! unwind_protect_cleanup
-%!   unlink (fname);
-%! end_unwind_protect
-
-%!testif HAVE_SNDFILE
-%! A = [-1:0.1:1; -1:0.1:1]';
-%! unwind_protect
-%!   wavwrite (A, 4000, 8, fname);
-%!   [B, samples_per_sec, bits_per_sample] = wavread (fname);
-%!   assert (B, A, 2^-6);
-%!   assert (samples_per_sec, 4000);
-%!   assert (bits_per_sample, 8);
-%! unwind_protect_cleanup
-%!   unlink (fname);
-%! end_unwind_protect
-
-%!testif HAVE_SNDFILE
-%! A = [-2:2]';
-%! unwind_protect
-%!   wavwrite (A, fname);
-%!   B = wavread (fname);
-%!   B *= 32768;
-%!   assert (B, [-32767 -32767 0 32767 32767]');
-%! unwind_protect_cleanup
-%!   unlink (fname);
-%! end_unwind_protect
-
-%!testif HAVE_SNDFILE
-%! A = [-1:0.1:1];
-%! unwind_protect
-%!   wavwrite (A, fname);
-%!   [B, samples_per_sec, bits_per_sample] = wavread (fname);
-%!   assert (B, A', 2^-14);
-%!   assert (samples_per_sec, 8000);
-%!   assert (bits_per_sample, 16);
-%! unwind_protect_cleanup
-%!   unlink (fname);
-%! end_unwind_protect
-
-%!testif HAVE_SNDFILE
-%! A = [-1:0.1:1; -1:0.1:1]';
-%! unwind_protect
-%!   wavwrite (A, fname);
-%!   B = wavread (fname, 15);
-%!   assert (B, A(1:15,:), 2^-14);
-%!   wavwrite (A, fname);
-%!   B = wavread (fname, [10, 20]);
-%!   assert (B, A(10:20,:), 2^-14);
-%! unwind_protect_cleanup
-%!   unlink (fname);
-%! end_unwind_protect
-
-%!testif HAVE_SNDFILE
-%! A = [-1:0.1:1; -1:0.1:1]';
-%! unwind_protect
-%!   wavwrite (A, fname);
-%!   [nsamp, nchan] = wavread (fname, "size");
-%!   assert (nsamp, 21);
-%!   assert (nchan, 2);
-%! unwind_protect_cleanup
-%!   unlink (fname);
-%! end_unwind_protect
-
-## Test input validation
-%!error wavwrite ()
-%!error wavwrite (1)
-%!error wavwrite (1,2,3,4,5)
-%!error wavwrite ([], "foo.wav")
--- a/scripts/general/bitset.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/general/bitset.m	Fri Aug 10 09:09:51 2018 +0200
@@ -22,20 +22,41 @@
 ## @deftypefnx {} {@var{C} =} bitset (@var{A}, @var{n}, @var{val})
 ## Set or reset bit(s) @var{n} of the unsigned integers in @var{A}.
 ##
-## @var{val} = 0 resets and @var{val} = 1 sets the bits.
-## The least significant bit is @var{n} = 1.  All variables must be the same
-## size or scalars.
+## The least significant bit is @var{n} = 1.  @w{@var{val} = 0} resets bits and
+## @w{@var{val} = 1} sets bits.  If no @var{val} is specified it defaults to
+## 1 (set bit).  All inputs must be the same size or scalars.
+##
+## Example 1: Set multiple bits
 ##
 ## @example
 ## @group
-## dec2bin (bitset (10, 1))
-##   @result{} 1011
+## x = bitset (1, 3:5)
+## x =
+##
+##    5    9   17
+##
+## dec2bin (x)
+##   @result{}
+##      00101
+##      01001
+##      10001
+## @end group
+## @end example
+##
+## Example 2: Reset and set bits
+##
+## @example
+## @group
+## x = bitset ([15 14], 1, [0 1])
+## x =
+##
+##    14    15
 ## @end group
 ## @end example
 ## @seealso{bitand, bitor, bitxor, bitget, bitcmp, bitshift, intmax, flintmax}
 ## @end deftypefn
 
-function C = bitset (A, n, val)
+function C = bitset (A, n, val = true)
 
   if (nargin < 2 || nargin > 3)
     print_usage ();
@@ -45,12 +66,18 @@
     error ("bitset: A must be >= 0");
   endif
 
-  sz = size (A);
-
-  if (nargin == 2)
-    val = true (sz);
+  [size_err, A, n, val] = common_size (A, n, val);
+  if (size_err)
+    error ("bitset: A, N, and VAL must be the same size or scalar");
   endif
 
+  ## Special case of empty input
+  if (isempty (A))
+    C = [];
+    return;
+  endif
+
+  sz = size (A);
   cl = class (A);
 
   if (isfloat (A) && isreal (A))
@@ -76,9 +103,6 @@
     onmask = mask;
     offmask = mask;
   else
-    if (! size_equal (A, n))
-      error ("bitset: N must be scalar or the same size as A");
-    endif
     onmask = mask(on);
     offmask = mask(off);
   endif
@@ -101,12 +125,21 @@
 %!   endfor
 %! endfor
 
+%!assert (bitset ([], 1), [])
+
 %!assert <*36458> (bitset (uint8 ([1, 2;3 4]), 1, [0 1; 0 1]),
-%!                uint8 ([0, 3; 2 5]))
+%!                 uint8 ([0, 3; 2 5]))
+
+%!assert (bitset (1:5, 1), [1, 3, 3, 5, 5])
+%!assert (bitset (1:5, 1, [1, 1, 1, 1, 1]), [1, 3, 3, 5, 5])
+%!assert <*54110> (bitset (1:5, 1, 1), [1, 3, 3, 5, 5])
+%!assert (bitset (1:5, 1, [1, 1, 1, 1, 0]), [1, 3, 3, 5, 4])
 
 %!error bitset (1)
 %!error bitset (1, 2, 3, 4)
 %!error <A must be .= 0> bitset (-1, 2)
+%!error <must be the same size or scalar> bitset (1, [1 2], [1 2 3])
+%!error <must be the same size or scalar> bitset ([1 2], [1 2 3])
 %!error <invalid class char> bitset ("1", 2)
 %!error <N must be in the range \[1,53\]> bitset (0, 0)
 %!error <N must be in the range \[1,53\]> bitset (0, 55)
@@ -121,5 +154,3 @@
 %!error <N must be in the range \[1,32\]> bitset (uint32 (0), 33)
 %!error <N must be in the range \[1,63\]> bitset (int64 (0), 65)
 %!error <N must be in the range \[1,64\]> bitset (uint64 (0), 65)
-%!error <N must be scalar or the same size as A> bitset (uint8 (1), [1 3])
-%!error <N must be scalar or the same size as A> bitset (uint8 (1:3), [1 3])
--- a/scripts/general/cumtrapz.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/general/cumtrapz.m	Fri Aug 10 09:09:51 2018 +0200
@@ -59,9 +59,9 @@
     have_xy = true;
     have_dim = true;
   elseif (nargin == 2)
-    if (! size_equal (x, y) && isscalar (y))
+    if (isscalar (y) && ! isscalar (x))
+      have_dim = true;
       dim = y;
-      have_dim = true;
     else
       have_xy = true;
     endif
@@ -86,28 +86,28 @@
   endif
 
   n = sz(dim);
-  idx1 = idx2 = repmat ({':'}, [nd, 1]);
+  idx1 = idx2 = {':'}(ones (nd, 1));  # repmat ({':'}, [nd, 1]), but faster
   idx1{dim} = 2 : n;
   idx2{dim} = 1 : (n - 1);
 
   if (! have_xy)
     z = 0.5 * cumsum (x(idx1{:}) + x(idx2{:}), dim);
-  else
-    if (isvector (x) && ! isvector (y))
-      if (length (x) != sz(dim))
-        error ("cumtrapz: length of X and length of Y along DIM must match");
-      endif
+  elseif (isscalar (x))
+    z = x * 0.5 * cumsum (y(idx1{:}) + y(idx2{:}), dim);
+  elseif (isvector (x))
+    if (length (x) != n)
+      error ("cumtrapz: length of X and length of Y along DIM must match");
+    endif
       ## Reshape vector to point along dimension DIM
       shape = ones (nd, 1);
-      shape(dim) = sz(dim);
+      shape(dim) = n;
       x = reshape (x, shape);
       z = 0.5 * cumsum (diff (x) .* (y(idx1{:}) + y(idx2{:})), dim);
-    else
-      if (! size_equal (x, y))
-        error ("cumtrapz: X and Y must have same shape");
-      endif
-      z = 0.5 * cumsum (diff (x, 1, dim) .* (y(idx1{:}) + y(idx2{:})), dim);
+  else
+    if (! size_equal (x, y))
+      error ("cumtrapz: X and Y must have same shape");
     endif
+    z = 0.5 * cumsum (diff (x, 1, dim) .* (y(idx1{:}) + y(idx2{:})), dim);
   endif
 
   sz(dim) = 1;
@@ -116,17 +116,34 @@
 endfunction
 
 
-%!shared x1,x2,y
+%!shared x1, x2, y
+%! x1 = [1:5];
+%! x2 = [2:2:10];
+%! y = [1:5];
+%!
+%!assert (cumtrapz (y), [0, 1.5, 4, 7.5, 12])
+%!assert (cumtrapz (y'), [0, 1.5, 4, 7.5, 12]')
+%!assert (cumtrapz (1, y), [0, 1.5, 4, 7.5, 12])
+%!assert (cumtrapz (2, y), [0, 3, 8, 15, 24])
+%!assert (cumtrapz (x1, y),[0, 1.5, 4, 7.5, 12])
+%!assert (cumtrapz (x2, y),[0, 3, 8, 15, 24])
+%!assert (cumtrapz (2, y, 2), [0, 3, 8, 15, 24])
+%!assert (cumtrapz (x2, y, 2), [0, 3, 8, 15, 24])
+%!assert (cumtrapz (y, 1), [0, 0, 0, 0, 0])
+%!assert (cumtrapz (2, y, 1), [0, 0, 0, 0, 0])
+%!assert (cumtrapz (y', 2), [0, 0, 0, 0, 0]')
+
+%!shared x1, x2, y
 %! x1 = [0,0,0;2,2,2];
 %! x2 = [0,2,4;0,2,4];
 %! y = [1,2,3;4,5,6];
 %!
 %!assert (cumtrapz (y), [0,0,0;2.5,3.5,4.5])
-%!assert (cumtrapz (x1,y), [0,0,0;5,7,9])
-%!assert (cumtrapz (y,1), [0,0,0;2.5,3.5,4.5])
-%!assert (cumtrapz (x1,y,1), [0,0,0;5,7,9])
-%!assert (cumtrapz (y,2), [0,1.5,4;0,4.5,10])
-%!assert (cumtrapz (x2,y,2), [0,3,8;0,9,20])
+%!assert (cumtrapz (x1, y), [0,0,0;5,7,9])
+%!assert (cumtrapz (y, 1), [0,0,0;2.5,3.5,4.5])
+%!assert (cumtrapz (x1, y, 1), [0,0,0;5,7,9])
+%!assert (cumtrapz (y, 2), [0,1.5,4;0,4.5,10])
+%!assert (cumtrapz (x2, y, 2), [0,3,8;0,9,20])
 
 ## Test ND-array implementation
 %!shared x1,x2,y
@@ -137,3 +154,13 @@
 %!assert (cumtrapz (y,3), reshape ([0,1.5,4;0,4.5,10],[1 2 3]))
 %!assert (cumtrapz (x1,y,3), reshape ([0,1.5,4;0,4.5,10],[1 2 3]))
 %!assert (cumtrapz (x2,y,3), reshape ([0,3,8;0,9,20],[1 2 3]))
+
+## Test input validation
+%!error cumtrapz ()
+%!error cumtrapz (1,2,3,4)
+%!error <DIM must be an integer> cumtrapz (1, 2, [1 2])
+%!error <DIM must be an integer> cumtrapz (1, 2, 1.5)
+%!error <DIM must be .* a valid dimension> cumtrapz (1, 2, 0)
+%!error <length of X and length of Y.*must match> cumtrapz ([1 2], [1 2 3])
+%!error <X and Y must have same shape> cumtrapz (ones (2,3), ones (2,4))
+
--- a/scripts/general/flipdim.m	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-## Copyright (C) 2004-2018 David Bateman
-## Copyright (C) 2009 VZLU Prague
-##
-## This file is part of Octave.
-##
-## Octave is free software: you can redistribute it and/or modify it
-## under the terms of the GNU General Public License as published by
-## the Free Software Foundation, either version 3 of the License, or
-## (at your option) any later version.
-##
-## Octave is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-## GNU General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with Octave; see the file COPYING.  If not, see
-## <https://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn  {} {} flipdim (@var{x})
-## @deftypefnx {} {} flipdim (@var{x}, @var{dim})
-## Flip array across dimension @var{dim}.
-##
-## This function is an alias for @code{flip} and exists for backwards and
-## @sc{matlab} compatibility.  See @code{flip} for complete usage information.
-##
-## @seealso{flip, fliplr, flipud, rot90, rotdim}
-## @end deftypefn
-
-## Author: David Bateman, Jaroslav Hajek
-
-function y = flipdim (varargin)
-  y = flip (varargin{:});
-endfunction
-
-
-## No tests needed for alias.  All tests for functionality are in flip.m
-%!assert (1)
--- a/scripts/general/interpft.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/general/interpft.m	Fri Aug 10 09:09:51 2018 +0200
@@ -118,21 +118,28 @@
 
 %!shared n,y
 %! x = [0:10]';  y = sin(x);  n = length (x);
-%!assert (interpft (y, n), y, 20*eps)
-%!assert (interpft (y', n), y', 20*eps)
-%!assert (interpft ([y,y],n), [y,y], 20*eps)
+%!testif HAVE_FFTW
+%! assert (interpft (y, n), y, 20*eps)
+%!testif HAVE_FFTW
+%! assert (interpft (y', n), y', 20*eps)
+%!testif HAVE_FFTW
+%! assert (interpft ([y,y],n), [y,y], 20*eps)
 
 ## Test case with complex input
-%!test <*39566>
+%!testif HAVE_FFTW <*39566>
 %! x = (1 + j) * [1:4]';
 %! y = ifft ([15 + 15*j; -6; -1.5 - 1.5*j; 0; -1.5 - 1.5*j; -6*j]);
 %! assert (interpft (x, 6), y, 10*eps);
 
 ## Test for correct spectral symmetry with even/odd lengths
-%!assert (max (abs (imag (interpft ([1:8], 20)))), 0, 20*eps)
-%!assert (max (abs (imag (interpft ([1:8], 21)))), 0, 21*eps)
-%!assert (max (abs (imag (interpft ([1:9], 20)))), 0, 20*eps)
-%!assert (max (abs (imag (interpft ([1:9], 21)))), 0, 21*eps)
+%!testif HAVE_FFTW
+%! assert (max (abs (imag (interpft ([1:8], 20)))), 0, 20*eps)
+%!testif HAVE_FFTW
+%! assert (max (abs (imag (interpft ([1:8], 21)))), 0, 21*eps)
+%!testif HAVE_FFTW
+%! assert (max (abs (imag (interpft ([1:9], 20)))), 0, 20*eps)
+%!testif HAVE_FFTW
+%! assert (max (abs (imag (interpft ([1:9], 21)))), 0, 21*eps)
 
 ## Test input validation
 %!error interpft ()
--- a/scripts/general/logspace.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/general/logspace.m	Fri Aug 10 09:09:51 2018 +0200
@@ -97,6 +97,16 @@
 %! assert (size (x2) == [1, 10] && abs (x2(1) - 10) < eps && abs (x2(10) - 100) < eps);
 %! assert (size (x3) == [1, 10] && abs (x3(1) - 10) < eps && abs (x3(10) - 0.01) < eps);
 %! assert (size (x4) == [1, 10] && abs (x4(1) - 10) < eps && abs (x4(10) - pi) < sqrt (eps));
+%!assert (logspace (Inf, Inf, 3), [Inf, Inf, Inf])
+%!assert (logspace (-Inf, -Inf, 3), [0, 0, 0])
+%!assert (logspace (-Inf, Inf, 3), [0, NaN, Inf])
+%!assert (logspace (Inf + 1i, Inf + 1i, 3), repmat (complex (-Inf,Inf), [1, 3]))
+%!assert (logspace (-Inf + 1i, Inf + 1i, 3), [0, NaN + NaN * 1i, complex(-Inf, Inf)])
+%!assert (logspace (0, Inf, 3), [1, Inf, Inf])
+%!assert (logspace (0, -Inf, 3), [1, 0, 0])
+%!assert (logspace (-Inf, 0, 3), [0, NaN, 1])
+%!assert (logspace (Inf, 0, 3), [Inf, NaN, 1])
+%!assert (logspace (Inf, -Inf, 3), [Inf, NaN, 0])
 
 ## Test input validation
 %!error logspace ()
--- a/scripts/general/module.mk	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/general/module.mk	Fri Aug 10 09:09:51 2018 +0200
@@ -28,7 +28,6 @@
   %reldir%/del2.m \
   %reldir%/divergence.m \
   %reldir%/flip.m \
-  %reldir%/flipdim.m \
   %reldir%/fliplr.m \
   %reldir%/flipud.m \
   %reldir%/gradient.m \
--- a/scripts/general/nextpow2.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/general/nextpow2.m	Fri Aug 10 09:09:51 2018 +0200
@@ -17,7 +17,7 @@
 ## <https://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {} {} nextpow2 (@var{x})
+## @deftypefn {} {@var{n} =} nextpow2 (@var{x})
 ## Compute the exponent for the smallest power of two larger than the input.
 ##
 ## For each element in the input array @var{x}, return the first integer
@@ -47,6 +47,8 @@
   endif
 
   [f, n] = log2 (abs (x));
+  idx = (n == 0);   # Find any failures of log2 function (n == 0)
+  n(idx) = f(idx);  # and copy over value.
   n(f == 0.5)--;
 
 endfunction
@@ -59,6 +61,15 @@
 %!assert (nextpow2 (-17), 5)
 %!assert (nextpow2 (-31), 5)
 %!assert (nextpow2 (1:17), [0 1 2 2 3 3 3 3 4 4 4 4 4 4 4 4 5])
+## Special cases
+%!assert (nextpow2 (0), 0)
+%!assert (nextpow2 (1), 0)
+%!assert (nextpow2 (Inf), Inf)
+%!assert (nextpow2 (-Inf), Inf)
+%!assert (nextpow2 (NaN), NaN)
+%!assert (nextpow2 ([1, Inf, 3, -Inf, 9, NaN]), [0, Inf, 2, Inf, 4, NaN])
 
+## Test input validation
 %!error nexpow2 ()
 %!error nexpow2 (1, 2)
+%!error <X must be numeric> nextpow2 ("t")
--- a/scripts/general/num2str.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/general/num2str.m	Fri Aug 10 09:09:51 2018 +0200
@@ -104,7 +104,7 @@
           ndgt = 0;  # All Inf or all zero array
         endif
 
-        if (any (x(valid) != fix (x(valid))))
+        if (ndgt > 15 || any (x(valid) != fix (x(valid))))
           ## Floating point input
           ndgt = max (ndgt + 5, 5);   # Keep at least 5 significant digits
           ndgt = min (ndgt, 16);      # Cap significant digits at 16
@@ -115,8 +115,6 @@
           if (any (! valid))
             ndgt = max (ndgt, 5);     # Allow space for Inf/NaN
           endif
-          ## FIXME: Integers must be masked to show only 16 significant digits
-          ##        See test case for bug #36133 below
           fmt = sprintf ("%%%d.0f", ndgt);
         endif
       else
@@ -190,6 +188,7 @@
 endfunction
 
 
+## Basic tests
 %!assert (num2str (123), "123")
 %!assert (num2str (1.23), "1.23")
 %!assert (num2str (123.456, 4), "123.5")
@@ -197,6 +196,7 @@
 %!assert (num2str (1.234 + 27.3i), "1.234+27.3i")
 %!assert (num2str ([true false true]), "1  0  1")
 
+## Exceptional values
 %!assert (num2str (19440606), "19440606")
 %!assert (num2str (2^33), "8589934592")
 %!assert (num2str (-2^33), "-8589934592")
@@ -222,7 +222,7 @@
 %! x = cat (3, m, -m);
 
 ## real case
-%!test
+%!test <*46770>
 %! y = num2str (x);
 %! assert (rows (y) == 3);
 %! assert (y, ["8  1  6 -8 -1 -6"
@@ -230,7 +230,7 @@
 %!             "4  9  2 -4 -9 -2"]);
 
 ## complex case
-%!test
+%!test <*46770>
 %! x(1,1,2) = -8+2i;
 %! y = num2str (x);
 %! assert (rows (y) == 3);
@@ -241,16 +241,26 @@
 ## Clear shared variables
 %!shared
 
-## FIXME: Integers greater than flintmax() - 1 should be masked to show just
-##        16 digits of precision.
-%!test <36133>
-%! assert (num2str (1e23), "100000000000000000000000");
+## Integers greater than 1e15 should switch to exponential notation
+%!assert <*36133> (num2str (1e15), "1000000000000000")
+%!assert <*36133> (num2str (1e16), "1e+16")
+## Even exact integers in IEEE notation should use exponential notation
+%!assert <*36133> (num2str(2^512), "1.34078079299426e+154")
+## Mixed integer/floating point arrays
+%!assert <*36133> (num2str ([2.1, 1e23, pi]),
+%!                 "2.1  9.999999999999999e+22      3.141592653589793")
+
+## Large integers should not switch sign when printed due to overflow
+%!assert <*36121> (num2str (2.4e9, 15), "2400000000")
 
 ## Test for extra rows generated from newlines in format
 %!assert <*44864> (rows (num2str (magic (3), "%3d %3d %3d\n")), 3)
 
+## Test that string conversion of numeric objects results in characters
+## if the numbers are within range for ASCII.
 %!assert <*45174> (num2str ([65 66 67], "%s"), "ABC")
 
+## Test input validation
 %!error num2str ()
 %!error num2str (1, 2, 3)
 %!error <X must be a numeric> num2str ({1})
--- a/scripts/geometry/delaunayn.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/geometry/delaunayn.m	Fri Aug 10 09:09:51 2018 +0200
@@ -66,23 +66,37 @@
   endif
 
   ## Try to remove the zero volume simplices.  The volume of the i-th simplex is
-  ## given by abs(det(pts(T(i,1:end-1),:)-pts(T(i,2:end),:)))/prod(1:n)
+  ## given by abs(det(pts(T(i,1:end-1),:)-pts(T(i,2:end),:)))/factorial(ndim+1)
   ## (reference http://en.wikipedia.org/wiki/Simplex).  Any simplex with a
   ## relative volume less than some arbitrary criteria is rejected.  The
   ## criteria we use is the volume of the simplex corresponding to an
   ## orthogonal simplex is equal edge length all equal to the edge length of
   ## the original simplex.  If the relative volume is 1e3*eps then the simplex
   ## is rejected.  Note division of the two volumes means that the factor
-  ## prod(1:n) is dropped.
-  idx = [];
-  [nt, n] = size (T);
-  ## FIXME: Vectorize this for loop or convert delaunayn to .oct function
-  for i = 1:nt
-    X = pts(T(i,1:end-1),:) - pts(T(i,2:end),:);
-    if (abs (det (X)) / sqrt (sumsq (X, 2)) < tol)
-      idx(end+1) = i;
-    endif
-  endfor
+  ## factorial(ndim+1) is dropped.
+  [nt, nd] = size (T);
+  if (nd == 3)
+    ## 2-D case
+    np = rows (pts);
+    ptsz = [pts, zeros(np, 1)];
+    p1 = ptsz(T(:,1), :);
+    p2 = ptsz(T(:,2), :);
+    p3 = ptsz(T(:,3), :);
+    p12 = p1 - p2;
+    p23 = p2 - p3;
+    det = cross (p12, p23, 2);
+    idx = abs (det(:,3) ./ sqrt (sumsq (p12, 2))) < tol & ...
+          abs (det(:,3) ./ sqrt (sumsq (p23, 2))) < tol;
+  else
+    ## FIXME: Vectorize this for loop or convert delaunayn to .oct function
+    idx = [];
+    for i = 1:nt
+      X = pts(T(i,1:end-1),:) - pts(T(i,2:end),:);
+      if (abs (det (X)) / sqrt (sumsq (X, 2)) < tol)
+        idx(end+1) = i;
+      endif
+    endfor
+  endif
   T(idx,:) = [];
 
 endfunction
--- a/scripts/gui/uibuttongroup.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/gui/uibuttongroup.m	Fri Aug 10 09:09:51 2018 +0200
@@ -23,7 +23,7 @@
 ##
 ## Create a uibuttongroup object and return a handle to it.
 ##
-## uibuttongroups are used to create group uicontrols.
+## A uibuttongroup is used to group uicontrol objects.
 ##
 ## If @var{parent} is omitted then a uibuttongroup for the current figure is
 ## created.  If no figure is available, a new figure is created first.
@@ -34,29 +34,34 @@
 ## Any provided property value pairs will override the default values of the
 ## created uibuttongroup object.
 ##
-## Uibuttongroup properties are documented at @ref{Uibuttongroup Properties}.
+## Properties of uibuttongroup objects are documented at
+## @ref{Uibuttongroup Properties}.
 ##
 ## Examples:
 ##
 ## @example
 ## @group
-## % create figure and panel on it
+## ## Create figure and panel on it
 ## f = figure;
-## % create a button group
+## ## Create a button group
 ## gp = uibuttongroup (f, "Position", [ 0 0.5 1 1])
-## % create a buttons in the group
+## ## Create a buttons in the group
 ## b1 = uicontrol (gp, "style", "radiobutton", ...
 ##                 "string", "Choice 1", ...
 ##                 "Position", [ 10 150 100 50 ]);
 ## b2 = uicontrol (gp, "style", "radiobutton", ...
 ##                 "string", "Choice 2", ...
 ##                 "Position", [ 10 50 100 30 ]);
-## % create a button not in the group
+## ## Create a button not in the group
 ## b3 = uicontrol (f, "style", "radiobutton", ...
 ##                 "string", "Not in the group", ...
 ##                 "Position", [ 10 50 100 50 ]);
 ## @end group
 ## @end example
+##
+## When called with a single argument @var{h} which is a handle to an existing
+## uibuttongroup object, switch the focus to the specified uibuttongroup.  This
+## functionality is not currently implemented.
 ## @seealso{figure, uipanel}
 ## @end deftypefn
 
@@ -65,7 +70,8 @@
 function hui = uibuttongroup (varargin)
 
   if (nargin == 1 && isgraphics (varargin{1}, "uibuttongroup"))
-    error ("uibuttongroup: focusing not implemented yet");
+    warning ("uibuttongroup: focusing not implemented yet");
+    return;
   endif
 
   [h, args] = __uiobject_split_args__ ("uibuttongroup", varargin,
@@ -74,6 +80,7 @@
 
 endfunction
 
+
 %!demo
 %! f = figure;
 %! gp = uibuttongroup (f, "Position", [ 0 0.5 1 1], ...
--- a/scripts/gui/uicontrol.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/gui/uicontrol.m	Fri Aug 10 09:09:51 2018 +0200
@@ -23,8 +23,8 @@
 ##
 ## Create a uicontrol object and return a handle to it.
 ##
-## uicontrols are used to create simple interactive controls such as push
-## buttons, checkboxes, edit and list controls.
+## A uicontrol object is used to create simple interactive controls such as
+## push buttons, checkboxes, edit and list controls.
 ##
 ## If @var{parent} is omitted then a uicontrol for the current figure is
 ## created.  If no figure is available, a new figure is created first.
@@ -35,11 +35,11 @@
 ## Any provided property value pairs will override the default values of the
 ## created uicontrol object.
 ##
-## Uicontrol properties are documented at @ref{Uicontrol Properties}.
+## Properties of uicontrol objects are documented at
+## @ref{Uicontrol Properties}.
 ##
-## Control of the type of uicontrol created is through the use of the
-## @var{style} property.  If no style property is provided, a push button will
-## be created.
+## The type of uicontrol created is specified by the @var{style} property.  If
+## no style property is provided, a push button will be created.
 ##
 ## Valid styles for uicontrol are:
 ##
@@ -83,16 +83,22 @@
 ##
 ## @example
 ## @group
-## % create figure and panel on it
+## ## Create figure and panel on it
 ## f = figure;
-## % create a button (default style)
-## b1 = uicontrol (f, "string", "A Button", "position",[10 10 150 40]);
-## % create an edit control
-## e1 = uicontrol (f, "style", "edit", "string", "editable text", "position",[10 60 300 40]);
-## % create a checkbox
-## c1 = uicontrol (f, "style", "checkbox", "string", "a checkbox", "position",[10 120 150 40]);
+## ## Create a button (default style)
+## b1 = uicontrol (f, "string", "A Button", "position", [10 10 150 40]);
+## ## Create an edit control
+## e1 = uicontrol (f, "style", "edit", "string", "editable text", ...
+##                    "position", [10 60 300 40]);
+## ## Create a checkbox
+## c1 = uicontrol (f, "style", "checkbox", "string", "a checkbox", ...
+##                    "position", [10 120 150 40]);
 ## @end group
 ## @end example
+##
+## When called with a single argument @var{h} which is a handle to an existing
+## uicontrol object, switch the focus to the specified uicontrol.  This
+## functionality is not currently implemented.
 ## @seealso{figure, uipanel}
 ## @end deftypefn
 
@@ -101,7 +107,8 @@
 function hui = uicontrol (varargin)
 
   if (nargin == 1 && isgraphics (varargin{1}, "uicontrol"))
-    error ("uicontrol: focusing not implemented yet");
+    warning ("uicontrol: focusing not implemented yet");
+    return;
   endif
 
   [h, args] = __uiobject_split_args__ ("uicontrol", varargin,
--- a/scripts/help/__unimplemented__.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/help/__unimplemented__.m	Fri Aug 10 09:09:51 2018 +0200
@@ -1065,7 +1065,6 @@
   "openfig",
   "openFile",
   "opengl",
-  "ordeig",
   "ordqz",
   "outdegree",
   "outerjoin",
--- a/scripts/help/warning_ids.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/help/warning_ids.m	Fri Aug 10 09:09:51 2018 +0200
@@ -212,6 +212,15 @@
 ## The @option{--traditional} or @option{--braindead} startup options for
 ## Octave may also be of use, @pxref{Command Line Options}.
 ##
+## @item Octave:legacy-function
+## If the @code{Octave:legacy-function} warning is enabled, a
+## warning is issued when Octave encounters a function that Matlab has
+## suggested should be avoided.  The function may become obsolete at some
+## point in the future and removed, in which case the warning will change to
+## @code{Octave:deprecated-function}, and the function will continue to exist
+## for two further versions of Octave before being removed.
+## By default, the @code{Octave:legacy-function} warning is enabled.
+##
 ## @item Octave:logical-conversion
 ## By default, the @code{Octave:logical-conversion} warning is enabled.
 ##
--- a/scripts/image/getframe.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/image/getframe.m	Fri Aug 10 09:09:51 2018 +0200
@@ -101,12 +101,7 @@
               || __have_feature__ ("QT_OFFSCREEN"))))
     cdata = __get_frame__ (hf);
   else
-    ## Use OpenGL offscreen rendering with OSMesa for non-visible figures
-    try
-      cdata = __osmesa_print__ (hf);
-    catch
-      error ("getframe: couldn't render invisible figure. %s", lasterr ());
-    end_try_catch
+    error ("getframe: figure must be visible or qt toolkit must be used with __gl_window__ property 'on' or QT_OFFSCREEN feature available");
   endif
 
   i1 = max (floor (pos(1)), 1);
--- a/scripts/io/csvread.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/io/csvread.m	Fri Aug 10 09:09:51 2018 +0200
@@ -32,7 +32,7 @@
 ##
 ## Any optional arguments are passed directly to @code{dlmread}
 ## (@pxref{XREFdlmread,,dlmread}).
-## @seealso{dlmread, textread, textscan, csvwrite, dlmwrite}
+## @seealso{dlmread, textscan, csvwrite, dlmwrite}
 ## @end deftypefn
 
 function x = csvread (filename, varargin)
--- a/scripts/io/fileread.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/io/fileread.m	Fri Aug 10 09:09:51 2018 +0200
@@ -19,7 +19,7 @@
 ## -*- texinfo -*-
 ## @deftypefn {} {@var{str} =} fileread (@var{filename})
 ## Read the contents of @var{filename} and return it as a string.
-## @seealso{fread, textread, sscanf}
+## @seealso{fread, fscanf, importdata, textscan, type}
 ## @end deftypefn
 
 function str = fileread (filename)
--- a/scripts/io/module.mk	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/io/module.mk	Fri Aug 10 09:09:51 2018 +0200
@@ -7,9 +7,7 @@
   %reldir%/dlmwrite.m \
   %reldir%/fileread.m \
   %reldir%/importdata.m \
-  %reldir%/is_valid_file_id.m \
-  %reldir%/strread.m \
-  %reldir%/textread.m
+  %reldir%/is_valid_file_id.m
 
 %canon_reldir%dir = $(fcnfiledir)/io
 
--- a/scripts/io/strread.m	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1122 +0,0 @@
-## Copyright (C) 2009-2018 Eric Chassande-Mottin, CNRS (France)
-## Parts Copyright (C) 2012-2018 Philip Nienhuis
-##
-## This file is part of Octave.
-##
-## Octave is free software: you can redistribute it and/or modify it
-## under the terms of the GNU General Public License as published by
-## the Free Software Foundation, either version 3 of the License, or
-## (at your option) any later version.
-##
-## Octave is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-## GNU General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with Octave; see the file COPYING.  If not, see
-## <https://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn  {} {[@var{a}, @dots{}] =} strread (@var{str})
-## @deftypefnx {} {[@var{a}, @dots{}] =} strread (@var{str}, @var{format})
-## @deftypefnx {} {[@var{a}, @dots{}] =} strread (@var{str}, @var{format}, @var{format_repeat})
-## @deftypefnx {} {[@var{a}, @dots{}] =} strread (@var{str}, @var{format}, @var{prop1}, @var{value1}, @dots{})
-## @deftypefnx {} {[@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.
-##
-## The string @var{format} describes how the words in @var{str} should be
-## parsed.  It may contain any combination of the following specifiers:
-##
-## @table @code
-## @item %s
-## The word is parsed as a string.
-##
-## @item  %f
-## @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  %*
-## @itemx %*f
-## @itemx %*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}.  This will do if @var{str} contains only numeric fields.
-##
-## For example, the string
-##
-## @example
-## @group
-## @var{str} = "\
-## Bunny Bugs   5.5\n\
-## Duck Daffy  -7.5e-5\n\
-## Penguin Tux   6"
-## @end group
-## @end example
-##
-## @noindent
-## can be read using
-##
-## @example
-## [@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:
-##
-## @table @asis
-## @item @qcode{"commentstyle"}
-## Parts of @var{str} are considered comments and will be skipped.
-## @var{value} is the comment style and can be any of the following.
-##
-## @itemize
-## @item @qcode{"shell"}
-## Everything from @code{#} characters to the nearest end-of-line is skipped.
-##
-## @item @qcode{"c"}
-## Everything between @code{/*} and @code{*/} is skipped.
-##
-## @item @qcode{"c++"}
-## Everything from @code{//} characters to the nearest end-of-line is skipped.
-##
-## @item @qcode{"matlab"}
-## 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 @qcode{"delimiter"}
-## Any character in @var{value} will be used to split @var{str} into words
-## (default value = any whitespace).  Note that whitespace is implicitly added
-## to the set of delimiter characters unless a @qcode{"%s"} format conversion
-## specifier is supplied; see @qcode{"whitespace"} parameter below.  The set
-## of delimiter characters cannot be empty; if needed Octave substitutes a
-## space as delimiter.
-##
-## @item @qcode{"emptyvalue"}
-## Value to return for empty numeric values in non-whitespace delimited data.
-## The default is NaN@.  When the data type does not support NaN (int32 for
-## example), then default is zero.
-##
-## @item @qcode{"multipledelimsasone"}
-## Treat a series of consecutive delimiters, without whitespace in between,
-## as a single delimiter.  Consecutive delimiter series need not be vertically
-## @qcode{"aligned"}.
-##
-## @item @qcode{"treatasempty"}
-## Treat single occurrences (surrounded by delimiters or whitespace) of the
-## string(s) in @var{value} as missing values.
-##
-## @item @qcode{"returnonerror"}
-## If @var{value} true (1, default), ignore read errors and return normally.
-## If false (0), return an error.
-##
-## @item @qcode{"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 @qcode{"@xbackslashchar{}t"}.  In
-## each data field, multiple consecutive whitespace characters are collapsed
-## into one space and leading and trailing whitespace is removed.  The default
-## value for whitespace is
-## @c Note: the next line specifically has a newline which generates a space
-## @c       in the output of qcode, but keeps the next line < 80 characters.
-## @qcode{"
-## @xbackslashchar{}b@xbackslashchar{}r@xbackslashchar{}n@xbackslashchar{}t"}
-## (note the space).  Whitespace is always added to the set of delimiter
-## characters unless at least one @qcode{"%s"} format conversion specifier is
-## supplied; in that case only whitespace explicitly specified in
-## @qcode{"delimiter"} is retained as delimiter and removed from the set of
-## whitespace characters.  If whitespace characters are to be kept as-is (in
-## e.g., strings), specify an empty value (i.e., @qcode{""}) for
-## @qcode{"whitespace"}; obviously, whitespace cannot be a delimiter then.
-##
-## @end table
-##
-## When the number of words in @var{str} doesn't match an exact multiple of
-## the number of format conversion specifiers, strread's behavior depends on
-## the last character of @var{str}:
-##
-## @table @asis
-## @item last character = @qcode{"@xbackslashchar{}n"}
-## Data columns are padded with empty fields or NaN so that all columns have
-## equal length
-##
-## @item last character is not @qcode{"@xbackslashchar{}n"}
-## Data columns are not padded; strread returns columns of unequal length
-##
-## @end table
-##
-## @seealso{textscan, textread, load, dlmread, fscanf}
-## @end deftypefn
-
-function varargout = strread (str, format = "%f", varargin)
-
-  ## Check input
-  if (nargin < 1)
-    print_usage ();
-  endif
-
-  if (isempty (str))
-    ## Return empty args (no match), rather than raising an error
-    varargout = cell (1, nargout);
-    return;
-  endif
-
-  if (isempty (format))
-    format = "%f";
-  endif
-
-  if (! ischar (str) || ! ischar (format))
-    error ("strread: STR and FORMAT arguments must be strings");
-  endif
-
-  if (strcmp (typeinfo (format), "sq_string"))
-    format = do_string_escapes (format);
-  endif
-
-  ## Parse format string to compare number of conversion fields and nargout
-  nfields = numel (regexp (format, '(%(\d*|\d*\.\d*)?[nfduscq]|%\[)', "match"));
-  ## If str only has numeric fields, a (default) format ("%f") will do.
-  ## Otherwise:
-  if (! nfields)
-    error ("strread.m: no valid format conversion specifiers found\n");
-  elseif ((max (nargout, 1) != nfields) && ! strcmp (format, "%f"))
-    error ("strread: the number of output variables must match that specified by FORMAT");
-  endif
-
-  ## 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;
-  open_comment = false;
-  cmt_eol = "\n";
-  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}))
-      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}))
-          case "c"
-            [comment_start, comment_end] = deal ("/*", "*/");
-          case "c++"
-            [comment_start, comment_end] = deal ("//", "cmt_eol");
-            open_comment = true;
-          case "shell"
-            [comment_start, comment_end] = deal ("#" , "cmt_eol");
-            open_comment = true;
-          case "matlab"
-            [comment_start, comment_end] = deal ("%" , "cmt_eol");
-            open_comment = true;
-          otherwise
-            if (ischar (varargin{n+1})
-                || (numel (varargin{n+1}) == 1 && iscellstr (varargin{n+1})))
-              [comment_start, comment_end] = deal (char (varargin{n+1}), "cmt_eol");
-            open_comment = true;
-            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};
-        if (strcmp (typeinfo (delimiter_str), "sq_string"))
-          delimiter_str = do_string_escapes (delimiter_str);
-        endif
-      case "emptyvalue"
-        numeric_fill_value = varargin{n+1};
-      case "expchars"
-        warning ("strread: property 'expchars' is not implemented");
-      case "whitespace"
-        white_spaces = varargin{n+1};
-        if (strcmp (typeinfo (white_spaces), "sq_string"))
-          white_spaces = do_string_escapes (white_spaces);
-        endif
-      ## The following parameters are specific to textscan and textread
-      case "endofline"
-        eol_char = varargin{n+1};
-        if (strcmp (typeinfo (eol_char), "sq_string"))
-          eol_char = do_string_escapes (eol_char);
-        endif
-        cmt_eol = eol_char;
-        open_comment = false;
-      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});
-    endswitch
-  endfor
-
-  ## First parse of FORMAT
-  if (strcmpi (strtrim (format), "%f"))
-    ## Default format specified.  Expand it (to desired nargout)
-    fmt_words = cell (max (nargout, 1), 1);
-    fmt_words (1:max (nargout, 1)) = 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");
-
-    ## Find position of conversion specifiers (they start with %)
-    fcs_ptrn = '(%\*?(\d*|\d*\.\d*)?[nfduscq]|%\*?\[)';
-    idy2 = find (! cellfun ("isempty", regexp (fmt_words, fcs_ptrn)));
-
-    ## Check for unsupported format specifiers
-    errpat = '(\[.*\]|[cq]|[nfdu]8|[nfdu]16|[nfdu]32|[nfdu]64)';
-    if (! all (cellfun ("isempty", regexp (fmt_words(idy2), errpat))))
-      error ("strread: %q, %c, %[] or bit width format specifiers are not supported yet.");
-    endif
-
-    ## Format conversion specifiers following literals w/o space/delim
-    ## in between are separate now.  Separate those w trailing literals
-    a = strfind (fmt_words(idy2), "%");
-    b = regexp (fmt_words(idy2), '[nfdus]', "end");
-    for jj = 1:numel (a)
-      ## From right to left to avoid losing track
-      ii = numel (a) - jj + 1;
-      ## Check for illegal format specifiers
-      if (isempty (b{ii}))
-        error ("strread: unknown format specifier #%d ('%s')\n",
-              ii, fmt_words{idy2(ii)});
-      endif
-      if (! (length (fmt_words{idy2(ii)}) == b{ii}(1)))
-        ## Split fmt_words(ii) into % conv specifier and trailing literal
-        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
-
-  ## Remove comments in str
-  if (comment_flag)
-    ## Expand 'cmt_eol' here, after option processing which may have set value
-    comment_end = strrep (comment_end, "cmt_eol", cmt_eol);
-    cstart = strfind (str, comment_start);
-    cstop  = strfind (str, comment_end);
-    if (open_comment)
-      cstop -= 1;
-    endif
-    ## 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))
-        cidx(end) = []; # Drop the last one if orphaned.
-      endif
-      cstart = cstart(cidx);
-    endif
-    if (! isempty (cstop))
-      ## Ignore nested closers.
-      [idx, cidx] = unique (lookup (cstart, cstop), "first");
-      if (idx(1) == 0)
-        cidx(1) = []; # Drop the first one if orphaned.
-      endif
-      cstop = cstop(cidx);
-    endif
-    len = length (str);
-    c2len = length (comment_end);
-    if (cstop + c2len == len)
-      ## Ignore last char of to-the-end-of-line comments
-      c2len += 1;
-    endif
-    str = cellslices (str, [1, cstop + c2len], [cstart - 1, len]);
-    str = [str{:}];
-  endif
-
-  if (! isempty (white_spaces))
-    ## For numeric fields, whitespace is always a delimiter, but not for text
-    ## fields
-    if (isempty (regexp (format, '%\*?\d*s')))
-      ## Add whitespace to delimiter set
-      delimiter_str = unique ([white_spaces delimiter_str]);
-    else
-      ## Remove any delimiter chars from white_spaces list
-      white_spaces = setdiff (white_spaces, delimiter_str);
-    endif
-  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
-
-  ii = numel (fmt_words);
-  while (ii > 0)
-    if (ismember (fmt_words{ii}, delimiter_str)(1))
-      fmt_words(ii) = [];
-      --num_words_per_line;
-    endif
-    --ii;
-  endwhile
-
-  pad_out = 0;
-  ## Trim whitespace if needed
-  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) == "\n" && nargout > 1)
-      pad_out = 1;
-    endif
-    ## Condense all repeated whitespace into one single space
-    ## FIXME: this will also fold repeated whitespace in a char field
-    rxp_wsp = sprintf ("[%s]+", white_spaces);
-    str = regexprep (str, rxp_wsp, ' ');
-    ## Remove possible leading space at string
-    if (str(1) == " ")
-       str = str(2:end);
-    endif
-    ## Check for single delimiter followed/preceded by whitespace
-    if (! isempty (delimiter_str))
-      dlmstr = setdiff (delimiter_str, " ");
-      if (! isempty (dlmstr))
-        rxp_dlmwsp = sprintf ('( [%s] | [%s]|[%s] )', dlmstr, dlmstr, dlmstr);
-        str = regexprep (str, rxp_dlmwsp, delimiter_str(1));
-      endif
-    endif
-    ## Wipe leading and trailing whitespace on each line (it may be
-    ## delimiter too)
-    ## FIXME: Double strrep on str is enormously expensive in CPU time.
-    ## Can this be eliminated?
-    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, mult_dlms_s1, eol_char);
-  if (! isempty (white_spaces))
-    ## Trim leading and trailing 'white_spaces'.
-    ## All whitespace has been converted to space above
-    words = strtrim (words);
-  endif
-  num_words = numel (words);
-  ## First guess at nr. of lines in file (ignoring leading/trailing literals)
-  num_lines = ceil (num_words / num_words_per_line);
-
-  ## Replace TreatAsEmpty char sequences by empty strings
-  if (! isempty (empty_str))
-    for ii = 1:numel (empty_str)
-      idz = strncmp (empty_str{ii}, words, length (empty_str{ii}));
-      words(idz) = {""};
-    endfor
-  endif
-
-  ## fmt_words has been split properly now, but words{} has only been split on
-  ## delimiter positions.  As numeric fields can also be separated by
-  ## whitespace, more splits may be needed.
-  ## We also don't know the number of lines (as EndOfLine may have been set to
-  ## "" (empty) by the caller).
-  ##
-  ## We also may have to cope with 3 cases as far as literals go:
-  ## 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 )
-  ## Some words columns may have to be split further to fix these.
-  ## To find out, we'll match fmt_words to the words array to see what
-  ## needs to be done.  fwptr tracks which {fmt_words} starts in what {words}
-
-  ## 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);
-  ## Find indices to numeric conversion specifiers
-  idn = ! cellfun ("isempty", regexp (fmt_words, '%[dnfu]'));
-
-  ## 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
-      ## matching fmt_words to words until the fmt_words array is exhausted.
-      ## iwrd: ptr to current analyzed word.
-      ## iwrdp: ptr to pos before analyzed char.
-      iwrd = 1; iwrdp = 0; iwrdl = length (words{1});
-      fwptr = zeros (1, numel (fmt_words));
-      ii = 1;
-      while (ii <= numel (fmt_words))
-
-        nxt_wrd = 0;
-        ## Keep track of which words nr. every fmt_words{} is (starts) in.
-        fwptr(ii) = iwrd;
-
-        if (idf(ii))
-          ## Literal expected
-          if (isempty (strfind (fmt_words{ii}, words(iwrd))))
-            ## Not found in current word; supposed to be in next word
-            nxt_wrd = 1;
-          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)
-              warning ("strread: literal '%s' (fmt spec # %d) does not match data", ...
-                fmt_words{ii}, ii);
-              ## Word assumed to be completely "used up".  Next word
-              nxt_wrd = 1;
-            elseif (iwrdp == iwrdl)
-              ## Word completely "used up".  Next word
-              nxt_wrd = 1;
-            endif
-          endif
-
-        elseif (idg(ii))
-          ## Fixed width specifier (%N or %*N): read just a part of word
-          sw = regexp (fmt_words{ii}, '\d', "once");
-          ew = regexp (fmt_words{ii}, '[nfuds]') - 1;
-          iwrdp += floor (str2double (fmt_words{ii}(sw:ew)));
-          if (iwrdp > iwrdl)
-            ## Match error.  Field extends beyond word boundary.
-            warning  ...
-            ("strread: field width '%s' (fmt spec # %d) extends beyond actual word limit", ...
-               fmt_words{ii}, ii);
-            ## Assume word to be completely "used up".  Next word
-            nxt_wrd = 1;
-          elseif (iwrdp == iwrdl)
-            ## Word completely "used up".  Next word
-            nxt_wrd = 1;
-          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
-              nxt_wrd = 1;
-            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
-            nxt_wrd = 1;
-          endif
-
-        endif
-
-        if (nxt_wrd)
-          ++iwrd; iwrdp = 0;
-          if (iwrd > numel (words))
-            ## Apparently EOF; assume incomplete row already at L.1 of data
-            ii = numel (fmt_words);
-          elseif (ii < numel (fmt_words) && iwrd <= numel (words))
-            iwrdl = length (words{iwrd});
-          endif
-        endif
-
-        ++ii;
-
-      endwhile
-      ## Done
-      words_period = max (iwrd - 1, 1);
-      num_lines = ceil (num_words / words_period);
-
-      ## 2. Pad words array so that it can be reshaped
-      num_words_padded = num_lines * words_period - num_words;
-      if (num_words_padded)
-        words = [words'; cell(num_words_padded, 1)];
-      endif
-      words = reshape (words, words_period, num_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};
-              fwptr = [fwptr(1:ii) (++fwptr(ii+1:end))];
-
-            else
-              if (idg(ii))
-                ## Current field = fixed width.
-                ## Strip into icol, rest in icol+1
-                sw = regexp (fmt_words{ii}, '\d', "once");
-                ew = regexp (fmt_words{ii}, '[nfuds]') - 1;
-                wdth = floor (str2double (fmt_words{ii}(sw:ew)));
-                words(icol+1, jptr) = cellfun (@(x) x(wdth+1:end),
-                     words(icol,jptr), "UniformOutput", false);
-                if (isempty ([words(icol+1, :){:}]))
-                  ## Apparently split wasn't needed as turns out to cover
-                  ## entire column. So delete column again
-                  words(icol+1, :) = [];
-                else
-                  words(icol, jptr) = strtrunc (words(icol, jptr), wdth);
-                  fwptr = [fwptr(1:ii) (++fwptr(ii+1:end))];
-                endif
-              else
-                if (! isempty (strfind (fmt_words{ii-1}, "%s")))
-                  ## Trailing literal.
-                  ## Could be ambiguous if preceding format == '%s'
-                  warning ("strread.m:\n  Ambiguous '%%s' specifier immediately before literal in column %d", icol);
-                endif
-                ## 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 = ostrsplit ([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) = ostrsplit (strrep ([wrds{2:end}], ...
-                   char (254), fmt_words{ii}), char (255));
-                ## Former trailing literal may now be leading for next specifier
-                --ii;
-                fwptr = [fwptr(1:ii) (++fwptr(ii+1:end))];
-              endif
-            endif
-          endif
-
-        else
-          ## Conversion specifier.
-          ## Peek if next fmt_word needs split from current column.
-          if (ii < num_words_per_line)
-            if (fwptr(ii) == fwptr(ii+1))
-              --icol;
-            endif
-          endif
-        endif
-        ## Next fmt_word, next column
-        ++ii; ++icol;
-      endwhile
-
-      ## Done.
-      ## Reshape words back into one 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
-    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);
-        if (num_lines > format_repeat_count)
-          num_lines = format_repeat_count;
-        endif
-      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 += 1;
-        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);
-          endif
-          data(n) = numeric_fill_value;
-          if (pad_out)
-            data(end+1:num_lines) = numeric_fill_value;
-          endif
-          varargout{k} = data.';
-          k += 1;
-        case {"%0", "%1", "%2", "%3", "%4", "%5", "%6", "%7", "%8", "%9"}
-          sw = regexp (fmt_words{m}, '\d', "once");
-          ew = regexp (fmt_words{m}, '[nfudsq]') - 1;
-          nfmt = ostrsplit (fmt_words{m}(2:ew), ".");
-          swidth = str2double (nfmt{1});
-          switch (fmt_words{m}(ew+1))
-            case {"d", "u", "f", "n"}
-              n = cellfun ("isempty", data);
-              ### FIXME: Erroneously formatted data lead to NaN, not an error
-              ###        => ReturnOnError can't be implemented for numeric data
-              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);
-              endif
-              varargout{k} = data.';
-              k += 1;
-            case "s"
-              if (pad_out)
-                data(end+1:num_lines) = {""};
-              endif
-              varargout{k} = strtrunc (data, swidth)';
-              k += 1;
-            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, 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 text
-    ## to avoid it being included in consecutive delim series
-    enchr = ' ';
-    ## However watch out if eol_char is also in delimiters
-    if (index (sep, eol_char)); enchr = char (255); endif
-    text = strrep (text, eol_char, [enchr eol_char enchr]);
-  else
-    mult_dlms_s1 = false;
-  endif
-
-  ## Split text string along delimiters
-  out = ostrsplit (text, sep, mult_dlms_s1);
-  if (index (sep, eol_char)); out = strrep (out, char (255), ''); endif
-  ## In case of trailing delimiter, strip stray last empty word
-  if (! isempty (out) && any (sep == text(end)) && ! mult_dlms_s1)
-    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);
-%! assert (b, 2);
-
-%!test
-%! str = "";
-%! a = 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));
-%! endfor
-%! [aa, bb] = strread (str, "%f %s");
-%! assert (aa, a, 1e-6);
-%! assert (bb, cellstr (b));
-
-%!test
-%! str = "";
-%! a = 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));
-%! endfor
-%! aa = strread (str, "%f %*s");
-%! assert (aa, a, 1e-6);
-
-%!test
-%! str = sprintf ("/* this is\nacomment*/ 1 2 3");
-%! a = strread (str, "%f", "commentstyle", "c");
-%! 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
-%! assert (strread ("Hello World! // this is comment", "%s",
-%!                  "commentstyle", "c++"),
-%!         {"Hello"; "World!"});
-%! assert (strread ("Hello World! % this is comment", "%s",...
-%!                  "commentstyle", "matlab"), ...
-%!         {"Hello"; "World!"});
-%! assert (strread ("Hello World! # this is comment", "%s",...
-%!                  "commentstyle", "shell"), ...
-%!         {"Hello"; "World!"});
-
-%!test <*49454>
-%! assert (strread ("hello%foo\nworld, another%bar\r\nday", "%s", ...
-%!                  "commentstyle", "matlab", "delimiter", " ,"),...
-%!         {"hello"; "world"; "another"; "day"});
-
-%!test
-%! str = sprintf ("Tom 100 miles/hr\nDick 90 miles/hr\nHarry 80 miles/hr");
-%! fmt = "%s %f miles/hr";
-%! c = cell (1, 2);
-%! [c{:}] = strread (str, fmt);
-%! assert (c{1}, {"Tom"; "Dick"; "Harry"});
-%! assert (c{2}, [100; 90; 80]);
-
-%!test
-%! a = strread ("a b c, d e, , f", "%s", "delimiter", ",");
-%! assert (a, {"a b c"; "d e"; ""; "f"});
-
-%! ## Format repeat counters w & w/o trailing EOL even within partly read files
-%!test
-%! [a, b] = strread ("10 a 20 b\n 30 c 40", "%d %s", 4);
-%! assert (a, int32 ([10; 20; 30; 40]));
-%! assert (b, {"a"; "b"; "c"});
-%! [a, b] = strread ("10 a 20 b\n 30 c 40\n", "%d %s", 4);
-%! assert (a, int32 ([10; 20; 30; 40]));
-%! assert (b, {"a"; "b"; "c"; ""});
-%! [a, b] = strread ("10 a 20 b\n 30 c 40", "%d %s", 1);
-%! assert (a, int32 (10));
-%! assert (b, {"a"});
-
-%!test <*33536>
-%! [a, b, c] = strread ("1,,2", "%s%s%s", "delimiter", ",");
-%! assert (a{1}, "1");
-%! assert (b{1}, "");
-%! assert (c{1}, "2");
-
-%!test <*33536>
-%!test
-%! 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]));
-
-## Default format (= %f)
-%!test
-%! [a, b, c] = strread ("0.12 0.234 0.3567");
-%! assert (a, 0.12);
-%! assert (b, 0.234);
-%! assert (c, 0.3567);
-
-%!test
-%! [a, b] = strread ("0.41 8.24 3.57 6.24 9.27", "%f%f", 2, "delimiter", " ");
-%! assert (a, [0.41; 3.57]);
-
-## TreatAsEmpty
-%!test
-%! [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]);
-
-## No delimiters at all besides EOL.  Plain reading numbers & strings
-%!test
-%! str = "Text1Text2Text\nText398Text4Text\nText57Text";
-%! [a, b] = strread (str, "Text%dText%1sText");
-%! assert (a, int32 ([1; 398; 57]));
-%! assert (b(1:2), {"2"; "4"});
-%! assert (isempty (b{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]);
-
-%!assert <*44750> (strread ('/home/foo/','%s','delimiter','/','MultipleDelimsAsOne',1),
-%!                {"home"; "foo"})
-
-## delimiter as sq_string and dq_string
-%!assert (strread ("1\n2\n3", "%d", "delimiter", "\n"),
-%!        strread ("1\n2\n3", "%d", "delimiter", '\n'))
-
-## whitespace as sq_string and dq_string
-%!assert (strread ("1\b2\r3\b4\t5", "%d", "whitespace", "\b\r\n\t"),
-%!        strread ("1\b2\r3\b4\t5", "%d", "whitespace", '\b\r\n\t'))
-
-%!test
-%! str =  "0.31 0.86 0.94\n 0.60 0.72 0.87";
-%! fmt = "%f %f %f";
-%! args = {"delimiter", " ", "endofline", "\n", "whitespace", " "};
-%! [a, b, c] = strread (str, fmt, args{:});
-%! assert (a, [0.31; 0.60], 0.01);
-%! assert (b, [0.86; 0.72], 0.01);
-%! assert (c, [0.94; 0.87], 0.01);
-
-%!test
-%! str =  "0.31,0.86,0.94\n0.60,0.72,0.87";
-%! fmt = "%f %f %f";
-%! args = {"delimiter", ",", "endofline", "\n", "whitespace", " "};
-%! [a, b, c] = strread (str, fmt, args{:});
-%! assert (a, [0.31; 0.60], 0.01);
-%! assert (b, [0.86; 0.72], 0.01);
-%! assert (c, [0.94; 0.87], 0.01);
-
-%!test
-%! str =  "0.31 0.86 0.94\n 0.60 0.72 0.87";
-%! fmt = "%f %f %f";
-%! args = {"delimiter", ",", "endofline", "\n", "whitespace", " "};
-%! [a, b, c] = strread (str, fmt, args{:});
-%! assert (a, [0.31; 0.60], 0.01);
-%! assert (b, [0.86; 0.72], 0.01);
-%! assert (c, [0.94; 0.87], 0.01);
-
-%!test
-%! str =  "0.31, 0.86, 0.94\n 0.60, 0.72, 0.87";
-%! fmt = "%f %f %f";
-%! args = {"delimiter", ",", "endofline", "\n", "whitespace", " "};
-%! [a, b, c] = strread (str, fmt, args{:});
-%! assert (a, [0.31; 0.60], 0.01);
-%! assert (b, [0.86; 0.72], 0.01);
-%! assert (c, [0.94; 0.87], 0.01);
-
-%!test
-%! [a, b] = strread (["Empty 1" char(10)], "Empty%s %f");
-%! assert (a{1}, '1');
-%! assert (b, NaN);
-
-%!test
-%! [a, b] = strread (["Empty" char(10)], "Empty%f %f");
-%! assert (a, NaN);
-%! assert (b, NaN);
-
-%!test <*35999>
-%! [a, b, c] = strread ("", "%f");
-%! assert (isempty (a));
-%! assert (isempty (b));
-%! assert (isempty (c));
-
-%!test <*37023>
-%! [a, b] = strread (" 1. 1 \n  2 3 \n", "%f %f", "endofline", "\n");
-%! assert (a, [1; 2], 1e-15);
-%! assert (b, [1; 3], 1e-15);
-
-## Test for no output arg (interactive use)
-%!assert (strread (",2,,4\n5,,7,", "", "delimiter", ","),
-%!        [NaN; 2; NaN; 4; 5; NaN; 7])
-
-## Test #1 bug #42609
-%!test <*42609>
-%! [a, b, c] = strread ("1 2 3\n4 5 6\n7 8 9\n", "%f %f %f\n");
-%! assert (a, [1; 4; 7]);
-%! assert (b, [2; 5; 8]);
-%! assert (c, [3; 6; 9]);
-
-## Test #2 bug #42609
-%!test <*42609>
-%! [a, b, c] = strread ("1 2\n3\n4 5\n6\n7 8\n9\n", "%f %f\n%f");
-%! assert (a, [1;4;7]);
-%! assert (b, [2; 5; 8]);
-%! assert (c, [3; 6; 9]);
-
-## Test #3 bug #42609
-%!test <*42609>
-%! [a, b, c] = strread ("1 2 3\n4 5 6\n7 8 9\n", '%f %f %f\n');
-%! assert (a, [1; 4; 7]);
-%! assert (b, [2; 5; 8]);
-%! assert (c, [3; 6; 9]);
-
-## Test #4 bug #42609
-%!test <*42609>
-%! [a, b, c] = strread ("1 2\n3\n4 5\n6\n7 8\n9\n", '%f %f\n%f');
-%! assert (a, [1;4;7]);
-%! assert (b, [2; 5; 8]);
-%! assert (c, [3; 6; 9]);
-
-## Unsupported format specifiers
-%!error <format specifiers are not supported> strread ("a", "%c")
-%!error <format specifiers are not supported> strread ("a", "%*c %d")
-%!error <format specifiers are not supported> strread ("a", "%q")
-%!error <format specifiers are not supported> strread ("a", "%*q %d")
-%!error <format specifiers are not supported> strread ("a", "%[a]")
-%!error <format specifiers are not supported> strread ("a", "%*[a] %d")
-%!error <format specifiers are not supported> strread ("a", "%[^a]")
-%!error <format specifiers are not supported> strread ("a", "%*[^a] %d")
-%!error <format specifiers are not supported> strread ("a", "%d8")
-%!error <format specifiers are not supported> strread ("a", "%*d8 %s")
-%!error <format specifiers are not supported> strread ("a", "%f64")
-%!error <format specifiers are not supported> strread ("a", "%*f64 %s")
-%!error <format specifiers are not supported> strread ("a", "%u32")
-%!error <format specifiers are not supported> strread ("a", "%*u32 %d")
-
-## Illegal format specifiers
-%!error <no valid format conversion specifiers> strread ("1.0", "%z")
-
-## Test for false positives in check for non-supported format specifiers
-%!assert (strread ("Total: 32.5 % (of cm values)","Total: %f % (of cm values)"), 32.5, 1e-5)
-
-## Test various forms of string format specifiers
-%!test <*45712>
-%! str = "14 :1 z:2 z:3 z:5 z:11";
-%! [a, b, c, d] = strread (str, "%f %s %*s %3s %*3s %f", "delimiter", ":");
-%! assert ({a, b, c, d}, {14, {"1 z"}, {"3 z"}, 11});
-
-## Allow cuddling %sliteral but warn that it is ambiguous
-%!warning <Ambiguous '%s' specifier immediately before literal in column 1>
-%! [a, b] = strread ("abcxyz51\nxyz83\n##xyz101", "%s xyz %d");
-%! assert (a([1 3]), {"abc"; "##"});
-%! assert (isempty (a{2}), true);
-%! assert (b, int32([51; 83; 101]));
--- a/scripts/io/textread.m	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,509 +0,0 @@
-## Copyright (C) 2009-2018 Eric Chassande-Mottin, CNRS (France)
-##
-## 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
-## <https://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn  {} {[@var{a}, @dots{}] =} textread (@var{filename})
-## @deftypefnx {} {[@var{a}, @dots{}] =} textread (@var{filename}, @var{format})
-## @deftypefnx {} {[@var{a}, @dots{}] =} textread (@var{filename}, @var{format}, @var{n})
-## @deftypefnx {} {[@var{a}, @dots{}] =} textread (@var{filename}, @var{format}, @var{prop1}, @var{value1}, @dots{})
-## @deftypefnx {} {[@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.
-##
-## In addition to the options supported by @code{strread}, this function
-## supports two more:
-##
-## @itemize
-## @item @qcode{"headerlines"}:
-## The first @var{value} number of lines of @var{filename} are skipped.
-##
-## @item @qcode{"endofline"}:
-## Specify a single character or
-## @qcode{"@xbackslashchar{}r@xbackslashchar{}n"}.  If no value is given, it
-## will be inferred from the file.  If set to @qcode{""} (empty string) EOLs
-## are ignored as delimiters.
-## @end itemize
-##
-## The optional input @var{n} (format repeat count) specifies the number of
-## times the format string is to be used or the number of lines to be read,
-## whichever happens first while reading.  The former is equivalent to
-## requesting that the data output vectors should be of length @var{N}.
-## Note that when reading files with format strings referring to multiple
-## lines, @var{n} should rather be the number of lines to be read than the
-## number of format string uses.
-##
-## If the format string is empty (not just omitted) and the file contains only
-## numeric data (excluding headerlines), textread will return a rectangular
-## matrix with the number of columns matching the number of numeric fields on
-## the first data line of the file.  Empty fields are returned as zero values.
-##
-## Examples:
-##
-## @example
-## @group
-##   Assume a data file like:
-##   1 a 2 b
-##   3 c 4 d
-##   5 e
-## @end group
-## @end example
-##
-## @example
-## @group
-##   [a, b] = textread (f, "%f %s")
-##   returns two columns of data, one with doubles, the other a
-##   cellstr array:
-##   a = [1; 2; 3; 4; 5]
-##   b = @{"a"; "b"; "c"; "d"; "e"@}
-## @end group
-## @end example
-##
-## @example
-## @group
-##   [a, b] = textread (f, "%f %s", 3)
-##   (read data into two culumns, try to use the format string
-##   three times)
-##   returns
-##   a = [1; 2; 3]
-##   b = @{"a"; "b"; "c"@}
-##
-## @end group
-## @end example
-##
-## @example
-## @group
-##   With a data file like:
-##   1
-##   a
-##   2
-##   b
-##
-##   [a, b] = textread (f, "%f %s", 2)
-##   returns a = 1 and b = @{"a"@}; i.e., the format string is used
-##   only once because the format string refers to 2 lines of the
-##   data file.  To obtain 2x1 data output columns, specify N = 4
-##   (number of data lines containing all requested data) rather
-##   than 2.
-## @end group
-## @end example
-##
-## @seealso{strread, load, dlmread, fscanf, textscan}
-## @end deftypefn
-
-function varargout = textread (filename, format = "%f", varargin)
-
-  BUFLENGTH = 4096;       # Read buffer to speed up processing @var{n}
-
-  ## Check input
-  if (nargin < 1)
-    print_usage ();
-  endif
-
-  if (! ischar (filename) || ! ischar (format))
-    error ("textread: FILENAME and FORMAT arguments must be strings");
-  endif
-
-  if (! isempty (varargin) && isnumeric (varargin{1}))
-    nlines = varargin{1};
-  else
-    nlines = Inf;
-  endif
-  if (nlines < 1)
-    printf ("textread: N = 0, no data read\n");
-    varargout = cell (1, nargout);
-    return;
-  endif
-
-  ## Read file
-  fid = fopen (filename, "r");
-  if (fid == -1)
-    error ("textread: could not open '%s' for reading", filename);
-  endif
-
-  ## Skip header lines if requested
-  headerlines = find (strcmpi (varargin, "headerlines"), 1);
-  if (! isempty (headerlines))
-    ## Beware of missing or wrong headerline value
-    if (headerlines == numel (varargin)
-       || ! isnumeric (varargin{headerlines + 1}))
-      error ("textread: missing or invalid value for 'headerlines'" );
-    endif
-    ## Avoid conveying floats to fskipl
-    varargin{headerlines + 1} = round (varargin{headerlines + 1});
-    ## Beware of zero valued headerline, fskipl would skip to EOF
-    if (varargin{headerlines + 1} > 0)
-      fskipl (fid, varargin{headerlines + 1});
-    elseif (varargin{headerlines + 1} < 0)
-      warning ("textread: negative headerline value ignored");
-    endif
-    varargin(headerlines:headerlines+1) = [];
-  endif
-  st_pos = ftell (fid);
-
-  ## Read a first file chunk.  Rest follows after endofline processing
-  [str, count] = fscanf (fid, "%c", BUFLENGTH);
-  if (isempty (str) || count < 1)
-    warning ("textread: empty file");
-    varargout = cell (1, nargout);
-    return;
-  endif
-
-  endofline = find (strcmpi (varargin, "endofline"), 1);
-  if (! isempty (endofline))
-    ## 'endofline' option set by user.
-    if (ischar (varargin{endofline + 1}))
-      eol_char = varargin{endofline + 1};
-      if (strcmp (typeinfo (eol_char), "sq_string"))
-        eol_char = do_string_escapes (eol_char);
-      endif
-      if (! any (strcmp (eol_char, {"", "\n", "\r", "\r\n"})))
-        error ("textread: invalid EndOfLine character value specified");
-      endif
-    else
-      error ("textread: character value required for EndOfLine");
-    endif
-  else
-    ## Determine EOL from file.
-    ## Search for EOL candidates in the first BUFLENGTH chars
-    ## FIXME: Ignore risk of 2-byte EOL (\r\n) being split at exactly BUFLENGTH
-    eol_srch_len = min (length (str), BUFLENGTH);
-    ## First try DOS (CRLF)
-    if (! isempty (strfind (str(1 : eol_srch_len), "\r\n")))
-      eol_char = "\r\n";
-    ## Perhaps old Macintosh? (CR)
-    elseif (! isempty (strfind (str(1 : eol_srch_len), "\r")))
-      eol_char = "\r";
-    ## Otherwise, use plain *nix (LF)
-    else
-      eol_char = "\n";
-    endif
-    ## Set up default endofline param value
-    varargin(end+1:end+2) = {"endofline", eol_char};
-  endif
-
-  ## Now that we know what EOL looks like, we can process format_repeat_count.
-  ## FIXME: The below isn't ML-compatible: counts lines, not format string uses
-  if (isfinite (nlines) && (nlines > 0))
-    l_eol_char = length (eol_char);
-    eoi = findstr (str, eol_char);
-    n_eoi = length (eoi);
-    nblks = 0;
-    ## Avoid slow repeated str concatenation, first seek requested end of data
-    while (n_eoi < nlines && count == BUFLENGTH)
-      [nstr, count] = fscanf (fid, "%c", BUFLENGTH);
-      if (count > 0)
-        ## Watch out for multichar EOL being missed across buffer boundaries
-        if (l_eol_char > 1)
-          str = [str(end - length (eol_char) + 2 : end) nstr];
-        else
-          str = nstr;
-        endif
-        eoi = findstr (str, eol_char);
-        n_eoi += numel (eoi);
-        ++nblks;
-      endif
-    endwhile
-    ## Handle case of missing or incomplete trailing EOL
-    if (! strcmp (str(end - length (eol_char) + 1 : end), eol_char))
-      eoi = [ eoi (length (str)) ];
-      ++n_eoi;
-    endif
-    ## Found EOL delimiting last requested line.  Compute ptr (incl. EOL)
-    if (isempty (eoi))
-      eoi_pos = nblks * BUFLENGTH + count;
-    else
-      eoi_pos = (nblks * BUFLENGTH) + eoi(end + min (nlines, n_eoi) - n_eoi);
-    endif
-    fseek (fid, st_pos, "bof");
-    str = fscanf (fid, "%c", eoi_pos);
-  else
-    fseek (fid, st_pos, "bof");
-    str = fread (fid, "char=>char").';
-  endif
-  fclose (fid);
-
-  ## 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{:});
-
-  ## Hack to concatenate/reshape numeric output into 2D array (undocumented ML)
-  ## In ML this only works in case of an empty format string
-  if (isempty (format))
-    ## Get number of fields per line.
-    ## 1. Get eol_char position
-    iwhsp = find (strcmpi ("whitespace", varargin));
-    whsp = varargin{iwhsp + 1};
-    idx = regexp (str, eol_char, "once");
-    ## 2. Get first data line til EOL. Avoid corner case of just one line
-    if (! isempty (idx))
-      str = str(1:idx-1);
-    endif
-    idelimiter = find (strcmpi (varargin, "delimiter"), 1);
-    if (isempty (idelimiter))
-      ## Assume delimiter = whitespace
-      ## 3A. whitespace incl. consecutive whitespace => single space
-      str = regexprep (str, sprintf ("[%s]+", whsp), ' ');
-      ## 4A. Remove possible leading & trailing spaces
-      str = strtrim (str);
-      ## 5A. Count spaces, add one to get nr of data fields per line
-      ncols = numel (strfind (str, " ")) + 1;
-    else
-      ## 3B. Just count delimiters. FIXME: delimiters could occur in literals
-      delimiter = varargin{idelimiter+1};
-      ncols = numel (regexp (str, sprintf ("[%s]", delimiter))) + 1;
-    endif
-    ## 6. Reshape; watch out, we need a transpose
-    nrows = ceil (numel (varargout{1}) / ncols);
-    pad = mod (numel (varargout{1}), ncols);
-    if (pad > 0)
-      pad = ncols - pad;
-      varargout{1}(end+1 : end+pad) = NaN;
-    endif
-    varargout{1} = reshape (varargout{1}, ncols, nrows)';
-    ## ML replaces empty values with NaNs
-    varargout{1}(find (isnan (varargout{1}))) = 0;
-  endif
-
-endfunction
-
-
-%!test
-%! f = tempname ();
-%! 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
-%! f = tempname ();
-%! d = rand (7, 2);
-%! dlmwrite (f, d, "precision", "%5.2f");
-%! [a, b] = textread (f, "%f, %f", "headerlines", 1);
-%! unlink (f);
-%! assert (a, d(2:7, 1), 1e-2);
-
-## Test reading 2D matrix with empty format
-%!test
-%! f = tempname ();
-%! d = rand (5, 2);
-%! dlmwrite (f, d, "precision", "%5.2f");
-%! A = textread (f, "", "headerlines", 3);
-%! unlink (f);
-%! assert (A, d(4:5, :), 1e-2);
-
-## Read multiple lines using empty format string
-%!test
-%! f = tempname ();
-%! unlink (f);
-%! fid = fopen (f, "w");
-%! d = rand (1, 4);
-%! fprintf (fid, "  %f %f   %f  %f ", d);
-%! fclose (fid);
-%! A = textread (f, "");
-%! unlink (f);
-%! assert (A, d, 1e-6);
-
-## Empty format, corner case = one line w/o EOL
-%!test
-%! f = tempname ();
-%! unlink (f);
-%! fid = fopen (f, "w");
-%! d = rand (1, 4);
-%! fprintf (fid, "  %f %f   %f  %f ", d);
-%! fclose (fid);
-%! A = textread (f, "");
-%! unlink (f);
-%! assert (A, d, 1e-6);
-
-## Tests with format repeat count #1
-%!test
-%! f = tempname ();
-%! fid = fopen (f, "w");
-%! fprintf (fid, "%2d %s %2d %s\n %2d %s %2d %s \n", ...
-%!                10, "a", 20, "b", 30, "c", 40, "d");
-%! fclose (fid);
-%! [a, b] = textread (f, "%d %s", 1);
-%! assert (a, int32 (10));
-%! assert (b, {"a"});
-%! [a, b] = textread (f, "%d %s", 2);
-%! assert (a, int32 ([10; 20]));
-%! assert (b, {"a"; "b"});
-%! [a, b] = textread (f, "%d %s", 3);
-%! assert (a, int32 ([10; 20; 30]));
-%! assert (b, {"a"; "b"; "c"});
-%! [a, b] = textread (f, "%d %s", 4);
-%! assert (a, int32 ([10; 20; 30; 40]));
-%! assert (b, {"a"; "b"; "c"; "d"});
-%! [a, b] = textread (f, "%d %s", 5);
-%! assert (a, int32 ([10; 20; 30; 40]));
-%! assert (b, {"a"; "b"; "c"; "d"});
-%! unlink (f);
-
-## Tests with format repeat count #2, missing last EOL
-%!test
-%! f = tempname ();
-%! fid = fopen (f, "w");
-%! fprintf (fid, "%2d %s %2d %s\n %2d %s %2d %s", ...
-%!                10, "a", 20, "b", 30, "c", 40, "d");
-%! fclose (fid);
-%! [a, b] = textread (f, "%d %s", 1);
-%! assert (a, int32 (10));
-%! assert (b, {"a"});
-%! [a, b] = textread (f, "%d %s", 2);
-%! assert (a, int32 ([10; 20]));
-%! assert (b, {"a"; "b"});
-%! [a, b] = textread (f, "%d %s", 3);
-%! assert (a, int32 ([10; 20; 30]));
-%! assert (b, {"a"; "b"; "c"});
-%! [a, b] = textread (f, "%d %s", 4);
-%! assert (a, int32 ([10; 20; 30; 40]));
-%! assert (b, {"a"; "b"; "c"; "d"});
-%! [a, b] = textread (f, "%d %s", 5);
-%! assert (a, int32 ([10; 20; 30; 40]));
-%! assert (b, {"a"; "b"; "c"; "d"});
-%! unlink (f);
-
-## Tests with format repeat count #3, incomplete last line
-%!test
-%! f = tempname ();
-%! fid = fopen (f, "w");
-%! fprintf (fid, "%2d %s %2d %s\n %2d %s %2d", ...
-%!                10, "a", 20, "b", 30, "c", 40);
-%! fclose (fid);
-%! [a, b] = textread (f, "%d %s", 1);
-%! assert (a, int32 (10));
-%! assert (b, {"a"});
-%! [a, b] = textread (f, "%d %s", 2);
-%! assert (a, int32 ([10; 20]));
-%! assert (b, {"a"; "b"});
-%! [a, b] = textread (f, "%d %s", 3);
-%! assert (a, int32 ([10; 20; 30]));
-%! assert (b, {"a"; "b"; "c"});
-%! [a, b] = textread (f, "%d %s", 4);
-%! assert (a, int32 ([10; 20; 30; 40]));
-%! assert (b, {"a"; "b"; "c"});
-%! [a, b] = textread (f, "%d %s", 5);
-%! assert (a, int32 ([10; 20; 30; 40]));
-%! assert (b, {"a"; "b"; "c"});
-%! unlink (f);
-
-## Tests with format repeat count #4, incomplete last line but with trailing EOL
-%!test
-%! f = tempname ();
-%! fid = fopen (f, "w");
-%! fprintf (fid, "%2d %s %2d %s\n %2d %s %2d\n", ...
-%!                10, "a", 20, "b", 30, "c", 40);
-%! fclose (fid);
-%! [a, b] = textread (f, "%d %s", 4);
-%! assert (a, int32 ([10; 20; 30; 40]));
-%! assert (b, {"a"; "b"; "c"; ""});
-%! [a, b] = textread (f, "%d %s", 5);
-%! assert (a, int32 ([10; 20; 30; 40]));
-%! assert (b, {"a"; "b"; "c"; ""});
-%! unlink (f);
-
-### Tests with format repeat count #5, nr of data lines = limiting factor
-#%!test
-#%! f = tempname ();
-#%! fid = fopen (f, "w");
-#%! fprintf (fid, "%2d\n%s\n%2dn%s", ...
-#%!                1, "a", 2, "b");
-#%! fclose (fid);
-#%! [a, b] = textread (f, "%d %s", 2);
-#%! assert (a, int32 (1));
-#%! assert (b, {"a"});
-
-### Read multiple lines using empty format string, missing data (should be 0)
-#%!test
-#%! f = tempname ();
-#%! unlink (f);
-#%! fid = fopen (f, "w");
-#%! d = rand (1, 4);
-#%! fprintf (fid, "%f, %f, ,  %f,  %f ", d);
-#%! fclose (fid);
-#%! A = textread (f, "");
-#%! unlink (f);
-#%! assert (A, [ d(1:2) 0 d(3:4)], 1e-6);
-
-### Test with empty positions - ML returns 0 for empty fields
-#%!test
-#%! f = tempname ();
-#%! unlink (f);
-#%! fid = fopen (f, "w");
-#%! d = rand (1, 4);
-#%! fprintf (fid, ",2,,4\n5,,7,\n");
-#%! fclose (fid);
-#%! A = textread (f, "", "delimiter", ",");
-#%! unlink (f);
-#%! assert (A, [0 2 0 4; 5 0 7 0], 1e-6);
-
-### Another test with empty format + positions, now with more incomplete lower
-### row (must be appended with zeros to get rectangular matrix)
-#%!test
-#%! f = tempname ();
-#%! unlink (f);
-#%! fid = fopen (f, "w");
-#%! d = rand (1, 4);
-#%! fprintf (fid, ",2,,4\n5,\n");
-#%! fclose (fid);
-#%! A = textread (f, "", "delimiter", ",");
-#%! unlink (f);
-#%! assert (A, [0 2 0 4; 5 0 0 0], 1e-6);
-
-### Test endofline
-#%!test <*45046>
-#%! f = tempname ();
-#%! fid = fopen (f, "w");
-#%! fprintf (fid, "a\rb\rc");
-#%! fclose (fid);
-#%! ## Test EOL detection
-#%! d = textread (f, "%s");
-#%! assert (d, {"a";"b";"c"});
-#%! ## Test explicit EOL specification (bug #45046)
-#%! d = textread (f, "%s", "endofline", "\r");
-#%! assert (d, {"a"; "b"; "c"});
-#%! unlink (f);
-
-### Properly process single-quoted EOL args
-#%!test <*46477>
-#%! f = tempname ();
-#%! fid = fopen (f, "w");
-#%! fprintf (fid, "hello, world!");
-#%! fclose (fid);
-#%! [a, b] = textread (f, "%s%s", "endofline", '\n');
-#%! assert (a{1}, "hello,");
-#%! assert (b{1}, "world!");
-
-### Test input validation
-#%!error textread ()
-#%!error textread (1)
-#%!error <arguments must be strings> textread (1, "%f")
-#%!error <arguments must be strings> textread ("fname", 1)
-#%!error <missing or invalid value for> textread (file_in_loadpath ("textread.m"), "", "headerlines")
-#%!error <missing or invalid value for> textread (file_in_loadpath ("textread.m"), "", "headerlines", 'hh')
-#%!error <character value required for> textread (file_in_loadpath ("textread.m"), "%s", "endofline", true)
--- a/scripts/java/org/octave/ClassHelper.java	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/java/org/octave/ClassHelper.java	Fri Aug 10 09:09:51 2018 +0200
@@ -40,7 +40,7 @@
    * Add the given path to the classpath.
    * @param name String - path to addd to the classpath
    * @return boolean - true if the given path exists and was added to the classpath.
-   * @throws Exception
+   * @throws Exception if an error occurs
    */
   public static boolean addClassPath (String name)
     throws Exception
@@ -61,7 +61,7 @@
    *
    * @param name String - path to remove from classpath.
    * @return boolean - true if the given path existed in the classpath before it was removed.
-   * @throws Exception
+   * @throws Exception if an error occurs
    */
   public static boolean removeClassPath (String name)
     throws Exception
@@ -98,7 +98,7 @@
 
   public static String getClassPath ()
   {
-    StringBuffer buf = new StringBuffer ();
+    StringBuilder buf = new StringBuilder();
     String pathSep = System.getProperty ("path.separator");
     java.net.URL[] urls = loader.getURLs ();
 
@@ -142,7 +142,7 @@
   // return list of methods for given class
   public static String getMethods (Class klass)
   {
-    StringBuffer sb = new StringBuffer ();
+    StringBuilder sb = new StringBuilder();
 
     Method theMethod[] = klass.getMethods ();
     for (int i = 0; i < theMethod.length; i++)
@@ -190,7 +190,7 @@
   // return list of fields for given class
   public static String getFields (Class klass)
   {
-    StringBuffer sb = new StringBuffer ();
+    StringBuilder sb = new StringBuilder();
 
     Field theField[] = klass.getFields ();
     for (int i = 0; i < theField.length; i++)
@@ -224,7 +224,7 @@
   }
 
 
-  public static Method findMethod (Class cls, String name, Class[] argTypes)
+  public static Method findMethod (Class<?> cls, String name, Class<?>[] argTypes)
   {
     try
       {
@@ -249,7 +249,7 @@
   }
 
 
-  public static Constructor findConstructor (Class cls, Class[] argTypes)
+  public static Constructor findConstructor (Class<?> cls, Class<?>[] argTypes)
   {
     try
       {
@@ -285,8 +285,8 @@
     catch (IllegalAccessException ex)
       {
         String mName = m.getName ();
-        Class[] pTypes = m.getParameterTypes ();
-        Class currClass = target.getClass ();
+        Class<?>[] pTypes = m.getParameterTypes ();
+        Class<?> currClass = target.getClass ();
 
         while (currClass != null)
           {
@@ -303,7 +303,7 @@
             catch (IllegalAccessException ex2)
               {}
 
-            Class[] ifaceList = currClass.getInterfaces ();
+            Class<?>[] ifaceList = currClass.getInterfaces ();
             for (int i = 0; i < ifaceList.length; i++)
               {
                 try
@@ -492,7 +492,7 @@
   }
 
 
-  private static boolean isCallableFrom (Class expCls, Class argCls)
+  private static boolean isCallableFrom (Class<?> expCls, Class<?> argCls)
   {
     //System.out.println("isCallableFrom: "+expCls.getCanonicalName() + " <=? " + argCls.getCanonicalName());
     if (argCls == null)
@@ -598,7 +598,7 @@
   }
 
 
-  private static Object castArgument (Object obj, Class type, Class expType)
+  private static Object castArgument (Object obj, Class<?> type, Class<?> expType)
   {
     // System.out.println("expType:"+expType.getCanonicalName() + " <= type:" + type.getCanonicalName());
     if (type == null || expType.isAssignableFrom (type))
--- a/scripts/java/org/octave/Octave.java	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/java/org/octave/Octave.java	Fri Aug 10 09:09:51 2018 +0200
@@ -28,8 +28,8 @@
 {
   private static Object notifyObject = null;
   private static Object[] args = null;
-  private static LinkedList invokeList = new LinkedList ();
-  private static LinkedList waitList = new LinkedList ();
+  private static LinkedList<Object> invokeList = new LinkedList<Object> ();
+  private static LinkedList<Object> waitList = new LinkedList<Object> ();
 
   public native static boolean call (String name, Object[] argin, Object[] argout);
   public native static void doInvoke (int ID, Object[] args);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/legacy/findstr.m	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,158 @@
+## Copyright (C) 1996-2018 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
+## <https://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {} {} findstr (@var{s}, @var{t})
+## @deftypefnx {} {} findstr (@var{s}, @var{t}, @var{overlap})
+##
+## This function is obsolete.  Use @code{strfind} instead.
+##
+## Return the vector of all positions in the longer of the two strings @var{s}
+## and @var{t} where an occurrence of the shorter of the two starts.
+##
+## If the optional argument @var{overlap} is true (default), the returned
+## vector can include overlapping positions.  For example:
+##
+## @example
+## @group
+## findstr ("ababab", "a")
+##      @result{} [1, 3, 5];
+## findstr ("abababa", "aba", 0)
+##      @result{} [1, 5]
+## @end group
+## @end example
+##
+## @strong{Caution:} @code{findstr} is obsolete.  Use @code{strfind} in all new
+## code.
+## @seealso{strfind, strmatch, strcmp, strncmp, strcmpi, strncmpi, find}
+## @end deftypefn
+
+## Note that this implementation swaps the strings if second one is longer
+## than the first, so try to put the longer one first.
+
+## Author: Kurt Hornik <Kurt.Hornik@wu-wien.ac.at>
+## Adapted-By: jwe
+
+function v = findstr (s, t, overlap = true)
+
+  persistent warned = false;
+  if (! warned)
+    warned = true;
+    warning ("Octave:legacy-function",
+             "findstr is obsolete; use strfind instead\n");
+  endif
+
+  if (nargin < 2 || nargin > 3)
+    print_usage ();
+  endif
+
+  if (all (size (s) > 1) || all (size (t) > 1))
+    error ("findstr: arguments must have only one non-singleton dimension");
+  endif
+
+  ## Make S be the longer string.
+  if (length (s) < length (t))
+    [s, t] = deal (t, s);
+  endif
+
+  l_s = length (s);
+  l_t = length (t);
+
+  if (l_t == 0)
+    ## zero length target: return empty set
+    v = [];
+
+  elseif (l_t == 1)
+    ## length one target: simple find
+    v = find (s == t);
+
+  elseif (l_t == 2)
+    ## length two target: find first at i and second at i+1
+    v = find (s(1:l_s-1) == t(1) & s(2:l_s) == t(2));
+
+  else
+    ## length three or more: match the first three by find then go through
+    ## the much smaller list to determine which of them are real matches
+    limit = l_s - l_t + 1;
+    v = find (  s(1:limit)   == t(1)
+              & s(2:limit+1) == t(2)
+              & s(3:limit+2) == t(3));
+  endif
+
+  ## Need to search the index vector if our find was too short
+  ## (target length > 3), or if we don't allow overlaps.  Note though
+  ## that there cannot be any overlaps if the first character in the
+  ## target is different from the remaining characters in the target,
+  ## so a single character, two different characters, or first character
+  ## different from the second two don't need to be searched.
+  if (l_t >= 3 || (! overlap && l_t > 1 && any (t(1) == t(2:l_t))))
+    ## force strings to be both row vectors or both column vectors
+    if (all (size (s) != size (t)))
+      t = t.';
+    endif
+
+    ## determine which ones to keep
+    keep = zeros (size (v));
+    ind = 0:l_t-1;
+    if (overlap)
+      for idx = 1:length (v)
+        keep(idx) = all (s(v(idx) + ind) == t);
+      endfor
+    else
+      ## First possible position for next non-overlapping match.
+      next = 1;
+      for idx = 1:length (v)
+        if (v(idx) >= next && s(v(idx) + ind) == t)
+          keep(idx) = 1;
+          ## Skip to the next possible match position.
+          next = v(idx) + l_t;
+        else
+          keep(idx) = 0;
+        endif
+      endfor
+    endif
+    if (! isempty (v))
+      v = v(find (keep));
+    endif
+  endif
+
+  if (isempty (v))
+    v = [];
+  endif
+
+  ## Always return a row vector, because that's what the old one did.
+  if (iscolumn (v))
+    v = v.';
+  endif
+
+endfunction
+
+
+## First test is necessary to provoke 1-time legacy warning
+%!test
+%! warning ("off", "Octave:legacy-function", "local");
+%! findstr ("", "");
+
+%!assert (findstr ("abababa", "a"), [1, 3, 5, 7])
+%!assert (findstr ("abababa", "aba"), [1, 3, 5])
+%!assert (findstr ("aba", "abababa", 0), [1, 5])
+
+## Test input validation
+%!error findstr ()
+%!error findstr ("foo", "bar", 3, 4)
+%!error <must have only one non-singleton dimension> findstr (["AB" ; "CD"], "C")
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/legacy/flipdim.m	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,37 @@
+## Copyright (C) 2004-2018 David Bateman
+## Copyright (C) 2009 VZLU Prague
+##
+## This file is part of Octave.
+##
+## Octave is free software: you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <https://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {} {} flipdim (@var{x})
+## @deftypefnx {} {} flipdim (@var{x}, @var{dim})
+## This function is obsolete.  Use @code{flip} instead.
+## @seealso{flip, fliplr, flipud, rot90, rotdim}
+## @end deftypefn
+
+function y = flipdim (varargin)
+
+  persistent warned = false;
+  if (! warned)
+    warned = true;
+    warning ("Octave:legacy-function",
+             "flipdim is obsolete; please use flip instead");
+  endif
+
+  y = flip (varargin{:});
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/legacy/isequalwithequalnans.m	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,40 @@
+## Copyright (C) 2018 Rik Wehbring
+##
+## This file is part of Octave.
+##
+## Octave is free software: you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <https://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {} isequalwithequalnans (@var{x1}, @var{x2}, @dots{})
+## This function is obsolete.  Use @code{isequaln} instead.
+## @seealso{isequaln}
+## @end deftypefn
+
+## At one time, Matlab docs stated that this function is obsolete and would be
+## removed in some future version.  Now users are told that it should be
+## avoided, but there is no mention of possible future removal.
+
+function retval = isequalwithequalnans (varargin)
+
+  persistent warned = false;
+  if (! warned)
+    warned = true;
+    warning ("Octave:legacy-function",
+             "isequalwithequalnans is obsolete; please use isequaln instead");
+  endif
+
+  retval = isequaln (varargin{:});
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/legacy/isstr.m	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,42 @@
+## Copyright (C) 2003-2018 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
+## <https://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {} {} isstr (@var{x})
+## This function is obsolete.  Use @code{ischar} instead.
+## @seealso{ischar}
+## @end deftypefn
+
+## Author: jwe
+
+## At one time, Matlab docs stated that this function is obsolete and would be
+## removed in some future version.  Now users are told that it should be
+## avoided, but there is no mention of possible future removal.
+
+function retval = isstr (varargin)
+
+  persistent warned = false;
+  if (! warned)
+    warned = true;
+    warning ("Octave:legacy-function",
+             "isstr is obsolete; please use ischar instead");
+  endif
+
+  retval = ischar (varargin{:});
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/legacy/module.mk	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,21 @@
+FCN_FILE_DIRS += scripts/legacy
+
+%canon_reldir%_FCN_FILES = \
+  %reldir%/findstr.m \
+  %reldir%/flipdim.m \
+  %reldir%/isequalwithequalnans.m \
+  %reldir%/isstr.m \
+  %reldir%/setstr.m \
+  %reldir%/strmatch.m \
+  %reldir%/strread.m \
+  %reldir%/textread.m
+
+%canon_reldir%dir = $(fcnfiledir)/legacy
+
+%canon_reldir%_DATA = $(%canon_reldir%_FCN_FILES)
+
+FCN_FILES += $(%canon_reldir%_FCN_FILES)
+
+PKG_ADD_FILES += %reldir%/PKG_ADD
+
+DIRSTAMP_FILES += %reldir%/$(octave_dirstamp)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/legacy/setstr.m	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,42 @@
+## Copyright (C) 2003-2018 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 {} {@var{s} =} setstr (@var{x})
+## This function is obsolete.  Use @code{char} instead.
+## @seealso{char}
+## @end deftypefn
+
+## Author: jwe
+
+## At one time, Matlab docs stated that this function is obsolete and would be
+## removed in some future version.  Now users are told that it should be
+## avoided, but there is no mention of possible future removal.
+
+function retval = setstr (varargin)
+
+  persistent warned = false;
+  if (! warned)
+    warned = true;
+    warning ("Octave:legacy-function",
+             "setstr is obsolete; please use char instead");
+  endif
+
+  retval = char (varargin{:});
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/legacy/strmatch.m	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,156 @@
+## Copyright (C) 2000-2018 Paul Kienzle
+## Copyright (C) 2003 Alois Schloegl
+## Copyright (C) 2010 VZLU Prague
+##
+## This file is part of Octave.
+##
+## Octave is free software: you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <https://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {} {} strmatch (@var{s}, @var{A})
+## @deftypefnx {} {} strmatch (@var{s}, @var{A}, "exact")
+##
+## This function is obsolete.  Use an alternative such as @code{strncmp}
+## or @code{strcmp} instead.
+##
+## Return indices of entries of @var{A} which begin with the string @var{s}.
+##
+## The second argument @var{A} must be a string, character matrix, or a cell
+## array of strings.
+##
+## If the third argument @qcode{"exact"} is not given, then @var{s} only
+## needs to match @var{A} up to the length of @var{s}.  Trailing spaces and
+## nulls in @var{s} and @var{A} are ignored when matching.
+##
+## For example:
+##
+## @example
+## @group
+## strmatch ("apple", "apple juice")
+##      @result{} 1
+##
+## strmatch ("apple", ["apple  "; "apple juice"; "an apple"])
+##      @result{} [1; 2]
+##
+## strmatch ("apple", ["apple  "; "apple juice"; "an apple"], "exact")
+##      @result{} [1]
+## @end group
+## @end example
+##
+## @strong{Caution:} @code{strmatch} is obsolete.  Use @code{strncmp} (normal
+## case) or @code{strcmp} (@qcode{"exact"} case) in all new code.  Other
+## replacement possibilities, depending on application, include @code{regexp}
+## or @code{validatestring}.
+## @seealso{strncmp, strcmp, regexp, strfind, validatestring}
+## @end deftypefn
+
+## Author: Paul Kienzle, Alois Schloegl
+## Adapted-by: jwe
+
+function idx = strmatch (s, A, exact)
+
+  persistent warned = false;
+  if (! warned)
+    warned = true;
+    warning ("Octave:legacy-function",
+             "strmatch is obsolete; use strncmp or strcmp instead\n");
+  endif
+
+  if (nargin < 2 || nargin > 3)
+    print_usage ();
+  endif
+
+  if (iscellstr (s))
+    if (numel (s) > 1)
+      error ("strmatch: a cell array S must contain only one string");
+    endif
+    s = char (s);
+  elseif (! ischar (s) || (! isempty (s) && ! isrow (s)))
+    error ("strmatch: S must be a string");
+  elseif (! (ischar (A) || iscellstr (A)))
+    error ("strmatch: A must be a string or cell array of strings");
+  endif
+
+  ## Trim blanks and nulls from search string
+  if (any (s != " " & s != "\0"))
+    s = regexprep (s, "[ \\0]+$", '');
+  endif
+  len = length (s);
+
+  exact = nargin == 3 && ischar (exact) && strcmp (exact, "exact");
+
+  if (ischar (A))
+    [nr, nc] = size (A);
+    if (len > nc)
+      idx = [];
+    else
+      match = all (bsxfun (@eq, A(:,1:len), s), 2);
+      if (exact)
+        AA = A(:,len+1:nc);
+        match &= all (AA == " " | AA == "\0", 2);
+      endif
+      idx = find (match);
+    endif
+  else
+    if (len > 0)
+      idx = find (strncmp (s, A, len));
+    else
+      idx = find (strcmp (s, A));
+    endif
+    if (exact)
+      ## We can't just use strcmp, because we need to ignore spaces at end.
+      B = regexprep (A(idx), "[ \\0]+$", '');
+      idx = idx(strcmp (s, B));
+    endif
+  endif
+
+endfunction
+
+
+## First test is necessary to provoke 1-time legacy warning
+%!test
+%! warning ("off", "Octave:legacy-function", "local");
+%! strmatch ("", "");
+
+%!assert (strmatch ("a", {"aaa", "bab", "bbb"}), 1)
+%!assert (strmatch ("apple", "apple juice"), 1)
+%!assert (strmatch ("apple", ["apple pie"; "apple juice"; "an apple"]), [1; 2])
+%!assert (strmatch ("apple", {"apple pie"; "apple juice"; "tomato"}), [1; 2])
+%!assert (strmatch ("apple pie", "apple"), [])
+%!assert (strmatch ("a ", "a"), 1)
+%!assert (strmatch ("a", "a \0", "exact"), 1)
+%!assert (strmatch ("a b", {"a b", "a c", "c d"}), 1)
+%!assert (strmatch ("", {"", "foo", "bar", ""}), [1, 4])
+%!assert (strmatch ('', { '', '% comment', 'var a = 5', ''}, "exact"), [1,4])
+
+## Weird Matlab corner cases
+%!test <*49601>
+%! assert (strmatch (" ", " "), 1);
+%! assert (strmatch (" ", "   "), 1);
+%! assert (strmatch ("  ", " "), []);
+%! assert (strmatch ("  ", "  "), 1);
+%!test <*54432>
+%! assert (strmatch ({"a"}, {"aaa", "bab", "bbb"}), 1);
+%! assert (isempty (strmatch ({}, {"aaa", "bab"})));
+
+## 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 contain only one string> strmatch ({"a", "b"}, "aaa")
+%!error <S must be a string> strmatch (1, "aaa")
+%!error <S must be a string> strmatch (char ("a", "bb"), "aaa")
+%!error <A must be a string> strmatch ("a", 1)
+%!error <A must be a string> strmatch ("a", {"hello", [1]})
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/legacy/strread.m	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,1137 @@
+## Copyright (C) 2009-2018 Eric Chassande-Mottin, CNRS (France)
+## Parts Copyright (C) 2012-2018 Philip Nienhuis
+##
+## This file is part of Octave.
+##
+## Octave is free software: you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <https://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {} {[@var{a}, @dots{}] =} strread (@var{str})
+## @deftypefnx {} {[@var{a}, @dots{}] =} strread (@var{str}, @var{format})
+## @deftypefnx {} {[@var{a}, @dots{}] =} strread (@var{str}, @var{format}, @var{format_repeat})
+## @deftypefnx {} {[@var{a}, @dots{}] =} strread (@var{str}, @var{format}, @var{prop1}, @var{value1}, @dots{})
+## @deftypefnx {} {[@var{a}, @dots{}] =} strread (@var{str}, @var{format}, @var{format_repeat}, @var{prop1}, @var{value1}, @dots{})
+##
+## This function is obsolete.  Use @code{textscan} instead.
+##
+## 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.
+##
+## The string @var{format} describes how the words in @var{str} should be
+## parsed.  It may contain any combination of the following specifiers:
+##
+## @table @code
+## @item %s
+## The word is parsed as a string.
+##
+## @item  %f
+## @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  %*
+## @itemx %*f
+## @itemx %*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}.  This will do if @var{str} contains only numeric fields.
+##
+## For example, the string
+##
+## @example
+## @group
+## @var{str} = "\
+## Bunny Bugs   5.5\n\
+## Duck Daffy  -7.5e-5\n\
+## Penguin Tux   6"
+## @end group
+## @end example
+##
+## @noindent
+## can be read using
+##
+## @example
+## [@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:
+##
+## @table @asis
+## @item @qcode{"commentstyle"}
+## Parts of @var{str} are considered comments and will be skipped.
+## @var{value} is the comment style and can be any of the following.
+##
+## @itemize
+## @item @qcode{"shell"}
+## Everything from @code{#} characters to the nearest end-of-line is skipped.
+##
+## @item @qcode{"c"}
+## Everything between @code{/*} and @code{*/} is skipped.
+##
+## @item @qcode{"c++"}
+## Everything from @code{//} characters to the nearest end-of-line is skipped.
+##
+## @item @qcode{"matlab"}
+## 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 @qcode{"delimiter"}
+## Any character in @var{value} will be used to split @var{str} into words
+## (default value = any whitespace).  Note that whitespace is implicitly added
+## to the set of delimiter characters unless a @qcode{"%s"} format conversion
+## specifier is supplied; see @qcode{"whitespace"} parameter below.  The set
+## of delimiter characters cannot be empty; if needed Octave substitutes a
+## space as delimiter.
+##
+## @item @qcode{"emptyvalue"}
+## Value to return for empty numeric values in non-whitespace delimited data.
+## The default is NaN@.  When the data type does not support NaN (int32 for
+## example), then default is zero.
+##
+## @item @qcode{"multipledelimsasone"}
+## Treat a series of consecutive delimiters, without whitespace in between,
+## as a single delimiter.  Consecutive delimiter series need not be vertically
+## @qcode{"aligned"}.
+##
+## @item @qcode{"treatasempty"}
+## Treat single occurrences (surrounded by delimiters or whitespace) of the
+## string(s) in @var{value} as missing values.
+##
+## @item @qcode{"returnonerror"}
+## If @var{value} true (1, default), ignore read errors and return normally.
+## If false (0), return an error.
+##
+## @item @qcode{"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 @qcode{"@xbackslashchar{}t"}.  In
+## each data field, multiple consecutive whitespace characters are collapsed
+## into one space and leading and trailing whitespace is removed.  The default
+## value for whitespace is
+## @c Note: the next line specifically has a newline which generates a space
+## @c       in the output of qcode, but keeps the next line < 80 characters.
+## @qcode{"
+## @xbackslashchar{}b@xbackslashchar{}r@xbackslashchar{}n@xbackslashchar{}t"}
+## (note the space).  Whitespace is always added to the set of delimiter
+## characters unless at least one @qcode{"%s"} format conversion specifier is
+## supplied; in that case only whitespace explicitly specified in
+## @qcode{"delimiter"} is retained as delimiter and removed from the set of
+## whitespace characters.  If whitespace characters are to be kept as-is (in
+## e.g., strings), specify an empty value (i.e., @qcode{""}) for
+## @qcode{"whitespace"}; obviously, whitespace cannot be a delimiter then.
+##
+## @end table
+##
+## When the number of words in @var{str} doesn't match an exact multiple of
+## the number of format conversion specifiers, strread's behavior depends on
+## the last character of @var{str}:
+##
+## @table @asis
+## @item last character = @qcode{"@xbackslashchar{}n"}
+## Data columns are padded with empty fields or NaN so that all columns have
+## equal length
+##
+## @item last character is not @qcode{"@xbackslashchar{}n"}
+## Data columns are not padded; strread returns columns of unequal length
+##
+## @end table
+##
+## @seealso{textscan, sscanf}
+## @end deftypefn
+
+function varargout = strread (str, format = "%f", varargin)
+
+  persistent warned = false;
+  if (! warned)
+    warned = true;
+    warning ("Octave:legacy-function",
+             "strread is obsolete; use textscan instead\n");
+  endif
+
+  ## Check input
+  if (nargin < 1)
+    print_usage ();
+  endif
+
+  if (isempty (str))
+    ## Return empty args (no match), rather than raising an error
+    varargout = cell (1, nargout);
+    return;
+  endif
+
+  if (isempty (format))
+    format = "%f";
+  endif
+
+  if (! ischar (str) || ! ischar (format))
+    error ("strread: STR and FORMAT arguments must be strings");
+  endif
+
+  if (strcmp (typeinfo (format), "sq_string"))
+    format = do_string_escapes (format);
+  endif
+
+  ## Parse format string to compare number of conversion fields and nargout
+  nfields = numel (regexp (format, '(%(\d*|\d*\.\d*)?[nfduscq]|%\[)', "match"));
+  ## If str only has numeric fields, a (default) format ("%f") will do.
+  ## Otherwise:
+  if (! nfields)
+    error ("strread.m: no valid format conversion specifiers found\n");
+  elseif ((max (nargout, 1) != nfields) && ! strcmp (format, "%f"))
+    error ("strread: the number of output variables must match that specified by FORMAT");
+  endif
+
+  ## 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;
+  open_comment = false;
+  cmt_eol = "\n";
+  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}))
+      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}))
+          case "c"
+            [comment_start, comment_end] = deal ("/*", "*/");
+          case "c++"
+            [comment_start, comment_end] = deal ("//", "cmt_eol");
+            open_comment = true;
+          case "shell"
+            [comment_start, comment_end] = deal ("#" , "cmt_eol");
+            open_comment = true;
+          case "matlab"
+            [comment_start, comment_end] = deal ("%" , "cmt_eol");
+            open_comment = true;
+          otherwise
+            if (ischar (varargin{n+1})
+                || (numel (varargin{n+1}) == 1 && iscellstr (varargin{n+1})))
+              [comment_start, comment_end] = deal (char (varargin{n+1}), "cmt_eol");
+            open_comment = true;
+            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};
+        if (strcmp (typeinfo (delimiter_str), "sq_string"))
+          delimiter_str = do_string_escapes (delimiter_str);
+        endif
+      case "emptyvalue"
+        numeric_fill_value = varargin{n+1};
+      case "expchars"
+        warning ("strread: property 'expchars' is not implemented");
+      case "whitespace"
+        white_spaces = varargin{n+1};
+        if (strcmp (typeinfo (white_spaces), "sq_string"))
+          white_spaces = do_string_escapes (white_spaces);
+        endif
+      ## The following parameters are specific to textscan and textread
+      case "endofline"
+        eol_char = varargin{n+1};
+        if (strcmp (typeinfo (eol_char), "sq_string"))
+          eol_char = do_string_escapes (eol_char);
+        endif
+        cmt_eol = eol_char;
+        open_comment = false;
+      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});
+    endswitch
+  endfor
+
+  ## First parse of FORMAT
+  if (strcmpi (strtrim (format), "%f"))
+    ## Default format specified.  Expand it (to desired nargout)
+    fmt_words = cell (max (nargout, 1), 1);
+    fmt_words (1:max (nargout, 1)) = 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");
+
+    ## Find position of conversion specifiers (they start with %)
+    fcs_ptrn = '(%\*?(\d*|\d*\.\d*)?[nfduscq]|%\*?\[)';
+    idy2 = find (! cellfun ("isempty", regexp (fmt_words, fcs_ptrn)));
+
+    ## Check for unsupported format specifiers
+    errpat = '(\[.*\]|[cq]|[nfdu]8|[nfdu]16|[nfdu]32|[nfdu]64)';
+    if (! all (cellfun ("isempty", regexp (fmt_words(idy2), errpat))))
+      error ("strread: %q, %c, %[] or bit width format specifiers are not supported yet.");
+    endif
+
+    ## Format conversion specifiers following literals w/o space/delim
+    ## in between are separate now.  Separate those w trailing literals
+    a = strfind (fmt_words(idy2), "%");
+    b = regexp (fmt_words(idy2), '[nfdus]', "end");
+    for jj = 1:numel (a)
+      ## From right to left to avoid losing track
+      ii = numel (a) - jj + 1;
+      ## Check for illegal format specifiers
+      if (isempty (b{ii}))
+        error ("strread: unknown format specifier #%d ('%s')\n",
+              ii, fmt_words{idy2(ii)});
+      endif
+      if (! (length (fmt_words{idy2(ii)}) == b{ii}(1)))
+        ## Split fmt_words(ii) into % conv specifier and trailing literal
+        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
+
+  ## Remove comments in str
+  if (comment_flag)
+    ## Expand 'cmt_eol' here, after option processing which may have set value
+    comment_end = strrep (comment_end, "cmt_eol", cmt_eol);
+    cstart = strfind (str, comment_start);
+    cstop  = strfind (str, comment_end);
+    if (open_comment)
+      cstop -= 1;
+    endif
+    ## 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))
+        cidx(end) = []; # Drop the last one if orphaned.
+      endif
+      cstart = cstart(cidx);
+    endif
+    if (! isempty (cstop))
+      ## Ignore nested closers.
+      [idx, cidx] = unique (lookup (cstart, cstop), "first");
+      if (idx(1) == 0)
+        cidx(1) = []; # Drop the first one if orphaned.
+      endif
+      cstop = cstop(cidx);
+    endif
+    len = length (str);
+    c2len = length (comment_end);
+    if (cstop + c2len == len)
+      ## Ignore last char of to-the-end-of-line comments
+      c2len += 1;
+    endif
+    str = cellslices (str, [1, cstop + c2len], [cstart - 1, len]);
+    str = [str{:}];
+  endif
+
+  if (! isempty (white_spaces))
+    ## For numeric fields, whitespace is always a delimiter, but not for text
+    ## fields
+    if (isempty (regexp (format, '%\*?\d*s')))
+      ## Add whitespace to delimiter set
+      delimiter_str = unique ([white_spaces delimiter_str]);
+    else
+      ## Remove any delimiter chars from white_spaces list
+      white_spaces = setdiff (white_spaces, delimiter_str);
+    endif
+  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
+
+  ii = numel (fmt_words);
+  while (ii > 0)
+    if (ismember (fmt_words{ii}, delimiter_str)(1))
+      fmt_words(ii) = [];
+      --num_words_per_line;
+    endif
+    --ii;
+  endwhile
+
+  pad_out = 0;
+  ## Trim whitespace if needed
+  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) == "\n" && nargout > 1)
+      pad_out = 1;
+    endif
+    ## Condense all repeated whitespace into one single space
+    ## FIXME: this will also fold repeated whitespace in a char field
+    rxp_wsp = sprintf ("[%s]+", white_spaces);
+    str = regexprep (str, rxp_wsp, ' ');
+    ## Remove possible leading space at string
+    if (str(1) == " ")
+       str = str(2:end);
+    endif
+    ## Check for single delimiter followed/preceded by whitespace
+    if (! isempty (delimiter_str))
+      dlmstr = setdiff (delimiter_str, " ");
+      if (! isempty (dlmstr))
+        rxp_dlmwsp = sprintf ('( [%s] | [%s]|[%s] )', dlmstr, dlmstr, dlmstr);
+        str = regexprep (str, rxp_dlmwsp, delimiter_str(1));
+      endif
+    endif
+    ## Wipe leading and trailing whitespace on each line (it may be
+    ## delimiter too)
+    ## FIXME: Double strrep on str is enormously expensive in CPU time.
+    ## Can this be eliminated?
+    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, mult_dlms_s1, eol_char);
+  if (! isempty (white_spaces))
+    ## Trim leading and trailing 'white_spaces'.
+    ## All whitespace has been converted to space above
+    words = strtrim (words);
+  endif
+  num_words = numel (words);
+  ## First guess at nr. of lines in file (ignoring leading/trailing literals)
+  num_lines = ceil (num_words / num_words_per_line);
+
+  ## Replace TreatAsEmpty char sequences by empty strings
+  if (! isempty (empty_str))
+    for ii = 1:numel (empty_str)
+      idz = strncmp (empty_str{ii}, words, length (empty_str{ii}));
+      words(idz) = {""};
+    endfor
+  endif
+
+  ## fmt_words has been split properly now, but words{} has only been split on
+  ## delimiter positions.  As numeric fields can also be separated by
+  ## whitespace, more splits may be needed.
+  ## We also don't know the number of lines (as EndOfLine may have been set to
+  ## "" (empty) by the caller).
+  ##
+  ## We also may have to cope with 3 cases as far as literals go:
+  ## 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 )
+  ## Some words columns may have to be split further to fix these.
+  ## To find out, we'll match fmt_words to the words array to see what
+  ## needs to be done.  fwptr tracks which {fmt_words} starts in what {words}
+
+  ## 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);
+  ## Find indices to numeric conversion specifiers
+  idn = ! cellfun ("isempty", regexp (fmt_words, '%[dnfu]'));
+
+  ## 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
+      ## matching fmt_words to words until the fmt_words array is exhausted.
+      ## iwrd: ptr to current analyzed word.
+      ## iwrdp: ptr to pos before analyzed char.
+      iwrd = 1; iwrdp = 0; iwrdl = length (words{1});
+      fwptr = zeros (1, numel (fmt_words));
+      ii = 1;
+      while (ii <= numel (fmt_words))
+
+        nxt_wrd = 0;
+        ## Keep track of which words nr. every fmt_words{} is (starts) in.
+        fwptr(ii) = iwrd;
+
+        if (idf(ii))
+          ## Literal expected
+          if (isempty (strfind (fmt_words{ii}, words(iwrd))))
+            ## Not found in current word; supposed to be in next word
+            nxt_wrd = 1;
+          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)
+              warning ("strread: literal '%s' (fmt spec # %d) does not match data", ...
+                fmt_words{ii}, ii);
+              ## Word assumed to be completely "used up".  Next word
+              nxt_wrd = 1;
+            elseif (iwrdp == iwrdl)
+              ## Word completely "used up".  Next word
+              nxt_wrd = 1;
+            endif
+          endif
+
+        elseif (idg(ii))
+          ## Fixed width specifier (%N or %*N): read just a part of word
+          sw = regexp (fmt_words{ii}, '\d', "once");
+          ew = regexp (fmt_words{ii}, '[nfuds]') - 1;
+          iwrdp += floor (str2double (fmt_words{ii}(sw:ew)));
+          if (iwrdp > iwrdl)
+            ## Match error.  Field extends beyond word boundary.
+            warning  ...
+            ("strread: field width '%s' (fmt spec # %d) extends beyond actual word limit", ...
+               fmt_words{ii}, ii);
+            ## Assume word to be completely "used up".  Next word
+            nxt_wrd = 1;
+          elseif (iwrdp == iwrdl)
+            ## Word completely "used up".  Next word
+            nxt_wrd = 1;
+          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
+              nxt_wrd = 1;
+            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
+            nxt_wrd = 1;
+          endif
+
+        endif
+
+        if (nxt_wrd)
+          ++iwrd; iwrdp = 0;
+          if (iwrd > numel (words))
+            ## Apparently EOF; assume incomplete row already at L.1 of data
+            ii = numel (fmt_words);
+          elseif (ii < numel (fmt_words) && iwrd <= numel (words))
+            iwrdl = length (words{iwrd});
+          endif
+        endif
+
+        ++ii;
+
+      endwhile
+      ## Done
+      words_period = max (iwrd - 1, 1);
+      num_lines = ceil (num_words / words_period);
+
+      ## 2. Pad words array so that it can be reshaped
+      num_words_padded = num_lines * words_period - num_words;
+      if (num_words_padded)
+        words = [words'; cell(num_words_padded, 1)];
+      endif
+      words = reshape (words, words_period, num_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};
+              fwptr = [fwptr(1:ii) (++fwptr(ii+1:end))];
+
+            else
+              if (idg(ii))
+                ## Current field = fixed width.
+                ## Strip into icol, rest in icol+1
+                sw = regexp (fmt_words{ii}, '\d', "once");
+                ew = regexp (fmt_words{ii}, '[nfuds]') - 1;
+                wdth = floor (str2double (fmt_words{ii}(sw:ew)));
+                words(icol+1, jptr) = cellfun (@(x) x(wdth+1:end),
+                     words(icol,jptr), "UniformOutput", false);
+                if (isempty ([words(icol+1, :){:}]))
+                  ## Apparently split wasn't needed as turns out to cover
+                  ## entire column. So delete column again
+                  words(icol+1, :) = [];
+                else
+                  words(icol, jptr) = strtrunc (words(icol, jptr), wdth);
+                  fwptr = [fwptr(1:ii) (++fwptr(ii+1:end))];
+                endif
+              else
+                if (! isempty (strfind (fmt_words{ii-1}, "%s")))
+                  ## Trailing literal.
+                  ## Could be ambiguous if preceding format == '%s'
+                  warning ("strread.m:\n  Ambiguous '%%s' specifier immediately before literal in column %d", icol);
+                endif
+                ## 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 = ostrsplit ([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) = ostrsplit (strrep ([wrds{2:end}], ...
+                   char (254), fmt_words{ii}), char (255));
+                ## Former trailing literal may now be leading for next specifier
+                --ii;
+                fwptr = [fwptr(1:ii) (++fwptr(ii+1:end))];
+              endif
+            endif
+          endif
+
+        else
+          ## Conversion specifier.
+          ## Peek if next fmt_word needs split from current column.
+          if (ii < num_words_per_line)
+            if (fwptr(ii) == fwptr(ii+1))
+              --icol;
+            endif
+          endif
+        endif
+        ## Next fmt_word, next column
+        ++ii; ++icol;
+      endwhile
+
+      ## Done.
+      ## Reshape words back into one 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
+    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);
+        if (num_lines > format_repeat_count)
+          num_lines = format_repeat_count;
+        endif
+      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 += 1;
+        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);
+          endif
+          data(n) = numeric_fill_value;
+          if (pad_out)
+            data(end+1:num_lines) = numeric_fill_value;
+          endif
+          varargout{k} = data.';
+          k += 1;
+        case {"%0", "%1", "%2", "%3", "%4", "%5", "%6", "%7", "%8", "%9"}
+          sw = regexp (fmt_words{m}, '\d', "once");
+          ew = regexp (fmt_words{m}, '[nfudsq]') - 1;
+          nfmt = ostrsplit (fmt_words{m}(2:ew), ".");
+          swidth = str2double (nfmt{1});
+          switch (fmt_words{m}(ew+1))
+            case {"d", "u", "f", "n"}
+              n = cellfun ("isempty", data);
+              ### FIXME: Erroneously formatted data lead to NaN, not an error
+              ###        => ReturnOnError can't be implemented for numeric data
+              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);
+              endif
+              varargout{k} = data.';
+              k += 1;
+            case "s"
+              if (pad_out)
+                data(end+1:num_lines) = {""};
+              endif
+              varargout{k} = strtrunc (data, swidth)';
+              k += 1;
+            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, 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 text
+    ## to avoid it being included in consecutive delim series
+    enchr = ' ';
+    ## However watch out if eol_char is also in delimiters
+    if (index (sep, eol_char)); enchr = char (255); endif
+    text = strrep (text, eol_char, [enchr eol_char enchr]);
+  else
+    mult_dlms_s1 = false;
+  endif
+
+  ## Split text string along delimiters
+  out = ostrsplit (text, sep, mult_dlms_s1);
+  if (index (sep, eol_char)); out = strrep (out, char (255), ''); endif
+  ## In case of trailing delimiter, strip stray last empty word
+  if (! isempty (out) && any (sep == text(end)) && ! mult_dlms_s1)
+    out(end) = [];
+  endif
+
+  ## Empty cells converted to empty cellstrings.
+  out(cellfun ("isempty", out)) = {""};
+
+endfunction
+
+
+## First test is necessary to provoke 1-time legacy warning
+%!test
+%! warning ("off", "Octave:legacy-function", "local");
+%! strread ("");
+
+%!test
+%! [a, b] = strread ("1 2", "%f%f");
+%! assert (a, 1);
+%! assert (b, 2);
+
+%!test
+%! str = "";
+%! a = 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));
+%! endfor
+%! [aa, bb] = strread (str, "%f %s");
+%! assert (aa, a, 1e-6);
+%! assert (bb, cellstr (b));
+
+%!test
+%! str = "";
+%! a = 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));
+%! endfor
+%! aa = strread (str, "%f %*s");
+%! assert (aa, a, 1e-6);
+
+%!test
+%! str = sprintf ("/* this is\nacomment*/ 1 2 3");
+%! a = strread (str, "%f", "commentstyle", "c");
+%! 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
+%! assert (strread ("Hello World! // this is comment", "%s",
+%!                  "commentstyle", "c++"),
+%!         {"Hello"; "World!"});
+%! assert (strread ("Hello World! % this is comment", "%s",...
+%!                  "commentstyle", "matlab"), ...
+%!         {"Hello"; "World!"});
+%! assert (strread ("Hello World! # this is comment", "%s",...
+%!                  "commentstyle", "shell"), ...
+%!         {"Hello"; "World!"});
+
+%!test <*49454>
+%! assert (strread ("hello%foo\nworld, another%bar\r\nday", "%s", ...
+%!                  "commentstyle", "matlab", "delimiter", " ,"),...
+%!         {"hello"; "world"; "another"; "day"});
+
+%!test
+%! str = sprintf ("Tom 100 miles/hr\nDick 90 miles/hr\nHarry 80 miles/hr");
+%! fmt = "%s %f miles/hr";
+%! c = cell (1, 2);
+%! [c{:}] = strread (str, fmt);
+%! assert (c{1}, {"Tom"; "Dick"; "Harry"});
+%! assert (c{2}, [100; 90; 80]);
+
+%!test
+%! a = strread ("a b c, d e, , f", "%s", "delimiter", ",");
+%! assert (a, {"a b c"; "d e"; ""; "f"});
+
+%! ## Format repeat counters w & w/o trailing EOL even within partly read files
+%!test
+%! [a, b] = strread ("10 a 20 b\n 30 c 40", "%d %s", 4);
+%! assert (a, int32 ([10; 20; 30; 40]));
+%! assert (b, {"a"; "b"; "c"});
+%! [a, b] = strread ("10 a 20 b\n 30 c 40\n", "%d %s", 4);
+%! assert (a, int32 ([10; 20; 30; 40]));
+%! assert (b, {"a"; "b"; "c"; ""});
+%! [a, b] = strread ("10 a 20 b\n 30 c 40", "%d %s", 1);
+%! assert (a, int32 (10));
+%! assert (b, {"a"});
+
+%!test <*33536>
+%! [a, b, c] = strread ("1,,2", "%s%s%s", "delimiter", ",");
+%! assert (a{1}, "1");
+%! assert (b{1}, "");
+%! assert (c{1}, "2");
+
+%!test <*33536>
+%!test
+%! 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]));
+
+## Default format (= %f)
+%!test
+%! [a, b, c] = strread ("0.12 0.234 0.3567");
+%! assert (a, 0.12);
+%! assert (b, 0.234);
+%! assert (c, 0.3567);
+
+%!test
+%! [a, b] = strread ("0.41 8.24 3.57 6.24 9.27", "%f%f", 2, "delimiter", " ");
+%! assert (a, [0.41; 3.57]);
+
+## TreatAsEmpty
+%!test
+%! [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]);
+
+## No delimiters at all besides EOL.  Plain reading numbers & strings
+%!test
+%! str = "Text1Text2Text\nText398Text4Text\nText57Text";
+%! [a, b] = strread (str, "Text%dText%1sText");
+%! assert (a, int32 ([1; 398; 57]));
+%! assert (b(1:2), {"2"; "4"});
+%! assert (isempty (b{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]);
+
+%!assert <*44750> (strread ('/home/foo/','%s','delimiter','/','MultipleDelimsAsOne',1),
+%!                {"home"; "foo"})
+
+## delimiter as sq_string and dq_string
+%!assert (strread ("1\n2\n3", "%d", "delimiter", "\n"),
+%!        strread ("1\n2\n3", "%d", "delimiter", '\n'))
+
+## whitespace as sq_string and dq_string
+%!assert (strread ("1\b2\r3\b4\t5", "%d", "whitespace", "\b\r\n\t"),
+%!        strread ("1\b2\r3\b4\t5", "%d", "whitespace", '\b\r\n\t'))
+
+%!test
+%! str =  "0.31 0.86 0.94\n 0.60 0.72 0.87";
+%! fmt = "%f %f %f";
+%! args = {"delimiter", " ", "endofline", "\n", "whitespace", " "};
+%! [a, b, c] = strread (str, fmt, args{:});
+%! assert (a, [0.31; 0.60], 0.01);
+%! assert (b, [0.86; 0.72], 0.01);
+%! assert (c, [0.94; 0.87], 0.01);
+
+%!test
+%! str =  "0.31,0.86,0.94\n0.60,0.72,0.87";
+%! fmt = "%f %f %f";
+%! args = {"delimiter", ",", "endofline", "\n", "whitespace", " "};
+%! [a, b, c] = strread (str, fmt, args{:});
+%! assert (a, [0.31; 0.60], 0.01);
+%! assert (b, [0.86; 0.72], 0.01);
+%! assert (c, [0.94; 0.87], 0.01);
+
+%!test
+%! str =  "0.31 0.86 0.94\n 0.60 0.72 0.87";
+%! fmt = "%f %f %f";
+%! args = {"delimiter", ",", "endofline", "\n", "whitespace", " "};
+%! [a, b, c] = strread (str, fmt, args{:});
+%! assert (a, [0.31; 0.60], 0.01);
+%! assert (b, [0.86; 0.72], 0.01);
+%! assert (c, [0.94; 0.87], 0.01);
+
+%!test
+%! str =  "0.31, 0.86, 0.94\n 0.60, 0.72, 0.87";
+%! fmt = "%f %f %f";
+%! args = {"delimiter", ",", "endofline", "\n", "whitespace", " "};
+%! [a, b, c] = strread (str, fmt, args{:});
+%! assert (a, [0.31; 0.60], 0.01);
+%! assert (b, [0.86; 0.72], 0.01);
+%! assert (c, [0.94; 0.87], 0.01);
+
+%!test
+%! [a, b] = strread (["Empty 1" char(10)], "Empty%s %f");
+%! assert (a{1}, '1');
+%! assert (b, NaN);
+
+%!test
+%! [a, b] = strread (["Empty" char(10)], "Empty%f %f");
+%! assert (a, NaN);
+%! assert (b, NaN);
+
+%!test <*35999>
+%! [a, b, c] = strread ("", "%f");
+%! assert (isempty (a));
+%! assert (isempty (b));
+%! assert (isempty (c));
+
+%!test <*37023>
+%! [a, b] = strread (" 1. 1 \n  2 3 \n", "%f %f", "endofline", "\n");
+%! assert (a, [1; 2], 1e-15);
+%! assert (b, [1; 3], 1e-15);
+
+## Test for no output arg (interactive use)
+%!assert (strread (",2,,4\n5,,7,", "", "delimiter", ","),
+%!        [NaN; 2; NaN; 4; 5; NaN; 7])
+
+## Test #1 bug #42609
+%!test <*42609>
+%! [a, b, c] = strread ("1 2 3\n4 5 6\n7 8 9\n", "%f %f %f\n");
+%! assert (a, [1; 4; 7]);
+%! assert (b, [2; 5; 8]);
+%! assert (c, [3; 6; 9]);
+
+## Test #2 bug #42609
+%!test <*42609>
+%! [a, b, c] = strread ("1 2\n3\n4 5\n6\n7 8\n9\n", "%f %f\n%f");
+%! assert (a, [1;4;7]);
+%! assert (b, [2; 5; 8]);
+%! assert (c, [3; 6; 9]);
+
+## Test #3 bug #42609
+%!test <*42609>
+%! [a, b, c] = strread ("1 2 3\n4 5 6\n7 8 9\n", '%f %f %f\n');
+%! assert (a, [1; 4; 7]);
+%! assert (b, [2; 5; 8]);
+%! assert (c, [3; 6; 9]);
+
+## Test #4 bug #42609
+%!test <*42609>
+%! [a, b, c] = strread ("1 2\n3\n4 5\n6\n7 8\n9\n", '%f %f\n%f');
+%! assert (a, [1;4;7]);
+%! assert (b, [2; 5; 8]);
+%! assert (c, [3; 6; 9]);
+
+## Unsupported format specifiers
+%!error <format specifiers are not supported> strread ("a", "%c")
+%!error <format specifiers are not supported> strread ("a", "%*c %d")
+%!error <format specifiers are not supported> strread ("a", "%q")
+%!error <format specifiers are not supported> strread ("a", "%*q %d")
+%!error <format specifiers are not supported> strread ("a", "%[a]")
+%!error <format specifiers are not supported> strread ("a", "%*[a] %d")
+%!error <format specifiers are not supported> strread ("a", "%[^a]")
+%!error <format specifiers are not supported> strread ("a", "%*[^a] %d")
+%!error <format specifiers are not supported> strread ("a", "%d8")
+%!error <format specifiers are not supported> strread ("a", "%*d8 %s")
+%!error <format specifiers are not supported> strread ("a", "%f64")
+%!error <format specifiers are not supported> strread ("a", "%*f64 %s")
+%!error <format specifiers are not supported> strread ("a", "%u32")
+%!error <format specifiers are not supported> strread ("a", "%*u32 %d")
+
+## Illegal format specifiers
+%!error <no valid format conversion specifiers> strread ("1.0", "%z")
+
+## Test for false positives in check for non-supported format specifiers
+%!assert (strread ("Total: 32.5 % (of cm values)","Total: %f % (of cm values)"), 32.5, 1e-5)
+
+## Test various forms of string format specifiers
+%!test <*45712>
+%! str = "14 :1 z:2 z:3 z:5 z:11";
+%! [a, b, c, d] = strread (str, "%f %s %*s %3s %*3s %f", "delimiter", ":");
+%! assert ({a, b, c, d}, {14, {"1 z"}, {"3 z"}, 11});
+
+## Allow cuddling %sliteral but warn that it is ambiguous
+%!warning <Ambiguous '%s' specifier immediately before literal in column 1>
+%! [a, b] = strread ("abcxyz51\nxyz83\n##xyz101", "%s xyz %d");
+%! assert (a([1 3]), {"abc"; "##"});
+%! assert (isempty (a{2}), true);
+%! assert (b, int32([51; 83; 101]));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/legacy/textread.m	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,529 @@
+## Copyright (C) 2009-2018 Eric Chassande-Mottin, CNRS (France)
+##
+## 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
+## <https://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {} {[@var{a}, @dots{}] =} textread (@var{filename})
+## @deftypefnx {} {[@var{a}, @dots{}] =} textread (@var{filename}, @var{format})
+## @deftypefnx {} {[@var{a}, @dots{}] =} textread (@var{filename}, @var{format}, @var{n})
+## @deftypefnx {} {[@var{a}, @dots{}] =} textread (@var{filename}, @var{format}, @var{prop1}, @var{value1}, @dots{})
+## @deftypefnx {} {[@var{a}, @dots{}] =} textread (@var{filename}, @var{format}, @var{n}, @var{prop1}, @var{value1}, @dots{})
+##
+## This function is obsolete.  Use @code{textscan} instead.
+##
+## 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.
+##
+## In addition to the options supported by @code{strread}, this function
+## supports two more:
+##
+## @itemize
+## @item @qcode{"headerlines"}:
+## The first @var{value} number of lines of @var{filename} are skipped.
+##
+## @item @qcode{"endofline"}:
+## Specify a single character or
+## @qcode{"@xbackslashchar{}r@xbackslashchar{}n"}.  If no value is given, it
+## will be inferred from the file.  If set to @qcode{""} (empty string) EOLs
+## are ignored as delimiters.
+## @end itemize
+##
+## The optional input @var{n} (format repeat count) specifies the number of
+## times the format string is to be used or the number of lines to be read,
+## whichever happens first while reading.  The former is equivalent to
+## requesting that the data output vectors should be of length @var{N}.
+## Note that when reading files with format strings referring to multiple
+## lines, @var{n} should rather be the number of lines to be read than the
+## number of format string uses.
+##
+## If the format string is empty (not just omitted) and the file contains only
+## numeric data (excluding headerlines), textread will return a rectangular
+## matrix with the number of columns matching the number of numeric fields on
+## the first data line of the file.  Empty fields are returned as zero values.
+##
+## Examples:
+##
+## @example
+## @group
+##   Assume a data file like:
+##   1 a 2 b
+##   3 c 4 d
+##   5 e
+## @end group
+## @end example
+##
+## @example
+## @group
+##   [a, b] = textread (f, "%f %s")
+##   returns two columns of data, one with doubles, the other a
+##   cellstr array:
+##   a = [1; 2; 3; 4; 5]
+##   b = @{"a"; "b"; "c"; "d"; "e"@}
+## @end group
+## @end example
+##
+## @example
+## @group
+##   [a, b] = textread (f, "%f %s", 3)
+##   (read data into two culumns, try to use the format string
+##   three times)
+##   returns
+##   a = [1; 2; 3]
+##   b = @{"a"; "b"; "c"@}
+##
+## @end group
+## @end example
+##
+## @example
+## @group
+##   With a data file like:
+##   1
+##   a
+##   2
+##   b
+##
+##   [a, b] = textread (f, "%f %s", 2)
+##   returns a = 1 and b = @{"a"@}; i.e., the format string is used
+##   only once because the format string refers to 2 lines of the
+##   data file.  To obtain 2x1 data output columns, specify N = 4
+##   (number of data lines containing all requested data) rather
+##   than 2.
+## @end group
+## @end example
+##
+## @seealso{textscan, load, dlmread, fscanf, strread}
+## @end deftypefn
+
+function varargout = textread (filename, format = "%f", varargin)
+
+  persistent warned = false;
+  if (! warned)
+    warned = true;
+    warning ("Octave:legacy-function",
+             "textread is obsolete; use textscan instead\n");
+  endif
+
+  ## Check input
+  if (nargin < 1)
+    print_usage ();
+  endif
+
+  if (! ischar (filename) || ! ischar (format))
+    error ("textread: FILENAME and FORMAT arguments must be strings");
+  endif
+
+  if (! isempty (varargin) && isnumeric (varargin{1}))
+    nlines = varargin{1};
+  else
+    nlines = Inf;
+  endif
+  if (nlines < 1)
+    printf ("textread: N = 0, no data read\n");
+    varargout = cell (1, nargout);
+    return;
+  endif
+
+  BUFLENGTH = 4096;       # Read buffer to speed up processing @var{n}
+
+  ## Read file
+  fid = fopen (filename, "r");
+  if (fid == -1)
+    error ("textread: could not open '%s' for reading", filename);
+  endif
+
+  ## Skip header lines if requested
+  headerlines = find (strcmpi (varargin, "headerlines"), 1);
+  if (! isempty (headerlines))
+    ## Beware of missing or wrong headerline value
+    if (headerlines == numel (varargin)
+       || ! isnumeric (varargin{headerlines + 1}))
+      error ("textread: missing or invalid value for 'headerlines'" );
+    endif
+    ## Avoid conveying floats to fskipl
+    varargin{headerlines + 1} = round (varargin{headerlines + 1});
+    ## Beware of zero valued headerline, fskipl would skip to EOF
+    if (varargin{headerlines + 1} > 0)
+      fskipl (fid, varargin{headerlines + 1});
+    elseif (varargin{headerlines + 1} < 0)
+      warning ("textread: negative headerline value ignored");
+    endif
+    varargin(headerlines:headerlines+1) = [];
+  endif
+  st_pos = ftell (fid);
+
+  ## Read a first file chunk.  Rest follows after endofline processing
+  [str, count] = fscanf (fid, "%c", BUFLENGTH);
+  if (isempty (str) || count < 1)
+    warning ("textread: empty file");
+    varargout = cell (1, nargout);
+    return;
+  endif
+
+  endofline = find (strcmpi (varargin, "endofline"), 1);
+  if (! isempty (endofline))
+    ## 'endofline' option set by user.
+    if (ischar (varargin{endofline + 1}))
+      eol_char = varargin{endofline + 1};
+      if (strcmp (typeinfo (eol_char), "sq_string"))
+        eol_char = do_string_escapes (eol_char);
+      endif
+      if (! any (strcmp (eol_char, {"", "\n", "\r", "\r\n"})))
+        error ("textread: invalid EndOfLine character value specified");
+      endif
+    else
+      error ("textread: character value required for EndOfLine");
+    endif
+  else
+    ## Determine EOL from file.
+    ## Search for EOL candidates in the first BUFLENGTH chars
+    ## FIXME: Ignore risk of 2-byte EOL (\r\n) being split at exactly BUFLENGTH
+    eol_srch_len = min (length (str), BUFLENGTH);
+    ## First try DOS (CRLF)
+    if (! isempty (strfind (str(1 : eol_srch_len), "\r\n")))
+      eol_char = "\r\n";
+    ## Perhaps old Macintosh? (CR)
+    elseif (! isempty (strfind (str(1 : eol_srch_len), "\r")))
+      eol_char = "\r";
+    ## Otherwise, use plain *nix (LF)
+    else
+      eol_char = "\n";
+    endif
+    ## Set up default endofline param value
+    varargin(end+1:end+2) = {"endofline", eol_char};
+  endif
+
+  ## Now that we know what EOL looks like, we can process format_repeat_count.
+  ## FIXME: The below isn't ML-compatible: counts lines, not format string uses
+  if (isfinite (nlines) && (nlines > 0))
+    l_eol_char = length (eol_char);
+    eoi = strfind (str, eol_char);
+    n_eoi = length (eoi);
+    nblks = 0;
+    ## Avoid slow repeated str concatenation, first seek requested end of data
+    while (n_eoi < nlines && count == BUFLENGTH)
+      [nstr, count] = fscanf (fid, "%c", BUFLENGTH);
+      if (count > 0)
+        ## Watch out for multichar EOL being missed across buffer boundaries
+        if (l_eol_char > 1)
+          str = [str(end - length (eol_char) + 2 : end) nstr];
+        else
+          str = nstr;
+        endif
+        eoi = strfind (str, eol_char);
+        n_eoi += numel (eoi);
+        ++nblks;
+      endif
+    endwhile
+    ## Handle case of missing or incomplete trailing EOL
+    if (! strcmp (str(end - length (eol_char) + 1 : end), eol_char))
+      eoi = [ eoi (length (str)) ];
+      ++n_eoi;
+    endif
+    ## Found EOL delimiting last requested line.  Compute ptr (incl. EOL)
+    if (isempty (eoi))
+      eoi_pos = nblks * BUFLENGTH + count;
+    else
+      eoi_pos = (nblks * BUFLENGTH) + eoi(end + min (nlines, n_eoi) - n_eoi);
+    endif
+    fseek (fid, st_pos, "bof");
+    str = fscanf (fid, "%c", eoi_pos);
+  else
+    fseek (fid, st_pos, "bof");
+    str = fread (fid, "char=>char").';
+  endif
+  fclose (fid);
+
+  ## 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
+  warning ("off", "Octave:legacy-function", "local");
+  [varargout{1:max (nargout, 1)}] = strread (str, format, varargin{:});
+
+  ## Hack to concatenate/reshape numeric output into 2D array (undocumented ML)
+  ## In ML this only works in case of an empty format string
+  if (isempty (format))
+    ## Get number of fields per line.
+    ## 1. Get eol_char position
+    iwhsp = find (strcmpi ("whitespace", varargin));
+    whsp = varargin{iwhsp + 1};
+    idx = regexp (str, eol_char, "once");
+    ## 2. Get first data line til EOL. Avoid corner case of just one line
+    if (! isempty (idx))
+      str = str(1:idx-1);
+    endif
+    idelimiter = find (strcmpi (varargin, "delimiter"), 1);
+    if (isempty (idelimiter))
+      ## Assume delimiter = whitespace
+      ## 3A. whitespace incl. consecutive whitespace => single space
+      str = regexprep (str, sprintf ("[%s]+", whsp), ' ');
+      ## 4A. Remove possible leading & trailing spaces
+      str = strtrim (str);
+      ## 5A. Count spaces, add one to get nr of data fields per line
+      ncols = numel (strfind (str, " ")) + 1;
+    else
+      ## 3B. Just count delimiters. FIXME: delimiters could occur in literals
+      delimiter = varargin{idelimiter+1};
+      ncols = numel (regexp (str, sprintf ("[%s]", delimiter))) + 1;
+    endif
+    ## 6. Reshape; watch out, we need a transpose
+    nrows = ceil (numel (varargout{1}) / ncols);
+    pad = mod (numel (varargout{1}), ncols);
+    if (pad > 0)
+      pad = ncols - pad;
+      varargout{1}(end+1 : end+pad) = NaN;
+    endif
+    varargout{1} = reshape (varargout{1}, ncols, nrows)';
+    ## ML replaces empty values with NaNs
+    varargout{1}(find (isnan (varargout{1}))) = 0;
+  endif
+
+endfunction
+
+
+## First test is necessary to provoke 1-time legacy warning
+%!test
+%! warning ("off", "Octave:legacy-function", "local");
+%! try
+%!   textread ("");
+%! catch
+%!   ## Nothing to do, just wanted to suppress error.
+%! end_try_catch
+
+%!test
+%! f = tempname ();
+%! 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
+%! f = tempname ();
+%! d = rand (7, 2);
+%! dlmwrite (f, d, "precision", "%5.2f");
+%! [a, b] = textread (f, "%f, %f", "headerlines", 1);
+%! unlink (f);
+%! assert (a, d(2:7, 1), 1e-2);
+
+## Test reading 2D matrix with empty format
+%!test
+%! f = tempname ();
+%! d = rand (5, 2);
+%! dlmwrite (f, d, "precision", "%5.2f");
+%! A = textread (f, "", "headerlines", 3);
+%! unlink (f);
+%! assert (A, d(4:5, :), 1e-2);
+
+## Read multiple lines using empty format string
+%!test
+%! f = tempname ();
+%! unlink (f);
+%! fid = fopen (f, "w");
+%! d = rand (1, 4);
+%! fprintf (fid, "  %f %f   %f  %f ", d);
+%! fclose (fid);
+%! A = textread (f, "");
+%! unlink (f);
+%! assert (A, d, 1e-6);
+
+## Empty format, corner case = one line w/o EOL
+%!test
+%! f = tempname ();
+%! unlink (f);
+%! fid = fopen (f, "w");
+%! d = rand (1, 4);
+%! fprintf (fid, "  %f %f   %f  %f ", d);
+%! fclose (fid);
+%! A = textread (f, "");
+%! unlink (f);
+%! assert (A, d, 1e-6);
+
+## Tests with format repeat count #1
+%!test
+%! f = tempname ();
+%! fid = fopen (f, "w");
+%! fprintf (fid, "%2d %s %2d %s\n %2d %s %2d %s \n", ...
+%!                10, "a", 20, "b", 30, "c", 40, "d");
+%! fclose (fid);
+%! [a, b] = textread (f, "%d %s", 1);
+%! assert (a, int32 (10));
+%! assert (b, {"a"});
+%! [a, b] = textread (f, "%d %s", 2);
+%! assert (a, int32 ([10; 20]));
+%! assert (b, {"a"; "b"});
+%! [a, b] = textread (f, "%d %s", 3);
+%! assert (a, int32 ([10; 20; 30]));
+%! assert (b, {"a"; "b"; "c"});
+%! [a, b] = textread (f, "%d %s", 4);
+%! assert (a, int32 ([10; 20; 30; 40]));
+%! assert (b, {"a"; "b"; "c"; "d"});
+%! [a, b] = textread (f, "%d %s", 5);
+%! assert (a, int32 ([10; 20; 30; 40]));
+%! assert (b, {"a"; "b"; "c"; "d"});
+%! unlink (f);
+
+## Tests with format repeat count #2, missing last EOL
+%!test
+%! f = tempname ();
+%! fid = fopen (f, "w");
+%! fprintf (fid, "%2d %s %2d %s\n %2d %s %2d %s", ...
+%!                10, "a", 20, "b", 30, "c", 40, "d");
+%! fclose (fid);
+%! [a, b] = textread (f, "%d %s", 1);
+%! assert (a, int32 (10));
+%! assert (b, {"a"});
+%! [a, b] = textread (f, "%d %s", 2);
+%! assert (a, int32 ([10; 20]));
+%! assert (b, {"a"; "b"});
+%! [a, b] = textread (f, "%d %s", 3);
+%! assert (a, int32 ([10; 20; 30]));
+%! assert (b, {"a"; "b"; "c"});
+%! [a, b] = textread (f, "%d %s", 4);
+%! assert (a, int32 ([10; 20; 30; 40]));
+%! assert (b, {"a"; "b"; "c"; "d"});
+%! [a, b] = textread (f, "%d %s", 5);
+%! assert (a, int32 ([10; 20; 30; 40]));
+%! assert (b, {"a"; "b"; "c"; "d"});
+%! unlink (f);
+
+## Tests with format repeat count #3, incomplete last line
+%!test
+%! f = tempname ();
+%! fid = fopen (f, "w");
+%! fprintf (fid, "%2d %s %2d %s\n %2d %s %2d", ...
+%!                10, "a", 20, "b", 30, "c", 40);
+%! fclose (fid);
+%! [a, b] = textread (f, "%d %s", 1);
+%! assert (a, int32 (10));
+%! assert (b, {"a"});
+%! [a, b] = textread (f, "%d %s", 2);
+%! assert (a, int32 ([10; 20]));
+%! assert (b, {"a"; "b"});
+%! [a, b] = textread (f, "%d %s", 3);
+%! assert (a, int32 ([10; 20; 30]));
+%! assert (b, {"a"; "b"; "c"});
+%! [a, b] = textread (f, "%d %s", 4);
+%! assert (a, int32 ([10; 20; 30; 40]));
+%! assert (b, {"a"; "b"; "c"});
+%! [a, b] = textread (f, "%d %s", 5);
+%! assert (a, int32 ([10; 20; 30; 40]));
+%! assert (b, {"a"; "b"; "c"});
+%! unlink (f);
+
+## Tests with format repeat count #4, incomplete last line but with trailing EOL
+%!test
+%! f = tempname ();
+%! fid = fopen (f, "w");
+%! fprintf (fid, "%2d %s %2d %s\n %2d %s %2d\n", ...
+%!                10, "a", 20, "b", 30, "c", 40);
+%! fclose (fid);
+%! [a, b] = textread (f, "%d %s", 4);
+%! assert (a, int32 ([10; 20; 30; 40]));
+%! assert (b, {"a"; "b"; "c"; ""});
+%! [a, b] = textread (f, "%d %s", 5);
+%! assert (a, int32 ([10; 20; 30; 40]));
+%! assert (b, {"a"; "b"; "c"; ""});
+%! unlink (f);
+
+### Tests with format repeat count #5, nr of data lines = limiting factor
+#%!test
+#%! f = tempname ();
+#%! fid = fopen (f, "w");
+#%! fprintf (fid, "%2d\n%s\n%2dn%s", ...
+#%!                1, "a", 2, "b");
+#%! fclose (fid);
+#%! [a, b] = textread (f, "%d %s", 2);
+#%! assert (a, int32 (1));
+#%! assert (b, {"a"});
+
+### Read multiple lines using empty format string, missing data (should be 0)
+#%!test
+#%! f = tempname ();
+#%! unlink (f);
+#%! fid = fopen (f, "w");
+#%! d = rand (1, 4);
+#%! fprintf (fid, "%f, %f, ,  %f,  %f ", d);
+#%! fclose (fid);
+#%! A = textread (f, "");
+#%! unlink (f);
+#%! assert (A, [ d(1:2) 0 d(3:4)], 1e-6);
+
+### Test with empty positions - ML returns 0 for empty fields
+#%!test
+#%! f = tempname ();
+#%! unlink (f);
+#%! fid = fopen (f, "w");
+#%! d = rand (1, 4);
+#%! fprintf (fid, ",2,,4\n5,,7,\n");
+#%! fclose (fid);
+#%! A = textread (f, "", "delimiter", ",");
+#%! unlink (f);
+#%! assert (A, [0 2 0 4; 5 0 7 0], 1e-6);
+
+### Another test with empty format + positions, now with more incomplete lower
+### row (must be appended with zeros to get rectangular matrix)
+#%!test
+#%! f = tempname ();
+#%! unlink (f);
+#%! fid = fopen (f, "w");
+#%! d = rand (1, 4);
+#%! fprintf (fid, ",2,,4\n5,\n");
+#%! fclose (fid);
+#%! A = textread (f, "", "delimiter", ",");
+#%! unlink (f);
+#%! assert (A, [0 2 0 4; 5 0 0 0], 1e-6);
+
+### Test endofline
+#%!test <*45046>
+#%! f = tempname ();
+#%! fid = fopen (f, "w");
+#%! fprintf (fid, "a\rb\rc");
+#%! fclose (fid);
+#%! ## Test EOL detection
+#%! d = textread (f, "%s");
+#%! assert (d, {"a";"b";"c"});
+#%! ## Test explicit EOL specification (bug #45046)
+#%! d = textread (f, "%s", "endofline", "\r");
+#%! assert (d, {"a"; "b"; "c"});
+#%! unlink (f);
+
+### Properly process single-quoted EOL args
+#%!test <*46477>
+#%! f = tempname ();
+#%! fid = fopen (f, "w");
+#%! fprintf (fid, "hello, world!");
+#%! fclose (fid);
+#%! [a, b] = textread (f, "%s%s", "endofline", '\n');
+#%! assert (a{1}, "hello,");
+#%! assert (b{1}, "world!");
+
+### Test input validation
+#%!error textread ()
+#%!error textread (1)
+#%!error <arguments must be strings> textread (1, "%f")
+#%!error <arguments must be strings> textread ("fname", 1)
+#%!error <missing or invalid value for> textread (file_in_loadpath ("textread.m"), "", "headerlines")
+#%!error <missing or invalid value for> textread (file_in_loadpath ("textread.m"), "", "headerlines", 'hh')
+#%!error <character value required for> textread (file_in_loadpath ("textread.m"), "%s", "endofline", true)
--- a/scripts/linear-algebra/condest.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/linear-algebra/condest.m	Fri Aug 10 09:09:51 2018 +0200
@@ -146,18 +146,6 @@
     print_usage ();
   endif
 
-  if ((nargin == 3 && is_function_handle (varargin{3}))
-      || (nargin == 4 && is_function_handle (varargin{3})
-          && isnumeric (varargin{4})))
-    ## onenormest syntax, deprecated in 4.2
-    [cest, v] = condest_legacy (varargin{:});
-    return;
-  elseif ((nargin >= 5) && is_function_handle (varargin{4}))
-    ## onenormest syntax, deprecated in 4.2
-    [cest, v] = condest_legacy (varargin{:});
-    return;
-  endif
-
   have_A = false;
   have_t = false;
   have_apply_normest1 = false;
@@ -254,97 +242,6 @@
   endswitch
 endfunction
 
-## FIXME: remove after 4.4
-function [cest, v] = condest_legacy (varargin)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "condest: this syntax is deprecated, call condest (A, SOLVEFUN, T, P1, P2, ...) instead.");
-  endif
-
-  default_t = 5;
-
-  have_A = false;
-  have_t = false;
-  have_solve = false;
-  if (isnumeric (varargin{1}))
-    A = varargin{1};
-    if (! issquare (A))
-      error ("condest: matrix must be square");
-    endif
-    n = rows (A);
-    have_A = true;
-
-    if (nargin > 1)
-      if (! is_function_handle (varargin{2}))
-        t = varargin{2};
-        have_t = true;
-      elseif (nargin > 2)
-        solve = varargin{2};
-        solve_t = varargin{3};
-        have_solve = true;
-        if (nargin > 3)
-          t = varargin{4};
-          have_t = true;
-        endif
-      else
-        error ("condest: must supply both SOLVE and SOLVE_T");
-      endif
-    endif
-  elseif (nargin > 4)
-    apply = varargin{1};
-    apply_t = varargin{2};
-    solve = varargin{3};
-    solve_t = varargin{4};
-    have_solve = true;
-    n = varargin{5};
-    if (! isscalar (n))
-      error ("condest: dimension argument of implicit form must be scalar");
-    endif
-    if (nargin > 5)
-      t = varargin{6};
-      have_t = true;
-    endif
-  else
-    error ("condest: implicit form of condest requires at least 5 arguments");
-  endif
-
-  if (! have_t)
-    t = min (n, default_t);
-  endif
-
-  if (! have_solve)
-    if (issparse (A))
-      [L, U, P, Pc] = lu (A);
-      solve = @(x) Pc' * (U \ (L \ (P * x)));
-      solve_t = @(x) P' * (L' \ (U' \ (Pc * x)));
-    else
-      [L, U, P] = lu (A);
-      solve = @(x) U \ (L \ (P*x));
-      solve_t = @(x) P' * (L' \ (U' \ x));
-    endif
-  endif
-
-  ## We already warned about this usage being deprecated.
-  ## Don't warn again about onenormest.
-  warning ("off", "Octave:deprecated-function", "local");
-
-  if (have_A)
-    Anorm = norm (A, 1);
-  else
-    Anorm = onenormest (apply, apply_t, n, t);
-  endif
-
-  [Ainv_norm, v, w] = onenormest (solve, solve_t, n, t);
-
-  cest = Anorm * Ainv_norm;
-  v = w / norm (w, 1);
-
-endfunction
-
-
 ## Note: These test bounds are very loose.  There is enough randomization to
 ## trigger odd cases with hilb().
 
@@ -386,35 +283,6 @@
 %! cA_test = norm (inv (A), 1) * norm (A, 1);
 %! assert (cA, cA_test, -2^-8);
 
-%!test # to be removed after 4.4
-%! warning ("off", "Octave:deprecated-function", "local");
-%! N = 6;
-%! A = hilb (N);
-%! solve = @(x) A\x; solve_t = @(x) A'\x;
-%! cA = condest (A, solve, solve_t);
-%! cA_test = norm (inv (A), 1) * norm (A, 1);
-%! assert (cA, cA_test, -2^-8);
-
-%!test # to be removed after 4.4
-%! warning ("off", "Octave:deprecated-function", "local");
-%! N = 6;
-%! A = hilb (N);
-%! apply = @(x) A*x; apply_t = @(x) A'*x;
-%! solve = @(x) A\x; solve_t = @(x) A'\x;
-%! cA = condest (apply, apply_t, solve, solve_t, N);
-%! cA_test = norm (inv (A), 1) * norm (A, 1);
-%! assert (cA, cA_test, -2^-6);
-
-%!test # to be removed after 4.4
-%! warning ("off", "Octave:deprecated-function", "local");
-%! N = 6;
-%! A = hilb (N);
-%! apply = @(x) A*x; apply_t = @(x) A'*x;
-%! solve = @(x) A\x; solve_t = @(x) A'\x;
-%! cA = condest (apply, apply_t, solve, solve_t, N, 2);
-%! cA_test = norm (inv (A), 1) * norm (A, 1);
-%! assert (cA, cA_test, -2^-6);
-
 %!test
 %! warning ("off", "Octave:nearly-singular-matrix", "local");
 %! N = 12;
--- a/scripts/linear-algebra/expm.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/linear-algebra/expm.m	Fri Aug 10 09:09:51 2018 +0200
@@ -82,7 +82,10 @@
     error ("expm: A must be a square matrix");
   endif
 
-  if (isscalar (A))
+  if (isempty (A))
+    r = A;
+    return;
+  elseif (isscalar (A))
     r = exp (A);
     return;
   elseif (strfind (typeinfo (A), "diagonal matrix"))
@@ -91,36 +94,31 @@
   endif
 
   n = rows (A);
+  id = eye (n);
   ## Trace reduction.
   A(A == -Inf) = -realmax;
-  trshift = trace (A) / length (A);
+  trshift = trace (A) / n;
   if (trshift > 0)
-    A -= trshift*eye (n);
+    A -= trshift * id;
   endif
   ## Balancing.
   [d, p, aa] = balance (A);
-  ## FIXME: can we both permute and scale at once? Or should we rather do
-  ## this:
-  ##
-  ##   [d, xx, aa] = balance (A, "noperm");
-  ##   [xx, p, aa] = balance (aa, "noscal");
-  [f, e] = log2 (norm (aa, "inf"));
+  [~, e] = log2 (norm (aa, "inf"));
   s = max (0, e);
   s = min (s, 1023);
   aa *= 2^(-s);
 
   ## Pade approximation for exp(A).
-  c = [5.0000000000000000e-1,...
-       1.1666666666666667e-1,...
-       1.6666666666666667e-2,...
-       1.6025641025641026e-3,...
-       1.0683760683760684e-4,...
-       4.8562548562548563e-6,...
-       1.3875013875013875e-7,...
+  c = [5.0000000000000000e-1, ...
+       1.1666666666666667e-1, ...
+       1.6666666666666667e-2, ...
+       1.6025641025641026e-3, ...
+       1.0683760683760684e-4, ...
+       4.8562548562548563e-6, ...
+       1.3875013875013875e-7, ...
        1.9270852604185938e-9];
 
   a2 = aa^2;
-  id = eye (n);
   x = (((c(8) * a2 + c(6) * id) * a2 + c(4) * id) * a2 + c(2) * id) * a2 + id;
   y = (((c(7) * a2 + c(5) * id) * a2 + c(3) * id) * a2 + c(1) * id) * aa;
 
@@ -136,7 +134,7 @@
   r = d * r / d;
   r(p, p) = r;
   ## Inverse trace reduction.
-  if (trshift >0)
+  if (trshift > 0)
     r *= exp (trshift);
   endif
 
@@ -146,11 +144,13 @@
 %!assert (norm (expm ([1 -1;0 1]) - [e -e; 0 e]) < 1e-5)
 %!assert (expm ([1 -1 -1;0 1 -1; 0 0 1]), [e -e -e/2; 0 e -e; 0 0 e], 1e-5)
 
-%!assert (expm (10), expm (10))
+%!assert (expm ([]), [])
+%!assert (expm (10), exp (10))
 %!assert (full (expm (eye (3))), expm (full (eye (3))))
 %!assert (full (expm (10*eye (3))), expm (full (10*eye (3))), 8*eps)
 
 ## Test input validation
 %!error expm ()
 %!error expm (1, 2)
+%!error <expm: A must be a square matrix> expm ({1})
 %!error <expm: A must be a square matrix> expm ([1 0;0 1; 2 2])
--- a/scripts/linear-algebra/isdiag.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/linear-algebra/isdiag.m	Fri Aug 10 09:09:51 2018 +0200
@@ -30,7 +30,7 @@
     print_usage ();
   endif
 
-  if (strcmp (typeinfo (A), "diagonal matrix"))
+  if (strfind (typeinfo (A), "diagonal matrix"))
     retval = true;
   elseif ((isnumeric (A) || islogical (A)) && ndims (A) == 2)
     [i, j] = find (A);
@@ -49,8 +49,9 @@
 %!assert (isdiag ([1, 1]), false)
 %!assert (isdiag ([1; 1]), false)
 %!assert (isdiag (eye (10)))
+%!assert (isdiag (single (eye (10))))
 %!assert (isdiag (logical (eye (10))))
-%!assert (isdiag (speye (1e6)))
+%!assert (isdiag (speye (1e2)))
 %!assert (isdiag (diag (1:10)))
 
 ## Test input validation
--- a/scripts/linear-algebra/ishermitian.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/linear-algebra/ishermitian.m	Fri Aug 10 09:09:51 2018 +0200
@@ -20,13 +20,27 @@
 ## -*- texinfo -*-
 ## @deftypefn  {} {} ishermitian (@var{A})
 ## @deftypefnx {} {} ishermitian (@var{A}, @var{tol})
-## Return true if @var{A} is Hermitian within the tolerance specified by
-## @var{tol}.
+## @deftypefnx {} {} ishermitian (@var{A}, @qcode{"skew"})
+## @deftypefnx {} {} ishermitian (@var{A}, @qcode{"skew"}, @var{tol})
+## Return true if @var{A} is a Hermitian or skew-Hermitian matrix within the
+## tolerance specified by @var{tol}.
 ##
 ## The default tolerance is zero (uses faster code).
 ##
-## Matrix @var{A} is considered symmetric if
+## The type of symmetry to check may be specified with the additional input
+## @qcode{"nonskew"} (default) for regular Hermitian or @qcode{"skew"} for
+## skew-Hermitian.
+##
+## Background: A matrix is Hermitian if the complex conjugate transpose of the
+## matrix is equal to the original matrix: @w{@tcode{@var{A} == @var{A}'}}.  If
+## a tolerance is given then the calculation is
 ## @code{norm (@var{A} - @var{A}', Inf) / norm (@var{A}, Inf) < @var{tol}}.
+##
+## A matrix is skew-hermitian if the complex conjugate transpose of the matrix
+## is equal to the negative of the original matrix:
+## @w{@tcode{@var{A} == -@var{A}'}}.  If a
+## tolerance is given then the calculation is
+## @code{norm (@var{A} + @var{A}', Inf) / norm (@var{A}, Inf) < @var{tol}}.
 ## @seealso{issymmetric, isdefinite}
 ## @end deftypefn
 
@@ -34,19 +48,52 @@
 ## Created: August 1993
 ## Adapted-By: jwe
 
-function retval = ishermitian (A, tol = 0)
+function retval = ishermitian (A, skewopt = "nonskew", tol = 0)
 
-  if (nargin < 1 || nargin > 2)
+  if (nargin < 1 || nargin > 3)
     print_usage ();
   endif
 
-  retval = isnumeric (A) && issquare (A);
-  if (retval)
+  if (nargin == 2)
+    ## Decode whether second argument is skewopt or tol
+    if (isnumeric (skewopt))
+      tol = skewopt;
+      skewopt = "nonskew";
+    elseif (! ischar (skewopt))
+      error ("ishermitian: second argument must be a non-negative scalar TOL, or one of the strings: 'skew' / 'nonskew'");
+    endif
+  endif
+
+  ## Validate inputs
+  retval = (isnumeric (A) || islogical (A)) && issquare (A);
+  if (! retval)
+    return;
+  endif
+
+  if (! (strcmp (skewopt, "skew") || strcmp (skewopt, "nonskew")))
+    error ("ishermitian: SKEWOPT must be 'skew' or 'nonskew'");
+  endif
+
+  if (! (isnumeric (tol) && isscalar (tol) && tol >= 0))
+    error ("ishermitian: TOL must be a scalar >= 0");
+  endif
+
+  ## Calculate Hermitian-ness
+  if (strcmp (skewopt, "nonskew"))
     if (tol == 0)
-      retval = all ((A == A')(:));
+      ## check for exact symmetry
+      retval = ! any ((A != A')(:));
     else
-      norm_x = norm (A, inf);
-      retval = norm_x == 0 || norm (A - A', inf) / norm_x <= tol;
+      norm_x = norm (A, Inf);
+      retval = norm_x == 0 || norm (A - A', Inf) / norm_x <= tol;
+    endif
+  else
+    ## skew-Hermitian
+    if (tol == 0)
+      retval = ! any ((A != -A')(:));
+    else
+      norm_x = norm (A, Inf);
+      retval = norm_x == 0 || norm (A + A', Inf) / norm_x <= tol;
     endif
   endif
 
@@ -57,15 +104,28 @@
 %!assert (! ishermitian ([1, 2]))
 %!assert (ishermitian ([]))
 %!assert (ishermitian ([1, 2; 2, 1]))
-%!assert (! ishermitian ("test"))
 %!assert (ishermitian ([1, 2.1; 2, 1.1], 0.2))
 %!assert (ishermitian ([1, -2i; 2i, 1]))
-%!assert (! ishermitian ("t"))
-%!assert (! ishermitian (["te"; "et"]))
+%!assert (ishermitian (speye (100)))
+%!assert (ishermitian (logical (eye (2))))
+%!assert (ishermitian ([0, 2i; 2i, 0], "skew"))
+%!assert (! ishermitian ([0, 2; -2, eps], "skew"))
+%!assert (ishermitian ([0, 2; -2, eps], "skew", eps))
 
+%!assert (! (ishermitian ("test")))
+%!assert (! (ishermitian ("t")))
+%!assert (! (ishermitian (["te"; "et"])))
+%!assert (! ishermitian ({1}))
 %!test
 %! s.a = 1;
 %! assert (! ishermitian (s));
 
-%!error ishermitian ([1, 2; 2, 1], 0, 0)
+## Test input validation
 %!error ishermitian ()
+%!error ishermitian (1,2,3,4)
+%!error <second argument must be> ishermitian (1, {"skew"})
+%!error <SKEWOPT must be 'skew' or 'nonskew'> ishermitian (1, "foobar")
+%!error <SKEWOPT must be 'skew' or 'nonskew'> ishermitian (1, "foobar")
+%!error <TOL must be a scalar .= 0> ishermitian (1, "skew", {1})
+%!error <TOL must be a scalar .= 0> ishermitian (1, "skew", [1 1])
+%!error <TOL must be a scalar .= 0> ishermitian (1, -1)
--- a/scripts/linear-algebra/issymmetric.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/linear-algebra/issymmetric.m	Fri Aug 10 09:09:51 2018 +0200
@@ -20,13 +20,26 @@
 ## -*- texinfo -*-
 ## @deftypefn  {} {} issymmetric (@var{A})
 ## @deftypefnx {} {} issymmetric (@var{A}, @var{tol})
-## Return true if @var{A} is a symmetric matrix within the tolerance specified
-## by @var{tol}.
+## @deftypefnx {} {} issymmetric (@var{A}, @qcode{"skew"})
+## @deftypefnx {} {} issymmetric (@var{A}, @qcode{"skew"}, @var{tol})
+## Return true if @var{A} is a symmetric or skew-symmetric matrix within the
+## tolerance specified by @var{tol}.
 ##
 ## The default tolerance is zero (uses faster code).
 ##
-## Matrix @var{A} is considered symmetric if
+## The type of symmetry to check may be specified with the additional input
+## @qcode{"nonskew"} (default) for regular symmetry or @qcode{"skew"} for
+## skew-symmetry.
+##
+## Background: A matrix is symmetric if the transpose of the matrix is equal
+## to the original matrix: @w{@tcode{@var{A} == @var{A}.'}}.  If a tolerance
+## is given then symmetry is determined by
 ## @code{norm (@var{A} - @var{A}.', Inf) / norm (@var{A}, Inf) < @var{tol}}.
+##
+## A matrix is skew-symmetric if the transpose of the matrix is equal to the
+## negative of the original matrix: @w{@tcode{@var{A} == -@var{A}.'}}.  If a
+## tolerance is given then skew-symmetry is determined by
+## @code{norm (@var{A} + @var{A}.', Inf) / norm (@var{A}, Inf) < @var{tol}}.
 ## @seealso{ishermitian, isdefinite}
 ## @end deftypefn
 
@@ -34,20 +47,52 @@
 ## Created: August 1993
 ## Adapted-By: jwe
 
-function retval = issymmetric (A, tol = 0)
+function retval = issymmetric (A, skewopt = "nonskew", tol = 0)
 
-  if (nargin < 1 || nargin > 2)
+  if (nargin < 1 || nargin > 3)
     print_usage ();
   endif
 
+  if (nargin == 2)
+    ## Decode whether second argument is skewopt or tol
+    if (isnumeric (skewopt))
+      tol = skewopt;
+      skewopt = "nonskew";
+    elseif (! ischar (skewopt))
+      error ("issymmetric: second argument must be a non-negative scalar TOL, or one of the strings: 'skew' / 'nonskew'");
+    endif
+  endif
+
+  ## Validate inputs
   retval = (isnumeric (A) || islogical (A)) && issquare (A);
-  if (retval)
+  if (! retval)
+    return;
+  endif
+
+  if (! (strcmp (skewopt, "skew") || strcmp (skewopt, "nonskew")))
+    error ("issymmetric: SKEWOPT must be 'skew' or 'nonskew'");
+  endif
+
+  if (! (isnumeric (tol) && isscalar (tol) && tol >= 0))
+    error ("issymmetric: TOL must be a scalar >= 0");
+  endif
+
+  ## Calculate symmetry
+  if (strcmp (skewopt, "nonskew"))
     if (tol == 0)
-      ## Handle large sparse matrices as well as full ones
-      retval = nnz (A != A.') == 0;
+      ## check for exact symmetry
+      retval = ! any ((A != A.')(:));
     else
-      norm_x = norm (A, inf);
-      retval = norm_x == 0 || norm (A - A.', inf) / norm_x <= tol;
+      norm_x = norm (A, Inf);
+      retval = norm_x == 0 || norm (A - A.', Inf) / norm_x <= tol;
+    endif
+  else
+    ## skew symmetry
+    if (tol == 0)
+      retval = ! any ((A != -A.')(:));
+    else
+      norm_x = norm (A, Inf);
+      retval = norm_x == 0 || norm (A + A.', Inf) / norm_x <= tol;
     endif
   endif
 
@@ -58,17 +103,28 @@
 %!assert (! issymmetric ([1, 2]))
 %!assert (issymmetric ([]))
 %!assert (issymmetric ([1, 2; 2, 1]))
-%!assert (! (issymmetric ("test")))
 %!assert (issymmetric ([1, 2.1; 2, 1.1], 0.2))
 %!assert (issymmetric ([1, 2i; 2i, 1]))
+%!assert (issymmetric (speye (100)))
+%!assert (issymmetric (logical (eye (2))))
+%!assert (issymmetric ([0, 2; -2, 0], "skew"))
+%!assert (! issymmetric ([0, 2; -2, eps], "skew"))
+%!assert (issymmetric ([0, 2; -2, eps], "skew", eps))
+
+%!assert (! (issymmetric ("test")))
 %!assert (! (issymmetric ("t")))
 %!assert (! (issymmetric (["te"; "et"])))
-%!assert (issymmetric (speye (100000)))
-%!assert (issymmetric (logical (eye (2))))
-
+%!assert (! issymmetric ({1}))
 %!test
 %! s.a = 1;
 %! assert (! issymmetric (s));
 
-%!error issymmetric ([1, 2; 2, 1], 0, 0)
+## Test input validation
 %!error issymmetric ()
+%!error issymmetric (1,2,3,4)
+%!error <second argument must be> issymmetric (1, {"skew"})
+%!error <SKEWOPT must be 'skew' or 'nonskew'> issymmetric (1, "foobar")
+%!error <SKEWOPT must be 'skew' or 'nonskew'> issymmetric (1, "foobar")
+%!error <TOL must be a scalar .= 0> issymmetric (1, "skew", {1})
+%!error <TOL must be a scalar .= 0> issymmetric (1, "skew", [1 1])
+%!error <TOL must be a scalar .= 0> issymmetric (1, -1)
--- a/scripts/linear-algebra/module.mk	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/linear-algebra/module.mk	Fri Aug 10 09:09:51 2018 +0200
@@ -26,6 +26,7 @@
   %reldir%/normest1.m \
   %reldir%/null.m \
   %reldir%/ols.m \
+  %reldir%/ordeig.m \
   %reldir%/orth.m \
   %reldir%/planerot.m \
   %reldir%/qzhess.m \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/linear-algebra/ordeig.m	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,140 @@
+## Copyright (C) 2018 Marco Caliari
+## Copyright (C) 2018 Sébastien Villemot <sebastien@debian.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
+## <https://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {} {@var{lambda} =} ordeig (@var{A})
+## @deftypefnx {} {@var{lambda} =} ordeig (@var{A}, @var{B})
+## Return the eigenvalues of quasi-triangular matrices in their order of
+## appearance in the matrix @var{A}.
+##
+## The quasi-triangular matrix @var{A} is usually the result of a Schur
+## factorization.  If called with a second input @var{B} then the generalized
+## eigenvalues of the pair @var{A}, @var{B} are returned in the order of
+## appearance of the matrix @code{@var{A}-@var{lambda}*@var{B}}.  The pair
+## @var{A}, @var{B} is usually the result of a QZ decomposition.
+##
+## @seealso{ordschur, eig, schur, qz}
+## @end deftypefn
+
+function lambda = ordeig (A, B)
+
+  if (nargin < 1 || nargin > 2)
+    print_usage ();
+  endif
+
+  if (! isnumeric (A) || ! issquare (A))
+    error ("ordeig: A must be a square matrix")
+  endif
+
+  n = length (A);
+
+  if (nargin == 1)
+    B = eye (n);
+    if (isreal (A))
+      if (! isquasitri (A))
+        error ("ordeig: A must be quasi-triangular (i.e., upper block triangular with 1x1 or 2x2 blocks on the diagonal)");
+      endif
+    else
+      if (! istriu (A))
+        error ("ordeig: A must be upper-triangular when it is complex");
+      endif
+    endif
+  else
+    if (! isnumeric (B) || ! issquare (B))
+      error ("ordeig: B must be a square matrix");
+    elseif (length (B) != n)
+      error ("ordeig: A and B must be the same size");
+    endif
+    if (isreal (A) && isreal (B))
+      if (! isquasitri (A) || ! isquasitri (B))
+        error ("ordeig: A and B must be quasi-triangular (i.e., upper block triangular with 1x1 or 2x2 blocks on the diagonal)");
+      endif
+    else
+      if (! istriu (A) || ! istriu (B))
+        error ("ordeig: A and B must both be upper-triangular if either is complex");
+      endif
+    endif
+  endif
+
+  ## Start of algorithm
+  lambda = zeros (n, 1);
+
+  i = 1;
+  while (i <= n)
+    if (i == n || (A(i+1,i) == 0 && B(i+1,i) == 0))
+      lambda(i) = A(i,i) / B(i,i);
+    else
+      a = B(i,i) * B(i+1,i+1);
+      b = - (A(i,i) * B(i+1,i+1) + A(i+1,i+1) * B(i,i));
+      c = A(i,i) * A(i+1,i+1) - ...
+          (A(i,i+1) - B(i,i+1)) * (A(i+1,i) - B(i+1,i));
+      if (b > 0)
+        lambda(i) = 2*c / (-b - sqrt (b^2 - 4*a*c));
+        i += 1;
+        lambda(i) = (-b - sqrt (b^2 - 4*a*c)) / 2 / a;
+      else
+        lambda(i) = (-b + sqrt (b^2 - 4*a*c)) / 2 / a;
+        i += 1;
+        lambda(i) = 2*c / (-b + sqrt (b^2 - 4*a*c));
+      endif
+    endif
+    i += 1;
+  endwhile
+
+endfunction
+
+# Checks whether a matrix is quasi-triangular
+function retval = isquasitri (A)
+  v = diag (A, -1) != 0;
+  retval = all (tril (A, -2)(:) == 0) && all (v(1:end-1) + v(2:end) < 2);
+endfunction
+
+
+%!test
+%! A = toeplitz ([0, 1, 0, 0], [0, -1, 0, 0]);
+%! T = schur (A);
+%! lambda = ordeig (T);
+%! assert (lambda, [1.61803i; -1.61803i; 0.61803i; -0.61803i], 1e-4);
+
+%!test
+%! A = toeplitz ([0, 1, 0, 0], [0, -1, 0, 0]);
+%! B = toeplitz ([0, 0, 0, 1], [0, -1, 0, 2]);
+%! [AA, BB] = qz (A, B);
+%! assert (isreal (AA) && isreal (BB));
+%! lambda = ordeig (AA, BB);
+%! assert (lambda, [0.5+0.86603i; 0.5-0.86603i; i; -i], 1e-4);
+%! [AA, BB] = qz (complex (A), complex (B));
+%! assert (iscomplex (AA) && iscomplex (BB));
+%! lambda = ordeig (AA, BB);
+%! assert (lambda, diag (AA) ./ diag (BB));
+
+## Test input validation
+%!error ordeig ()
+%!error ordeig (1,2,3)
+%!error <A must be a square matrix> ordeig ('a')
+%!error <A must be a square matrix> ordeig ([1, 2, 3])
+%!error <A must be quasi-triangular> ordeig (magic (3))
+%!error <A must be upper-triangular> ordeig ([1, 0; i, 1])
+%!error <B must be a square matrix> ordeig (1, 'a')
+%!error <B must be a square matrix> ordeig (1, [1, 2])
+%!error <A and B must be the same size> ordeig (1, ones (2,2))
+%!error <A and B must be quasi-triangular>
+%! ordeig (triu (magic (3)), magic (3))
+%!error <A and B must both be upper-triangular>
+%! ordeig ([1, 1; 0, 1], [1, 0; i, 1])
--- a/scripts/miscellaneous/open.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/miscellaneous/open.m	Fri Aug 10 09:09:51 2018 +0200
@@ -22,19 +22,38 @@
 ## Open the file @var{file} in Octave or in an external application based on
 ## the file type as determined by the filename extension.
 ##
-## Recognized file types are
+## By default, recognized file types are
 ##
 ## @table @code
 ## @item .m
-## Open file in the editor.
+## Open file in the editor. No @var{output} value is returned.
 ##
 ## @item .mat
-## Load the file in the base workspace.
+## @item octave-workspace
+## Open the data file with @code{load}. If no return value @var{output}
+## is requested, variables are loaded in the base workspace. Otherwise
+## @var{output} will be a structure containing loaded data.
+## @xref{XREFload, , load function}.
+##
+## @item .ofig
+## Open the figure with hgload.  @xref{XREFhgload, , hgload function}.
 ##
 ## @item .exe
-## Execute the program (on Windows systems only).
+## Execute the program (on Windows systems only). No @var{output} value
+## is returned.
 ## @end table
 ##
+## Custom file extensions may also be handled if a function @code{openxxx},
+## where @code{xxx} is the extension, is found in the load path.  The function
+## must accept the file name as input.  For example, in order to load ".dat"
+## data files in the base workspace, as is done by default for ".mat" files, one
+## may define "opendat.m" with the following contents:
+## @example
+## function retval = opendat (fname)
+##   evalin ("base", sprintf ("load ('%s');", fname));
+## endfunction
+## @end example
+##
 ## Other file types are opened in the appropriate external application.
 ## @end deftypefn
 
@@ -48,17 +67,31 @@
     error ("open: FILE must be a string");
   endif
 
-  [~, ~, ext] = fileparts (file);
+  if (! exist (file, "file"))
+    error ("open: unable to find file %s", file);
+  endif
+
+  [~, fname, ext] = fileparts (file);
 
-  if (strcmpi (ext, ".m"))
+  if (! isempty (ext)
+      && any (exist (["open" tolower(ext(2:end))]) == [2 3 5 103]))
+    try
+      feval (["open" tolower(ext(2:end))], file)
+    catch
+      error ("open: %s", lasterr);
+    end_try_catch
+  elseif (strcmpi (ext, ".m"))
     edit (file);
-  elseif (strcmpi (ext, ".mat"))
+  elseif (strcmpi (ext, ".mat") || strcmp (fname, "octave-workspace"))
     if (nargout > 0)
       output = load (file);
     else
       evalin ("base", sprintf ("load ('%s');", file));
     endif
-  elseif (any (strcmpi (ext, {".fig", ".mdl", ".slx", ".prj"})))
+  elseif (strcmpi (ext, ".ofig"))
+    output = hgload (file);
+    drawnow ();
+  elseif (any (strcmpi (ext, {".mdl", ".slx", ".prj"})))
     error ("open: opening file type '%s' is not supported", ext);
   elseif (strcmpi (ext, ".exe"))
     if (ispc ())
--- a/scripts/miscellaneous/publish.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/miscellaneous/publish.m	Fri Aug 10 09:09:51 2018 +0200
@@ -393,6 +393,7 @@
 
   if (options.evalCode)
     doc = eval_code (doc, options);
+    eval_context ("clear");
   endif
 
   output_file = create_output (doc, options);
@@ -425,9 +426,23 @@
   ##
   ## Checks line to have N "%" or "#" lines
   ## followed either by a space or end of string
-  is_publish_markup = @(cstr, N) ...
-    any (strncmp (char (cstr), {"%%%", "##"}, N)) ...
-    && ((length (char (cstr)) == N) || ((char (cstr))(N + 1) == " "));
+  function r = is_publish_markup (cstr, N)
+    str = char (cstr);
+
+    r = any (strncmp (str, {"%%%", "##"}, N));
+    if (r)
+      len = length (str);
+      if (len == N)
+        r = true;
+      elseif (len > N && str(N+1) == " ")
+        r = true;
+      else
+        r = false;
+      endif
+    endif
+
+    return;
+  endfunction
   ## Checks line of cellstring to be a paragraph line
   is_paragraph = @(cstr) is_publish_markup (cstr, 1);
   ## Checks line of cellstring to be a section headline
@@ -945,11 +960,8 @@
   fig_num = 1;
   fig_list = struct ();
 
-  ## File used as temporary context
-  tmp_context = [tempname() ".var"];
-
   ## Evaluate code, that does not appear in the output.
-  eval_code_helper (tmp_context, options.codeToEvaluate);
+  eval_code_helper (options.codeToEvaluate);
 
   ## Create a new figure, if there are existing plots
   if (! isempty (fig_ids) && options.useNewFigure)
@@ -962,13 +974,13 @@
       code_str = strjoin (doc.m_source(r(1):r(2)), "\n");
       if (options.catchError)
         try
-          doc.body{i}.output = eval_code_helper (tmp_context, code_str);
+          doc.body{i}.output = eval_code_helper (code_str);
          catch err
           doc.body{i}.output = cellstr (["error: ", err.message, ...
                                                  "\n\tin:\n\n", code_str]);
         end_try_catch
       else
-        doc.body{i}.output = eval_code_helper (tmp_context, code_str);
+        doc.body{i}.output = eval_code_helper (code_str);
       endif
 
       ## Check for newly created figures ...
@@ -1022,9 +1034,6 @@
   ## Close any figures opened by publish function
   delete (setdiff (findall (0, "type", "figure"), fig_ids));
 
-  ## Remove temporary context
-  unlink (tmp_context);
-
   ## Insert figures to document
   fig_code_blocks = fieldnames (fig_list);
   body_offset = 0;
@@ -1039,29 +1048,63 @@
 endfunction
 
 
-function cstr = eval_code_helper (context, code)
+function cstr = eval_code_helper (__code__)
   ## EVAL_CODE_HELPER evaluates a given string with Octave code in an extra
   ## temporary context and returns a cellstring with the eval output.
 
-  if (isempty (code))
+  if (isempty (__code__))
     return;
   endif
 
-  load_snippet = "";
-  if (exist (context, "file") == 2)
-    load_snippet = sprintf ('load ("%s");', context);
-  endif
-  save_snippet = sprintf ('save ("-binary", "%s");', context);
-
-  eval (sprintf ("function __eval__ ()\n%s\n%s\n%s\nendfunction",
-                 load_snippet, code, save_snippet));
-
-  cstr = strsplit (evalc ("__eval__"), "\n");
+  eval_context ("load");
+  cstr = evalc (__code__);
+  ## Split string by lines and preserve blank lines.
+  cstr = strsplit (strrep (cstr, "\n\n", "\n \n"), "\n");
+  eval_context ("save");
 endfunction
 
 
-## FIXME: Missing any functional BIST tests
-## FIXME: Need to create a temporary file for use with error testing
+function cstr = eval_context (op)
+  ## EVAL_CONTEXT temporary evaluation context.
+  persistent ctext
+
+  ## Variable cstr in "eval_code_helper" is newly created anyways.
+  forbidden_var_names = {"__code__"};
+
+  switch (op)
+    case "save"
+      ## Clear previous context
+      ctext = containers.Map;
+      ## Get variable names
+      var_names = evalin ("caller", "whos");
+      var_names = {var_names.name};
+      ## Store all variables to context
+      for i = 1:length (var_names)
+        if (! any (strcmp (var_names{i}, forbidden_var_names)))
+          ctext(var_names{i}) = evalin ("caller", var_names{i});
+        end
+      endfor
+
+    case "load"
+      if (! isempty (ctext))
+        keys = ctext.keys ();
+        for i = 1:length (keys)
+          assignin ("caller", keys{i}, ctext(keys{i}));
+        endfor
+      endif
+
+    case "clear"
+      ## Clear any context
+      ctext = [];
+
+    otherwise
+      ## Do nothing
+
+  endswitch
+endfunction
+
+
+## Note: Functional BIST tests are located in the `test/publish` directory.
 
 ## Test input validation
 %!error publish ()
--- a/scripts/module.mk	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/module.mk	Fri Aug 10 09:09:51 2018 +0200
@@ -15,6 +15,7 @@
 include %reldir%/image/module.mk
 include %reldir%/io/module.mk
 include %reldir%/java/module.mk
+include %reldir%/legacy/module.mk
 include %reldir%/linear-algebra/module.mk
 include %reldir%/miscellaneous/module.mk
 include %reldir%/ode/module.mk
--- a/scripts/optimization/fminbnd.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/optimization/fminbnd.m	Fri Aug 10 09:09:51 2018 +0200
@@ -19,37 +19,58 @@
 ## Author: Jaroslav Hajek <highegg@gmail.com>
 
 ## -*- texinfo -*-
-## @deftypefn {} {[@var{x}, @var{fval}, @var{info}, @var{output}] =} fminbnd (@var{fun}, @var{a}, @var{b}, @var{options})
+## @deftypefn  {} {@var{x} =} fminbnd (@var{fun}, @var{a}, @var{b})
+## @deftypefnx {} {@var{x} =} fminbnd (@var{fun}, @var{a}, @var{b}, @var{options})
+## @deftypefnx {} {[@var{x}, @var{fval}, @var{info}, @var{output}] =} fminbnd (@dots{})
 ## Find a minimum point of a univariate function.
 ##
-## @var{fun} should be a function handle or name.  @var{a}, @var{b} specify a
-## starting interval.  @var{options} is a structure specifying additional
-## options.  Currently, @code{fminbnd} recognizes these options:
-## @qcode{"FunValCheck"}, @qcode{"OutputFcn"}, @qcode{"TolX"},
-## @qcode{"MaxIter"}, @qcode{"MaxFunEvals"}.  For a description of these
-## options, see @ref{XREFoptimset,,optimset}.
+## @var{fun} must be a function handle or name.
+##
+## The starting interval is specified by @var{a} (left boundary) and @var{b}
+## (right boundary).  The endpoints must be finite.
+##
+## @var{options} is a structure specifying additional parameters which
+## control the algorithm.  Currently, @code{fminbnd} recognizes these options:
+## @qcode{"Display"}, @qcode{"FunValCheck"}, @qcode{"MaxFunEvals"},
+## @qcode{"MaxIter"}, @qcode{"OutputFcn"}, @qcode{"TolX"}.
+##
+## @qcode{"MaxFunEvals"} proscribes the maximum number of function evaluations
+## before optimization is halted.  The default value is 500.
+## The value must be a positive integer.
 ##
-## On exit, the function returns @var{x}, the approximate minimum point and
-## @var{fval}, the function value thereof.
+## @qcode{"MaxIter"} proscribes the maximum number of algorithm iterations
+## before optimization is halted.  The default value is 500.
+## The value must be a positive integer.
+##
+## @qcode{"TolX"} specifies the termination tolerance for the solution @var{x}.
+## The default is @code{1e-4}.
 ##
-## @var{info} is an exit flag that can have these values:
+## For a description of the other options, see @ref{XREFoptimset,,optimset}.
+## To initialize an options structure with default values for @code{fminbnd}
+## use @code{options = optimset ("fminbnd")}.
+##
+## On exit, the function returns @var{x}, the approximate minimum point, and
+## @var{fval}, the function evaluated @var{x}.
+##
+## The third output @var{info} reports whether the algorithm succeeded and may
+## take one of the following values:
 ##
 ## @itemize
 ## @item 1
 ## The algorithm converged to a solution.
 ##
 ## @item 0
-## Maximum number of iterations or function evaluations has been exhausted.
+## Iteration limit (either @code{MaxIter} or @code{MaxFunEvals}) exceeded.
 ##
 ## @item -1
-## The algorithm has been terminated from user output function.
+## The algorithm was terminated by a user @code{OutputFcn}.
 ## @end itemize
 ##
-## Notes: The search for a minimum is restricted to be in the interval bound by
-## @var{a} and @var{b}.  If you only have an initial point to begin searching
-## from you will need to use an unconstrained minimization algorithm such as
-## @code{fminunc} or @code{fminsearch}.  @code{fminbnd} internally uses a
-## Golden Section search strategy.
+## Programming Notes: The search for a minimum is restricted to be in the
+## finite interval bound by @var{a} and @var{b}.  If you have only one initial
+## point to begin searching from then you will need to use an unconstrained
+## minimization algorithm such as @code{fminunc} or @code{fminsearch}.
+## @code{fminbnd} internally uses a Golden Section search strategy.
 ## @seealso{fzero, fminunc, fminsearch, optimset}
 ## @end deftypefn
 
@@ -63,9 +84,10 @@
 function [x, fval, info, output] = fminbnd (fun, a, b, options = struct ())
 
   ## Get default options if requested.
-  if (nargin == 1 && ischar (fun) && strcmp (fun, 'defaults'))
-    x = optimset ("MaxIter", Inf, "MaxFunEvals", Inf, "TolX", 1e-8,
-                  "OutputFcn", [], "FunValCheck", "off");
+  if (nargin == 1 && ischar (fun) && strcmp (fun, "defaults"))
+    x = optimset ("Display", "notify", "FunValCheck", "off",
+                  "MaxFunEvals", 500, "MaxIter", 500,
+                  "OutputFcn", [], "TolX", 1e-4);
     return;
   endif
 
@@ -85,9 +107,9 @@
   displ = optimget (options, "Display", "notify");
   funvalchk = strcmpi (optimget (options, "FunValCheck", "off"), "on");
   outfcn = optimget (options, "OutputFcn");
-  tolx = optimget (options, "TolX", 1e-8);
-  maxiter = optimget (options, "MaxIter", Inf);
-  maxfev = optimget (options, "MaxFunEvals", Inf);
+  tolx = optimget (options, "TolX", 1e-4);
+  maxiter = optimget (options, "MaxIter", 500);
+  maxfev = optimget (options, "MaxFunEvals", 500);
 
   if (funvalchk)
     ## Replace fun with a guarded version.
@@ -160,9 +182,8 @@
     if (dogs)
       ## Default to golden section step.
 
-      ## WARNING: This is also the "initial" procedure following
-      ## MATLAB nomenclature.  After the loop we'll fix the string
-      ## for the first step.
+      ## WARNING: This is also the "initial" procedure following MATLAB
+      ## nomenclature.  After the loop we'll fix the string for the first step.
       iter(niter+1).procedure = "golden";
 
       e = ifelse (x >= xm, a - x, b - x);
@@ -225,13 +246,13 @@
   switch (displ)
     case "iter"
       print_formatted_table (iter);
-      print_exit_msg (info, struct("TolX", tolx, "fx", fval));
+      print_exit_msg (info, struct ("TolX", tolx, "fx", fval));
     case "notify"
       if (info == 0)
-        print_exit_msg (info, struct("fx",fval));
+        print_exit_msg (info, struct ("fx",fval));
       endif
     case "final"
-      print_exit_msg (info, struct("TolX", tolx, "fx", fval));
+      print_exit_msg (info, struct ("TolX", tolx, "fx", fval));
     case "off"
       "skip";
     otherwise
@@ -240,6 +261,7 @@
 
   output.iterations = niter;
   output.funcCount = nfev;
+  output.algorithm = "golden section search, parabolic interpolation";
   output.bracket = [a, b];
   ## FIXME: bracketf possibly unavailable.
 
--- a/scripts/optimization/fminsearch.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/optimization/fminsearch.m	Fri Aug 10 09:09:51 2018 +0200
@@ -23,7 +23,8 @@
 ## @deftypefnx {} {@var{x} =} fminsearch (@var{fun}, @var{x0}, @var{options}, @var{fun_arg1}, @var{fun_arg2}, @dots{})
 ## @deftypefnx {} {[@var{x}, @var{fval}, @var{exitflag}, @var{output}] =} fminsearch (@dots{})
 ##
-## Find a value of @var{x} which minimizes the function @var{fun}.
+## Find a value of @var{x} which minimizes the multi-variable function
+## @var{fun}.
 ##
 ## The search begins at the point @var{x0} and iterates using the
 ## @nospell{Nelder & Mead} Simplex algorithm (a derivative-free method).  This
@@ -32,9 +33,22 @@
 ##
 ## Options for the search are provided in the parameter @var{options} using the
 ## function @code{optimset}.  Currently, @code{fminsearch} accepts the options:
-## @qcode{"TolX"}, @qcode{"TolFun"}, @qcode{"MaxFunEvals"}, @qcode{"MaxIter"},
-## @qcode{"Display"}, @qcode{"FunValCheck"}, and @qcode{"OutputFcn"}.
-## For a description of these options, see @code{optimset}.
+## @qcode{"Display"}, @qcode{"FunValCheck"},@qcode{"MaxFunEvals"},
+## @qcode{"MaxIter"}, @qcode{"OutputFcn"}, @qcode{"TolFun"}, @qcode{"TolX"}. 
+##
+## @qcode{"MaxFunEvals"} proscribes the maximum number of function evaluations
+## before optimization is halted.  The default value is
+## @code{200 * number_of_variables}, i.e., @code{200 * length (@var{x0})}.
+## The value must be a positive integer.
+##
+## @qcode{"MaxIter"} proscribes the maximum number of algorithm iterations
+## before optimization is halted.  The default value is
+## @code{200 * number_of_variables}, i.e., @code{200 * length (@var{x0})}.
+## The value must be a positive integer.
+## 
+## For a description of the other options, see @code{optimset}.  To initialize
+## an options structure with default values for @code{fminsearch} use
+## @code{options = optimset ("fminsearch")}.
 ##
 ## Additional inputs for the function @var{fun} can be passed as the fourth
 ## and higher arguments.  To pass function arguments while using the default
@@ -43,14 +57,14 @@
 ## On exit, the function returns @var{x}, the minimum point, and @var{fval},
 ## the function value at the minimum.
 ##
-## The third return value @var{exitflag} is
+## The third output @var{exitflag} reports whether the algorithm succeeded and
+## may take one of the following values:
 ##
 ## @table @asis
 ## @item 1
 ## if the algorithm converged
-## (size of the simplex is smaller than @code{@var{options}.TolX} @strong{AND}
-## the step in the function value between iterations is smaller than
-## @code{@var{options}.TolFun}).
+## (size of the simplex is smaller than @code{TolX} @strong{AND} the step in
+## function value between iterations is smaller than @code{TolFun}).
 ##
 ## @item 0
 ## if the maximum number of iterations or the maximum number of function
@@ -60,10 +74,11 @@
 ## if the iteration is stopped by the @qcode{"OutputFcn"}.
 ## @end table
 ##
-## The fourth return value is a structure @var{output} with the fields,
-## @code{funcCount} containing the number of function calls to @var{fun},
-## @code{iterations} containing the number of iteration steps,
-## @code{algorithm} with the name of the search algorithm (always:
+## The fourth output is a structure @var{output} containing runtime
+## about the algorithm.  Fields in the structure are @code{funcCount}
+## containing the number of function calls to @var{fun}, @code{iterations}
+## containing the number of iteration steps, @code{algorithm} with the name of
+## the search algorithm (always: 
 ## @nospell{@qcode{"Nelder-Mead simplex direct search"}}), and @code{message}
 ## with the exit message.
 ##
@@ -72,6 +87,9 @@
 ## @example
 ## fminsearch (@@(x) (x(1)-5).^2+(x(2)-8).^4, [0;0])
 ## @end example
+##
+## Note: If you need to find the minimum of a single variable function it is
+## probably better to use @code{fminbnd}.
 ## @seealso{fminbnd, fminunc, optimset}
 ## @end deftypefn
 
@@ -85,9 +103,9 @@
   ## Get default options if requested.
   if (nargin == 1 && ischar (fun) && strcmp (fun, "defaults"))
     x = optimset ("Display", "notify", "FunValCheck", "off",
-                  "MaxFunEvals", 400, "MaxIter", 400,
+                  "MaxFunEvals", [], "MaxIter", [],
                   "OutputFcn", [],
-                  "TolFun", 1e-7, "TolX", 1e-4);
+                  "TolFun", 1e-4, "TolX", 1e-4);
     return;
   endif
 
@@ -154,13 +172,13 @@
   stopit(1) = tol = optimget (options, "TolX", 1e-4);
 
   ## Tolerance for cgce test based on step in function value.
-  tol_f = optimget (options, "TolFun", 1e-7);
+  tol_f = optimget (options, "TolFun", 1e-4);
 
   ## Max number of function evaluations.
-  stopit(2) = optimget (options, "MaxFunEvals", length (x) * 200);
+  stopit(2) = optimget (options, "MaxFunEvals", 200 * length (x));
 
   ## Max number of iterations
-  maxiter = optimget (options, "MaxIter", length (x) * 200);
+  maxiter = optimget (options, "MaxIter", 200 * length (x));
 
   ## Default target for function values.
   stopit(3) = Inf;  # FIXME: expose this parameter to the outside
@@ -269,7 +287,7 @@
     k += 1;
 
     if (k > maxiter)
-      msg = "Exceeded maximum iterations...quitting\n";
+      msg = "Exceeded maximum iterations\n";
       break;
     endif
 
@@ -293,14 +311,15 @@
     ## Stopping Test 1 - f reached target value?
     if (fmax >= stopit(3))
       msg = "Exceeded target...quitting\n";
-      ## FIXME: Add docu when stopit(3) gets exposed to the outside
+      ## FIXME: Add documentation when stopit(3) gets exposed to the outside
       exitflag = -1;
       break;
     endif
 
     ## Stopping Test 2 - too many f-evals?
     if (nf >= stopit(2))
-      msg = "Max no. of function evaluations exceeded...quitting\n";
+      msg = "Exceeded maximum number of function evaluations\n";
+      exitflag = 0;
       break;
     endif
 
@@ -309,8 +328,8 @@
     size_simplex = norm (V(:,2:n+1)-v1(:,ones (1,n)),1) / max (1, norm (v1,1));
     step_f = max (abs (f(1) - f(2:n+1)));
     if (size_simplex <= tol && step_f <= tol_f )
-      msg = sprintf (["Simplex size %9.4e <= %9.4e and ", ...
-                      "step in function value %9.4e <= %9.4e...quitting\n"], ...
+      msg = sprintf (["Algorithm converged.  Simplex size %9.4e <= %9.4e ", ...
+                      "and step in function value %9.4e <= %9.4e\n"], ...
                       size_simplex, tol, step_f, tol_f);
       exitflag = 1;
       break;
@@ -490,4 +509,3 @@
 ## Test input validation
 %!error fminsearch ()
 %!error fminsearch (1)
-
--- a/scripts/optimization/fsolve.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/optimization/fsolve.m	Fri Aug 10 09:09:51 2018 +0200
@@ -19,8 +19,9 @@
 ## Author: Jaroslav Hajek <highegg@gmail.com>
 
 ## -*- texinfo -*-
-## @deftypefn  {} {} fsolve (@var{fcn}, @var{x0}, @var{options})
-## @deftypefnx {} {[@var{x}, @var{fvec}, @var{info}, @var{output}, @var{fjac}] =} fsolve (@var{fcn}, @dots{})
+## @deftypefn  {} {} fsolve (@var{fcn}, @var{x0})
+## @deftypefnx {} {} fsolve (@var{fcn}, @var{x0}, @var{options})
+## @deftypefnx {} {[@var{x}, @var{fvec}, @var{info}, @var{output}, @var{fjac}] =} fsolve (@dots{})
 ## Solve a system of nonlinear equations defined by the function @var{fcn}.
 ##
 ## @var{fcn} should accept a vector (array) defining the unknown variables,
@@ -29,65 +30,98 @@
 ## determine a vector @var{x} such that @code{@var{fcn} (@var{x})} gives
 ## (approximately) all zeros.
 ##
-## @var{x0} determines a starting guess.  The shape of @var{x0} is preserved
-## in all calls to @var{fcn}, but otherwise it is treated as a column vector.
+## @var{x0} is an initial guess for the solution.  The shape of @var{x0} is
+## preserved in all calls to @var{fcn}, but otherwise is treated as a column
+## vector.
 ##
-## @var{options} is a structure specifying additional options.  Currently,
-## @code{fsolve} recognizes these options:
-## @qcode{"FunValCheck"}, @qcode{"OutputFcn"}, @qcode{"TolX"},
-## @qcode{"TolFun"}, @qcode{"MaxIter"}, @qcode{"MaxFunEvals"},
-## @qcode{"Jacobian"}, @qcode{"Updating"}, @qcode{"ComplexEqn"}
-## @qcode{"TypicalX"}, @qcode{"AutoScaling"} and @qcode{"FinDiffType"}.
-##
-## If @qcode{"Jacobian"} is @qcode{"on"}, it specifies that @var{fcn}, called
-## with 2 output arguments also returns the Jacobian matrix of right-hand sides
-## at the requested point.  @qcode{"TolX"} specifies the termination tolerance
-## in the unknown variables, while @qcode{"TolFun"} is a tolerance for
-## equations.  Default is @code{1e-7} for both @qcode{"TolX"} and
-## @qcode{"TolFun"}.
+## @var{options} is a structure specifying additional parameters which
+## control the algorithm.  Currently, @code{fsolve} recognizes these options:
+## @qcode{"AutoScaling"}, @qcode{"ComplexEqn"}, @qcode{"FinDiffType"},
+## @qcode{"FunValCheck"}, @qcode{"Jacobian"}, @qcode{"MaxFunEvals"},
+## @qcode{"MaxIter"}, @qcode{"OutputFcn"}, @qcode{"TolFun"}, @qcode{"TolX"},
+## @qcode{"TypicalX"}, and @qcode{"Updating"}.
 ##
 ## If @qcode{"AutoScaling"} is on, the variables will be automatically scaled
 ## according to the column norms of the (estimated) Jacobian.  As a result,
-## TolF becomes scaling-independent.  By default, this option is off because
-## it may sometimes deliver unexpected (though mathematically correct) results.
+## @code{TolFun} becomes scaling-independent.  By default, this option is off
+## because it may sometimes deliver unexpected (though mathematically
+## correct) results.
 ##
-## If @qcode{"Updating"} is @qcode{"on"}, the function will attempt to use
-## @nospell{Broyden} updates to update the Jacobian, in order to reduce the
-## amount of Jacobian calculations.  If your user function always calculates
-## the Jacobian (regardless of number of output arguments) then this option
-## provides no advantage and should be set to false.
-##
-## @qcode{"ComplexEqn"} is @qcode{"on"}, @code{fsolve} will attempt to solve
+## If @qcode{"ComplexEqn"} is @qcode{"on"}, @code{fsolve} will attempt to solve
 ## complex equations in complex variables, assuming that the equations possess
 ## a complex derivative (i.e., are holomorphic).  If this is not what you want,
 ## you should unpack the real and imaginary parts of the system to get a real
 ## system.
 ##
-## For description of the other options, see @code{optimset}.
+## If @qcode{"Jacobian"} is @qcode{"on"}, it specifies that @var{fcn}---when
+## called with 2 output arguments---also returns the Jacobian matrix of
+## right-hand sides at the requested point.
+##
+## @qcode{"MaxFunEvals"} proscribes the maximum number of function evaluations
+## before optimization is halted.  The default value is
+## @code{100 * number_of_variables}, i.e., @code{100 * length (@var{x0})}.
+## The value must be a positive integer.
+##
+## If @qcode{"Updating"} is @qcode{"on"}, the function will attempt to use
+## @nospell{Broyden} updates to update the Jacobian, in order to reduce the
+## number of Jacobian calculations.  If your user function always calculates
+## the Jacobian (regardless of number of output arguments) then this option
+## provides no advantage and should be disabled.
 ##
-## On return, @var{fval} contains the value of the function @var{fcn}
-## evaluated at @var{x}.
+## @qcode{"TolX"} specifies the termination tolerance in the unknown variables,
+## while @qcode{"TolFun"} is a tolerance for equations.  Default is @code{1e-6}
+## for both @qcode{"TolX"} and @qcode{"TolFun"}.
 ##
-## @var{info} may be one of the following values:
+## For a description of the other options, see @code{optimset}.  To initialize
+## an options structure with default values for @code{fsolve} use
+## @code{options = optimset ("fsolve")}.
+##
+## The first output @var{x} is the solution while the second output @var{fval}
+## contains the value of the function @var{fcn} evaluated at @var{x} (ideally
+## a vector of all zeros).
+##
+## The third output @var{info} reports whether the algorithm succeeded and may
+## take one of the following values:
 ##
 ## @table @asis
 ## @item 1
 ## Converged to a solution point.  Relative residual error is less than
-## specified by TolFun.
+## specified by @code{TolFun}.
 ##
 ## @item 2
-## Last relative step size was less that TolX.
+## Last relative step size was less than @code{TolX}.
 ##
 ## @item 3
-## Last relative decrease in residual was less than TolF.
+## Last relative decrease in residual was less than @code{TolFun}.
 ##
 ## @item 0
-## Iteration limit exceeded.
+## Iteration limit (either @code{MaxIter} or @code{MaxFunEvals}) exceeded.
+##
+## @item -1
+## Stopped by @code{OutputFcn}.
 ##
 ## @item -3
 ## The trust region radius became excessively small.
 ## @end table
 ##
+## @var{output} is a structure containing runtime information about the
+## @code{fsolve} algorithm.  Fields in the structure are:
+##
+## @table @code
+## @item iterations
+##  Number of iterations through loop.
+##
+## @item succesful
+##  Number of successful iterations.
+##
+## @item @nospell{funcCount}
+##  Number of function evaluations.
+##
+## @end table
+##
+## The final output @var{fjac} contains the value of the Jacobian evaluated
+## at @var{x}.
+##
 ## Note: If you only have a single nonlinear equation of one variable, using
 ## @code{fzero} is usually a much better idea.
 ##
@@ -97,12 +131,12 @@
 ## accepted successful step.  Often this will be one of the last two calls, but
 ## not always.  If the savings by reusing intermediate results from residual
 ## calculation in Jacobian calculation are significant, the best strategy is to
-## employ OutputFcn: After a vector is evaluated for residuals, if OutputFcn is
-## called with that vector, then the intermediate results should be saved for
-## future Jacobian evaluation, and should be kept until a Jacobian evaluation
-## is requested or until OutputFcn is called with a different vector, in which
-## case they should be dropped in favor of this most recent vector.  A short
-## example how this can be achieved follows:
+## employ @code{OutputFcn}: After a vector is evaluated for residuals, if
+## @code{OutputFcn} is called with that vector, then the intermediate results
+## should be saved for future Jacobian evaluation, and should be kept until a
+## Jacobian evaluation is requested or until @code{OutputFcn} is called with a
+## different vector, in which case they should be dropped in favor of this most
+## recent vector.  A short example how this can be achieved follows:
 ##
 ## @example
 ## function [fvec, fjac] = user_func (x, optimvalues, state)
@@ -137,12 +171,12 @@
 function [x, fvec, info, output, fjac] = fsolve (fcn, x0, options = struct ())
 
   ## Get default options if requested.
-  if (nargin == 1 && ischar (fcn) && strcmp (fcn, 'defaults'))
-    x = optimset ("MaxIter", 400, "MaxFunEvals", Inf, ...
-    "Jacobian", "off", "TolX", 1e-7, "TolFun", 1e-7,
-    "OutputFcn", [], "Updating", "on", "FunValCheck", "off",
-    "ComplexEqn", "off", "FinDiffType", "central",
-    "TypicalX", [], "AutoScaling", "off");
+  if (nargin == 1 && ischar (fcn) && strcmp (fcn, "defaults"))
+    x = optimset ("AutoScaling", "off", "ComplexEqn", "off", 
+                  "FunValCheck", "off", "FinDiffType", "forward",
+                  "Jacobian", "off",  "MaxFunEvals", [], "MaxIter", 400,
+                  "OutputFcn", [], "Updating", "off", "TolFun", 1e-6,
+                  "TolX", 1e-6, "TypicalX", []);
     return;
   endif
 
@@ -160,19 +194,17 @@
   n = numel (x0);
 
   has_jac = strcmpi (optimget (options, "Jacobian", "off"), "on");
-  cdif = strcmpi (optimget (options, "FinDiffType", "central"), "central");
+  cdif = strcmpi (optimget (options, "FinDiffType", "forward"), "central");
   maxiter = optimget (options, "MaxIter", 400);
-  maxfev = optimget (options, "MaxFunEvals", Inf);
+  maxfev = optimget (options, "MaxFunEvals", 100*n);
   outfcn = optimget (options, "OutputFcn");
-  updating = strcmpi (optimget (options, "Updating", "on"), "on");
+  updating = strcmpi (optimget (options, "Updating", "off"), "on");
   complexeqn = strcmpi (optimget (options, "ComplexEqn", "off"), "on");
 
   ## Get scaling matrix using the TypicalX option.  If set to "auto", the
   ## scaling matrix is estimated using the Jacobian.
-  typicalx = optimget (options, "TypicalX");
-  if (isempty (typicalx))
-    typicalx = ones (n, 1);
-  endif
+  typicalx = optimget (options, "TypicalX", ones (n, 1));
+
   autoscale = strcmpi (optimget (options, "AutoScaling", "off"), "on");
   if (! autoscale)
     dg = 1 ./ typicalx;
@@ -188,8 +220,8 @@
   ## These defaults are rather stringent.
   ## Normally user prefers accuracy to performance.
 
-  tolx = optimget (options, "TolX", 1e-7);
-  tolf = optimget (options, "TolFun", 1e-7);
+  tolx = optimget (options, "TolX", 1e-6);
+  tolf = optimget (options, "TolFun", 1e-6);
 
   factor = 1;
 
@@ -213,7 +245,7 @@
     optimvalues.funccount = nfev;
     optimvalues.fval = fn;
     optimvalues.searchdirection = zeros (n, 1);
-    state = 'init';
+    state = "init";
     stop = outfcn (x, optimvalues, state);
     if (stop)
       info = -1;
@@ -250,9 +282,9 @@
       nfev += (1 + cdif) * length (x);
     endif
 
-    ## For square and overdetermined systems, we update a QR
-    ## factorization of the Jacobian to avoid solving a full system in each
-    ## step.  In this case, we pass a triangular matrix to __dogleg__.
+    ## For square and overdetermined systems, we update a QR factorization of
+    ## the Jacobian to avoid solving a full system in each step.  In this case,
+    ## we pass a triangular matrix to __dogleg__.
     useqr = updating && m >= n && n > 10;
 
     if (useqr)
@@ -266,7 +298,7 @@
 
     if (autoscale)
       ## Get column norms, use them as scaling factors.
-      jcn = norm (fjac, 'columns').';
+      jcn = norm (fjac, "columns").';
       if (niter == 1)
         dg = jcn;
         dg(dg == 0) = 1;
@@ -388,7 +420,7 @@
         optimvalues.funccount = nfev;
         optimvalues.fval = fn;
         optimvalues.searchdirection = s;
-        state = 'iter';
+        state = "iter";
         stop = outfcn (x, optimvalues, state);
         if (stop)
           info = -1;
@@ -487,6 +519,48 @@
 
 endfunction
 
+## Solve the double dogleg trust-region least-squares problem:
+## Minimize norm (r*x-b) subject to the constraint norm (d.*x) <= delta,
+## x being a convex combination of the gauss-newton and scaled gradient.
+
+## FIXME: error checks
+## FIXME: handle singularity, or leave it up to mldivide?
+
+function x = __dogleg__ (r, b, d, delta)
+
+  ## Get Gauss-Newton direction.
+  x = r \ b;
+  xn = norm (d .* x);
+  if (xn > delta)
+    ## GN is too big, get scaled gradient.
+    s = (r' * b) ./ d;
+    sn = norm (s);
+    if (sn > 0)
+      ## Normalize and rescale.
+      s = (s / sn) ./ d;
+      ## Get the line minimizer in s direction.
+      tn = norm (r*s);
+      snm = (sn / tn) / tn;
+      if (snm < delta)
+        ## Get the dogleg path minimizer.
+        bn = norm (b);
+        dxn = delta/xn; snmd = snm/delta;
+        t = (bn/sn) * (bn/xn) * snmd;
+        t -= dxn * snmd^2 - sqrt ((t-dxn)^2 + (1-dxn^2)*(1-snmd^2));
+        alpha = dxn*(1-snmd^2) / t;
+      else
+        alpha = 0;
+      endif
+    else
+      alpha = delta / xn;
+      snm = 0;
+    endif
+    ## Form the appropriate convex combination.
+    x = alpha * x + ((1-alpha) * min (snm, delta)) * s;
+  endif
+
+endfunction
+
 
 %!function retval = __f (p)
 %!  x = p(1);
@@ -521,7 +595,7 @@
 %!test
 %! x_opt = [ -0.767297326653401, 0.590671081117440, ...
 %!            1.47190018629642, -1.52719341133957 ];
-%! tol = 1.0e-5;
+%! tol = 1.0e-4;
 %! [x, fval, info] = fsolve (@__f, [-1, 1, 2, -1]);
 %! assert (info > 0);
 %! assert (norm (x - x_opt, Inf) < tol);
@@ -612,45 +686,3 @@
 %! assert (x == 0);
 %! assert (fvec == 0);
 %! assert (info == 1);
-
-## Solve the double dogleg trust-region least-squares problem:
-## Minimize norm(r*x-b) subject to the constraint norm(d.*x) <= delta,
-## x being a convex combination of the gauss-newton and scaled gradient.
-
-## FIXME: error checks
-## FIXME: handle singularity, or leave it up to mldivide?
-
-function x = __dogleg__ (r, b, d, delta)
-
-  ## Get Gauss-Newton direction.
-  x = r \ b;
-  xn = norm (d .* x);
-  if (xn > delta)
-    ## GN is too big, get scaled gradient.
-    s = (r' * b) ./ d;
-    sn = norm (s);
-    if (sn > 0)
-      ## Normalize and rescale.
-      s = (s / sn) ./ d;
-      ## Get the line minimizer in s direction.
-      tn = norm (r*s);
-      snm = (sn / tn) / tn;
-      if (snm < delta)
-        ## Get the dogleg path minimizer.
-        bn = norm (b);
-        dxn = delta/xn; snmd = snm/delta;
-        t = (bn/sn) * (bn/xn) * snmd;
-        t -= dxn * snmd^2 - sqrt ((t-dxn)^2 + (1-dxn^2)*(1-snmd^2));
-        alpha = dxn*(1-snmd^2) / t;
-      else
-        alpha = 0;
-      endif
-    else
-      alpha = delta / xn;
-      snm = 0;
-    endif
-    ## Form the appropriate convex combination.
-    x = alpha * x + ((1-alpha) * min (snm, delta)) * s;
-  endif
-
-endfunction
--- a/scripts/optimization/fzero.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/optimization/fzero.m	Fri Aug 10 09:09:51 2018 +0200
@@ -42,14 +42,29 @@
 ##
 ## @var{options} is a structure specifying additional options.  Currently,
 ## @code{fzero} recognizes these options:
-## @qcode{"FunValCheck"}, @qcode{"OutputFcn"}, @qcode{"TolX"},
-## @qcode{"MaxIter"}, @qcode{"MaxFunEvals"}.
-## For a description of these options, see @ref{XREFoptimset,,optimset}.
+## @qcode{"FunValCheck"}, @qcode{"MaxFunEvals"}, @qcode{"MaxIter"},
+## @qcode{"OutputFcn"}, and @qcode{"TolX"}.
+##
+## @qcode{"MaxFunEvals"} proscribes the maximum number of function evaluations
+## before the search is halted.  The default value is @code{Inf}.
+## The value must be a positive integer.
+##
+## @qcode{"MaxIter"} proscribes the maximum number of algorithm iterations
+## before the search is halted.  The default value is @code{Inf}.
+## The value must be a positive integer.
 ##
-## On exit, the function returns @var{x}, the approximate zero point and
-## @var{fval}, the function value thereof.
+## @qcode{"TolX"} specifies the termination tolerance for the solution @var{x}.
+## The default value is @code{eps}.
 ##
-## @var{info} is an exit flag that can have these values:
+## For a description of the other options, see @ref{XREFoptimset,,optimset}.
+## To initialize an options structure with default values for @code{fzero} use
+## @code{options = optimset ("fzero")}.
+##
+## On exit, the function returns @var{x}, the approximate zero point, and
+## @var{fval}, the function evaluated at @var{x}.
+##
+## The third output @var{info} reports whether the algorithm succeeded and
+## may take one of the following values:
 ##
 ## @itemize
 ## @item 1
@@ -59,7 +74,7 @@
 ##  Maximum number of iterations or function evaluations has been reached.
 ##
 ## @item -1
-## The algorithm has been terminated from user output function.
+## The algorithm has been terminated by a user @code{OutputFcn}.
 ##
 ## @item -5
 ## The algorithm may have converged to a singular point.
@@ -72,9 +87,12 @@
 ## @item iterations
 ##  Number of iterations through loop.
 ##
-## @item @nospell{nfev}
+## @item funcCount
 ##  Number of function evaluations.
 ##
+## @item algorithm
+##  The string "bisection, interpolation".
+##
 ## @item bracketx
 ##  A two-element vector with the final bracketing of the zero along the
 ## x-axis.
@@ -104,9 +122,10 @@
 function [x, fval, info, output] = fzero (fun, x0, options = struct ())
 
   ## Get default options if requested.
-  if (nargin == 1 && ischar (fun) && strcmp (fun, 'defaults'))
-    x = optimset ("MaxIter", Inf, "MaxFunEvals", Inf, "TolX", eps,
-                  "OutputFcn", [], "FunValCheck", "off");
+  if (nargin == 1 && ischar (fun) && strcmp (fun, "defaults"))
+    x = optimset ("Display", "notify", "FunValCheck", "off",
+                  "MaxFunEvals", Inf, "MaxIter", Inf,
+                  "OutputFcn", [], "TolX", eps);
     return;
   endif
 
@@ -118,23 +137,22 @@
     fun = str2func (fun, "global");
   endif
 
-  ## FIXME:
+  ## FIXME: Display is not yet implemented
   ## displev = optimget (options, "Display", "notify");
   funvalchk = strcmpi (optimget (options, "FunValCheck", "off"), "on");
+  maxfev = optimget (options, "MaxFunEvals", Inf);
+  maxiter = optimget (options, "MaxIter", Inf);
   outfcn = optimget (options, "OutputFcn");
   tolx = optimget (options, "TolX", eps);
-  maxiter = optimget (options, "MaxIter", Inf);
-  maxfev = optimget (options, "MaxFunEvals", Inf);
 
-  persistent mu = 0.5;
+  mu = 0.5;
 
   if (funvalchk)
     ## Replace fun with a guarded version.
     fun = @(x) guarded_eval (fun, x);
   endif
 
-  ## The default exit flag if exceeded number of iterations.
-  info = 0;
+  info = 0;  # The default exit flag if number of iterations exceeded.
   niter = 0;
   nfev = 0;
 
@@ -243,7 +261,7 @@
           c = a + q31 + q32 + q33;
         endif
         if (l < 4 || sign (c - a) * sign (c - b) > 0)
-          ## Quadratic interpolation + newton.
+          ## Quadratic interpolation + Newton.
           a0 = fa;
           a1 = (fb - fa)/(b - a);
           a2 = ((fd - fb)/(d - b) - a1) / (d - a);
@@ -356,6 +374,7 @@
 
   output.iterations = niter;
   output.funcCount = nfev;
+  output.algorithm = "bisection, interpolation";
   output.bracketx = [a, b];
   output.brackety = [fa, fb];
 
--- a/scripts/optimization/private/__fdjac__.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/optimization/private/__fdjac__.m	Fri Aug 10 09:09:51 2018 +0200
@@ -25,7 +25,7 @@
 
   if (cdif)
     err = (max (eps, err)) ^ (1/3);
-    h = typicalx*err;
+    h = err * max (abs (x), typicalx);
     fjac = zeros (length (fvec), numel (x));
     for i = 1:numel (x)
       x1 = x2 = x;
@@ -35,7 +35,9 @@
     endfor
   else
     err = sqrt (max (eps, err));
-    h = typicalx*err;
+    signp = sign (x);
+    signp(signp == 0) = 1;
+    h = err * signp .* max (abs (x), typicalx);
     fjac = zeros (length (fvec), numel (x));
     for i = 1:numel (x)
       x1 = x;
--- a/scripts/pkg/pkg.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/pkg/pkg.m	Fri Aug 10 09:09:51 2018 +0200
@@ -102,6 +102,9 @@
 ## pkg update
 ## @end example
 ##
+## @noindent
+## To update a single package use @code{pkg install -forge}
+##
 ## @item uninstall
 ## Uninstall named packages.  For example,
 ##
@@ -309,10 +312,10 @@
 
   confirm_recursive_rmdir (false, "local");
 
-  available_actions = {"list", "install", "uninstall", "load", ...
-                       "unload", "prefix", "local_list", ...
-                       "global_list", "rebuild", "build", ...
-                       "describe", "update"};
+  # valid actions in alphabetical order
+  available_actions = {"build", "describe", "global_list",  "install", ...
+                       "list", "load", "local_list", "prefix", "rebuild", ...
+                       "uninstall", "unload", "update"};
 
   ## Parse input arguments
   if (isempty (varargin) || ! iscellstr (varargin))
@@ -571,19 +574,15 @@
 
     case "update"
       installed_pkgs_lst = installed_packages (local_list, global_list);
+
       if (numel (files) > 0)
-         update_lst = {};
-         installed_names = {installed_pkgs_lst.name}';
-         for i = 1:numel (files)
-           idx = find (strcmp (files{i}, installed_names), 1);
-           if (isempty (idx))
-             warning ("pkg: package %s is not installed - skipping update", files{i});
-           else
-             update_lst = { update_lst, installed_pkgs_lst{idx} };
-           endif
-         endfor
-         installed_pkgs_lst = update_lst;
+        ## This was option was broken during two releases and no one
+        ## notice so we are guessing no one actually uses it.  If the
+        ## user knows the names of the packages to be installed, it
+        ## might as well call install (which is what update is doing)
+        error ("pkg: to update individual packages, use 'pkg install -forge'");
       endif
+
       for i = 1:numel (installed_pkgs_lst)
         installed_pkg_name = installed_pkgs_lst{i}.name;
         installed_pkg_version = installed_pkgs_lst{i}.version;
--- a/scripts/pkg/private/install.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/pkg/private/install.m	Fri Aug 10 09:09:51 2018 +0200
@@ -288,7 +288,8 @@
   ## without creating it such as giving an invalid filename for the package
   if (exist ("desc", "var")
       && exist (fullfile (desc.dir, "packinfo", "NEWS"), "file"))
-    printf ("For information about changes from previous versions of the %s package, run 'news %s'.\n",
+    printf (["For information about changes from previous versions " ...
+             "of the %s package, run 'news %s'.\n"],
             desc.name, desc.name);
   endif
 
--- a/scripts/plot/appearance/datetick.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/plot/appearance/datetick.m	Fri Aug 10 09:09:51 2018 +0200
@@ -205,10 +205,10 @@
     else
       [ymin, mmin, dmin] = datevec (xmin);
       [ymax, mmax, dmax] = datevec (xmax);
-      minyear = ymin + (mmin - 1) / 12 + (dmin - 1) / 12 / 30;
-      maxyear = ymax + (mmax - 1) / 12 + (dmax - 1) / 12 / 30;
-      minmonth = mmin + (dmin - 1) / 30;
-      maxmonth = (ymax  - ymin) * 12 + mmax + (dmax - 1) / 30;
+      minyear = ymin + (mmin - 1) / 12 + (dmin - 1) / 12 / 30.5;
+      maxyear = ymax + (mmax - 1) / 12 + (dmax - 1) / 12 / 30.5;
+      minmonth = mmin + (dmin - 1) / 30.5;
+      maxmonth = (ymax  - ymin) * 12 + mmax + (dmax - 1) / 30.5;
 
       if (maxmonth - minmonth < N)
         sep = __calc_tick_sep__ (xmin, xmax);
--- a/scripts/plot/draw/camlight.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/plot/draw/camlight.m	Fri Aug 10 09:09:51 2018 +0200
@@ -24,6 +24,7 @@
 ## @deftypefnx {} {} camlight (@var{az}, @var{el})
 ## @deftypefnx {} {} camlight (@dots{}, @var{style})
 ## @deftypefnx {} {} camlight (@var{hl}, @dots{})
+## @deftypefnx {} {} camlight (@var{hax}, @dots{})
 ## @deftypefnx {} {@var{h} =} camlight (@dots{})
 ## Add a light object to a figure using a simple interface.
 ##
@@ -45,6 +46,9 @@
 ## If the first argument @var{hl} is a handle to a light object, then act on
 ## this light object rather than creating a new object.
 ##
+## If the first argument @var{hax} is an axes handle, then create a new light
+## object in this axes, rather than the current axes returned by @code{gca}.
+##
 ## The optional return value @var{h} is a graphics handle to the light object.
 ## This can be used to move or further change properties of the light object.
 ##
@@ -100,14 +104,21 @@
   ## We don't worry about that.
   if (numel (varargin) > 0 && numel (varargin{1}) == 1
       && ishghandle (varargin{1}))
-    hl = varargin{1};
-    if (! isgraphics (hl, "light"))
-      error ("camlight: HL must be a handle to a light object");
+    typ = get (varargin{1}, "type");
+    if (strcmp (typ, "light"))
+      hl  = varargin{1};
+      hax = get (hl, "parent");
+    elseif (strcmp (typ, "axes"))
+      hax = varargin{1};
+      hl  = [];
+    else
+      error ("camlight: HL must be a handle to an axes or light object");
     endif
     varargin(1) = [];
     nargin = nargin - 1;
   else
-    hl = [];
+    hl  = [];
+    hax = [];
   endif
 
   style = "local";
@@ -168,9 +179,12 @@
     endswitch
   endif
 
-  cam_up = get (gca (), "cameraupvector");
-  cam_pos = get (gca (), "cameraposition");
-  cam_target = get (gca (), "cameratarget");
+  if (isempty (hax))
+    hax = gca ();
+  endif
+  cam_up = get (hax, "cameraupvector");
+  cam_pos = get (hax, "cameraposition");
+  cam_target = get (hax, "cameratarget");
 
   view_ax = cam_target - cam_pos;
   view_ax /= norm (view_ax);
@@ -186,7 +200,7 @@
   pos = [pos{:}];
 
   if (isempty (hl))
-    hl = light ("Position", pos, "style", style);
+    hl = light (hax, "Position", pos, "style", style);
   else
     set (hl, "Position", pos, "style", style);
   endif
@@ -296,9 +310,23 @@
 %!   close (hf);
 %! end_unwind_protect
 
+## Test an axes handle as first argument
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   hax1 = subplot (1, 2, 1);
+%!   hax2 = subplot (1, 2, 2);
+%!   hl1  = camlight ();
+%!   hl2  = camlight (hax1);
+%!   assert (get (hl1, "Parent"), hax2);
+%!   assert (get (hl2, "Parent"), hax1);
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
 ## Test input validation
 %!error camlight (1,2,3,4,5)
-%!error <HL must be a handle to a light object> camlight (0, "left")
+%!error <HL must be a handle to an axes or light object> camlight (0, "left")
 %!error <Invalid call> camlight ({1}, {2})
 %!error <Invalid call> camlight (rand (), 1, 2, 3)
 %!error <invalid light position 'foobar'> camlight ("foobar")
--- a/scripts/plot/draw/light.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/plot/draw/light.m	Fri Aug 10 09:09:51 2018 +0200
@@ -1,4 +1,4 @@
-## Copyright (C) 2016-2018 Markus Muetzel
+## Copyright (C) 2016-2018 Markus Mützel
 ##
 ## This file is part of Octave.
 ##
@@ -26,13 +26,12 @@
 ## When a light object is present in an axes object, and the properties
 ## @qcode{"EdgeLighting"} or @qcode{"FaceLighting"} of a @code{patch} or
 ## @code{surface} object are set to a value other than @qcode{"none"}, these
-## objects are drawn with light and shadow effects.  Supported values for
-## Lighting properties are @qcode{"none"} (no lighting effects), @qcode{"flat"}
-## (faceted look of the objects), and @qcode{"gouraud"} (linear interpolation
-## of the lighting effects between the vertices).  For @code{patch} objects,
-## the normals must be set manually (property @qcode{"VertexNormals"}).
+## objects are drawn with lighting effects.  Supported values for Lighting
+## properties are @qcode{"none"} (no lighting effects), @qcode{"flat"} (faceted
+## look of the objects), and @qcode{"gouraud"} (linear interpolation of the
+## lighting effects between the vertices).
 ##
-## Up to eight light objects are supported per axes.
+## Up to eight light objects are supported per axes. (Implementation dependent)
 ##
 ## Lighting is only supported for OpenGL graphic toolkits (i.e., @qcode{"fltk"}
 ## and @qcode{"qt"}).
--- a/scripts/plot/draw/patch.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/plot/draw/patch.m	Fri Aug 10 09:09:51 2018 +0200
@@ -252,6 +252,25 @@
 %! p = patch (x, y, [1 32]);
 %! title ("Autoscaling of colors: Red UL and Blue LR triangles");
 
+%!demo
+%! clf;
+%! vertices = [0 0 0; 0.5 -0.5 0; 1 0 0; 1 1 0; 0 1 1; 1 0 1; 0 -1 0;]+3;
+%! faces = [1 2 3 4 5 6 7];
+%! ha = axes ();
+%! hp = patch ('Vertices', vertices, 'Faces', faces, 'FaceColor', 'g');
+%! xlabel('x'), ylabel('y'), zlabel('z')
+%! view(3)
+%! set (ha, "XTick", [], "YTick", [], "ZTick", [])
+%! text (vertices(1,1), vertices(1,2), vertices(1,3), "1")
+%! text (vertices(2,1), vertices(2,2), vertices(2,3), "2")
+%! text (vertices(3,1), vertices(3,2), vertices(3,3), "3")
+%! text (vertices(4,1), vertices(4,2), vertices(4,3), "4")
+%! text (vertices(5,1), vertices(5,2), vertices(5,3), "5")
+%! text (vertices(6,1), vertices(6,2), vertices(6,3), "6")
+%! text (vertices(7,1), vertices(7,2), vertices(7,3), "7")
+%! title ("Non-coplanar patch")
+
+
 %!test
 %! hf = figure ("visible", "off");
 %! unwind_protect
@@ -263,12 +282,22 @@
 %!   assert (isempty (get (h, "cdata")));
 %!   assert (get (h, "faces"), [1, 2, 3], eps);
 %!   assert (get (h, "vertices"), [0 1; 1 1; 0 0], eps);
+%!   assert (get (h, "facenormalsmode"), "auto");
+%!   assert (get (h, "facenormals"), get (0, "defaultpatchfacenormals"));
+%!   assert (get (h, "vertexnormalsmode"), "auto");
+%!   assert (get (h, "vertexnormals"), get (0, "defaultpatchvertexnormals"));
 %!   assert (get (h, "type"), "patch");
 %!   assert (get (h, "facecolor"), [0 0 0]);
 %!   assert (get (h, "linestyle"), get (0, "defaultpatchlinestyle"));
 %!   assert (get (h, "linewidth"), get (0, "defaultpatchlinewidth"), eps);
 %!   assert (get (h, "marker"), get (0, "defaultpatchmarker"));
 %!   assert (get (h, "markersize"), get (0, "defaultpatchmarkersize"));
+%!   hl = light;
+%!   assert (get (h, "facelighting"), "flat");
+%!   assert (get (h, "facenormals"), [0 0 1], eps);
+%!   assert (get (h, "vertexnormals"), []);
+%!   set (h, "facelighting", "gouraud")
+%!   assert (get (h, "vertexnormals"), [0 0 1; 0 0 1; 0 0 1], eps);
 %! unwind_protect_cleanup
 %!   close (hf);
 %! end_unwind_protect
--- a/scripts/plot/draw/pie.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/plot/draw/pie.m	Fri Aug 10 09:09:51 2018 +0200
@@ -60,6 +60,10 @@
     print_usage ();
   endif
 
+  if (! all (isfinite (varargin{1})))
+    error ("pie: all data in X must be finite");
+  endif
+
   oldfig = [];
   if (! isempty (hax))
     oldfig = get (0, "currentfigure");
@@ -100,3 +104,8 @@
 %! colormap ([1,0,0;0,1,0;0,0,1;1,1,0;1,0,1;0,1,1]);
 %! axis ([-2,2,-2,2]);
 %! title ("pie() with missing slice");
+
+## Test input validation
+%!error pie ()
+%!error <all data in X must be finite> pie ([1 2 Inf])
+%!error <all data in X must be finite> pie ([1 2 NaN])
--- a/scripts/plot/draw/pie3.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/plot/draw/pie3.m	Fri Aug 10 09:09:51 2018 +0200
@@ -61,6 +61,10 @@
     print_usage ();
   endif
 
+  if (! all (isfinite (varargin{1})))
+    error ("pie3: all data in X must be finite");
+  endif
+
   oldfig = [];
   if (! isempty (hax))
     oldfig = get (0, "currentfigure");
@@ -100,3 +104,8 @@
 %! colormap ([1,0,0;0,1,0;0,0,1;1,1,0;1,0,1;0,1,1]);
 %! axis ([-2,2,-2,2]);
 %! title ("pie3() with missing slice");
+
+## Test input validation
+%!error pie3 ()
+%!error <all data in X must be finite> pie3 ([1 2 Inf])
+%!error <all data in X must be finite> pie3 ([1 2 NaN])
--- a/scripts/plot/draw/private/__pie__.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/plot/draw/private/__pie__.m	Fri Aug 10 09:09:51 2018 +0200
@@ -131,8 +131,10 @@
     elseif (strcmp (caller, "pie"))
       if (xt > 0)
         align = "left";
+      elseif (xt < 0)
+        align = "right";
       else
-        align = "right";
+        align = "center";
       endif
 
       hlist = [hlist; patch(xoff + [0, -sind(xn)], yoff + [0, cosd(xn)], i);
--- a/scripts/plot/util/__gnuplot_drawnow__.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/plot/util/__gnuplot_drawnow__.m	Fri Aug 10 09:09:51 2018 +0200
@@ -146,15 +146,15 @@
       if (output_to_screen (term) && ! strcmp (term, "dumb"))
         fig.numbertitle = get (h, "numbertitle");
         fig.name = strrep (get (h, "name"), '"', '\"');
-        if (strcmp (get (h, "numbertitle"), "on"))
+        if (! isempty (get (h, "number")) && strcmp (get (h, "numbertitle"), "on"))
           title_str = sprintf ("Figure %d", h);
+          if (! isempty (fig.name))
+            title_str = sprintf ("%s: %s", title_str, fig.name);
+          endif
+        elseif (! isempty (fig.name))
+          title_str = fig.name;
         else
-          title_str = "";
-        endif
-        if (! isempty (fig.name) && ! isempty (title_str))
-          title_str = sprintf ("%s: %s", title_str, fig.name);
-        elseif (! isempty (fig.name) && isempty (title_str))
-          title_str = fig.name;
+          title_str = " ";
         endif
         if (! isempty (title_str))
           title_str = sprintf ('title "%s"', title_str);
--- a/scripts/plot/util/hdl2struct.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/plot/util/hdl2struct.m	Fri Aug 10 09:09:51 2018 +0200
@@ -135,15 +135,12 @@
   persistent excluded;
 
   if (isempty (excluded))
-    excluded = cell2struct (repmat ({[]}, 1, 21),
+    excluded = cell2struct (repmat ({[]}, 1, 15),
                             {"beingdeleted", "busyaction", "buttondownfcn", ...
                              "children", "clipping", "createfcn", ...
                              "deletefcn", "handlevisibility", "hittest", ...
                              "interruptible", "parent", "selected" , ...
-                             "selectionhighlight", "type", "uicontextmenu", ...
-                             "currentaxes", "currentcharacter", ...
-                             "currentobject", "tightinset", "currentpoint", ...
-                             "extent"}, 2);
+                             "selectionhighlight", "type", "uicontextmenu"}, 2);
   endif
 
   obj = get (h);
--- a/scripts/plot/util/print.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/plot/util/print.m	Fri Aug 10 09:09:51 2018 +0200
@@ -131,7 +131,7 @@
 ##   @itemx pdfcairolatex
 ##   @itemx epscairolatexstandalone
 ##   @itemx pdfcairolatexstandalone
-##     Generate Cairo based output when using the Gnuplot graphics toolkit.
+##     Generate Cairo-based output when using the Gnuplot graphics toolkit.
 ## The @samp{epscairo} and @samp{pdfcairo} devices are synonymous with
 ## the @samp{epsc} device.  The @LaTeX{} variants generate a @LaTeX{} file,
 ## @file{@var{filename}.tex}, for the text portions of a plot, and an image
@@ -141,7 +141,7 @@
 ##
 ##   @item  ill
 ##   @itemx @nospell{aifm}
-##     Adobe Illustrator (Obsolete for Gnuplot versions > 4.2)
+##     Adobe Illustrator (obsolete for Gnuplot versions > 4.2)
 ##
 ##   @item canvas
 ##     Javascript-based drawing on HTML5 canvas viewable in a web browser
@@ -188,16 +188,20 @@
 ##     Metafont
 ##
 ##   @item png
-##     Portable network graphics
+##     Portable Network Graphics
 ##
 ##   @item pbm
 ##     PBMplus
 ##
 ##   @item pdf
-##     Portable document format
+##     Portable Document Format
 ##
 ##   @item svg
-##     Scalable vector graphics
+##     Scalable Vector Graphics
+##
+##   @item  tif
+##   @itemx tiff
+##     TIFF image, compressed
 ##
 ##   @item  tikz
 ##   @itemx tikzstandalone
--- a/scripts/plot/util/private/__ghostscript__.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/plot/util/private/__ghostscript__.m	Fri Aug 10 09:09:51 2018 +0200
@@ -76,6 +76,10 @@
     gs_opts = sprintf ("%s -dLanguageLevel=%d", gs_opts, opts.level);
   endif
 
+  if (strfind (opts.device, "tiffscaled"))
+    gs_opts = [gs_opts " -sCompression=lzw"];
+  endif
+
   if (opts.antialiasing && isempty (strfind (opts.device, "write")))
     ## Apply anti-aliasing to all bitmap formats/devices
     gs_opts = sprintf ("%s -dTextAlphaBits=%d -dGraphicsAlphaBits=%d",
--- a/scripts/plot/util/private/__gnuplot_draw_axes__.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/plot/util/private/__gnuplot_draw_axes__.m	Fri Aug 10 09:09:51 2018 +0200
@@ -247,8 +247,7 @@
   else
     xaxisloc = "x";
     xaxisloc_using = "x1";
-### FIXME: DEPRECATED: Remove "zero" in version 5.
-    if (any (strcmp (axis_obj.xaxislocation, {"origin", "zero"})))
+    if (strcmp (axis_obj.xaxislocation, "origin"))
       fputs (plot_stream, "set xzeroaxis;\n");
     endif
   endif
@@ -258,8 +257,7 @@
   else
     yaxisloc = "y";
     yaxisloc_using = "y1";
-### FIXME: DEPRECATED: Remove "zero" in version 5.
-    if (any (strcmp (axis_obj.yaxislocation, {"origin", "zero"})))
+    if (strcmp (axis_obj.yaxislocation, "origin"))
       fputs (plot_stream, "set yzeroaxis;\n");
     endif
   endif
@@ -1498,13 +1496,13 @@
         if (isempty (axis_obj.xtick))
         elseif (strcmp (axis_obj.xaxislocation, "top"))
           fprintf (plot_stream, "set x2tics %s nomirror\n", axis_obj.tickdir);
-        else # xaxislocation == "bottom", "origin" or "zero"
+        else # xaxislocation == "bottom" or "origin"
           fprintf (plot_stream, "set xtics %s nomirror\n", axis_obj.tickdir);
         endif
         if (isempty (axis_obj.ytick))
         elseif (strcmp (axis_obj.yaxislocation, "right"))
           fprintf (plot_stream, "set y2tics %s nomirror\n", axis_obj.tickdir);
-        else # yaxislocation == "left", "origin" or "zero"
+        else # yaxislocation == "left" or "origin"
           fprintf (plot_stream, "set ytics %s nomirror\n",  axis_obj.tickdir);
         endif
       endif
@@ -1809,12 +1807,10 @@
     arrow (4, obj.ycolor, obj.linewidth, [1,0,0], [1,1,0]);
   endif
 
-### FIXME: DEPRECATED: Remove "zero" in version 5.
-  if (any (strcmp (obj.xaxislocation, {"origin", "zero"})))
+  if (strcmp (obj.xaxislocation, "origin"))
     idx = zeroaxis (idx, obj.xcolor, "x");
   endif
-### FIXME: DEPRECATED: Remove "zero" in version 5.
-  if (any (strcmp (obj.yaxislocation, {"origin", "zero"})))
+  if (strcmp (obj.yaxislocation, "origin"))
     idx = zeroaxis (idx, obj.ycolor, "y");
   endif
 
@@ -2180,8 +2176,7 @@
                obj.xcolor, "x", plot_stream, true, "border",
                "", "", fontname, fontspec, obj.ticklabelinterpreter,
                obj.xscale, obj.xsgn, gnuplot_term);
-### FIXME: DEPRECATED: Remove "zero" in version 5.
-  elseif (any (strcmp (obj.xaxislocation, {"origin", "zero"})))
+  elseif (strcmp (obj.xaxislocation, "origin"))
     do_tics_1 (obj.xtickmode, obj.xtick, obj.xminortick, obj.xticklabelmode,
                obj.xticklabel, obj.xcolor, "x", plot_stream, true,
                "axis", obj.tickdir, ticklength, fontname, fontspec,
@@ -2209,8 +2204,7 @@
                obj.ycolor, "y", plot_stream, ymirror, "border",
                "", "", fontname, fontspec, obj.ticklabelinterpreter,
                obj.yscale, obj.ysgn, gnuplot_term);
-### FIXME: DEPRECATED: Remove "zero" in version 5.
-  elseif (any (strcmp (obj.yaxislocation, {"origin", "zero"})))
+  elseif (strcmp (obj.yaxislocation, "origin"))
     do_tics_1 (obj.ytickmode, obj.ytick, obj.yminortick, obj.yticklabelmode,
                obj.yticklabel, obj.ycolor, "y", plot_stream, ymirror,
                "axis", obj.tickdir, ticklength, fontname, fontspec,
--- a/scripts/plot/util/private/__opengl_print__.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/plot/util/private/__opengl_print__.m	Fri Aug 10 09:09:51 2018 +0200
@@ -157,8 +157,7 @@
       ## Use toolkits "print_figure" method
       drawnow (gl2ps_device{n}, ['|' pipeline{n}]);
     else
-      ## Use OpenGL offscreen rendering with OSMesa
-      __osmesa_print__ (opts.figure, ['|' pipeline{n}], gl2ps_device{n});
+      error ("print: figure must be visible or qt toolkit must be used with __gl_window__ property 'on' or QT_OFFSCREEN feature available");
     endif
   endfor
 
--- a/scripts/plot/util/private/__print_parse_opts__.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/plot/util/private/__print_parse_opts__.m	Fri Aug 10 09:09:51 2018 +0200
@@ -211,6 +211,8 @@
     arg_st.devopt = "emf";
   elseif (strcmp (arg_st.devopt, "jpg"))
     arg_st.devopt = "jpeg";
+  elseif (strcmp (arg_st.devopt, "tif"))
+    arg_st.devopt = "tiff";
   endif
 
   persistent dev_list = {"aifm", "corel", "fig", "png", "jpeg", ...
@@ -614,10 +616,13 @@
                  "pcxcmyk"; "pcxgray"; "pcxmono"; "pdfwrite"; "pgm"; ...
                  "pgmraw"; "pgnm"; "pgnmraw"; "png16"; "png16m"; ...
                  "png256"; "png48"; "pngalpha"; "pnggray"; "pngmono"; ...
-                 "pnm"; "pnmraw"; "ppm"; "ppmraw"; "pswrite"; ...
-                 "ps2write"; "tiff12nc"; "tiff24nc"; "tiff32nc"; ...
-                 "tiffcrle"; "tiffg3"; "tiffg32d"; "tiffg4"; ...
-                 "tiffgray"; "tifflzw"; "tiffpack"; "tiffsep"};
+                 "pnm"; "pnmraw"; "ppm"; "ppmraw"; "pswrite"; "ps2write"; ...
+                 "tiff12nc"; "tiff24nc"; "tiff32nc"; "tiff48nc"; ...
+                 "tiff64nc"; "tiffcrle"; "tiffg3"; "tiffg32d"; "tiffg4"; ...
+                 "tiffgray"; "tifflzw"; "tiffpack"; "tiffscaled"; ...
+                 "tiffscaled24"; "tiffscaled32"; "tiffscaled4"; ...
+                 "tiffscaled8"; "tiffsep"; "tiffsep1" };
+
 endfunction
 
 function aliases = gs_aliases ()
@@ -633,6 +638,6 @@
   aliases.ps2   = "ps2write";
   aliases.psc   = "ps2write";
   aliases.psc2  = "ps2write";
-  aliases.tiff  = "tiff24nc";
+  aliases.tiff  = "tiffscaled24";
   aliases.tiffn = "tiff24nc";
 endfunction
--- a/scripts/plot/util/saveas.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/plot/util/saveas.m	Fri Aug 10 09:09:51 2018 +0200
@@ -39,10 +39,13 @@
 ##     JPEG Image
 ##
 ##   @item png
-##     PNG Image
+##     Portable Network Graphics image
 ##
 ##   @item emf
-##     Enhanced Meta File
+##     Enhanced MetaFile
+##
+##   @item tif
+##     TIFF Image, compressed
 ##
 ## @end table
 ##
--- a/scripts/plot/util/struct2hdl.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/plot/util/struct2hdl.m	Fri Aug 10 09:09:51 2018 +0200
@@ -123,12 +123,16 @@
     h = 0;
     s.properties = rmfield (s.properties, ...
                               {"callbackobject", "commandwindowsize", ...
+                               "monitorpositions", "pointerwindow", ...
                                "screendepth", "screenpixelsperinch", ...
                                "screensize"});
   elseif (strcmp (s.type, "figure"))
     h = figure ();
+    s.properties = rmfield (s.properties, ...
+                              {"currentaxes", "currentcharacter", ...
+                               "currentobject", "currentpoint", "number"});
   elseif (strcmp (s.type, "axes"))
-    ## legends and colorbars are "transformed" in normal axes
+    ## legends and colorbars are "transformed" in to normal axes
     ## if hilev is not requested
     if (! hilev)
       if (strcmp (s.properties.tag, "legend"))
@@ -141,13 +145,14 @@
         par = gcf;
       endif
     endif
-
+    s.properties = rmfield (s.properties, {"tightinset"});
     [h, s] = createaxes (s, p, par);
   elseif (strcmp (s.type, "line"))
     h = createline (s, par);
   elseif (strcmp (s.type, "patch"))
     [h, s] = createpatch (s, par);
   elseif (strcmp (s.type, "text"))
+    s.properties = rmfield (s.properties, "extent");
     h = createtext (s, par);
   elseif (strcmp (s.type, "image"))
     h = createimage (s, par);
@@ -579,8 +584,8 @@
       set (h, s.properties);
     else
       ## Specials are objects that where automatically constructed with
-      ## current object.  Among them are "x(yz)labels", "title", high
-      ## level hggroup children
+      ## current object.  Among them are "x(yz)labels", "title", and
+      ## high level hggroup children
       fields = fieldnames (s.properties);
       vals = struct2cell (s.properties);
       idx = find (cellfun (@(x) valcomp(x, hdls) , vals));
@@ -597,8 +602,14 @@
         field = fields{nf};
         idx = find (hdls == vals{nf});
         spec = specs(idx);
+        ## FIXME: Wouldn't it be better to call struct2hdl recursively
+        ##        for this handle?  That way the function could determine
+        ##        based on type what special actions to take.
+        try
+          spec.properties = rmfield (spec.properties, "extent");
+        end_try_catch
         if (isprop (h, field))
-          h2 = get (h , field);
+          h2 = get (h, field);
           addmissingprops (h2, spec.properties);
           set (h2, spec.properties);
         endif
--- a/scripts/polynomial/residue.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/polynomial/residue.m	Fri Aug 10 09:09:51 2018 +0200
@@ -87,8 +87,8 @@
 ## polynomial specified by @var{r}, @var{p} and @var{k}, and the pole
 ## multiplicity @var{e}.
 ##
-## If the multiplicity, @var{e}, is not explicitly specified the
-## multiplicity is determined by the function @code{mpoles}.
+## If the multiplicity, @var{e}, is not explicitly specified the multiplicity
+## is determined by the function @code{mpoles}.
 ##
 ## For example:
 ##
@@ -151,7 +151,7 @@
     print_usage ();
   endif
 
-  toler = .001;
+  tol = .001;
 
   if (nargin >= 3)
     if (nargin >= 4)
@@ -159,14 +159,13 @@
     else
       e = [];
     endif
-    ## The inputs are the residue, pole, and direct part.  Solve for the
-    ## corresponding numerator and denominator polynomials
-    [r, p] = rresidue (b, a, varargin{1}, toler, e);
+    ## The inputs are the residue, pole, and direct part.
+    ## Solve for the corresponding numerator and denominator polynomials.
+    [r, p] = rresidue (b, a, varargin{1}, tol, e);
     return;
   endif
 
-  ## Make sure both polynomials are in reduced form.
-
+  ## Make sure both polynomials are in reduced form, and scaled.
   a = polyreduce (a);
   b = polyreduce (b);
 
@@ -177,7 +176,6 @@
   lb = length (b);
 
   ## Handle special cases here.
-
   if (la == 0 || lb == 0)
     k = r = p = e = [];
     return;
@@ -188,19 +186,16 @@
   endif
 
   ## Find the poles.
-
   p = roots (a);
   lp = length (p);
 
   ## Sort poles so that multiplicity loop will work.
-
-  [e, indx] = mpoles (p, toler, 1);
-  p = p(indx);
+  [e, idx] = mpoles (p, tol, 1);
+  p = p(idx);
 
   ## For each group of pole multiplicity, set the value of each
   ## pole to the average of the group.  This reduces the error in
   ## the resulting poles.
-
   p_group = cumsum (e == 1);
   for ng = 1:p_group(end)
     m = find (p_group == ng);
@@ -208,7 +203,6 @@
   endfor
 
   ## Find the direct term if there is one.
-
   if (lb >= la)
     ## Also return the reduced numerator.
     [k, b] = deconv (b, a);
@@ -218,7 +212,6 @@
   endif
 
   ## Determine if the poles are (effectively) zero.
-
   small = max (abs (p));
   if (isa (a, "single") || isa (b, "single"))
     small = max ([small, 1]) * eps ("single") * 1e4 * (1 + numel (p))^2;
@@ -228,36 +221,31 @@
   p(abs (p) < small) = 0;
 
   ## Determine if the poles are (effectively) real, or imaginary.
+  idx = (abs (imag (p)) < small);
+  p(idx) = real (p(idx));
+  idx = (abs (real (p)) < small);
+  p(idx) = 1i * imag (p(idx));
 
-  index = (abs (imag (p)) < small);
-  p(index) = real (p(index));
-  index = (abs (real (p)) < small);
-  p(index) = 1i * imag (p(index));
-
-  ## The remainder determines the residues.  The case of one pole
-  ## is trivial.
-
+  ## The remainder determines the residues.  The case of one pole is trivial.
   if (lp == 1)
     r = polyval (b, p);
     return;
   endif
 
   ## Determine the order of the denominator and remaining numerator.
-  ## With the direct term removed the potential order of the numerator
+  ## With the direct term removed, the potential order of the numerator
   ## is one less than the order of the denominator.
-
   aorder = numel (a) - 1;
   border = aorder - 1;
 
   ## Construct a system of equations relating the individual
   ## contributions from each residue to the complete numerator.
-
   A = zeros (border+1, border+1);
   B = prepad (reshape (b, [numel(b), 1]), border+1, 0);
   for ip = 1:numel (p)
     ri = zeros (size (p));
     ri(ip) = 1;
-    A(:,ip) = prepad (rresidue (ri, p, [], toler), border+1, 0).';
+    A(:,ip) = prepad (rresidue (ri, p, [], tol), border+1, 0).';
   endfor
 
   ## Solve for the residues.
@@ -269,37 +257,20 @@
 
 endfunction
 
-function [pnum, pden, e] = rresidue (r, p, k, toler, e)
-
-  ## Reconstitute the numerator and denominator polynomials from the
-  ## residues, poles, and direct term.
+## Reconstitute the numerator and denominator polynomials
+## from the residues, poles, and direct term.
+function [pnum, pden, e] = rresidue (r, p, k = [], tol = [], e = [])
 
-  if (nargin < 2 || nargin > 5)
-    print_usage ();
-  endif
-
-  if (nargin < 5)
-    e = [];
+  if (! isempty (e))
+    idx = 1:numel (p);
+  else
+    [e, idx] = mpoles (p, tol, 0);
+    p = p(idx);
+    r = r(idx);
   endif
 
-  if (nargin < 4)
-    toler = [];
-  endif
-
-  if (nargin < 3)
-    k = [];
-  endif
-
-  if (numel (e))
-    indx = 1:numel (p);
-  else
-    [e, indx] = mpoles (p, toler, 0);
-    p = p(indx);
-    r = r(indx);
-  endif
-
-  indx = 1:numel (p);
-  for n = indx
+  idx = 1:numel (p);
+  for n = idx
     pn = [1, -p(n)];
     if (n == 1)
       pden = pn;
@@ -320,7 +291,7 @@
   K = numel (k) - 1;
   N = K + D;
   pnum = zeros (1, N+1);
-  for n = indx(abs (r) > 0)
+  for n = idx(abs (r) > 0)
     p1 = [1, -p(n)];
     pn = 1;
     for j = 1:n - 1
--- a/scripts/signal/fftconv.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/signal/fftconv.m	Fri Aug 10 09:09:51 2018 +0200
@@ -66,7 +66,7 @@
 
 
 ## FIXME: Borrow tests from conv.m.  May need tolerance on the assert stmt.
-%!test
+%!testif HAVE_FFTW
 %! x = ones (3,1);
 %! y = ones (1,3);
 %! b = 2;
--- a/scripts/signal/fftfilt.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/signal/fftfilt.m	Fri Aug 10 09:09:51 2018 +0200
@@ -132,7 +132,7 @@
 
 %!shared b, x, r
 
-%!test
+%!testif HAVE_FFTW
 %! b = [1 1];
 %! x = [1, zeros(1,9)];
 %! assert (fftfilt (b,  x  ), [1 1 0 0 0 0 0 0 0 0]  );
@@ -142,14 +142,14 @@
 %! assert (fftfilt (b,  [x.' x.']), [1 1 0 0 0 0 0 0 0 0].'*[1 1]);
 %! assert (fftfilt (b,  [x.'+2*eps x.']) == [1 1 0 0 0 0 0 0 0 0].'*[1 1], [false(10, 1) true(10, 1)]);
 
-%!test
+%!testif HAVE_FFTW
 %! r = sqrt (1/2) * (1+i);
 %! b = b*r;
 %! assert (fftfilt (b, x  ), r*[1 1 0 0 0 0 0 0 0 0]  , eps  );
 %! assert (fftfilt (b, r*x), r*r*[1 1 0 0 0 0 0 0 0 0], 2*eps);
 %! assert (fftfilt (b, x.'), r*[1 1 0 0 0 0 0 0 0 0].', eps  );
 
-%!test
+%!testif HAVE_FFTW
 %! b  = [1 1];
 %! x  = zeros (10,3); x(1,1)=-1; x(1,2)=1;
 %! y0 = zeros (10,3); y0(1:2,1)=-1; y0(1:2,2)=1;
@@ -166,7 +166,7 @@
 %! assert (true, isreal (y(:,1)));
 %! assert (false, any (real (y(:,2))));
 
-%!test
+%!testif HAVE_FFTW
 %! b  = rand (10, 1);
 %! x  = rand (10, 1);
 %! y0 = filter (b, 1, x);
@@ -176,7 +176,7 @@
 %! y  = fftfilt (b*i, x*i);
 %! assert (y0, y, 16*eps);
 
-%!test
+%!testif HAVE_FFTW
 %! b  = rand (10, 1) + i*rand (10, 1);
 %! x  = rand (10, 1) + i*rand (10, 1);
 %! y0 = filter (b, 1, x);
--- a/scripts/signal/freqz.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/signal/freqz.m	Fri Aug 10 09:09:51 2018 +0200
@@ -201,7 +201,7 @@
 endfunction
 
 
-%!test # correct values and fft-polyval consistency
+%!testif HAVE_FFTW # correct values and fft-polyval consistency
 %! ## butterworth filter, order 2, cutoff pi/2 radians
 %! b = [0.292893218813452  0.585786437626905  0.292893218813452];
 %! a = [1  0  0.171572875253810];
@@ -210,7 +210,7 @@
 %! assert (abs (h(17)).^2,0.5,10*eps);
 %! assert (h,freqz (b,a,w),10*eps);  # fft should be consistent with polyval
 
-%!test # whole-half consistency
+%!testif HAVE_FFTW # whole-half consistency
 %! b = [1 1 1]/3; # 3-sample average
 %! [h,w] = freqz (b,1,32,"whole");
 %! assert (h(2:16),conj (h(32:-1:18)),20*eps);
@@ -218,7 +218,7 @@
 %! assert (h(1:16),h2,20*eps);
 %! assert (w(1:16),w2,20*eps);
 
-%!test # Sampling frequency properly interpreted
+%!testif HAVE_FFTW # Sampling frequency properly interpreted
 %! b = [1 1 1]/3; a = [1 0.2];
 %! [h,f] = freqz (b,a,16,320);
 %! assert (f,[0:15]'*10,10*eps);
--- a/scripts/sparse/eigs.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/sparse/eigs.m	Fri Aug 10 09:09:51 2018 +0200
@@ -1480,11 +1480,86 @@
 %! j_B = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
 %! v_B = [3, 10i, 1, 8i, 7, 6i, 5, 4i, 9, 7i];
 %! B = sparse(i_B, j_B, v_B); # not SPD
-%! [Evectors Evalues] = eigs(A, B, 5, 'SM'); # call_eig is true
+%! [Evectors, Evalues] = eigs(A, B, 5, "SM"); # call_eig is true
 %! ResidualVectors = A * Evectors - B * Evectors * Evalues;
 %! RelativeErrors = norm (ResidualVectors, "columns") ./ ...
 %! norm (A * Evectors, "columns");
-%! assert (RelativeErrors, zeros (1, 5))
+%! assert (RelativeErrors, zeros (1, 5));
 %!testif HAVE_ARPACK
 %! A = rand (8);
 %! eigs (A, 6, "lr"); # this failed on 4.2.x
+%!testif HAVE_ARPACK
+%! M = magic (10);
+%! A = sin (M);
+%! B = cos (M);
+%! B = B * B';
+%! opts.v0 = (1:10)';
+%! [Evector, Evalues] = eigs (A, B, 4, "LM", opts);
+%! Afun = @(x) A * x;
+%! [Evector_f Evalues_f] = eigs (Afun, 10, B, 4, "LM", opts);
+%! assert (Evector, Evector_f);
+%! assert (Evalues, Evalues_f);
+%!testif HAVE_ARPACK
+%! M = magic (10);
+%! A = sin (M);
+%! B = cos (M);
+%! B = B * B';
+%! opts.v0 = (1:10)';
+%! [Evector, Evalues] = eigs (A, B, 4, "SM", opts);
+%! [L, U, P] = lu (A);
+%! Afun = @(x) U \ (L \ (P * x));
+%! [Evector_f Evalues_f] = eigs (Afun, 10, B, 4, "SM", opts);
+%! assert (Evector, Evector_f);
+%! assert (Evalues, Evalues_f);
+%!testif HAVE_ARPACK
+%! M = magic (10);
+%! A = sin (M);
+%! A = A * A';
+%! B = cos (M);
+%! B = B * B';
+%! opts.v0 = (1:10)';
+%! [Evector, Evalues] = eigs (A, B, 4, "LM", opts);
+%! Afun = @(x) A * x;
+%! opts.issym = true;
+%! [Evector_f Evalues_f] = eigs (Afun, 10, B, 4, "LM", opts);
+%! assert (Evector, Evector_f);
+%! assert (Evalues, Evalues_f);
+%!testif HAVE_ARPACK
+%! M = magic (10);
+%! A = sin (M);
+%! A = A * A';
+%! B = cos (M);
+%! B = B * B';
+%! opts.v0 = (1:10)';
+%! [Evector, Evalues] = eigs (A, B, 4, "SM", opts);
+%! [L, U, P] = lu (A);
+%! Afun = @(x) U \ (L \ (P * x));
+%! opts.issym = true;
+%! [Evector_f Evalues_f] = eigs (Afun, 10, B, 4, "SM", opts);
+%! assert (Evector, Evector_f);
+%! assert (Evalues, Evalues_f);
+%!testif HAVE_ARPACK
+%! M = magic (10);
+%! A = sin (M) + 1i * cos (M);
+%! B = cos (M) + 1i * sin (M);
+%! B = B * B';
+%! opts.v0 = (1:10)';
+%! [Evector, Evalues] = eigs (A, B, 4, "LM", opts);
+%! Afun = @(x) A * x;
+%! opts.isreal = false;
+%! [Evector_f Evalues_f] = eigs (Afun, 10, B, 4, "LM", opts);
+%! assert (Evector, Evector_f);
+%! assert (Evalues, Evalues_f);
+%!testif HAVE_ARPACK
+%! M = magic (10);
+%! A = sin (M) + 1i * cos (M);
+%! B = cos (M) + 1i * sin (M);
+%! B = B * B';
+%! opts.v0 = (1:10)';
+%! [Evector, Evalues] = eigs (A, B, 4, "SM", opts);
+%! [L, U, P] = lu (A);
+%! Afun = @(x) U \ (L \ (P *x));
+%! opts.isreal = false;
+%! [Evector_f, Evalues_f] = eigs (Afun, 10, B, 4, "SM", opts);
+%! assert (Evector, Evector_f);
+%! assert (Evalues, Evalues_f);
--- a/scripts/sparse/nonzeros.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/sparse/nonzeros.m	Fri Aug 10 09:09:51 2018 +0200
@@ -17,20 +17,24 @@
 ## <https://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {} {} nonzeros (@var{s})
-## Return a vector of the nonzero values of the sparse matrix @var{s}.
+## @deftypefn {} {@var{v} =} nonzeros (@var{A})
+## Return a column vector of the nonzero values of the matrix @var{A}.
 ## @seealso{find, nnz}
 ## @end deftypefn
 
-function t = nonzeros (s)
+function v = nonzeros (A)
 
   if (nargin != 1)
     print_usage ();
   endif
 
-  [~, ~, t] = find (s);
-
-  t = t(:);
+  if (issparse (A))
+    [~, ~, v] = find (A);
+    v = v(:);
+  else
+    v = A(find (A));
+    v = v(:);
+  endif
 
 endfunction
 
@@ -39,3 +43,7 @@
 %!assert (nonzeros ([1,2,3,0]), [1;2;3])
 %!assert (nonzeros (sparse ([1,2;3,0])), [1;3;2])
 %!assert (nonzeros (sparse ([1,2,3,0])), [1;2;3])
+
+## Test input validation
+%!error nonzeros ()
+%!error nonzeros (1, 2)
--- a/scripts/sparse/pcg.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/sparse/pcg.m	Fri Aug 10 09:09:51 2018 +0200
@@ -551,10 +551,10 @@
 %!test
 %! ## solve tridiagonal system, do not converge in default 20 iterations
 %! N = 100;
-%! A = zeros (N, N);
-%! for i = 1 : N - 1  # form 1-D Laplacian matrix
-%!   A(i:i+1, i:i+1) = [2 -1; -1 2];
-%! endfor
+%! ## Form 1-D Laplacian matrix
+%! A = 2 * eye (N,N);
+%! A(2:(N+1):end) = -1;
+%! A((N+1):(N+1):end) = -1;
 %! b = ones (N, 1);
 %! [x, flag, relres, iter, resvec, eigest] = pcg (A, b, 1e-12);
 %! assert (flag);
@@ -564,10 +564,10 @@
 %! ## solve tridiagonal system with "perfect" preconditioner which converges
 %! ## in one iteration, so the eigest does not work and issues a warning.
 %! N = 100;
-%! A = zeros (N, N);
-%! for i = 1 : N - 1  # form 1-D Laplacian matrix
-%!   A(i:i+1, i:i+1) = [2 -1; -1 2];
-%! endfor
+%! ## Form 1-D Laplacian matrix
+%! A = 2 * eye (N,N);
+%! A(2:(N+1):end) = -1;
+%! A((N+1):(N+1):end) = -1;
 %! b = ones (N, 1);
 %! [x, flag, relres, iter, resvec, eigest] = pcg (A, b, [], [], A, [], b);
 %! assert (flag, 0);
--- a/scripts/sparse/pcr.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/sparse/pcr.m	Fri Aug 10 09:09:51 2018 +0200
@@ -363,10 +363,11 @@
 %! ## Note that we use here indefinite preconditioners!
 %!
 %! N = 100;
-%! A = zeros (N,N);
-%! for i=1:N-1 # form 1-D Laplacian matrix
-%!   A(i:i+1,i:i+1) = [2 -1; -1 2];
-%! endfor
+%! ## Form 1-D Laplacian matrix
+%! A = 2 * eye (N,N);
+%! A(2:(N+1):end) = -1;
+%! A((N+1):(N+1):end) = -1;
+%!
 %! A = [A, zeros(size(A)); zeros(size(A)), -A];
 %! b = rand (2*N,1);
 %! X = A \ b;  # X is the true solution
@@ -416,10 +417,10 @@
 %! ## should perform max allowable default number of iterations
 %!
 %! N = 100;
-%! A = zeros (N,N);
-%! for i=1:N-1 # form 1-D Laplacian matrix
-%!   A(i:i+1,i:i+1) = [2 -1; -1 2];
-%! endfor
+%! ## Form 1-D Laplacian matrix
+%! A = 2 * eye (N,N);
+%! A(2:(N+1):end) = -1;
+%! A((N+1):(N+1):end) = -1;
 %! b = ones (N,1);
 %! X = A \ b;  # X is the true solution
 %! [x, flag, relres, iter, resvec] = pcr (A,b,1e-12);
@@ -432,10 +433,10 @@
 %! ## converges in one iteration
 %!
 %! N = 100;
-%! A = zeros (N,N);
-%! for i=1:N-1 # form 1-D Laplacian matrix
-%!   A(i:i+1,i:i+1) = [2 -1; -1 2];
-%! endfor
+%! ## Form 1-D Laplacian matrix
+%! A = 2 * eye (N,N);
+%! A(2:(N+1):end) = -1;
+%! A((N+1):(N+1):end) = -1;
 %! b = ones (N,1);
 %! X = A \ b;  # X is the true solution
 %! [x, flag, relres, iter] = pcr (A,b,[],[],A,b);
--- a/scripts/specfun/factor.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/specfun/factor.m	Fri Aug 10 09:09:51 2018 +0200
@@ -23,32 +23,27 @@
 ##
 ## The prime factorization is defined as @code{prod (@var{pf}) == @var{q}}
 ## where every element of @var{pf} is a prime number.  If @code{@var{q} == 1},
-## return 1.
+## return 1.  The output @var{pf} is of the same numeric class as the input.
 ##
 ## With two output arguments, return the unique prime factors @var{pf} and
 ## their multiplicities.  That is,
 ## @code{prod (@var{pf} .^ @var{n}) == @var{q}}.
 ##
-## Implementation Note: The input @var{q} must be less than
-## @code{flintmax} (9.0072e+15) in order to factor correctly.
+## Implementation Note: The input @var{q} must be less than @code{flintmax}
+## (9.0072e+15) in order to factor correctly.
 ## @seealso{gcd, lcm, isprime, primes}
 ## @end deftypefn
 
 ## Author: Paul Kienzle
 
-## 2002-01-28 Paul Kienzle
-## * remove recursion; only check existing primes for multiplicity > 1
-## * return multiplicity as suggested by Dirk Laurie
-## * add error handling
-
 function [pf, n] = factor (q)
 
   if (nargin != 1)
     print_usage ();
   endif
 
-  if (! isreal (q) || ! isscalar (q) || q != fix (q))
-    error ("factor: Q must be a real integer");
+  if (! isscalar (q) || ! isreal (q) || q < 0 || q != fix (q))
+    error ("factor: Q must be a real non-negative integer");
   endif
 
   ## Special case of no primes less than sqrt(q).
@@ -58,7 +53,8 @@
     return;
   endif
 
-  q = double (q);  # For the time being, calcs rely on double precision var.
+  cls = class (q); # store class
+  q = double (q);  # internal algorithm relies on numbers being doubles.
   qorig = q;
   pf = [];
   ## There is at most one prime greater than sqrt(q), and if it exists,
@@ -79,7 +75,7 @@
   endwhile
   pf = sort (pf);
 
-  ## Verify algorithm was succesful
+  ## Verify algorithm was successful
   q = prod (pf);
   if (q != qorig)
     error ("factor: Q too large to factor");
@@ -87,13 +83,16 @@
     warning ("factor: Q too large.  Answer is unreliable");
   endif
 
-  ## Determine muliplicity.
+  ## Determine multiplicity.
   if (nargout > 1)
     idx = find ([0, pf] != [pf, 0]);
     pf = pf(idx(1:length (idx)-1));
     n = diff (idx);
   endif
 
+ ## Restore class of input
+ pf = feval (cls, pf);
+
 endfunction
 
 
@@ -108,9 +107,17 @@
 %!   assert (all ([0,pf] != [pf,0]));
 %! endfor
 
+%!assert (factor (uint8 (8)), uint8 ([2 2 2]))
+%!assert (factor (single (8)), single ([2 2 2]))
+%!test
+%! [pf, n] = factor (int16 (8));
+%! assert (pf, int16 (2));
+%! assert (n, double (3));
+
 ## Test input validation
 %!error factor ()
 %!error factor (1,2)
-%!error <Q must be a real integer> factor (6i)
-%!error <Q must be a real integer> factor ([1,2])
-%!error <Q must be a real integer> factor (1.5)
+%!error <Q must be a real non-negative integer> factor (6i)
+%!error <Q must be a real non-negative integer> factor ([1,2])
+%!error <Q must be a real non-negative integer> factor (1.5)
+%!error <Q must be a real non-negative integer> factor (-20)
--- a/scripts/specfun/primes.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/specfun/primes.m	Fri Aug 10 09:09:51 2018 +0200
@@ -48,8 +48,8 @@
     print_usage ();
   endif
 
-  if (! isscalar (n))
-    error ("primes: N must be a scalar");
+  if (! (isnumeric (n) && isscalar (n)))
+    error ("primes: N must be a numeric scalar");
   endif
 
   if (n > 100e3)
@@ -107,4 +107,5 @@
 
 %!error primes ()
 %!error primes (1, 2)
-%!error <N must be a scalar> primes (ones (2,2))
+%!error <N must be a numeric scalar> primes ("1")
+%!error <N must be a numeric scalar> primes (ones (2,2))
--- a/scripts/special-matrix/magic.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/special-matrix/magic.m	Fri Aug 10 09:09:51 2018 +0200
@@ -36,10 +36,10 @@
   endif
 
   n = fix (n);
-  if (n < 1)
-
+  if (n < 0)
+    error ("magic: N must be non-negative");
+  elseif (n < 1)
     A = [];
-
   elseif (mod (n, 2) == 1)
 
     shift = floor ((0:n*n-1)/n);
@@ -91,10 +91,8 @@
 %!test <*46672>
 %! m = magic (2);
 %! assert (size (m), [2 2]);
-%! assert (unique (m), [1; 2; 3; 4]);
+%! assert (m, [4 3; 1 2]);
 
-%!assert (magic (2), [4 3; 1 2])
-%!assert (isempty (magic (-1)))
 %!assert (isempty (magic (0)))
 %!assert (magic (1), 1)
 %!assert (magic (1.5), 1)
@@ -102,3 +100,4 @@
 ## Test input validation
 %!error magic ()
 %!error magic (1, 2)
+%!error <N must be non-negative> magic (-5)
--- a/scripts/statistics/quantile.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/statistics/quantile.m	Fri Aug 10 09:09:51 2018 +0200
@@ -187,21 +187,30 @@
   ## Permute dim to the 1st index.
   x = permute (x, perm);
 
-  ## Save the size of the permuted x N-d array.
+  ## Save the size of the permuted x N-D array.
   sx = size (x);
 
-  ## Reshape to a 2-d array.
-  x = reshape (x, [sx(1), prod(sx(2:end))]);
+  ## Reshape to a 2-D array.
+  x = reshape (x, sx(1), []);
 
   ## Calculate the quantiles.
   q = __quantile__ (x, p, method);
 
-  ## Return the shape to the original N-d array.
+  ## Return the shape to the original N-D array.
   q = reshape (q, [numel(p), sx(2:end)]);
 
   ## Permute the 1st index back to dim.
   q = ipermute (q, perm);
 
+  ## For Matlab compatibility, return vectors with the same orientation as p
+  if (isvector (q) && ! isscalar (q) && ! isscalar (p))
+    if (isrow (p))
+      q = reshape (q, 1, []);
+    else
+      q = reshape (q, [], 1);
+    endif
+  endif
+
 endfunction
 
 
@@ -251,7 +260,7 @@
 %!      1.0000   1.4167   2.5000   3.5833   4.0000
 %!      1.0000   1.4375   2.5000   3.5625   4.0000];
 %! for m = 1:9
-%!   q = quantile (x, p, 1, m).';
+%!   q = quantile (x, p, 1, m);
 %!   assert (q, a(m,:), 0.0001);
 %! endfor
 
@@ -268,7 +277,7 @@
 %!      1.0000   1.6667   3.0000   4.3333   5.0000
 %!      1.0000   1.6875   3.0000   4.3125   5.0000];
 %! for m = 1:9
-%!   q = quantile (x, p, 1, m).';
+%!   q = quantile (x, p, 1, m);
 %!   assert (q, a(m,:), 0.0001);
 %! endfor
 
@@ -285,7 +294,7 @@
 %!      1.0000   1.4167   3.5000   7.3333   9.0000
 %!      1.0000   1.4375   3.5000   7.2500   9.0000];
 %! for m = 1:9
-%!   q = quantile (x, p, 1, m).';
+%!   q = quantile (x, p, 1, m);
 %!   assert (q, a(m,:), 0.0001);
 %! endfor
 
@@ -302,7 +311,7 @@
 %!      1.0000    1.6667    5.0000    9.6667   11.0000
 %!      1.0000    1.6875    5.0000    9.6250   11.0000];
 %! for m = 1:9
-%!   q = quantile (x, p, 1, m).';
+%!   q = quantile (x, p, 1, m);
 %!   assert (q, a(m,:), 0.0001);
 %! endfor
 
@@ -319,7 +328,7 @@
 %!      6.0000    9.8333   11.5000   15.0000   16.0000
 %!      6.0000    9.8750   11.5000   15.0000   16.0000];
 %! for m = 1:9
-%!   q = quantile (x, p, 1, m).';
+%!   q = quantile (x, p, 1, m);
 %!   assert (q, a(m,:), 0.0001);
 %! endfor
 
@@ -337,7 +346,7 @@
 %!      -2.551474  -0.591566  -0.067751   0.146459   0.495271
 %!      -2.551474  -0.590801  -0.067751   0.140686   0.495271];
 %! for m = 1:9
-%!   q = quantile (x, p, 1, m).';
+%!   q = quantile (x, p, 1, m);
 %!   assert (q, a(m,:), 0.0001);
 %! endfor
 
@@ -366,6 +375,10 @@
 %! assert (yobs, yexp);
 
 %!assert <*45455> (quantile ([1 3 2], 0.5, 1), [1 3 2])
+%!assert <*54421> (quantile ([1:10], 0.5, 1), 1:10)
+%!assert <*54421> (quantile ([1:10]', 0.5, 2), [1:10]')
+%!assert <*54421> (quantile ([1:10], [0.25, 0.75]), [3, 8])
+%!assert <*54421> (quantile ([1:10], [0.25, 0.75]'), [3; 8])
 
 ## Test input validation
 %!error quantile ()
--- a/scripts/strings/base2dec.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/strings/base2dec.m	Fri Aug 10 09:09:51 2018 +0200
@@ -74,7 +74,7 @@
     endif
   elseif (! isscalar (base))
     error ("base2dec: cannot convert from several bases at once");
-  elseif (base < 2 || base > length (symbols))
+  elseif (! (base >= 2 && base <= length (symbols)))
     error ("base2dec: BASE must be between 2 and 36, or a string of symbols");
   else
     s = toupper (s);
@@ -127,7 +127,9 @@
 %!error base2dec ()
 %!error base2dec ("11120")
 %!error base2dec ("11120", 3, 4)
-%!error base2dec ("11120", "1231")
-%!error base2dec ("11120", "12 3")
-%!error base2dec ("11120", ones (2))
-%!error base2dec ("11120", 37)
+%!error <symbols .* must be unique> base2dec ("11120", "1231")
+%!error <whitespace characters are not valid> base2dec ("11120", "12 3")
+%!error <cannot convert from several bases> base2dec ("11120", ones (2))
+%!error <BASE must be between 2 and 36> base2dec ("11120", 1)
+%!error <BASE must be between 2 and 36> base2dec ("11120", 37)
+%!error <BASE must be between 2 and 36> base2dec ("11120", NaN)
--- a/scripts/strings/findstr.m	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,143 +0,0 @@
-## Copyright (C) 1996-2018 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
-## <https://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn  {} {} findstr (@var{s}, @var{t})
-## @deftypefnx {} {} findstr (@var{s}, @var{t}, @var{overlap})
-## Return the vector of all positions in the longer of the two strings @var{s}
-## and @var{t} where an occurrence of the shorter of the two starts.
-##
-## If the optional argument @var{overlap} is true (default), the returned
-## vector can include overlapping positions.  For example:
-##
-## @example
-## @group
-## findstr ("ababab", "a")
-##      @result{} [1, 3, 5];
-## findstr ("abababa", "aba", 0)
-##      @result{} [1, 5]
-## @end group
-## @end example
-##
-## @strong{Caution:} @code{findstr} is scheduled for deprecation.  Use
-## @code{strfind} in all new code.
-## @seealso{strfind, strmatch, strcmp, strncmp, strcmpi, strncmpi, find}
-## @end deftypefn
-
-## Note that this implementation swaps the strings if second one is longer
-## than the first, so try to put the longer one first.
-##
-## Author: Kurt Hornik <Kurt.Hornik@wu-wien.ac.at>
-## Adapted-By: jwe
-
-function v = findstr (s, t, overlap = true)
-
-  if (nargin < 2 || nargin > 3)
-    print_usage ();
-  endif
-
-  if (all (size (s) > 1) || all (size (t) > 1))
-    error ("findstr: arguments must have only one non-singleton dimension");
-  endif
-
-  ## Make S be the longer string.
-  if (length (s) < length (t))
-    [s, t] = deal (t, s);
-  endif
-
-  l_s = length (s);
-  l_t = length (t);
-
-  if (l_t == 0)
-    ## zero length target: return empty set
-    v = [];
-
-  elseif (l_t == 1)
-    ## length one target: simple find
-    v = find (s == t);
-
-  elseif (l_t == 2)
-    ## length two target: find first at i and second at i+1
-    v = find (s(1:l_s-1) == t(1) & s(2:l_s) == t(2));
-
-  else
-    ## length three or more: match the first three by find then go through
-    ## the much smaller list to determine which of them are real matches
-    limit = l_s - l_t + 1;
-    v = find (  s(1:limit)   == t(1)
-              & s(2:limit+1) == t(2)
-              & s(3:limit+2) == t(3));
-  endif
-
-  ## Need to search the index vector if our find was too short
-  ## (target length > 3), or if we don't allow overlaps.  Note though
-  ## that there cannot be any overlaps if the first character in the
-  ## target is different from the remaining characters in the target,
-  ## so a single character, two different characters, or first character
-  ## different from the second two don't need to be searched.
-  if (l_t >= 3 || (! overlap && l_t > 1 && any (t(1) == t(2:l_t))))
-    ## force strings to be both row vectors or both column vectors
-    if (all (size (s) != size (t)))
-      t = t.';
-    endif
-
-    ## determine which ones to keep
-    keep = zeros (size (v));
-    ind = 0:l_t-1;
-    if (overlap)
-      for idx = 1:length (v)
-        keep(idx) = all (s(v(idx) + ind) == t);
-      endfor
-    else
-      ## First possible position for next non-overlapping match.
-      next = 1;
-      for idx = 1:length (v)
-        if (v(idx) >= next && s(v(idx) + ind) == t)
-          keep(idx) = 1;
-          ## Skip to the next possible match position.
-          next = v(idx) + l_t;
-        else
-          keep(idx) = 0;
-        endif
-      endfor
-    endif
-    if (! isempty (v))
-      v = v(find (keep));
-    endif
-  endif
-
-  if (isempty (v))
-    v = [];
-  endif
-
-  ## Always return a row vector, because that's what the old one did.
-  if (iscolumn (v))
-    v = v.';
-  endif
-
-endfunction
-
-
-%!assert (findstr ("abababa", "a"), [1, 3, 5, 7])
-%!assert (findstr ("abababa", "aba"), [1, 3, 5])
-%!assert (findstr ("aba", "abababa", 0), [1, 5])
-
-## Test input validation
-%!error findstr ()
-%!error findstr ("foo", "bar", 3, 4)
-%!error <must have only one non-singleton dimension> findstr (["AB" ; "CD"], "C")
--- a/scripts/strings/module.mk	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/strings/module.mk	Fri Aug 10 09:09:51 2018 +0200
@@ -10,7 +10,6 @@
   %reldir%/dec2bin.m \
   %reldir%/dec2hex.m \
   %reldir%/erase.m \
-  %reldir%/findstr.m \
   %reldir%/hex2dec.m \
   %reldir%/index.m \
   %reldir%/isletter.m \
@@ -26,7 +25,6 @@
   %reldir%/strchr.m \
   %reldir%/strjoin.m \
   %reldir%/strjust.m \
-  %reldir%/strmatch.m \
   %reldir%/strsplit.m \
   %reldir%/strtok.m \
   %reldir%/strtrim.m \
--- a/scripts/strings/strmatch.m	Fri Aug 10 09:08:33 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,130 +0,0 @@
-## Copyright (C) 2000-2018 Paul Kienzle
-## Copyright (C) 2003 Alois Schloegl
-## Copyright (C) 2010 VZLU Prague
-##
-## This file is part of Octave.
-##
-## Octave is free software: you can redistribute it and/or modify it
-## under the terms of the GNU General Public License as published by
-## the Free Software Foundation, either version 3 of the License, or
-## (at your option) any later version.
-##
-## Octave is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-## GNU General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with Octave; see the file COPYING.  If not, see
-## <https://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn  {} {} strmatch (@var{s}, @var{A})
-## @deftypefnx {} {} strmatch (@var{s}, @var{A}, "exact")
-## Return indices of entries of @var{A} which begin with the string @var{s}.
-##
-## The second argument @var{A} must be a string, character matrix, or a cell
-## array of strings.
-##
-## If the third argument @qcode{"exact"} is not given, then @var{s} only
-## needs to match @var{A} up to the length of @var{s}.  Trailing spaces and
-## nulls in @var{s} and @var{A} are ignored when matching.
-##
-## For example:
-##
-## @example
-## @group
-## strmatch ("apple", "apple juice")
-##      @result{} 1
-##
-## strmatch ("apple", ["apple  "; "apple juice"; "an apple"])
-##      @result{} [1; 2]
-##
-## strmatch ("apple", ["apple  "; "apple juice"; "an apple"], "exact")
-##      @result{} [1]
-## @end group
-## @end example
-##
-## @strong{Caution:} @code{strmatch} is scheduled for deprecation.  Use
-## @code{strncmp} (normal case), or @code{strcmp} (@qcode{"exact"} case), or
-## @code{regexp} in all new code.
-## @seealso{strfind, findstr, strcmp, strncmp, strcmpi, strncmpi, find}
-## @end deftypefn
-
-## Author: Paul Kienzle, Alois Schloegl
-## Adapted-by: jwe
-
-function idx = strmatch (s, A, exact)
-
-  if (nargin < 2 || nargin > 3)
-    print_usage ();
-  endif
-
-  if (! ischar (s) || (! isempty (s) && ! isvector (s)))
-    error ("strmatch: S must be a string");
-  elseif (! (ischar (A) || iscellstr (A)))
-    error ("strmatch: A must be a string or cell array of strings");
-  endif
-
-  ## Trim blanks and nulls from search string
-  if (any (s != " " & s != "\0"))
-    s = regexprep (s, "[ \\0]+$", '');
-  endif
-  len = length (s);
-
-  exact = nargin == 3 && ischar (exact) && strcmp (exact, "exact");
-
-  if (ischar (A))
-    [nr, nc] = size (A);
-    if (len > nc)
-      idx = [];
-    else
-      match = all (bsxfun (@eq, A(:,1:len), s), 2);
-      if (exact)
-        AA = A(:,len+1:nc);
-        match &= all (AA == " " | AA == "\0", 2);
-      endif
-      idx = find (match);
-    endif
-  else
-    if (len > 0)
-      idx = find (strncmp (s, A, len));
-    else
-      idx = find (strcmp (s, A));
-    endif
-    if (exact)
-      ## We can't just use strcmp, because we need to ignore spaces at end.
-      B = regexprep (A(idx), "[ \\0]+$", '');
-      idx = idx(strcmp (s, B));
-    endif
-  endif
-
-endfunction
-
-
-%!assert (strmatch ("a", {"aaa", "bab", "bbb"}), 1)
-%!assert (strmatch ("apple", "apple juice"), 1)
-%!assert (strmatch ("apple", ["apple pie"; "apple juice"; "an apple"]), [1; 2])
-%!assert (strmatch ("apple", {"apple pie"; "apple juice"; "tomato"}), [1; 2])
-%!assert (strmatch ("apple pie", "apple"), [])
-%!assert (strmatch ("a ", "a"), 1)
-%!assert (strmatch ("a", "a \0", "exact"), 1)
-%!assert (strmatch ("a b", {"a b", "a c", "c d"}), 1)
-%!assert (strmatch ("", {"", "foo", "bar", ""}), [1, 4])
-%!assert (strmatch ('', { '', '% comment', 'var a = 5', ''}, "exact"), [1,4])
-
-## Weird Matlab corner cases
-%!test <*49601>
-%! assert (strmatch (" ", " "), 1);
-%! assert (strmatch (" ", "   "), 1);
-%! assert (strmatch ("  ", " "), []);
-%! assert (strmatch ("  ", "  "), 1);
-
-## 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/testfun/__run_test_suite__.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/testfun/__run_test_suite__.m	Fri Aug 10 09:09:51 2018 +0200
@@ -51,6 +51,7 @@
     page_screen_output (false);
     warning ("on", "quiet");
     warning ("off", "Octave:deprecated-function");
+    warning ("off", "Octave:legacy-function");
     nfail = dp = dn = dxf = dxb = dsk = drtsk = drgrs = 0;
     try
       fid = fopen (logfile, "wt");
@@ -116,10 +117,10 @@
         puts ("indicating which dependencies were not found.\n");
       endif
 
-      ## Weed out deprecated and private functions
-      weed_idx = cellfun (@isempty, regexp (files_with_tests, '\<deprecated\>|\<private\>', 'once'));
+      ## Weed out deprecated, legacy, and private functions
+      weed_idx = cellfun (@isempty, regexp (files_with_tests, '\<deprecated\>|\<legacy\>|\<private\>', 'once'));
       files_with_tests = files_with_tests(weed_idx);
-      weed_idx = cellfun (@isempty, regexp (files_with_no_tests, '\<deprecated\>|\<private\>', 'once'));
+      weed_idx = cellfun (@isempty, regexp (files_with_no_tests, '\<deprecated\>|\<legacy\>|\<private\>', 'once'));
       files_with_no_tests = files_with_no_tests(weed_idx);
 
       report_files_with_no_tests (files_with_tests, files_with_no_tests, ".m");
--- a/scripts/testfun/private/html_compare_plot_demos.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/testfun/private/html_compare_plot_demos.m	Fri Aug 10 09:09:51 2018 +0200
@@ -80,7 +80,7 @@
   fclose (fid);
 
   anchor = "<!-- ##ADD TABLE HERE## -->";
-  n = findstr (template, anchor);
+  n = strfind (template, anchor);
   header = strtrim (template(1:n-1));
   trailer = strtrim (template(n+numel(anchor):end));
 
--- a/scripts/testfun/speed.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/testfun/speed.m	Fri Aug 10 09:09:51 2018 +0200
@@ -288,8 +288,8 @@
   elseif (do_display)
 
     subplot (1, 2, 1);
-    semilogx (__test_n, __tnew./__torig, "-*g",
-              __test_n, __torig./__tnew, "-*r");
+    semilogx (__test_n, __tnew ./ __torig, "-*g",
+              __test_n, __torig ./ __tnew, "-*r");
     legend ({[strrep(__f1, ";", ".") " / " strrep(__f2, ";", ".")],
              [strrep(__f2, ";", ".") " / " strrep(__f1, ";", ".")]},
             "location", "northwest");
--- a/scripts/testfun/test.m	Fri Aug 10 09:08:33 2018 +0200
+++ b/scripts/testfun/test.m	Fri Aug 10 09:09:51 2018 +0200
@@ -293,6 +293,17 @@
     disp ([__signal_file, __file]);
   endif
 
+  ## Track file descriptor leaks
+  __fid_list_orig = fopen ("all");
+
+  ## Track variable leaks
+  __base_variables_orig = evalin ("base", "who");
+  ## Add automatic variable "ans" which may not have been created yet.
+  __base_variables_orig{end+1} = "ans";
+
+  ## Track variable leaks
+  __global_variables_orig = who ("global");
+
   ## Assume all tests will pass.
   __all_success = true;
 
@@ -729,9 +740,28 @@
     end_unwind_protect
   endfor
 
-  ## Clear any functions created during test run
+  ## Clear any functions created during test run.
   eval (__clearfcn, "");
 
+  ## Verify test file did not leak file descriptors.
+  if (! isempty (setdiff (fopen ("all"), __fid_list_orig)))
+    warning ("test: file %s leaked file descriptors\n", __file);
+  endif
+
+  ## Verify test file did not leak variables in to base workspace.
+  __leaked_vars = setdiff (evalin ("base", "who"), __base_variables_orig);
+  if (! isempty (__leaked_vars))
+    warning ("test: file %s leaked variables to base workspace:%s\n",
+             __file, sprintf (" %s", __leaked_vars{:}));
+  endif
+
+  ## Verify test file did not leak global variables.
+  __leaked_vars = setdiff (who ("global"), __global_variables_orig);
+  if (! isempty (__leaked_vars))
+    warning ("test: file %s leaked global variables:%s\n",
+             __file, sprintf (" %s", __leaked_vars{:}));
+  endif
+
   if (nargout == 0)
     if (__tests || __xfail || __xbug || __xskip || __xrtskip)
       if (__xfail || __xbug)
--- a/src/main-cli.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/src/main-cli.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -36,7 +36,6 @@
 #include "oct-env.h"
 #include "signal-wrappers.h"
 
-#include "defaults.h"
 #include "octave.h"
 #include "octave-build-info.h"
 #include "sysdep.h"
--- a/src/main-gui.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/src/main-gui.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -37,7 +37,6 @@
 
 #include "oct-env.h"
 
-#include "defaults.h"
 #include "octave.h"
 #include "octave-build-info.h"
 #include "octave-gui.h"
--- a/src/mkoctfile.in.cc	Fri Aug 10 09:08:33 2018 +0200
+++ b/src/mkoctfile.in.cc	Fri Aug 10 09:09:51 2018 +0200
@@ -36,15 +36,27 @@
 #include <vector>
 #include <cstdlib>
 
+// Programming note:  The CROSS macro here refers to building a
+// cross-compiler aware version of mkoctfile that can be used to cross
+// compile .oct file for Windows builds of Octave, not that mkoctfile
+// itself is being cross compiled.
+//
+// We don't use the wrapper and gnulib functions when we are building
+// with CROSS defined.  This configuration is only expected to work on
+// modern systems that should not need to have gnulib to fix POSIX
+// portability problems.  So we just assume a working POSIX system when
+// CROSS is defined.
+
 #if defined (CROSS)
+#  include <stdlib.h>
 #  include <sys/types.h>
 #  include <sys/wait.h>
 #  include <unistd.h>
-
 #  ifndef OCTAVE_UNUSED
 #    define OCTAVE_UNUSED
 #  endif
 #else
+#  include "mkostemps-wrapper.h"
 #  include "unistd-wrappers.h"
 #  include "wait-wrappers.h"
 #endif
@@ -68,6 +80,12 @@
 #if defined (CROSS)
 
 static int
+octave_mkostemps_wrapper (char *tmpl, int suffixlen)
+{
+  return mkostemps (tmpl, suffixlen, 0);
+}
+
+static int
 octave_unlink_wrapper (const char *nm)
 {
   return unlink (nm);
@@ -133,6 +151,40 @@
   vars["OCTAVE_HOME"] = Voctave_home;
   vars["OCTAVE_EXEC_HOME"] = Voctave_exec_home;
 
+  vars["API_VERSION"] = %OCTAVE_API_VERSION%;
+  vars["CANONICAL_HOST_TYPE"] = %OCTAVE_CANONICAL_HOST_TYPE%;
+  vars["DEFAULT_PAGER"] = %OCTAVE_DEFAULT_PAGER%;
+  vars["EXEEXT"] = %OCTAVE_EXEEXT%;
+  vars["MAN1EXT"] = %OCTAVE_MAN1EXT%;
+  vars["VERSION"] = %OCTAVE_VERSION%;
+
+  vars["ARCHLIBDIR"] = prepend_octave_exec_home (%OCTAVE_ARCHLIBDIR%);
+  vars["BINDIR"] = prepend_octave_exec_home (%OCTAVE_BINDIR%);
+  vars["DATADIR"] = prepend_octave_home (%OCTAVE_DATADIR%);
+  vars["DATAROOTDIR"] = prepend_octave_home (%OCTAVE_DATAROOTDIR%);
+  vars["FCNFILEDIR"] = prepend_octave_home (%OCTAVE_FCNFILEDIR%);
+  vars["IMAGEDIR"] = prepend_octave_home (%OCTAVE_IMAGEDIR%);
+  vars["INFODIR"] = prepend_octave_home (%OCTAVE_INFODIR%);
+  vars["INFOFILE"] = prepend_octave_home (%OCTAVE_INFOFILE%);
+  vars["LIBEXECDIR"] = prepend_octave_exec_home (%OCTAVE_LIBEXECDIR%);
+  vars["LOCALAPIARCHLIBDIR"] = prepend_octave_exec_home (%OCTAVE_LOCALAPIARCHLIBDIR%);
+  vars["LOCALAPIFCNFILEDIR"] = prepend_octave_home (%OCTAVE_LOCALAPIFCNFILEDIR%);
+  vars["LOCALAPIOCTFILEDIR"] = prepend_octave_exec_home (%OCTAVE_LOCALAPIOCTFILEDIR%);
+  vars["LOCALARCHLIBDIR"] = prepend_octave_exec_home (%OCTAVE_LOCALARCHLIBDIR%);
+  vars["LOCALFCNFILEDIR"] = prepend_octave_home (%OCTAVE_LOCALFCNFILEDIR%);
+  vars["LOCALOCTFILEDIR"] = prepend_octave_exec_home (%OCTAVE_LOCALOCTFILEDIR%);
+  vars["LOCALSTARTUPFILEDIR"] = prepend_octave_home (%OCTAVE_LOCALSTARTUPFILEDIR%);
+  vars["LOCALVERARCHLIBDIR"] = prepend_octave_exec_home (%OCTAVE_LOCALVERARCHLIBDIR%);
+  vars["LOCALVERFCNFILEDIR"] = prepend_octave_home (%OCTAVE_LOCALVERFCNFILEDIR%);
+  vars["LOCALVEROCTFILEDIR"] = prepend_octave_exec_home (%OCTAVE_LOCALVEROCTFILEDIR%);
+  vars["MAN1DIR"] = prepend_octave_home (%OCTAVE_MAN1DIR%);
+  vars["MANDIR"] = prepend_octave_home (%OCTAVE_MANDIR%);
+  vars["OCTDATADIR"] = prepend_octave_home (%OCTAVE_OCTDATADIR%);
+  vars["OCTDOCDIR"] = prepend_octave_home (%OCTAVE_OCTDOCDIR%);
+  vars["OCTFILEDIR"] = prepend_octave_exec_home (%OCTAVE_OCTFILEDIR%);
+  vars["OCTFONTSDIR"] = prepend_octave_home (%OCTAVE_OCTFONTSDIR%);
+  vars["STARTUPFILEDIR"] = prepend_octave_home (%OCTAVE_STARTUPFILEDIR%);
+
   vars["SED"] = get_variable ("SED", %OCTAVE_CONF_SED%);
 
   vars["OCTINCLUDEDIR"]
@@ -162,7 +214,15 @@
   if (vars["INCLUDEDIR"] != "/usr/include")
     DEFAULT_INCFLAGS += " -I" + quote_path (vars["INCLUDEDIR"]);
 
-  std::string DEFAULT_LFLAGS = "-L" + quote_path (vars["OCTLIBDIR"]);
+  std::string DEFAULT_LFLAGS;
+
+#if defined (OCTAVE_USE_WINDOWS_API) || defined (CROSS)
+
+  // We'll be linking the files we compile with -loctinterp and
+  // -loctave, so we need to know where to find them.
+
+  DEFAULT_LFLAGS += "-L" + quote_path (vars["OCTLIBDIR"]);
+#endif
 
   if (vars["LIBDIR"] != "/usr/lib")
     DEFAULT_LFLAGS += " -L" + quote_path (vars["LIBDIR"]);
@@ -322,36 +382,81 @@
 "\n"
 "  -g                      Enable debugging options for compilers.\n"
 "\n"
-"  -p VAR, --print VAR     Print configuration variable VAR.  Recognized\n"
-"                          variables are:\n"
+"  -p VAR, --print VAR     Print configuration variable VAR.  There are\n"
+"                          three categories of variables:\n"
+"\n"
+"                          Octave configuration variables that users may\n"
+"                          override with environment variables.  These are\n"
+"                          used in commands that mkoctfile executes.\n"
+"\n"
+"                            ALL_CFLAGS                  LAPACK_LIBS\n"
+"                            ALL_CXXFLAGS                LD_CXX\n"
+"                            ALL_FFLAGS                  LDFLAGS\n"
+"                            ALL_LDFLAGS                 LD_STATIC_FLAG\n"
+"                            BLAS_LIBS                   LFLAGS\n"
+"                            CC                          LIBDIR\n"
+"                            CFLAGS                      LIBOCTAVE\n"
+"                            CPICFLAG                    LIBOCTINTERP\n"
+"                            CPPFLAGS                    OCTAVE_LINK_OPTS\n"
+"                            CXX                         OCTINCLUDEDIR\n"
+"                            CXXFLAGS                    OCTAVE_LIBS\n"
+"                            CXXPICFLAG                  OCTAVE_LINK_DEPS\n"
+"                            DL_LD                       OCTLIBDIR\n"
+"                            DL_LDFLAGS                  OCT_LINK_DEPS\n"
+"                            F77                         OCT_LINK_OPTS\n"
+"                            F77_INTEGER8_FLAG           RDYNAMIC_FLAG\n"
+"                            FFLAGS                      SPECIAL_MATH_LIB\n"
+"                            FPICFLAG                    XTRA_CFLAGS\n"
+"                            INCFLAGS                    XTRA_CXXFLAGS\n"
+"                            INCLUDEDIR\n"
+"\n"
+"                          Octave configuration variables as above, but\n"
+"                          currently unused by mkoctfile.\n"
 "\n"
-"                            ALL_CFLAGS                  INCFLAGS\n"
-"                            ALL_CXXFLAGS                INCLUDEDIR\n"
-"                            ALL_FFLAGS                  LAPACK_LIBS\n"
-"                            ALL_LDFLAGS                 LD_CXX\n"
-"                            AR                          LDFLAGS\n"
-"                            BLAS_LIBS                   LD_STATIC_FLAG\n"
-"                            CC                          LFLAGS\n"
-"                            CFLAGS                      LIBDIR\n"
-"                            CPICFLAG                    LIBOCTAVE\n"
-"                            CPPFLAGS                    LIBOCTINTERP\n"
-"                            CXX                         LIBS\n"
-"                            CXXFLAGS                    OCTAVE_EXEC_HOME\n"
-"                            CXXPICFLAG                  OCTAVE_HOME\n"
-"                            DEPEND_EXTRA_SED_PATTERN    OCTAVE_LIBS\n"
-"                            DEPEND_FLAGS                OCTAVE_LINK_DEPS\n"
-"                            DL_LD                       OCTAVE_LINK_OPTS\n"
-"                            DL_LDFLAGS                  OCTINCLUDEDIR\n"
-"                            F77                         OCTLIBDIR\n"
-"                            F77_INTEGER8_FLAG           OCT_LINK_DEPS\n"
-"                            FFLAGS                      OCT_LINK_OPTS\n"
-"                            FFTW3F_LDFLAGS              RANLIB\n"
-"                            FFTW3F_LIBS                 RDYNAMIC_FLAG\n"
-"                            FFTW3_LDFLAGS               READLINE_LIBS\n"
-"                            FFTW3_LIBS                  SED\n"
-"                            FFTW_LIBS                   SPECIAL_MATH_LIB\n"
-"                            FLIBS                       XTRA_CFLAGS\n"
-"                            FPICFLAG                    XTRA_CXXFLAGS\n"
+"                             AR\n"
+"                             DEPEND_EXTRA_SED_PATTERN\n"
+"                             DEPEND_FLAGS\n"
+"                             FFTW3F_LDFLAGS\n"
+"                             FFTW3F_LIBS\n"
+"                             FFTW3_LDFLAGS\n"
+"                             FFTW3_LIBS\n"
+"                             FFTW_LIBS\n"
+"                             FLIBS\n"
+"                             LIBS\n"
+"                             RANLIB\n"
+"                             READLINE_LIBS\n"
+"                             SED\n"
+"\n"
+"                          Octave configuration variables that are provided\n"
+"                          for informational purposes only.  Except for\n"
+"                          OCTAVE_HOME and OCTAVE_EXEC_HOME, users may not\n"
+"                          override these variables.\n"
+"\n"
+"                          If OCTAVE_HOME or OCTAVE_EXEC_HOME are set in\n"
+"                          the environment, then other variables are adjusted\n"
+"                          accordingly with OCTAVE_HOME or OCTAVE_EXEC_HOME\n"
+"                          substituted for the original value of the directory\n"
+"                          specified by the --prefix or --exec-prefix options\n"
+"                          that were used when Octave was configured.\n"
+"\n"
+"                            API_VERSION            LOCALFCNFILEDIR\n"
+"                            ARCHLIBDIR             LOCALOCTFILEDIR\n"
+"                            BINDIR                 LOCALSTARTUPFILEDIR\n"
+"                            CANONICAL_HOST_TYPE    LOCALVERARCHLIBDIR\n"
+"                            DATADIR                LOCALVERFCNFILEDIR\n"
+"                            DATAROOTDIR            LOCALVEROCTFILEDIR\n"
+"                            DEFAULT_PAGER          MAN1DIR\n"
+"                            EXEC_PREFIX            MAN1EXT\n"
+"                            EXEEXT                 MANDIR\n"
+"                            FCNFILEDIR             OCTAVE_EXEC_HOME\n"
+"                            IMAGEDIR               OCTAVE_HOME\n"
+"                            INFODIR                OCTDATADIR\n"
+"                            INFOFILE               OCTDOCDIR\n"
+"                            LIBEXECDIR             OCTFILEDIR\n"
+"                            LOCALAPIARCHLIBDIR     OCTFONTSDIR\n"
+"                            LOCALAPIFCNFILEDIR     STARTUPFILEDIR\n"
+"                            LOCALAPIOCTFILEDIR     VERSION\n"
+"                            LOCALARCHLIBDIR\n"
 "\n"
 "  --link-stand-alone      Link a stand-alone executable file.\n"
 "\n"
@@ -451,6 +556,78 @@
   return (s == "yes" || s == "true");
 }
 
+static std::string
+do_getenv (const std::string& name)
+{
+  char *value = ::getenv (name.c_str ());
+
+  return value ? value : "";
+}
+
+static std::string
+get_temp_directory (void)
+{
+  std::string tempd;
+
+#if defined (__MINGW32__) || defined (_MSC_VER)
+
+  tempd = do_getenv ("TEMP");
+
+  if (tempd.empty ())
+    tempd = do_getenv ("TMP");
+
+#if defined (P_tmpdir)
+  if (tempd.empty ())
+    tempd = P_tmpdir;
+#endif
+
+  // Some versions of MinGW and MSVC either don't define P_tmpdir, or
+  // define it to a single backslash.  In such cases just use C:\temp.
+  if (tempd.empty () || tempd == R"(\)")
+    tempd = R"(c:\temp)";
+
+#else
+
+  tempd = do_getenv ("TMP");
+
+#if defined (P_tmpdir)
+  if (tempd.empty ())
+    tempd = P_tmpdir;
+#else
+  if (tempd.empty ())
+    tempd = "/tmp";
+#endif
+
+#endif
+
+  return tempd;
+}
+
+static std::string
+tmp_objfile_name (void)
+{
+  std::string tmpl = get_temp_directory () + "/oct-XXXXXX.o";
+
+  char *ctmpl = new char [tmpl.length () + 1];
+
+  ctmpl = strcpy (ctmpl, tmpl.c_str ());
+
+  // mkostemps will open the file and return a file descriptor.  We
+  // won't worry about closing it because we will need the file until we
+  // are done and then the file will be closed when mkoctfile exits.
+
+  octave_mkostemps_wrapper (ctmpl, 2);
+
+  return std::string (ctmpl);
+}
+
+static void
+clean_up_tmp_files (const std::list<std::string>& tmp_files)
+{
+  for (const auto& file : tmp_files)
+    octave_unlink_wrapper (file.c_str ());
+}
+
 int
 main (int argc, char **argv)
 {
@@ -470,16 +647,17 @@
       return 0;
     }
 
-  std::list<std::string> cfiles, ccfiles, f77files;
+  std::list<std::string> cfiles, ccfiles, f77files, tmp_objfiles;
   std::string output_ext = ".oct";
   std::string objfiles, libfiles, octfile, outputfile;
   std::string incflags, defs, ldflags, pass_on_options;
   bool strip = false;
   bool no_oct_file_strip_on_this_platform = is_true ("%NO_OCT_FILE_STRIP%");
-  bool link = true;
+  bool compile_only = false;
   bool link_stand_alone = false;
   bool depend = false;
   bool printonly = false;
+  bool output_file_option = false;
 
   for (int i = 1; i < argc; i++)
     {
@@ -573,6 +751,8 @@
         }
       else if (arg == "-o" || arg == "-output" || arg == "--output")
         {
+          output_file_option = true;
+
           if (i < argc-1)
             {
               arg = argv[++i];
@@ -606,7 +786,7 @@
         }
       else if (arg == "-c" || arg == "-compile" || arg == "--compile")
         {
-          link = false;
+          compile_only = true;
         }
       else if (arg == "-g")
         {
@@ -666,6 +846,14 @@
       defs += " -DMEX_DEBUG";
     }
 
+  if (compile_only && output_file_option
+      && (cfiles.size () + ccfiles.size () + f77files.size ()) > 1)
+    {
+      std::cerr << "mkoctfile: may not use -c and -o with multiple source files"
+                << std::endl;
+      return 1;
+    }
+
   std::string output_option;
 
   if (link_stand_alone)
@@ -677,10 +865,14 @@
     {
       if (! outputfile.empty ())
         {
+          // FIXME: should probably do a better job of finding the
+          // filename extension instead of just looking at the filename
+          // length.
+
           octfile = outputfile;
           size_t len = octfile.length ();
           size_t len_ext = output_ext.length ();
-          if (octfile.substr (len-len_ext) != output_ext)
+          if (len <= len_ext || octfile.substr (len-len_ext) != output_ext)
             octfile += output_ext;
         }
       else
@@ -762,21 +954,24 @@
 
   for (const auto& f : f77files)
     {
-      std::string b = basename (f, true);
-
       if (! vars["F77"].empty ())
         {
           std::string o;
-          if (! outputfile.empty ())
+          if (compile_only)
             {
-              if (link)
-                o = b + ".o";
+              if (! outputfile.empty ())
+                o = outputfile;
               else
-                o = outputfile;
+                o = basename (f, true) + ".o";
             }
           else
-            o = b + ".o";
-          objfiles += (' ' + o);
+            {
+              o = tmp_objfile_name ();
+
+              tmp_objfiles.push_back (o);
+
+              objfiles += (' ' + o);
+            }
 
           std::string cmd
             = (vars["F77"] + " -c " + vars["FPICFLAG"] + ' '
@@ -800,17 +995,22 @@
     {
       if (! vars["CC"].empty ())
         {
-          std::string b = basename (f, true), o;
-          if (! outputfile.empty ())
+          std::string o;
+          if (compile_only)
             {
-              if (link)
-                o = b + ".o";
+              if (! outputfile.empty ())
+                o = outputfile;
               else
-                o = outputfile;
+                o = basename (f, true) + ".o";
             }
           else
-            o = b + ".o";
-          objfiles += (' ' + o);
+            {
+              o = tmp_objfile_name ();
+
+              tmp_objfiles.push_back (o);
+
+              objfiles += (' ' + o);
+            }
 
           std::string cmd
             = (vars["CC"] + " -c " + vars["CPPFLAGS"] + ' '
@@ -835,17 +1035,22 @@
     {
       if (! vars["CXX"].empty ())
         {
-          std::string b = basename (f, true), o;
-          if (! outputfile.empty ())
+          std::string o;
+          if (compile_only)
             {
-              if (link)
-                o = b + ".o";
+              if (! outputfile.empty ())
+                o = outputfile;
               else
-                o = outputfile;
+                o = basename (f, true) + ".o";
             }
           else
-            o = b + ".o";
-          objfiles += (' ' + o);
+            {
+              o = tmp_objfile_name ();
+
+              tmp_objfiles.push_back (o);
+
+              objfiles += (' ' + o);
+            }
 
           std::string cmd
             = (vars["CXX"] + " -c " + vars["CPPFLAGS"] + ' '
@@ -866,57 +1071,74 @@
         }
     }
 
-  if (link && ! objfiles.empty ())
-    {
-      if (link_stand_alone)
-        {
-          if (! vars["LD_CXX"].empty ())
-            {
-              std::string cmd
-                = (vars["LD_CXX"] + ' ' + vars["CPPFLAGS"] + ' '
-                   + vars["ALL_CXXFLAGS"] + ' ' + vars["RDYNAMIC_FLAG"] + ' '
-                   + vars["ALL_LDFLAGS"] + ' ' + pass_on_options + ' '
-                   + output_option + ' ' + objfiles + ' ' + libfiles + ' '
-                   + ldflags + ' ' + vars["LFLAGS"] + " -loctinterp -loctave "
-                   + vars["OCTAVE_LINK_OPTS"] + ' ' + vars["OCTAVE_LINK_DEPS"]);
+  // If we are only compliling, we are done.
+
+  if (compile_only)
+    return 0;
 
-              int status = run_command (cmd, printonly);
+  if (objfiles.empty ())
+    {
+      std::cerr << "mkoctfile: no objects to link" << std::endl;
+      return 1;
+    }
 
-              if (status)
-                return status;
-            }
-          else
-            {
-              std::cerr
-                << "mkoctfile: no way to link stand-alone executable file"
-                << std::endl;
-              return 1;
-            }
-        }
-      else
+  std::string octave_libs;
+#if defined (OCTAVE_USE_WINDOWS_API) || defined(CROSS)
+  octave_libs = "-loctinterp -loctave";
+#endif
+
+  if (link_stand_alone)
+    {
+      if (! vars["LD_CXX"].empty ())
         {
           std::string cmd
-            = (vars["DL_LD"] + ' ' + vars["ALL_CXXFLAGS"] + ' '
-               + vars["DL_LDFLAGS"] + ' ' + pass_on_options
-               + " -o " + octfile + ' ' + objfiles + ' ' + libfiles + ' '
-               + ldflags + ' ' + vars["LFLAGS"] + " -loctinterp -loctave "
-               + vars["OCT_LINK_OPTS"] + ' ' + vars["OCT_LINK_DEPS"]);
+            = (vars["LD_CXX"] + ' ' + vars["CPPFLAGS"] + ' '
+               + vars["ALL_CXXFLAGS"] + ' ' + vars["RDYNAMIC_FLAG"] + ' '
+               + vars["ALL_LDFLAGS"] + ' ' + pass_on_options + ' '
+               + output_option + ' ' + objfiles + ' ' + libfiles + ' '
+               + ldflags + ' ' + vars["LFLAGS"] + ' ' + octave_libs + ' '
+               + vars["OCTAVE_LINK_OPTS"] + ' ' + vars["OCTAVE_LINK_DEPS"]);
 
           int status = run_command (cmd, printonly);
 
+          clean_up_tmp_files (tmp_objfiles);
+
           if (status)
             return status;
         }
-
-      if (strip)
+      else
         {
-          std::string cmd = "strip " + octfile;
+          std::cerr
+            << "mkoctfile: no way to link stand-alone executable file"
+            << std::endl;
+          return 1;
+        }
+    }
+  else
+    {
+      std::string cmd
+        = (vars["DL_LD"] + ' ' + vars["ALL_CXXFLAGS"] + ' '
+           + vars["DL_LDFLAGS"] + ' ' + pass_on_options
+           + " -o " + octfile + ' ' + objfiles + ' ' + libfiles + ' '
+           + ldflags + ' ' + vars["LFLAGS"] + ' ' + octave_libs + ' '
+           + vars["OCT_LINK_OPTS"] + ' ' + vars["OCT_LINK_DEPS"]);
 
-          int status = run_command (cmd, printonly);
+      int status = run_command (cmd, printonly);
+
+      clean_up_tmp_files (tmp_objfiles);
+
+      if (status)
+        return status;
+    }
 
-          if (status)
-            return status;
-        }
+  if (strip)
+    {
+      std::string cmd = "strip " + octfile;
+
+      int status = run_command (cmd, printonly);
+
+      if (status)
+        return status;
     }
 
   return 0;
--- a/src/module.mk	Fri Aug 10 09:08:33 2018 +0200
+++ b/src/module.mk	Fri Aug 10 09:09:51 2018 +0200
@@ -78,10 +78,6 @@
   $(SRC_DIR_CPPFLAGS) \
   $(OCTAVE_CPPFLAGS)
 
-%canon_reldir%_octave_CXXFLAGS = \
-  $(AM_CXXFLAGS) \
-  $(WARN_CXXFLAGS)
-
 %canon_reldir%_octave_cli_SOURCES = %reldir%/main-cli.cc
 nodist_%canon_reldir%_octave_cli_SOURCES = %reldir%/octave-build-info.cc
 
@@ -98,10 +94,6 @@
   $(SRC_DIR_CPPFLAGS) \
   $(OCTAVE_CPPFLAGS)
 
-%canon_reldir%_octave_cli_CXXFLAGS = \
-  $(AM_CXXFLAGS) \
-  $(WARN_CXXFLAGS)
-
 if AMCOND_BUILD_QT_GUI
   %canon_reldir%_octave_gui_SOURCES = %reldir%/main-gui.cc
   nodist_%canon_reldir%_octave_gui_SOURCES = %reldir%/octave-build-info.cc
@@ -123,10 +115,6 @@
   $(OCTAVE_GUI_LINK_OPTS) \
   $(WARN_LDFLAGS)
 
-%canon_reldir%_octave_gui_CXXFLAGS = \
-  $(AM_CXXFLAGS) \
-  $(WARN_CXXFLAGS)
-
 %canon_reldir%_mkoctfile_SOURCES =
 
 nodist_%canon_reldir%_mkoctfile_SOURCES = %reldir%/mkoctfile.cc
@@ -139,10 +127,6 @@
   $(SRC_DIR_CPPFLAGS) \
   $(OCTAVE_CPPFLAGS)
 
-%canon_reldir%_mkoctfile_CXXFLAGS = \
-  $(AM_CXXFLAGS) \
-  $(WARN_CXXFLAGS)
-
 %canon_reldir%_octave_config_SOURCES =
 
 nodist_%canon_reldir%_octave_config_SOURCES = %reldir%/octave-config.cc
@@ -156,10 +140,6 @@
   $(SRC_DIR_CPPFLAGS) \
   $(OCTAVE_CPPFLAGS)
 
-%canon_reldir%_octave_config_CXXFLAGS = \
-  $(AM_CXXFLAGS) \
-  $(WARN_CXXFLAGS)
-
 DIRSTAMP_FILES += %reldir%/$(octave_dirstamp)
 
 mostlyclean-local: src-mostlyclean-local
@@ -184,8 +164,8 @@
 %reldir%/$(host_triplet)-octave-config$(BUILD_EXEEXT): %reldir%/$(host_triplet)-octave-config.cc
 	$(BUILD_CXX) -o %reldir%/$(host_triplet)-octave-config$(BUILD_EXEEXT) -DCROSS=1 $(DEFAULT_INCLUDES) $(BUILD_CXXFLAGS) $(BUILD_LDFLAGS) -I$(srcdir)/src %reldir%/$(host_triplet)-octave-config.cc
 
-%reldir%/$(host_triplet)-octave-config.cc: %reldir%/octave-config.in.cc build-aux/subst-default-vals.sh | %reldir%/$(octave_dirstamp)
-	$(AM_V_GEN)$(call simple-filter-rule,build-aux/subst-default-vals.sh)
+%reldir%/$(host_triplet)-octave-config.cc: %reldir%/octave-config.in.cc build-aux/subst-config-vals.sh | %reldir%/$(octave_dirstamp)
+	$(AM_V_GEN)$(call simple-filter-rule,build-aux/subst-config-vals.sh)
 
 src-mostlyclean-local:
 	-rm -f $(OCTAVE_CROSS_TOOLS)
@@ -196,14 +176,14 @@
 
 endif
 
-%reldir%/octave-config.cc: %reldir%/octave-config.in.cc build-aux/subst-default-vals.sh | %reldir%/$(octave_dirstamp)
-	$(AM_V_GEN)$(call simple-filter-rule,build-aux/subst-default-vals.sh)
+%reldir%/octave-config.cc: %reldir%/octave-config.in.cc build-aux/subst-config-vals.sh | %reldir%/$(octave_dirstamp)
+	$(AM_V_GEN)$(call simple-filter-rule,build-aux/subst-config-vals.sh)
 
 %reldir%/mkoctfile.cc: %reldir%/mkoctfile.in.cc build-aux/subst-config-vals.sh | %reldir%/$(octave_dirstamp)
 	$(AM_V_GEN)$(call simple-filter-rule,build-aux/subst-config-vals.sh)
 
-%reldir%/main.cc: %reldir%/main.in.cc build-aux/subst-default-vals.sh | %reldir%/$(octave_dirstamp)
-	$(AM_V_GEN)$(call simple-filter-rule,build-aux/subst-default-vals.sh)
+%reldir%/main.cc: %reldir%/main.in.cc build-aux/subst-config-vals.sh | %reldir%/$(octave_dirstamp)
+	$(AM_V_GEN)$(call simple-filter-rule,build-aux/subst-config-vals.sh)
 
 %reldir%/octave-build-info.cc: %reldir%/octave-build-info.in.cc HG-ID | %reldir%/$(octave_dirstamp)
 	$(AM_V_GEN)$(build-info-commands)
--- a/test/deprecate-props.tst	Fri Aug 10 09:08:33 2018 +0200
+++ b/test/deprecate-props.tst	Fri Aug 10 09:09:51 2018 +0200
@@ -31,36 +31,6 @@
 %!  endif
 %!endfunction
 
-## patch/surface "normalmode" deprecated in 4.2, remove from version 5.
-%!test
-%! hf = figure ("visible", "off");
-%! unwind_protect
-%!   hp = patch ();
-%!   testprop (hp, "normalmode", "5.0");
-%! unwind_protect_cleanup
-%!   close (hf);
-%! end_unwind_protect
-
-%! hf = figure ("visible", "off");
-%! unwind_protect
-%!   hs = surface ();
-%!   testprop (hs, "normalmode", "5.0");
-%! unwind_protect_cleanup
-%!   close (hf);
-%! end_unwind_protect
-
-## axes, "zero" value for "x/yaxislocation" deprecated in 4.2, remove
-## from version 5.
-%!test
-%! hf = figure ("visible", "off");
-%! unwind_protect
-%!   ha = axes ();
-%!   testprop (ha, "xaxislocation", "5.0", "zero");
-%!   testprop (ha, "yaxislocation", "5.0", "zero");
-%! unwind_protect_cleanup
-%!   close (hf);
-%! end_unwind_protect
-
 ## annotation rectangle "edgecolor" deprecated in 4.4, remove from version 6.
 %!test
 %! hf = figure ("visible", "off");
--- a/test/func.tst	Fri Aug 10 09:08:33 2018 +0200
+++ b/test/func.tst	Fri Aug 10 09:09:51 2018 +0200
@@ -163,9 +163,9 @@
 %!test
 %! __fntestfunc__ ("flipud", m3);
 %!test
-%! __fntestfunc__ ("flipdim", m1, 2);
+%! __fntestfunc__ ("flip", m1, 2);
 %!test
-%! __fntestfunc__ ("flipdim", m3, 2);
+%! __fntestfunc__ ("flip", m3, 2);
 %!test
 %! __fntestfunc__ ("transpose", m1);
 %!test
--- a/test/io.tst	Fri Aug 10 09:08:33 2018 +0200
+++ b/test/io.tst	Fri Aug 10 09:09:51 2018 +0200
@@ -177,6 +177,9 @@
 %!    endfor
 %!  endif
 %!
+%!  ## Cleanup after test
+%!  clear -global a1;
+%!
 %!  ret = 1;
 %!endfunction
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/mex/bug-51725.tst	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,20 @@
+## Copyright (C) 2018 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
+## <https://www.gnu.org/licenses/>.
+
+%!assert (bug_51725 (), [])
+%!error <element number 2 undefined in return list> [x,y,z] = bug_51725 ();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/mex/bug-54096.tst	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,22 @@
+## Copyright (C) 2018 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
+## <https://www.gnu.org/licenses/>.
+
+%!test
+%! s = bug_54096 ();
+%! assert (s, struct ("field", []));
+%! assert (s.field, []);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/mex/bug_51725.c	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,10 @@
+#include "mex.h"
+
+void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+  if (nlhs > 0)
+    plhs[0] = mxCreateDoubleMatrix (0, 0, mxREAL);
+
+  if (nlhs > 2)
+    plhs[2] = mxCreateDoubleMatrix (0, 0, mxREAL);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/mex/bug_54096.c	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,19 @@
+#include "mex.h"
+
+static const char* field_names[] = {"field"};
+
+void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+  mxArray *tmp_val;
+
+  plhs[0] = mxCreateStructMatrix (1, 1, 1, field_names);
+
+  mxSetFieldByNumber (plhs[0], 0, 0, NULL);
+
+  tmp_val = mxGetFieldByNumber (plhs[0], 0, 0);
+
+  if (tmp_val)
+    mexErrMsgTxt ("struct elements set to NULL should be NULL internally");
+
+  /* But in the interpreter, they should appear as [].  */
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/mex/module.mk	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,49 @@
+mex_TEST_FILES = \
+  %reldir%/bug-54096.tst \
+  %reldir%/bug-51725.tst \
+  $(MEX_TEST_SRC)
+
+MEX_TEST_SRC = \
+  %reldir%/bug_54096.c \
+  %reldir%/bug_51725.c
+
+MEX_TEST_FUNCTIONS = $(MEX_TEST_SRC:%.c=%.mex)
+
+## Since these definitions for MKOCTFILE and MKMEXFILE are only used
+## here, defining them in this file is probably OK.  If there are ever
+## used elsewhre, maybe then they could be moved to build-aux/module.mk
+## or the main Makefile.am file.  The MKOCTFILE variables are included
+## for completeness, in case we someday want to test building .oct
+## files as well.
+
+AM_V_mkmexfile = $(am__v_mkmexfile_@AM_V@)
+am__v_mkmexfile_ = $(am__v_mkmexfile_@AM_DEFAULT_V@)
+am__v_mkmexfile_0 = @echo "  MKMEXFILE     " $@;
+am__v_mkmexfile_1 =
+
+AM_VOPT_mkmexfile = $(am__vopt_mkmexfile_@AM_V@)
+am__vopt_mkmexfile_ = $(am__vopt_mkmexfile_@AM_DEFAULT_V@)
+am__vopt_mkmexfile_0 =
+am__vopt_mkmexfile_1 = -v
+
+## And probably many others...
+MKOCTFILECPPFLAGS = \
+  -I$(top_srcdir)/libinterp/corefcn \
+  -Ilibinterp/corefcn
+
+MKOCTFILE = $(top_builddir)/src/mkoctfile $(MKOCTFILECPPFLAGS)
+
+MKMEXFILECPPFLAGS = \
+  -I$(top_srcdir)/libinterp/corefcn \
+  -Ilibinterp/corefcn
+
+MKMEXFILE = $(top_builddir)/src/mkoctfile --mex $(MKMEXFILECPPFLAGS)
+
+$(MEX_TEST_FUNCTIONS) : %.mex : %.c | %reldir%/$(octave_dirstamp)
+	$(AM_V_mkmexfile)$(MKMEXFILE) $(AM_VOPT_mkmexfile) $< -o $@ || rm -f $@
+
+DIRSTAMP_FILES += %reldir%/$(octave_dirstamp)
+
+## Until we decide how to handle installing the executable MEX files,
+## don't install them or the associated test files.
+noinst_TEST_FILES += $(mex_TEST_FILES)
--- a/test/module.mk	Fri Aug 10 09:08:33 2018 +0200
+++ b/test/module.mk	Fri Aug 10 09:09:51 2018 +0200
@@ -75,11 +75,13 @@
 include %reldir%/ctor-vs-method/module.mk
 include %reldir%/fcn-handle-derived-resolution/module.mk
 include %reldir%/local-functions/module.mk
+include %reldir%/mex/module.mk
 include %reldir%/nest/module.mk
 include %reldir%/publish/module.mk
+include %reldir%/pkg/module.mk
 
 define run-octave-tests
-  ( cd %reldir% && $(SHELL) ../run-octave $(RUN_OCTAVE_OPTIONS) $(1) --norc --silent --no-history $(abs_top_srcdir)/%reldir%/fntests.m $(abs_top_srcdir)/%reldir% ) && \
+  ( cd %reldir% && $(SHELL) ../run-octave $(RUN_OCTAVE_OPTIONS) $(1) --norc --silent --no-history -p $(abs_top_builddir)/%reldir%/mex $(abs_top_srcdir)/%reldir%/fntests.m $(abs_top_srcdir)/%reldir% ) && \
   if $(AM_V_P); then \
     echo ""; \
     if [ -f %reldir%/fntests.log ]; then \
@@ -92,7 +94,7 @@
   fi
 endef
 
-check-local: $(GENERATED_TEST_FILES) | $(OCTAVE_INTERPRETER_TARGETS) %reldir%/$(octave_dirstamp)
+check-local: $(GENERATED_TEST_FILES) $(MEX_TEST_FUNCTIONS) | $(OCTAVE_INTERPRETER_TARGETS) %reldir%/$(octave_dirstamp)
 	$(AM_V_at)$(call run-octave-tests)
 
 if AMCOND_HAVE_LLVM
@@ -189,7 +191,9 @@
   %reldir%/mk-sparse-tst.sh \
   %reldir%/mk_bc_overloads_expected.m \
   %reldir%/show-failures.awk \
-  $(TEST_FILES)
+  $(TEST_FILES) \
+  $(noinst_TEST_FILES) \
+  $(MEX_TEST_SRC)
 
 EXTRA_DIST += $(%canon_reldir%_EXTRA_DIST)
 
@@ -210,6 +214,7 @@
 	rm -f $(%canon_reldir%_CLEANFILES)
 	rm -rf $(GENERATED_BC_OVERLOADS_DIRS)
 	rm -rf $(COVERAGE_DIR)
+	rm -rf $(MEX_TEST_FUNCTIONS)
 
 test-distclean: test-clean
 	rm -f $(%canon_reldir%_DISTCLEANFILES)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/pkg/mfile_basic_test/COPYING	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,719 @@
+Appendix G GNU GENERAL PUBLIC LICENSE
+*************************************
+
+                        Version 3, 29 June 2007
+
+     Copyright (C) 2007 Free Software Foundation, Inc. `http://fsf.org/'
+
+     Everyone is permitted to copy and distribute verbatim copies of this
+     license document, but changing it is not allowed.
+
+Preamble
+========
+
+The GNU General Public License is a free, copyleft license for software
+and other kinds of works.
+
+   The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains
+free software for all its users.  We, the Free Software Foundation, use
+the GNU General Public License for most of our software; it applies
+also to any other work released this way by its authors.  You can apply
+it to your programs, too.
+
+   When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+   To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you
+have certain responsibilities if you distribute copies of the software,
+or if you modify it: responsibilities to respect the freedom of others.
+
+   For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+   Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+   For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+   Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the
+manufacturer can do so.  This is fundamentally incompatible with the
+aim of protecting users' freedom to change the software.  The
+systematic pattern of such abuse occurs in the area of products for
+individuals to use, which is precisely where it is most unacceptable.
+Therefore, we have designed this version of the GPL to prohibit the
+practice for those products.  If such problems arise substantially in
+other domains, we stand ready to extend this provision to those domains
+in future versions of the GPL, as needed to protect the freedom of
+users.
+
+   Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+   The precise terms and conditions for copying, distribution and
+modification follow.
+
+TERMS AND CONDITIONS
+====================
+
+  0. Definitions.
+
+     "This License" refers to version 3 of the GNU General Public
+     License.
+
+     "Copyright" also means copyright-like laws that apply to other
+     kinds of works, such as semiconductor masks.
+
+     "The Program" refers to any copyrightable work licensed under this
+     License.  Each licensee is addressed as "you".  "Licensees" and
+     "recipients" may be individuals or organizations.
+
+     To "modify" a work means to copy from or adapt all or part of the
+     work in a fashion requiring copyright permission, other than the
+     making of an exact copy.  The resulting work is called a "modified
+     version" of the earlier work or a work "based on" the earlier work.
+
+     A "covered work" means either the unmodified Program or a work
+     based on the Program.
+
+     To "propagate" a work means to do anything with it that, without
+     permission, would make you directly or secondarily liable for
+     infringement under applicable copyright law, except executing it
+     on a computer or modifying a private copy.  Propagation includes
+     copying, distribution (with or without modification), making
+     available to the public, and in some countries other activities as
+     well.
+
+     To "convey" a work means any kind of propagation that enables other
+     parties to make or receive copies.  Mere interaction with a user
+     through a computer network, with no transfer of a copy, is not
+     conveying.
+
+     An interactive user interface displays "Appropriate Legal Notices"
+     to the extent that it includes a convenient and prominently visible
+     feature that (1) displays an appropriate copyright notice, and (2)
+     tells the user that there is no warranty for the work (except to
+     the extent that warranties are provided), that licensees may
+     convey the work under this License, and how to view a copy of this
+     License.  If the interface presents a list of user commands or
+     options, such as a menu, a prominent item in the list meets this
+     criterion.
+
+  1. Source Code.
+
+     The "source code" for a work means the preferred form of the work
+     for making modifications to it.  "Object code" means any
+     non-source form of a work.
+
+     A "Standard Interface" means an interface that either is an
+     official standard defined by a recognized standards body, or, in
+     the case of interfaces specified for a particular programming
+     language, one that is widely used among developers working in that
+     language.
+
+     The "System Libraries" of an executable work include anything,
+     other than the work as a whole, that (a) is included in the normal
+     form of packaging a Major Component, but which is not part of that
+     Major Component, and (b) serves only to enable use of the work
+     with that Major Component, or to implement a Standard Interface
+     for which an implementation is available to the public in source
+     code form.  A "Major Component", in this context, means a major
+     essential component (kernel, window system, and so on) of the
+     specific operating system (if any) on which the executable work
+     runs, or a compiler used to produce the work, or an object code
+     interpreter used to run it.
+
+     The "Corresponding Source" for a work in object code form means all
+     the source code needed to generate, install, and (for an executable
+     work) run the object code and to modify the work, including
+     scripts to control those activities.  However, it does not include
+     the work's System Libraries, or general-purpose tools or generally
+     available free programs which are used unmodified in performing
+     those activities but which are not part of the work.  For example,
+     Corresponding Source includes interface definition files
+     associated with source files for the work, and the source code for
+     shared libraries and dynamically linked subprograms that the work
+     is specifically designed to require, such as by intimate data
+     communication or control flow between those subprograms and other
+     parts of the work.
+
+     The Corresponding Source need not include anything that users can
+     regenerate automatically from other parts of the Corresponding
+     Source.
+
+     The Corresponding Source for a work in source code form is that
+     same work.
+
+  2. Basic Permissions.
+
+     All rights granted under this License are granted for the term of
+     copyright on the Program, and are irrevocable provided the stated
+     conditions are met.  This License explicitly affirms your unlimited
+     permission to run the unmodified Program.  The output from running
+     a covered work is covered by this License only if the output,
+     given its content, constitutes a covered work.  This License
+     acknowledges your rights of fair use or other equivalent, as
+     provided by copyright law.
+
+     You may make, run and propagate covered works that you do not
+     convey, without conditions so long as your license otherwise
+     remains in force.  You may convey covered works to others for the
+     sole purpose of having them make modifications exclusively for
+     you, or provide you with facilities for running those works,
+     provided that you comply with the terms of this License in
+     conveying all material for which you do not control copyright.
+     Those thus making or running the covered works for you must do so
+     exclusively on your behalf, under your direction and control, on
+     terms that prohibit them from making any copies of your
+     copyrighted material outside their relationship with you.
+
+     Conveying under any other circumstances is permitted solely under
+     the conditions stated below.  Sublicensing is not allowed; section
+     10 makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+     No covered work shall be deemed part of an effective technological
+     measure under any applicable law fulfilling obligations under
+     article 11 of the WIPO copyright treaty adopted on 20 December
+     1996, or similar laws prohibiting or restricting circumvention of
+     such measures.
+
+     When you convey a covered work, you waive any legal power to forbid
+     circumvention of technological measures to the extent such
+     circumvention is effected by exercising rights under this License
+     with respect to the covered work, and you disclaim any intention
+     to limit operation or modification of the work as a means of
+     enforcing, against the work's users, your or third parties' legal
+     rights to forbid circumvention of technological measures.
+
+  4. Conveying Verbatim Copies.
+
+     You may convey verbatim copies of the Program's source code as you
+     receive it, in any medium, provided that you conspicuously and
+     appropriately publish on each copy an appropriate copyright notice;
+     keep intact all notices stating that this License and any
+     non-permissive terms added in accord with section 7 apply to the
+     code; keep intact all notices of the absence of any warranty; and
+     give all recipients a copy of this License along with the Program.
+
+     You may charge any price or no price for each copy that you convey,
+     and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+     You may convey a work based on the Program, or the modifications to
+     produce it from the Program, in the form of source code under the
+     terms of section 4, provided that you also meet all of these
+     conditions:
+
+       a. The work must carry prominent notices stating that you
+          modified it, and giving a relevant date.
+
+       b. The work must carry prominent notices stating that it is
+          released under this License and any conditions added under
+          section 7.  This requirement modifies the requirement in
+          section 4 to "keep intact all notices".
+
+       c. You must license the entire work, as a whole, under this
+          License to anyone who comes into possession of a copy.  This
+          License will therefore apply, along with any applicable
+          section 7 additional terms, to the whole of the work, and all
+          its parts, regardless of how they are packaged.  This License
+          gives no permission to license the work in any other way, but
+          it does not invalidate such permission if you have separately
+          received it.
+
+       d. If the work has interactive user interfaces, each must display
+          Appropriate Legal Notices; however, if the Program has
+          interactive interfaces that do not display Appropriate Legal
+          Notices, your work need not make them do so.
+
+     A compilation of a covered work with other separate and independent
+     works, which are not by their nature extensions of the covered
+     work, and which are not combined with it such as to form a larger
+     program, in or on a volume of a storage or distribution medium, is
+     called an "aggregate" if the compilation and its resulting
+     copyright are not used to limit the access or legal rights of the
+     compilation's users beyond what the individual works permit.
+     Inclusion of a covered work in an aggregate does not cause this
+     License to apply to the other parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+     You may convey a covered work in object code form under the terms
+     of sections 4 and 5, provided that you also convey the
+     machine-readable Corresponding Source under the terms of this
+     License, in one of these ways:
+
+       a. Convey the object code in, or embodied in, a physical product
+          (including a physical distribution medium), accompanied by the
+          Corresponding Source fixed on a durable physical medium
+          customarily used for software interchange.
+
+       b. Convey the object code in, or embodied in, a physical product
+          (including a physical distribution medium), accompanied by a
+          written offer, valid for at least three years and valid for
+          as long as you offer spare parts or customer support for that
+          product model, to give anyone who possesses the object code
+          either (1) a copy of the Corresponding Source for all the
+          software in the product that is covered by this License, on a
+          durable physical medium customarily used for software
+          interchange, for a price no more than your reasonable cost of
+          physically performing this conveying of source, or (2) access
+          to copy the Corresponding Source from a network server at no
+          charge.
+
+       c. Convey individual copies of the object code with a copy of
+          the written offer to provide the Corresponding Source.  This
+          alternative is allowed only occasionally and noncommercially,
+          and only if you received the object code with such an offer,
+          in accord with subsection 6b.
+
+       d. Convey the object code by offering access from a designated
+          place (gratis or for a charge), and offer equivalent access
+          to the Corresponding Source in the same way through the same
+          place at no further charge.  You need not require recipients
+          to copy the Corresponding Source along with the object code.
+          If the place to copy the object code is a network server, the
+          Corresponding Source may be on a different server (operated
+          by you or a third party) that supports equivalent copying
+          facilities, provided you maintain clear directions next to
+          the object code saying where to find the Corresponding Source.
+          Regardless of what server hosts the Corresponding Source, you
+          remain obligated to ensure that it is available for as long
+          as needed to satisfy these requirements.
+
+       e. Convey the object code using peer-to-peer transmission,
+          provided you inform other peers where the object code and
+          Corresponding Source of the work are being offered to the
+          general public at no charge under subsection 6d.
+
+
+     A separable portion of the object code, whose source code is
+     excluded from the Corresponding Source as a System Library, need
+     not be included in conveying the object code work.
+
+     A "User Product" is either (1) a "consumer product", which means
+     any tangible personal property which is normally used for personal,
+     family, or household purposes, or (2) anything designed or sold for
+     incorporation into a dwelling.  In determining whether a product
+     is a consumer product, doubtful cases shall be resolved in favor of
+     coverage.  For a particular product received by a particular user,
+     "normally used" refers to a typical or common use of that class of
+     product, regardless of the status of the particular user or of the
+     way in which the particular user actually uses, or expects or is
+     expected to use, the product.  A product is a consumer product
+     regardless of whether the product has substantial commercial,
+     industrial or non-consumer uses, unless such uses represent the
+     only significant mode of use of the product.
+
+     "Installation Information" for a User Product means any methods,
+     procedures, authorization keys, or other information required to
+     install and execute modified versions of a covered work in that
+     User Product from a modified version of its Corresponding Source.
+     The information must suffice to ensure that the continued
+     functioning of the modified object code is in no case prevented or
+     interfered with solely because modification has been made.
+
+     If you convey an object code work under this section in, or with,
+     or specifically for use in, a User Product, and the conveying
+     occurs as part of a transaction in which the right of possession
+     and use of the User Product is transferred to the recipient in
+     perpetuity or for a fixed term (regardless of how the transaction
+     is characterized), the Corresponding Source conveyed under this
+     section must be accompanied by the Installation Information.  But
+     this requirement does not apply if neither you nor any third party
+     retains the ability to install modified object code on the User
+     Product (for example, the work has been installed in ROM).
+
+     The requirement to provide Installation Information does not
+     include a requirement to continue to provide support service,
+     warranty, or updates for a work that has been modified or
+     installed by the recipient, or for the User Product in which it
+     has been modified or installed.  Access to a network may be denied
+     when the modification itself materially and adversely affects the
+     operation of the network or violates the rules and protocols for
+     communication across the network.
+
+     Corresponding Source conveyed, and Installation Information
+     provided, in accord with this section must be in a format that is
+     publicly documented (and with an implementation available to the
+     public in source code form), and must require no special password
+     or key for unpacking, reading or copying.
+
+  7. Additional Terms.
+
+     "Additional permissions" are terms that supplement the terms of
+     this License by making exceptions from one or more of its
+     conditions.  Additional permissions that are applicable to the
+     entire Program shall be treated as though they were included in
+     this License, to the extent that they are valid under applicable
+     law.  If additional permissions apply only to part of the Program,
+     that part may be used separately under those permissions, but the
+     entire Program remains governed by this License without regard to
+     the additional permissions.
+
+     When you convey a copy of a covered work, you may at your option
+     remove any additional permissions from that copy, or from any part
+     of it.  (Additional permissions may be written to require their own
+     removal in certain cases when you modify the work.)  You may place
+     additional permissions on material, added by you to a covered work,
+     for which you have or can give appropriate copyright permission.
+
+     Notwithstanding any other provision of this License, for material
+     you add to a covered work, you may (if authorized by the copyright
+     holders of that material) supplement the terms of this License
+     with terms:
+
+       a. Disclaiming warranty or limiting liability differently from
+          the terms of sections 15 and 16 of this License; or
+
+       b. Requiring preservation of specified reasonable legal notices
+          or author attributions in that material or in the Appropriate
+          Legal Notices displayed by works containing it; or
+
+       c. Prohibiting misrepresentation of the origin of that material,
+          or requiring that modified versions of such material be
+          marked in reasonable ways as different from the original
+          version; or
+
+       d. Limiting the use for publicity purposes of names of licensors
+          or authors of the material; or
+
+       e. Declining to grant rights under trademark law for use of some
+          trade names, trademarks, or service marks; or
+
+       f. Requiring indemnification of licensors and authors of that
+          material by anyone who conveys the material (or modified
+          versions of it) with contractual assumptions of liability to
+          the recipient, for any liability that these contractual
+          assumptions directly impose on those licensors and authors.
+
+     All other non-permissive additional terms are considered "further
+     restrictions" within the meaning of section 10.  If the Program as
+     you received it, or any part of it, contains a notice stating that
+     it is governed by this License along with a term that is a further
+     restriction, you may remove that term.  If a license document
+     contains a further restriction but permits relicensing or
+     conveying under this License, you may add to a covered work
+     material governed by the terms of that license document, provided
+     that the further restriction does not survive such relicensing or
+     conveying.
+
+     If you add terms to a covered work in accord with this section, you
+     must place, in the relevant source files, a statement of the
+     additional terms that apply to those files, or a notice indicating
+     where to find the applicable terms.
+
+     Additional terms, permissive or non-permissive, may be stated in
+     the form of a separately written license, or stated as exceptions;
+     the above requirements apply either way.
+
+  8. Termination.
+
+     You may not propagate or modify a covered work except as expressly
+     provided under this License.  Any attempt otherwise to propagate or
+     modify it is void, and will automatically terminate your rights
+     under this License (including any patent licenses granted under
+     the third paragraph of section 11).
+
+     However, if you cease all violation of this License, then your
+     license from a particular copyright holder is reinstated (a)
+     provisionally, unless and until the copyright holder explicitly
+     and finally terminates your license, and (b) permanently, if the
+     copyright holder fails to notify you of the violation by some
+     reasonable means prior to 60 days after the cessation.
+
+     Moreover, your license from a particular copyright holder is
+     reinstated permanently if the copyright holder notifies you of the
+     violation by some reasonable means, this is the first time you have
+     received notice of violation of this License (for any work) from
+     that copyright holder, and you cure the violation prior to 30 days
+     after your receipt of the notice.
+
+     Termination of your rights under this section does not terminate
+     the licenses of parties who have received copies or rights from
+     you under this License.  If your rights have been terminated and
+     not permanently reinstated, you do not qualify to receive new
+     licenses for the same material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+     You are not required to accept this License in order to receive or
+     run a copy of the Program.  Ancillary propagation of a covered work
+     occurring solely as a consequence of using peer-to-peer
+     transmission to receive a copy likewise does not require
+     acceptance.  However, nothing other than this License grants you
+     permission to propagate or modify any covered work.  These actions
+     infringe copyright if you do not accept this License.  Therefore,
+     by modifying or propagating a covered work, you indicate your
+     acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+     Each time you convey a covered work, the recipient automatically
+     receives a license from the original licensors, to run, modify and
+     propagate that work, subject to this License.  You are not
+     responsible for enforcing compliance by third parties with this
+     License.
+
+     An "entity transaction" is a transaction transferring control of an
+     organization, or substantially all assets of one, or subdividing an
+     organization, or merging organizations.  If propagation of a
+     covered work results from an entity transaction, each party to that
+     transaction who receives a copy of the work also receives whatever
+     licenses to the work the party's predecessor in interest had or
+     could give under the previous paragraph, plus a right to
+     possession of the Corresponding Source of the work from the
+     predecessor in interest, if the predecessor has it or can get it
+     with reasonable efforts.
+
+     You may not impose any further restrictions on the exercise of the
+     rights granted or affirmed under this License.  For example, you
+     may not impose a license fee, royalty, or other charge for
+     exercise of rights granted under this License, and you may not
+     initiate litigation (including a cross-claim or counterclaim in a
+     lawsuit) alleging that any patent claim is infringed by making,
+     using, selling, offering for sale, or importing the Program or any
+     portion of it.
+
+ 11. Patents.
+
+     A "contributor" is a copyright holder who authorizes use under this
+     License of the Program or a work on which the Program is based.
+     The work thus licensed is called the contributor's "contributor
+     version".
+
+     A contributor's "essential patent claims" are all patent claims
+     owned or controlled by the contributor, whether already acquired or
+     hereafter acquired, that would be infringed by some manner,
+     permitted by this License, of making, using, or selling its
+     contributor version, but do not include claims that would be
+     infringed only as a consequence of further modification of the
+     contributor version.  For purposes of this definition, "control"
+     includes the right to grant patent sublicenses in a manner
+     consistent with the requirements of this License.
+
+     Each contributor grants you a non-exclusive, worldwide,
+     royalty-free patent license under the contributor's essential
+     patent claims, to make, use, sell, offer for sale, import and
+     otherwise run, modify and propagate the contents of its
+     contributor version.
+
+     In the following three paragraphs, a "patent license" is any
+     express agreement or commitment, however denominated, not to
+     enforce a patent (such as an express permission to practice a
+     patent or covenant not to sue for patent infringement).  To
+     "grant" such a patent license to a party means to make such an
+     agreement or commitment not to enforce a patent against the party.
+
+     If you convey a covered work, knowingly relying on a patent
+     license, and the Corresponding Source of the work is not available
+     for anyone to copy, free of charge and under the terms of this
+     License, through a publicly available network server or other
+     readily accessible means, then you must either (1) cause the
+     Corresponding Source to be so available, or (2) arrange to deprive
+     yourself of the benefit of the patent license for this particular
+     work, or (3) arrange, in a manner consistent with the requirements
+     of this License, to extend the patent license to downstream
+     recipients.  "Knowingly relying" means you have actual knowledge
+     that, but for the patent license, your conveying the covered work
+     in a country, or your recipient's use of the covered work in a
+     country, would infringe one or more identifiable patents in that
+     country that you have reason to believe are valid.
+
+     If, pursuant to or in connection with a single transaction or
+     arrangement, you convey, or propagate by procuring conveyance of, a
+     covered work, and grant a patent license to some of the parties
+     receiving the covered work authorizing them to use, propagate,
+     modify or convey a specific copy of the covered work, then the
+     patent license you grant is automatically extended to all
+     recipients of the covered work and works based on it.
+
+     A patent license is "discriminatory" if it does not include within
+     the scope of its coverage, prohibits the exercise of, or is
+     conditioned on the non-exercise of one or more of the rights that
+     are specifically granted under this License.  You may not convey a
+     covered work if you are a party to an arrangement with a third
+     party that is in the business of distributing software, under
+     which you make payment to the third party based on the extent of
+     your activity of conveying the work, and under which the third
+     party grants, to any of the parties who would receive the covered
+     work from you, a discriminatory patent license (a) in connection
+     with copies of the covered work conveyed by you (or copies made
+     from those copies), or (b) primarily for and in connection with
+     specific products or compilations that contain the covered work,
+     unless you entered into that arrangement, or that patent license
+     was granted, prior to 28 March 2007.
+
+     Nothing in this License shall be construed as excluding or limiting
+     any implied license or other defenses to infringement that may
+     otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+     If conditions are imposed on you (whether by court order,
+     agreement or otherwise) that contradict the conditions of this
+     License, they do not excuse you from the conditions of this
+     License.  If you cannot convey a covered work so as to satisfy
+     simultaneously your obligations under this License and any other
+     pertinent obligations, then as a consequence you may not convey it
+     at all.  For example, if you agree to terms that obligate you to
+     collect a royalty for further conveying from those to whom you
+     convey the Program, the only way you could satisfy both those
+     terms and this License would be to refrain entirely from conveying
+     the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+     Notwithstanding any other provision of this License, you have
+     permission to link or combine any covered work with a work licensed
+     under version 3 of the GNU Affero General Public License into a
+     single combined work, and to convey the resulting work.  The terms
+     of this License will continue to apply to the part which is the
+     covered work, but the special requirements of the GNU Affero
+     General Public License, section 13, concerning interaction through
+     a network will apply to the combination as such.
+
+ 14. Revised Versions of this License.
+
+     The Free Software Foundation may publish revised and/or new
+     versions of the GNU General Public License from time to time.
+     Such new versions will be similar in spirit to the present
+     version, but may differ in detail to address new problems or
+     concerns.
+
+     Each version is given a distinguishing version number.  If the
+     Program specifies that a certain numbered version of the GNU
+     General Public License "or any later version" applies to it, you
+     have the option of following the terms and conditions either of
+     that numbered version or of any later version published by the
+     Free Software Foundation.  If the Program does not specify a
+     version number of the GNU General Public License, you may choose
+     any version ever published by the Free Software Foundation.
+
+     If the Program specifies that a proxy can decide which future
+     versions of the GNU General Public License can be used, that
+     proxy's public statement of acceptance of a version permanently
+     authorizes you to choose that version for the Program.
+
+     Later license versions may give you additional or different
+     permissions.  However, no additional obligations are imposed on any
+     author or copyright holder as a result of your choosing to follow a
+     later version.
+
+ 15. Disclaimer of Warranty.
+
+     THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+     APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE
+     COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS"
+     WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
+     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE
+     RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.
+     SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
+     NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+     IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+     WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES
+     AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU
+     FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+     CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
+     THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
+     BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+     PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+     PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF
+     THE POSSIBILITY OF SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+     If the disclaimer of warranty and limitation of liability provided
+     above cannot be given local legal effect according to their terms,
+     reviewing courts shall apply local law that most closely
+     approximates an absolute waiver of all civil liability in
+     connection with the Program, unless a warranty or assumption of
+     liability accompanies a copy of the Program in return for a fee.
+
+
+END OF TERMS AND CONDITIONS
+===========================
+
+How to Apply These Terms to Your New Programs
+=============================================
+
+If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these
+terms.
+
+   To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+     ONE LINE TO GIVE THE PROGRAM'S NAME AND A BRIEF IDEA OF WHAT IT DOES.
+     Copyright (C) YEAR NAME OF AUTHOR
+
+     This program is free software: you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published by
+     the Free Software Foundation, either version 3 of the License, or (at
+     your option) any later version.
+
+     This program is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with this program.  If not, see `http://www.gnu.org/licenses/'.
+
+   Also add information on how to contact you by electronic and paper
+mail.
+
+   If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+     PROGRAM Copyright (C) YEAR NAME OF AUTHOR
+     This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+     This is free software, and you are welcome to redistribute it
+     under certain conditions; type `show c' for details.
+
+   The hypothetical commands `show w' and `show c' should show the
+appropriate parts of the General Public License.  Of course, your
+program's commands might be different; for a GUI interface, you would
+use an "about box".
+
+   You should also get your employer (if you work as a programmer) or
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  For more information on this, and how to apply and follow
+the GNU GPL, see `http://www.gnu.org/licenses/'.
+
+   The GNU General Public License does not permit incorporating your
+program into proprietary programs.  If your program is a subroutine
+library, you may consider it more useful to permit linking proprietary
+applications with the library.  If this is what you want to do, use the
+GNU Lesser General Public License instead of this License.  But first,
+please read `http://www.gnu.org/philosophy/why-not-lgpl.html'.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/pkg/mfile_basic_test/DESCRIPTION	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,12 @@
+Name: mfile_basic_test
+Version: 0.1.0
+Date: 2017-12-07
+Author: hopefully various authors
+Maintainer: hopefully some of those authors.
+Title: Basic Example Package
+Description: Basic package structure with only m-files.
+Depends: octave (>= 4.2.1)
+License: GPLv3+
+# BuildRequires:
+# SystemRequirements:
+# Url: external homepage
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/pkg/mfile_basic_test/INDEX	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,3 @@
+mfile-basic-example-package >> Basic Example Package.
+Example m-file
+ example_mfile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/pkg/mfile_basic_test/NEWS	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,4 @@
+mfile-basic-example-package 0.1.0
+---------------------------------
+
+* Initial version
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/pkg/mfile_basic_test/doc/example-package.txi	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,89 @@
+\input texinfo
+@c %**start of header
+@setfilename example-package.info
+@settitle example-package_doc
+@c %**end of header
+
+@c Nowadays the predined function index has entries for each @deftypefn
+@c in additiont to each @findex.
+@defcodeindex mfn
+
+@copying
+Manual for the example-package for Octave.
+
+Copyright @copyright{} 2017-2018 @email{Olaf Till <i7tiol@@t-online.de>}
+
+You can redistribute this documentation and/or modify it under the terms
+of the GNU General Public License as published by the Free Software
+Foundation; either version 3 of the License, or (at your option) any
+later version.
+
+This documentation 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 documentation; if not, see <http://www.gnu.org/licenses/>.
+@end copying
+
+@include macros.texi
+
+@titlepage
+@title Manual for the example-package for Octave
+@page
+@vskip 0pt plus 1filll
+@insertcopying
+@end titlepage
+
+@c No table of contents. The table would occupy most of the top node in
+@c html and IMHO misleads the user to use the table instead of the menu
+@c structure of the nodes, which would let some information unused.
+@c
+@c @contents
+
+@c ------------------------------------------------------------------
+
+@node Top
+@top Manual for the example-package for Octave
+
+This documentation applies to version @PACKAGEVERSION of the
+example-package.
+
+This is a template simple m-file based package for users.
+
+Normally, a package manual should be structured and should contain more
+than just the helptexts of the functions.
+
+@menu
+Functions
+* example_mfile::                     Placeholder for an mfile.
+Indices
+* Function index::                    Index of functions.
+* Concept index::                     Concept index.
+@end menu
+
+@c ------------------------------------------------------------------
+
+@node example_mfile
+@chapter Placeholder for an mfile
+@mfnindex example_mfile
+
+@c include function helptext here
+@DOCSTRING(example_mfile)
+
+@c ------------------------------------------------------------------
+
+@node Function index
+@unnumbered Index of functions in example-package
+
+@printindex mfn
+
+@c ------------------------------------------------------------------
+
+@node Concept index
+@unnumbered Concept index
+
+@printindex cp
+
+@bye
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/pkg/mfile_basic_test/doc/macros.texi	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,88 @@
+@c Copyright (C) 2012-2018 John W. Eaton
+@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 The following macro marks words that aspell should ignore during
+@c spellchecking.  Within Texinfo it has no effect as it merely replaces
+@c the macro call with the argument itself.
+
+@macro nospell {arg}
+\arg\
+@end macro
+
+@c The following macro works around the Info/plain text expansion of @code{XXX}
+@c which is `XXX'.  This looks particularly bad when the macro body is
+@c single or double-quoted text, such as a property value `"position"'
+@ifinfo
+@rmacro qcode{arg}
+\arg\
+@end rmacro
+@end ifinfo
+@ifnotinfo
+@rmacro qcode{arg}
+@code{\arg\}
+@end rmacro
+@end ifnotinfo
+
+@c The following macro is used for the on-line help system, but we don't
+@c want lots of `See also: foo, bar, and baz' strings cluttering the
+@c printed manual (that information should be in the supporting text for
+@c each group of functions and variables).
+@c
+@c Implementation Note:
+@c For TeX, @vskip produces a nice separation.
+@c For Texinfo, '@sp 1' should work, but in practice produces ugly results
+@c for HTML.  We use a simple blank line to produce the correct behavior.
+
+@macro seealso {args}
+@iftex
+@vskip 2pt
+@end iftex
+@ifnottex
+
+@end ifnottex
+@ifnotinfo
+@noindent
+@strong{See also:} \args\.
+@end ifnotinfo
+@ifinfo
+@noindent
+See also: \args\.
+@end ifinfo
+@end macro
+
+@c The following macro works around a situation where the Info/plain text
+@c expansion of the @code{XXX} macro is `XXX'.  The use of the apostrophe
+@c can be confusing if the code segment itself ends with a transpose operator.
+@ifinfo
+@macro tcode{arg}
+\arg\
+@end macro
+@end ifinfo
+@ifnotinfo
+@macro tcode{arg}
+@code{\arg\}
+@end macro
+@end ifnotinfo
+
+@c FIXME: someday, when Texinfo 5.X is standard, we might replace this with
+@c @backslashchar, which is a new addition to Texinfo.
+
+@macro xbackslashchar
+\\
+@end macro
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/pkg/mfile_basic_test/inst/example_mfile.m	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,36 @@
+## Copyright (C) 2017-2018 Olaf Till <i7tiol@t-online.de>
+##
+## This program is free software; you can redistribute it and/or
+## modify it under the terms of the GNU General Public License as
+## published by the Free Software Foundation; either version 3 of the
+## License, or (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {@var{ret} =} example_mfile (@var{arg})
+## Placeholder for an mfile function.
+##
+## @var{arg}: argument. @var{ret}: returned value.
+##
+## Although this file is so short, a license text is contained as an
+## example.
+##
+## @seealso{example_open, example_close, example_do_something}
+## @end deftypefn
+
+function ret = example_mfile (arg)
+
+  if (nargin () != 1)
+    print_usage ();
+  endif
+
+  ret = arg;
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/pkg/mfile_minimal_test/COPYING	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,719 @@
+Appendix G GNU GENERAL PUBLIC LICENSE
+*************************************
+
+                        Version 3, 29 June 2007
+
+     Copyright (C) 2007 Free Software Foundation, Inc. `http://fsf.org/'
+
+     Everyone is permitted to copy and distribute verbatim copies of this
+     license document, but changing it is not allowed.
+
+Preamble
+========
+
+The GNU General Public License is a free, copyleft license for software
+and other kinds of works.
+
+   The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains
+free software for all its users.  We, the Free Software Foundation, use
+the GNU General Public License for most of our software; it applies
+also to any other work released this way by its authors.  You can apply
+it to your programs, too.
+
+   When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+   To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you
+have certain responsibilities if you distribute copies of the software,
+or if you modify it: responsibilities to respect the freedom of others.
+
+   For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+   Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+   For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+   Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the
+manufacturer can do so.  This is fundamentally incompatible with the
+aim of protecting users' freedom to change the software.  The
+systematic pattern of such abuse occurs in the area of products for
+individuals to use, which is precisely where it is most unacceptable.
+Therefore, we have designed this version of the GPL to prohibit the
+practice for those products.  If such problems arise substantially in
+other domains, we stand ready to extend this provision to those domains
+in future versions of the GPL, as needed to protect the freedom of
+users.
+
+   Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+   The precise terms and conditions for copying, distribution and
+modification follow.
+
+TERMS AND CONDITIONS
+====================
+
+  0. Definitions.
+
+     "This License" refers to version 3 of the GNU General Public
+     License.
+
+     "Copyright" also means copyright-like laws that apply to other
+     kinds of works, such as semiconductor masks.
+
+     "The Program" refers to any copyrightable work licensed under this
+     License.  Each licensee is addressed as "you".  "Licensees" and
+     "recipients" may be individuals or organizations.
+
+     To "modify" a work means to copy from or adapt all or part of the
+     work in a fashion requiring copyright permission, other than the
+     making of an exact copy.  The resulting work is called a "modified
+     version" of the earlier work or a work "based on" the earlier work.
+
+     A "covered work" means either the unmodified Program or a work
+     based on the Program.
+
+     To "propagate" a work means to do anything with it that, without
+     permission, would make you directly or secondarily liable for
+     infringement under applicable copyright law, except executing it
+     on a computer or modifying a private copy.  Propagation includes
+     copying, distribution (with or without modification), making
+     available to the public, and in some countries other activities as
+     well.
+
+     To "convey" a work means any kind of propagation that enables other
+     parties to make or receive copies.  Mere interaction with a user
+     through a computer network, with no transfer of a copy, is not
+     conveying.
+
+     An interactive user interface displays "Appropriate Legal Notices"
+     to the extent that it includes a convenient and prominently visible
+     feature that (1) displays an appropriate copyright notice, and (2)
+     tells the user that there is no warranty for the work (except to
+     the extent that warranties are provided), that licensees may
+     convey the work under this License, and how to view a copy of this
+     License.  If the interface presents a list of user commands or
+     options, such as a menu, a prominent item in the list meets this
+     criterion.
+
+  1. Source Code.
+
+     The "source code" for a work means the preferred form of the work
+     for making modifications to it.  "Object code" means any
+     non-source form of a work.
+
+     A "Standard Interface" means an interface that either is an
+     official standard defined by a recognized standards body, or, in
+     the case of interfaces specified for a particular programming
+     language, one that is widely used among developers working in that
+     language.
+
+     The "System Libraries" of an executable work include anything,
+     other than the work as a whole, that (a) is included in the normal
+     form of packaging a Major Component, but which is not part of that
+     Major Component, and (b) serves only to enable use of the work
+     with that Major Component, or to implement a Standard Interface
+     for which an implementation is available to the public in source
+     code form.  A "Major Component", in this context, means a major
+     essential component (kernel, window system, and so on) of the
+     specific operating system (if any) on which the executable work
+     runs, or a compiler used to produce the work, or an object code
+     interpreter used to run it.
+
+     The "Corresponding Source" for a work in object code form means all
+     the source code needed to generate, install, and (for an executable
+     work) run the object code and to modify the work, including
+     scripts to control those activities.  However, it does not include
+     the work's System Libraries, or general-purpose tools or generally
+     available free programs which are used unmodified in performing
+     those activities but which are not part of the work.  For example,
+     Corresponding Source includes interface definition files
+     associated with source files for the work, and the source code for
+     shared libraries and dynamically linked subprograms that the work
+     is specifically designed to require, such as by intimate data
+     communication or control flow between those subprograms and other
+     parts of the work.
+
+     The Corresponding Source need not include anything that users can
+     regenerate automatically from other parts of the Corresponding
+     Source.
+
+     The Corresponding Source for a work in source code form is that
+     same work.
+
+  2. Basic Permissions.
+
+     All rights granted under this License are granted for the term of
+     copyright on the Program, and are irrevocable provided the stated
+     conditions are met.  This License explicitly affirms your unlimited
+     permission to run the unmodified Program.  The output from running
+     a covered work is covered by this License only if the output,
+     given its content, constitutes a covered work.  This License
+     acknowledges your rights of fair use or other equivalent, as
+     provided by copyright law.
+
+     You may make, run and propagate covered works that you do not
+     convey, without conditions so long as your license otherwise
+     remains in force.  You may convey covered works to others for the
+     sole purpose of having them make modifications exclusively for
+     you, or provide you with facilities for running those works,
+     provided that you comply with the terms of this License in
+     conveying all material for which you do not control copyright.
+     Those thus making or running the covered works for you must do so
+     exclusively on your behalf, under your direction and control, on
+     terms that prohibit them from making any copies of your
+     copyrighted material outside their relationship with you.
+
+     Conveying under any other circumstances is permitted solely under
+     the conditions stated below.  Sublicensing is not allowed; section
+     10 makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+     No covered work shall be deemed part of an effective technological
+     measure under any applicable law fulfilling obligations under
+     article 11 of the WIPO copyright treaty adopted on 20 December
+     1996, or similar laws prohibiting or restricting circumvention of
+     such measures.
+
+     When you convey a covered work, you waive any legal power to forbid
+     circumvention of technological measures to the extent such
+     circumvention is effected by exercising rights under this License
+     with respect to the covered work, and you disclaim any intention
+     to limit operation or modification of the work as a means of
+     enforcing, against the work's users, your or third parties' legal
+     rights to forbid circumvention of technological measures.
+
+  4. Conveying Verbatim Copies.
+
+     You may convey verbatim copies of the Program's source code as you
+     receive it, in any medium, provided that you conspicuously and
+     appropriately publish on each copy an appropriate copyright notice;
+     keep intact all notices stating that this License and any
+     non-permissive terms added in accord with section 7 apply to the
+     code; keep intact all notices of the absence of any warranty; and
+     give all recipients a copy of this License along with the Program.
+
+     You may charge any price or no price for each copy that you convey,
+     and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+     You may convey a work based on the Program, or the modifications to
+     produce it from the Program, in the form of source code under the
+     terms of section 4, provided that you also meet all of these
+     conditions:
+
+       a. The work must carry prominent notices stating that you
+          modified it, and giving a relevant date.
+
+       b. The work must carry prominent notices stating that it is
+          released under this License and any conditions added under
+          section 7.  This requirement modifies the requirement in
+          section 4 to "keep intact all notices".
+
+       c. You must license the entire work, as a whole, under this
+          License to anyone who comes into possession of a copy.  This
+          License will therefore apply, along with any applicable
+          section 7 additional terms, to the whole of the work, and all
+          its parts, regardless of how they are packaged.  This License
+          gives no permission to license the work in any other way, but
+          it does not invalidate such permission if you have separately
+          received it.
+
+       d. If the work has interactive user interfaces, each must display
+          Appropriate Legal Notices; however, if the Program has
+          interactive interfaces that do not display Appropriate Legal
+          Notices, your work need not make them do so.
+
+     A compilation of a covered work with other separate and independent
+     works, which are not by their nature extensions of the covered
+     work, and which are not combined with it such as to form a larger
+     program, in or on a volume of a storage or distribution medium, is
+     called an "aggregate" if the compilation and its resulting
+     copyright are not used to limit the access or legal rights of the
+     compilation's users beyond what the individual works permit.
+     Inclusion of a covered work in an aggregate does not cause this
+     License to apply to the other parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+     You may convey a covered work in object code form under the terms
+     of sections 4 and 5, provided that you also convey the
+     machine-readable Corresponding Source under the terms of this
+     License, in one of these ways:
+
+       a. Convey the object code in, or embodied in, a physical product
+          (including a physical distribution medium), accompanied by the
+          Corresponding Source fixed on a durable physical medium
+          customarily used for software interchange.
+
+       b. Convey the object code in, or embodied in, a physical product
+          (including a physical distribution medium), accompanied by a
+          written offer, valid for at least three years and valid for
+          as long as you offer spare parts or customer support for that
+          product model, to give anyone who possesses the object code
+          either (1) a copy of the Corresponding Source for all the
+          software in the product that is covered by this License, on a
+          durable physical medium customarily used for software
+          interchange, for a price no more than your reasonable cost of
+          physically performing this conveying of source, or (2) access
+          to copy the Corresponding Source from a network server at no
+          charge.
+
+       c. Convey individual copies of the object code with a copy of
+          the written offer to provide the Corresponding Source.  This
+          alternative is allowed only occasionally and noncommercially,
+          and only if you received the object code with such an offer,
+          in accord with subsection 6b.
+
+       d. Convey the object code by offering access from a designated
+          place (gratis or for a charge), and offer equivalent access
+          to the Corresponding Source in the same way through the same
+          place at no further charge.  You need not require recipients
+          to copy the Corresponding Source along with the object code.
+          If the place to copy the object code is a network server, the
+          Corresponding Source may be on a different server (operated
+          by you or a third party) that supports equivalent copying
+          facilities, provided you maintain clear directions next to
+          the object code saying where to find the Corresponding Source.
+          Regardless of what server hosts the Corresponding Source, you
+          remain obligated to ensure that it is available for as long
+          as needed to satisfy these requirements.
+
+       e. Convey the object code using peer-to-peer transmission,
+          provided you inform other peers where the object code and
+          Corresponding Source of the work are being offered to the
+          general public at no charge under subsection 6d.
+
+
+     A separable portion of the object code, whose source code is
+     excluded from the Corresponding Source as a System Library, need
+     not be included in conveying the object code work.
+
+     A "User Product" is either (1) a "consumer product", which means
+     any tangible personal property which is normally used for personal,
+     family, or household purposes, or (2) anything designed or sold for
+     incorporation into a dwelling.  In determining whether a product
+     is a consumer product, doubtful cases shall be resolved in favor of
+     coverage.  For a particular product received by a particular user,
+     "normally used" refers to a typical or common use of that class of
+     product, regardless of the status of the particular user or of the
+     way in which the particular user actually uses, or expects or is
+     expected to use, the product.  A product is a consumer product
+     regardless of whether the product has substantial commercial,
+     industrial or non-consumer uses, unless such uses represent the
+     only significant mode of use of the product.
+
+     "Installation Information" for a User Product means any methods,
+     procedures, authorization keys, or other information required to
+     install and execute modified versions of a covered work in that
+     User Product from a modified version of its Corresponding Source.
+     The information must suffice to ensure that the continued
+     functioning of the modified object code is in no case prevented or
+     interfered with solely because modification has been made.
+
+     If you convey an object code work under this section in, or with,
+     or specifically for use in, a User Product, and the conveying
+     occurs as part of a transaction in which the right of possession
+     and use of the User Product is transferred to the recipient in
+     perpetuity or for a fixed term (regardless of how the transaction
+     is characterized), the Corresponding Source conveyed under this
+     section must be accompanied by the Installation Information.  But
+     this requirement does not apply if neither you nor any third party
+     retains the ability to install modified object code on the User
+     Product (for example, the work has been installed in ROM).
+
+     The requirement to provide Installation Information does not
+     include a requirement to continue to provide support service,
+     warranty, or updates for a work that has been modified or
+     installed by the recipient, or for the User Product in which it
+     has been modified or installed.  Access to a network may be denied
+     when the modification itself materially and adversely affects the
+     operation of the network or violates the rules and protocols for
+     communication across the network.
+
+     Corresponding Source conveyed, and Installation Information
+     provided, in accord with this section must be in a format that is
+     publicly documented (and with an implementation available to the
+     public in source code form), and must require no special password
+     or key for unpacking, reading or copying.
+
+  7. Additional Terms.
+
+     "Additional permissions" are terms that supplement the terms of
+     this License by making exceptions from one or more of its
+     conditions.  Additional permissions that are applicable to the
+     entire Program shall be treated as though they were included in
+     this License, to the extent that they are valid under applicable
+     law.  If additional permissions apply only to part of the Program,
+     that part may be used separately under those permissions, but the
+     entire Program remains governed by this License without regard to
+     the additional permissions.
+
+     When you convey a copy of a covered work, you may at your option
+     remove any additional permissions from that copy, or from any part
+     of it.  (Additional permissions may be written to require their own
+     removal in certain cases when you modify the work.)  You may place
+     additional permissions on material, added by you to a covered work,
+     for which you have or can give appropriate copyright permission.
+
+     Notwithstanding any other provision of this License, for material
+     you add to a covered work, you may (if authorized by the copyright
+     holders of that material) supplement the terms of this License
+     with terms:
+
+       a. Disclaiming warranty or limiting liability differently from
+          the terms of sections 15 and 16 of this License; or
+
+       b. Requiring preservation of specified reasonable legal notices
+          or author attributions in that material or in the Appropriate
+          Legal Notices displayed by works containing it; or
+
+       c. Prohibiting misrepresentation of the origin of that material,
+          or requiring that modified versions of such material be
+          marked in reasonable ways as different from the original
+          version; or
+
+       d. Limiting the use for publicity purposes of names of licensors
+          or authors of the material; or
+
+       e. Declining to grant rights under trademark law for use of some
+          trade names, trademarks, or service marks; or
+
+       f. Requiring indemnification of licensors and authors of that
+          material by anyone who conveys the material (or modified
+          versions of it) with contractual assumptions of liability to
+          the recipient, for any liability that these contractual
+          assumptions directly impose on those licensors and authors.
+
+     All other non-permissive additional terms are considered "further
+     restrictions" within the meaning of section 10.  If the Program as
+     you received it, or any part of it, contains a notice stating that
+     it is governed by this License along with a term that is a further
+     restriction, you may remove that term.  If a license document
+     contains a further restriction but permits relicensing or
+     conveying under this License, you may add to a covered work
+     material governed by the terms of that license document, provided
+     that the further restriction does not survive such relicensing or
+     conveying.
+
+     If you add terms to a covered work in accord with this section, you
+     must place, in the relevant source files, a statement of the
+     additional terms that apply to those files, or a notice indicating
+     where to find the applicable terms.
+
+     Additional terms, permissive or non-permissive, may be stated in
+     the form of a separately written license, or stated as exceptions;
+     the above requirements apply either way.
+
+  8. Termination.
+
+     You may not propagate or modify a covered work except as expressly
+     provided under this License.  Any attempt otherwise to propagate or
+     modify it is void, and will automatically terminate your rights
+     under this License (including any patent licenses granted under
+     the third paragraph of section 11).
+
+     However, if you cease all violation of this License, then your
+     license from a particular copyright holder is reinstated (a)
+     provisionally, unless and until the copyright holder explicitly
+     and finally terminates your license, and (b) permanently, if the
+     copyright holder fails to notify you of the violation by some
+     reasonable means prior to 60 days after the cessation.
+
+     Moreover, your license from a particular copyright holder is
+     reinstated permanently if the copyright holder notifies you of the
+     violation by some reasonable means, this is the first time you have
+     received notice of violation of this License (for any work) from
+     that copyright holder, and you cure the violation prior to 30 days
+     after your receipt of the notice.
+
+     Termination of your rights under this section does not terminate
+     the licenses of parties who have received copies or rights from
+     you under this License.  If your rights have been terminated and
+     not permanently reinstated, you do not qualify to receive new
+     licenses for the same material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+     You are not required to accept this License in order to receive or
+     run a copy of the Program.  Ancillary propagation of a covered work
+     occurring solely as a consequence of using peer-to-peer
+     transmission to receive a copy likewise does not require
+     acceptance.  However, nothing other than this License grants you
+     permission to propagate or modify any covered work.  These actions
+     infringe copyright if you do not accept this License.  Therefore,
+     by modifying or propagating a covered work, you indicate your
+     acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+     Each time you convey a covered work, the recipient automatically
+     receives a license from the original licensors, to run, modify and
+     propagate that work, subject to this License.  You are not
+     responsible for enforcing compliance by third parties with this
+     License.
+
+     An "entity transaction" is a transaction transferring control of an
+     organization, or substantially all assets of one, or subdividing an
+     organization, or merging organizations.  If propagation of a
+     covered work results from an entity transaction, each party to that
+     transaction who receives a copy of the work also receives whatever
+     licenses to the work the party's predecessor in interest had or
+     could give under the previous paragraph, plus a right to
+     possession of the Corresponding Source of the work from the
+     predecessor in interest, if the predecessor has it or can get it
+     with reasonable efforts.
+
+     You may not impose any further restrictions on the exercise of the
+     rights granted or affirmed under this License.  For example, you
+     may not impose a license fee, royalty, or other charge for
+     exercise of rights granted under this License, and you may not
+     initiate litigation (including a cross-claim or counterclaim in a
+     lawsuit) alleging that any patent claim is infringed by making,
+     using, selling, offering for sale, or importing the Program or any
+     portion of it.
+
+ 11. Patents.
+
+     A "contributor" is a copyright holder who authorizes use under this
+     License of the Program or a work on which the Program is based.
+     The work thus licensed is called the contributor's "contributor
+     version".
+
+     A contributor's "essential patent claims" are all patent claims
+     owned or controlled by the contributor, whether already acquired or
+     hereafter acquired, that would be infringed by some manner,
+     permitted by this License, of making, using, or selling its
+     contributor version, but do not include claims that would be
+     infringed only as a consequence of further modification of the
+     contributor version.  For purposes of this definition, "control"
+     includes the right to grant patent sublicenses in a manner
+     consistent with the requirements of this License.
+
+     Each contributor grants you a non-exclusive, worldwide,
+     royalty-free patent license under the contributor's essential
+     patent claims, to make, use, sell, offer for sale, import and
+     otherwise run, modify and propagate the contents of its
+     contributor version.
+
+     In the following three paragraphs, a "patent license" is any
+     express agreement or commitment, however denominated, not to
+     enforce a patent (such as an express permission to practice a
+     patent or covenant not to sue for patent infringement).  To
+     "grant" such a patent license to a party means to make such an
+     agreement or commitment not to enforce a patent against the party.
+
+     If you convey a covered work, knowingly relying on a patent
+     license, and the Corresponding Source of the work is not available
+     for anyone to copy, free of charge and under the terms of this
+     License, through a publicly available network server or other
+     readily accessible means, then you must either (1) cause the
+     Corresponding Source to be so available, or (2) arrange to deprive
+     yourself of the benefit of the patent license for this particular
+     work, or (3) arrange, in a manner consistent with the requirements
+     of this License, to extend the patent license to downstream
+     recipients.  "Knowingly relying" means you have actual knowledge
+     that, but for the patent license, your conveying the covered work
+     in a country, or your recipient's use of the covered work in a
+     country, would infringe one or more identifiable patents in that
+     country that you have reason to believe are valid.
+
+     If, pursuant to or in connection with a single transaction or
+     arrangement, you convey, or propagate by procuring conveyance of, a
+     covered work, and grant a patent license to some of the parties
+     receiving the covered work authorizing them to use, propagate,
+     modify or convey a specific copy of the covered work, then the
+     patent license you grant is automatically extended to all
+     recipients of the covered work and works based on it.
+
+     A patent license is "discriminatory" if it does not include within
+     the scope of its coverage, prohibits the exercise of, or is
+     conditioned on the non-exercise of one or more of the rights that
+     are specifically granted under this License.  You may not convey a
+     covered work if you are a party to an arrangement with a third
+     party that is in the business of distributing software, under
+     which you make payment to the third party based on the extent of
+     your activity of conveying the work, and under which the third
+     party grants, to any of the parties who would receive the covered
+     work from you, a discriminatory patent license (a) in connection
+     with copies of the covered work conveyed by you (or copies made
+     from those copies), or (b) primarily for and in connection with
+     specific products or compilations that contain the covered work,
+     unless you entered into that arrangement, or that patent license
+     was granted, prior to 28 March 2007.
+
+     Nothing in this License shall be construed as excluding or limiting
+     any implied license or other defenses to infringement that may
+     otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+     If conditions are imposed on you (whether by court order,
+     agreement or otherwise) that contradict the conditions of this
+     License, they do not excuse you from the conditions of this
+     License.  If you cannot convey a covered work so as to satisfy
+     simultaneously your obligations under this License and any other
+     pertinent obligations, then as a consequence you may not convey it
+     at all.  For example, if you agree to terms that obligate you to
+     collect a royalty for further conveying from those to whom you
+     convey the Program, the only way you could satisfy both those
+     terms and this License would be to refrain entirely from conveying
+     the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+     Notwithstanding any other provision of this License, you have
+     permission to link or combine any covered work with a work licensed
+     under version 3 of the GNU Affero General Public License into a
+     single combined work, and to convey the resulting work.  The terms
+     of this License will continue to apply to the part which is the
+     covered work, but the special requirements of the GNU Affero
+     General Public License, section 13, concerning interaction through
+     a network will apply to the combination as such.
+
+ 14. Revised Versions of this License.
+
+     The Free Software Foundation may publish revised and/or new
+     versions of the GNU General Public License from time to time.
+     Such new versions will be similar in spirit to the present
+     version, but may differ in detail to address new problems or
+     concerns.
+
+     Each version is given a distinguishing version number.  If the
+     Program specifies that a certain numbered version of the GNU
+     General Public License "or any later version" applies to it, you
+     have the option of following the terms and conditions either of
+     that numbered version or of any later version published by the
+     Free Software Foundation.  If the Program does not specify a
+     version number of the GNU General Public License, you may choose
+     any version ever published by the Free Software Foundation.
+
+     If the Program specifies that a proxy can decide which future
+     versions of the GNU General Public License can be used, that
+     proxy's public statement of acceptance of a version permanently
+     authorizes you to choose that version for the Program.
+
+     Later license versions may give you additional or different
+     permissions.  However, no additional obligations are imposed on any
+     author or copyright holder as a result of your choosing to follow a
+     later version.
+
+ 15. Disclaimer of Warranty.
+
+     THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+     APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE
+     COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS"
+     WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
+     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE
+     RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.
+     SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
+     NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+     IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+     WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES
+     AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU
+     FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+     CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
+     THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
+     BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+     PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+     PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF
+     THE POSSIBILITY OF SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+     If the disclaimer of warranty and limitation of liability provided
+     above cannot be given local legal effect according to their terms,
+     reviewing courts shall apply local law that most closely
+     approximates an absolute waiver of all civil liability in
+     connection with the Program, unless a warranty or assumption of
+     liability accompanies a copy of the Program in return for a fee.
+
+
+END OF TERMS AND CONDITIONS
+===========================
+
+How to Apply These Terms to Your New Programs
+=============================================
+
+If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these
+terms.
+
+   To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+     ONE LINE TO GIVE THE PROGRAM'S NAME AND A BRIEF IDEA OF WHAT IT DOES.
+     Copyright (C) YEAR NAME OF AUTHOR
+
+     This program is free software: you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published by
+     the Free Software Foundation, either version 3 of the License, or (at
+     your option) any later version.
+
+     This program is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with this program.  If not, see `http://www.gnu.org/licenses/'.
+
+   Also add information on how to contact you by electronic and paper
+mail.
+
+   If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+     PROGRAM Copyright (C) YEAR NAME OF AUTHOR
+     This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+     This is free software, and you are welcome to redistribute it
+     under certain conditions; type `show c' for details.
+
+   The hypothetical commands `show w' and `show c' should show the
+appropriate parts of the General Public License.  Of course, your
+program's commands might be different; for a GUI interface, you would
+use an "about box".
+
+   You should also get your employer (if you work as a programmer) or
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  For more information on this, and how to apply and follow
+the GNU GPL, see `http://www.gnu.org/licenses/'.
+
+   The GNU General Public License does not permit incorporating your
+program into proprietary programs.  If your program is a subroutine
+library, you may consider it more useful to permit linking proprietary
+applications with the library.  If this is what you want to do, use the
+GNU Lesser General Public License instead of this License.  But first,
+please read `http://www.gnu.org/philosophy/why-not-lgpl.html'.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/pkg/mfile_minimal_test/DESCRIPTION	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,13 @@
+Name: mfile_minimal_test
+Version: 0.1.0
+Date: 2017-12-08
+Author: hopefully various authors
+Maintainer: hopefully some of those authors.
+Title: Example Minimal Package
+Description: Minimal package structure with only m-files.
+Depends: octave (>= 4.2.1)
+License: GPLv3+
+Categories: Test
+# BuildRequires:
+# SystemRequirements:
+# Url: external homepage
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/pkg/mfile_minimal_test/inst/example_mfile.m	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,36 @@
+## Copyright (C) 2017-2018 Olaf Till <i7tiol@t-online.de>
+##
+## This program is free software; you can redistribute it and/or
+## modify it under the terms of the GNU General Public License as
+## published by the Free Software Foundation; either version 3 of the
+## License, or (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {@var{ret} =} example_mfile (@var{arg})
+## Placeholder for an mfile function.
+##
+## @var{arg}: argument. @var{ret}: returned value.
+##
+## Although this file is so short, a license text is contained as an
+## example.
+##
+## @seealso{example_open, example_close, example_do_something}
+## @end deftypefn
+
+function ret = example_mfile (arg)
+
+  if (nargin () != 1)
+    print_usage ();
+  endif
+
+  ret = arg;
+
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/pkg/module.mk	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,14 @@
+pkg_TEST_FILES = \
+    %reldir%/pkg.tst \
+    %reldir%/mfile_basic_test/INDEX \
+    %reldir%/mfile_basic_test/NEWS \
+    %reldir%/mfile_basic_test/DESCRIPTION \
+    %reldir%/mfile_basic_test/doc/macros.texi \
+    %reldir%/mfile_basic_test/doc/example-package.txi \
+    %reldir%/mfile_basic_test/COPYING \
+    %reldir%/mfile_basic_test/inst/example_mfile.m \
+    %reldir%/mfile_minimal_test/DESCRIPTION \
+    %reldir%/mfile_minimal_test/COPYING \
+    %reldir%/mfile_minimal_test/inst/example_mfile.m
+
+TEST_FILES += $(pkg_TEST_FILES)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/pkg/pkg.tst	Fri Aug 10 09:09:51 2018 +0200
@@ -0,0 +1,148 @@
+## Copyright (C) 2018 JuanPi Carbajal
+##
+## 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
+## <https://www.gnu.org/licenses/>.
+
+############################################################
+## Test suite for pkg.m
+## Tests are organized first by action, and then by options.
+## All actions should be tested, and ideally all options are tested.
+############################################################
+
+%!shared old_prefix, old_archprefix, old_local_list, prefix, restorecfg, restorecache, rmtmpdir, mfile_pkg_name, mfile_pkg_zip
+%!
+%! ## Do all tests in a temporary directory
+%! [old_prefix, old_archprefix] = pkg ("prefix");
+%! restorecfg = onCleanup (@() pkg ("prefix", old_prefix, old_archprefix));
+%! old_local_list = pkg ("local_list");
+%! restorecache = onCleanup (@() pkg ("local_list", old_local_list));
+%! prefix = tempname ();
+%! [status] = mkdir (prefix);
+%! if (! status)
+%!   error ("pkg.tst: Could not create temporary directory for pkg testing");
+%!   return;  # abort further testing
+%! endif
+%! pkg ("prefix", prefix, prefix);
+%! pkg ("local_list", fullfile (prefix, "octave_packages"));
+%! rmtmpdir = @onCleanup (@() confirm_recursive_rmdir (0, "local") && rmdir (prefix, "s"));
+%!
+%! ## Create zip file packages of testing directories in prefix directory
+%! mfile_pkg_name = {"mfile_basic_test", "mfile_minimal_test"};
+%! mfile_pkg_zip = fullfile (prefix, strcat (mfile_pkg_name, ".zip"));
+%! for i = 1:numel (mfile_pkg_name)
+%!   zip (mfile_pkg_zip{i}, mfile_pkg_name{i});
+%! endfor
+
+## Avoids printing to stdout when installing
+%!function silent_pkg_install (varargin) 
+%!  evalc (["pkg install", sprintf(" %s", varargin{:})]);
+%!endfunction
+
+## Action install/uninstall
+%!test
+%! for i = 1:numel (mfile_pkg_name)
+%!   silent_pkg_install (mfile_pkg_zip{i});
+%!   pkg ("uninstall", mfile_pkg_name{i});
+%! endfor
+%!
+%!error pkg ("install", "nonexistent.zip")
+
+# -local
+%!test
+%! for i = 1:numel (mfile_pkg_name)
+%!   silent_pkg_install ("-local", mfile_pkg_zip{i});
+%!   pkg ("uninstall", mfile_pkg_name{i});
+%! endfor
+
+# -forge (need check for options?)
+## FIXME: Need test
+# We do not test this yet ... fails if no internet connection
+# use dataframe which is an mfile only package
+#%!test
+#%! silent_pkg_install ("-forge", "dataframe");
+#%! pkg ("uninstall", "dataframe");
+
+# -nodeps
+## FIXME: Need test
+
+# -verbose
+## FIXME: Need test
+
+## Action load/unload (within install/uninstall)
+%!test
+%! for i = 1:numel (mfile_pkg_name)
+%!  name = mfile_pkg_name{i};
+%!  silent_pkg_install ("-local", mfile_pkg_zip{i});
+%!  unwind_protect
+%!    pkg ("load", name);
+%!    pkg ("unload", name);
+%!  unwind_protect_cleanup
+%!    pkg ("uninstall", name);
+%!  end_unwind_protect
+%! endfor
+%!
+%!error <package foobar is not installed> pkg ("load", "foobar");
+
+# -nodeps
+## FIXME: Need test
+
+# -verbose
+## FIXME: Need test
+
+## Action list
+%!test 
+%! [user_packages, system_packages] = pkg ("list");
+
+# -forge
+#%!test
+#%! oct_forge_pkgs = pkg ("list", "-forge");
+
+## Action describe
+%!test
+%! silent_pkg_install ("-local", mfile_pkg_zip{1});
+%! [desc, flag] = pkg ("describe", mfile_pkg_name{1});
+%! ## FIXME: this only tests that the describe command runs,
+%! ##        not that the output is in anyway correct.
+%! pkg ("uninstall", mfile_pkg_name{1});
+
+# -verbose
+## FIXME: Need test
+
+## Action prefix
+%!test
+%! pfx_old = pkg ("prefix");
+%! unwind_protect
+%!   pfx_new = pkg ("prefix", pwd ());
+%!   assert (pfx_new, pwd ());
+%! unwind_protect_cleanup
+%!   pfx = pkg ("prefix", pfx_old);
+%! end_unwind_protect
+
+## Action build
+## FIXME: Need test
+# pkg build -verbose /tmp image-*
+
+## Action rebuild
+## FIXME: Need test
+# pkg rebuild signal
+
+## Future commands
+%!error pkg ("whereis", "myfunc.m")
+%!error pkg ("whereis", "-forge", "myfunc.m")
+
+############################################################
+## End of Tests
+############################################################
--- a/test/prefer.tst	Fri Aug 10 09:08:33 2018 +0200
+++ b/test/prefer.tst	Fri Aug 10 09:09:51 2018 +0200
@@ -95,8 +95,8 @@
 %! print_empty_dimensions (0);
 %! a = cell (1, 1);
 %! b = type ("-q", "a");
-%! assert (!isempty (findstr (b{1}, "[]")));
-%! assert (isempty (findstr (b{1} ,"[](0x0)")));
+%! assert (! isempty (strfind (b{1}, "[]")));
+%! assert (isempty (strfind (b{1} ,"[](0x0)")));
 %! print_empty_dimensions (ped);
 
 %!test
@@ -104,7 +104,7 @@
 %! print_empty_dimensions (1);
 %! a = cell (1, 1);
 %! b = type ("-q", "a");
-%! assert (!isempty (findstr (b{1}, "[](0x0)")));
+%! assert (! isempty (strfind (b{1}, "[](0x0)")));
 %! print_empty_dimensions (ped);
 
 %!assert (all (size (inv ([])) == [0, 0]))