changeset 25535:ad25dee33a9f

maint: Merge stable to default.
author Kai T. Ohlhus <k.ohlhus@gmail.com>
date Mon, 02 Jul 2018 15:48:14 +0200
parents d6850dd2a6b4 (diff) 222e23e5e7c1 (current diff)
children 075b9f8a32d8
files liboctave/version.cc
diffstat 421 files changed, 16020 insertions(+), 14075 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile.am	Mon Jul 02 15:47:19 2018 +0200
+++ b/Makefile.am	Mon Jul 02 15:48:14 2018 +0200
@@ -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 =
--- a/NEWS	Mon Jul 02 15:47:19 2018 +0200
+++ b/NEWS	Mon Jul 02 15:48:14 2018 +0200
@@ -1,962 +1,32 @@
-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.
-
- ** 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)
+ ** 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.
 
-    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 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.
 
-    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
+ ** 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 ([]).
 
  ** 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):
+    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
       ---------------------|------------------
-      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):
+ ** The following functions were deprecated in Octave 4.2 and have been
+    removed from Octave 5.0.
 
       Function             | Replacement
       ---------------------|------------------
@@ -970,381 +40,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	Mon Jul 02 15:47:19 2018 +0200
+++ b/bootstrap.conf	Mon Jul 02 15:48:14 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/build-aux/inplace_edit.pl	Mon Jul 02 15:48:14 2018 +0200
@@ -0,0 +1,33 @@
+#!/usr/bin/perl -w
+
+################################################################################
+## File: inplace_edit.pl
+## Usage: perl inplace_edit.pl 'PERL_CODE' file1 [file2] [...]
+## Purpose: Run snippet of PERL_CODE on each line in a file and replace
+## existing line with the results of running the code.
+## This replaces perl -i -pe 'PERL_CODE' file1 [file2] ...
+## due to a problem in Perl 5.28 which restricts the number of files
+################################################################################
+
+## Create Perl code from first argument (-e CODE)
+eval "sub per_line_code { $ARGV[0]; }";
+shift @ARGV;
+
+## Loop over each file
+foreach $fname (@ARGV)
+{
+  rename ($fname, "$fname.$$") or die "Rename failed:$fname:$!"; 
+  open (my $FHI, "<", "$fname.$$") or die "Open failed:$fname.$$:$!";  
+  open (my $FHO, ">", "$fname") or die "Open failed:$fname:$!";  
+
+  ## Loop over each line
+  while (<$FHI>)
+  {
+    per_line_code ();
+    print $FHO $_;      
+  }
+
+  close ($FHI);
+  close ($FHO);
+  unlink "$fname.$$" or die "Delete failed:$fname.$$:$!";
+}
--- a/build-aux/mk-opts.pl	Mon Jul 02 15:47:19 2018 +0200
+++ b/build-aux/mk-opts.pl	Mon Jul 02 15:48:14 2018 +0200
@@ -512,7 +512,8 @@
 // this file.
 
 #include <iomanip>
-#include <iostream>
+#include <ostream>
+#include <sstream>
 
 #include "$header"
 
--- a/configure.ac	Mon Jul 02 15:47:19 2018 +0200
+++ b/configure.ac	Mon Jul 02 15:48:14 2018 +0200
@@ -1,4 +1,4 @@
-dnl Process this file with autoconf to produce a configure script.
+9dnl Process this file with autoconf to produce a configure script.
 dnl
 dnl Copyright (C) 1993-2018 John W. Eaton
 ###
@@ -20,7 +20,7 @@
 
 ### Initialize Autoconf
 AC_PREREQ([2.65])
-AC_INIT([GNU Octave], [4.4.0x], [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,9 @@
 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=0x
+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 +52,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 +188,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
@@ -3120,7 +3124,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"
 
@@ -3129,9 +3135,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)
@@ -3279,7 +3288,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.
@@ -3291,8 +3302,8 @@
 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
--- a/doc/interpreter/genpropdoc.m	Mon Jul 02 15:47:19 2018 +0200
+++ b/doc/interpreter/genpropdoc.m	Mon Jul 02 15:48:14 2018 +0200
@@ -1745,7 +1745,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/module.mk	Mon Jul 02 15:47:19 2018 +0200
+++ b/doc/interpreter/module.mk	Mon Jul 02 15:48:14 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 = \
@@ -300,7 +302,7 @@
 	 --css-ref=octave.css \
 	 -o $(OCTAVE_HTML_TMP_DIR) `test -f '%reldir%/octave.texi' || echo '$(abs_top_srcdir)/'`%reldir%/octave.texi; \
 	then \
-	  $(PERL) -i -pe 's|(?<=</a>): ||g' $(OCTAVE_HTML_TMP_DIR)/* && \
+	  $(PERL) $(srcdir)/build-aux/inplace_edit.pl 's|(?<=</a>): ||g' $(OCTAVE_HTML_TMP_DIR)/* && \
 	  rm -rf $(OCTAVE_HTML_DIR) && \
 	  mv $(OCTAVE_HTML_TMP_DIR) $(OCTAVE_HTML_DIR) && \
 	  touch $@; \
--- a/doc/interpreter/octave.texi	Mon Jul 02 15:47:19 2018 +0200
+++ b/doc/interpreter/octave.texi	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/doc/interpreter/strings.txi	Mon Jul 02 15:48:14 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
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/etc/NEWS.4	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/etc/RELEASE.PROCESS	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/etc/module.mk	Mon Jul 02 15:48:14 2018 +0200
@@ -8,6 +8,7 @@
   %reldir%/NEWS.1 \
   %reldir%/NEWS.2 \
   %reldir%/NEWS.3 \
+  %reldir%/NEWS.4 \
   %reldir%/PROJECTS \
   %reldir%/gdbinit
 
--- a/libgui/graphics/QtHandlesUtils.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libgui/graphics/QtHandlesUtils.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libgui/graphics/module.mk	Mon Jul 02 15:48:14 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 \
--- a/libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.cpp	Mon Jul 02 15:47:19 2018 +0200
+++ b/libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.cpp	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libgui/qterminal/libqterminal/win32/QWinTerminalImpl.cpp	Mon Jul 02 15:48:14 2018 +0200
@@ -52,7 +52,6 @@
 #include <versionhelpers.h>
 #include <cstring>
 #include <csignal>
-#include <limits>
 
 #include "QWinTerminalImpl.h"
 #include "QTerminalColors.h"
--- a/libgui/src/dialog.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libgui/src/dialog.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -230,8 +230,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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libgui/src/documentation-dock-widget.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libgui/src/documentation-dock-widget.h	Mon Jul 02 15:48:14 2018 +0200
@@ -53,7 +53,7 @@
 
   private:
 
-    octave::documentation *m_docs;
+    documentation *m_docs;
   };
 }
 
--- a/libgui/src/documentation.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libgui/src/documentation.cc	Mon Jul 02 15:48:14 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;
 
@@ -295,7 +300,12 @@
     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) { }
 
--- a/libgui/src/documentation.h	Mon Jul 02 15:47:19 2018 +0200
+++ b/libgui/src/documentation.h	Mon Jul 02 15:48:14 2018 +0200
@@ -26,6 +26,7 @@
 #include <QComboBox>
 #include <QWidget>
 #include <QSettings>
+#include <QShortcut>
 #include <QSplitter>
 #include <QTextBrowser>
 #include <QtHelp/QHelpEngine>
@@ -101,6 +102,9 @@
     QComboBox *m_filter;
     QString m_collection;
 
+    QShortcut *m_show_shortcut;
+    QShortcut *m_findnext_shortcut;
+    QShortcut *m_findprev_shortcut;
   };
 
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/dw-main-window.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:48:14 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/editor-settings.h	Mon Jul 02 15:48:14 2018 +0200
@@ -0,0 +1,44 @@
+/*
+
+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>
+
+// 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/files-dock-widget.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libgui/src/files-dock-widget.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libgui/src/files-dock-widget.h	Mon Jul 02 15:48:14 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);
--- a/libgui/src/history-dock-widget.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libgui/src/history-dock-widget.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libgui/src/m-editor/file-editor-interface.h	Mon Jul 02 15:48:14 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;
--- a/libgui/src/m-editor/file-editor-tab.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libgui/src/m-editor/file-editor-tab.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -60,7 +60,9 @@
 #include <QDialogButtonBox>
 #include <QPushButton>
 
+#include "editor-settings.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)
@@ -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);
       }
@@ -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)
+      {
+        // 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libgui/src/m-editor/file-editor-tab.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libgui/src/m-editor/file-editor.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -377,8 +377,8 @@
     QStringList fet_index;
 
     // 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
@@ -397,7 +397,11 @@
     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 +409,8 @@
         m_tab_widget->removeTab (i);
       }
 
+    setVisible (vis);
+
     return true;
   }
 
@@ -949,8 +955,8 @@
           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++)
+        for (auto p = m_editor_tab_map.cbegin ();
+             p != m_editor_tab_map.cend (); p++)
           {
             if (editor_tab == p->second.fet_ID)
               {
@@ -1490,7 +1496,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));
@@ -2316,8 +2322,8 @@
     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 ("../"))
@@ -2367,8 +2373,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/octave-qscintilla.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libgui/src/m-editor/octave-qscintilla.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -50,14 +50,14 @@
 #include <QToolTip>
 #include <QVBoxLayout>
 
-// FIXME: hardwired marker numbers?
-#include "marker.h"
+#include "editor-settings.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".
--- a/libgui/src/main-window.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libgui/src/main-window.cc	Mon Jul 02 15:48:14 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
@@ -380,6 +393,13 @@
                                file.toStdString ());
   }
 
+  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);
@@ -1253,7 +1273,7 @@
 
                 if (visible)
                   {
-                    if (settings->value ("DockWidgets/" + widget->objectName ()
+                    if (settings->value ("DockWidgets/" + name
                                          + "_minimized").toBool ())
                       widget->showMinimized ();
                     else
@@ -1822,6 +1842,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&)));
 
@@ -2533,6 +2556,20 @@
     command_editor::set_screen_size (sz.first, sz.second);
   }
 
+  void main_window::open_any_callback (const std::string& file)
+  {
+    // INTERPRETER THREAD
+
+    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_workspace_callback (void)
   {
     // INTERPRETER THREAD
--- a/libgui/src/main-window.h	Mon Jul 02 15:47:19 2018 +0200
+++ b/libgui/src/main-window.h	Mon Jul 02 15:48:14 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);
@@ -322,6 +323,8 @@
 
     void load_workspace_callback (const std::string& file);
 
+    void open_any_callback (const std::string& file);
+
     void rename_variable_callback (const name_pair& names);
 
     void command_window_undo_callback (void);
--- a/libgui/src/module.mk	Mon Jul 02 15:47:19 2018 +0200
+++ b/libgui/src/module.mk	Mon Jul 02 15:48:14 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 \
@@ -155,6 +156,8 @@
   %reldir%/octave-dock-widget.h \
   %reldir%/documentation-dock-widget.h \
   %reldir%/documentation.h \
+  %reldir%/dw-main-window.h \
+  %reldir%/editor-settings.h \
   %reldir%/external-editor-interface.h \
   %reldir%/files-dock-widget.h \
   %reldir%/history-dock-widget.h \
@@ -169,7 +172,6 @@
   %reldir%/octave-gui.h \
   %reldir%/octave-cmd.h \
   %reldir%/octave-qt-link.h \
-  %reldir%/octave-settings.h \
   %reldir%/qtinfo/texinfo-parser.h \
   %reldir%/qtinfo/webinfo.h \
   %reldir%/resource-manager.h \
@@ -190,6 +192,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 \
@@ -235,6 +238,7 @@
   -I$(srcdir)/%reldir%/m-editor \
   -I$(srcdir)/%reldir%/qtinfo \
   -I$(srcdir)/libgui/graphics \
+  -Iliboctave \
   -I$(srcdir)/liboctave/array \
   -Iliboctave/numeric -I$(srcdir)/liboctave/numeric \
   -Iliboctave/operators -I$(srcdir)/liboctave/operators \
--- a/libgui/src/octave-cmd.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libgui/src/octave-cmd.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -28,72 +28,74 @@
 
 #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_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 +128,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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libgui/src/octave-cmd.h	Mon Jul 02 15:48:14 2018 +0200
@@ -34,6 +34,8 @@
 
 namespace octave
 {
+  class interpreter;
+
   class octave_cmd
   {
   public:
@@ -42,7 +44,7 @@
 
     virtual ~octave_cmd (void) = default;
 
-    virtual void execute (void) { }
+    virtual void execute (interpreter&) { }
   };
 
   class octave_cmd_exec : public octave_cmd
@@ -51,7 +53,7 @@
 
     octave_cmd_exec (const QString& cmd) : octave_cmd () { m_cmd = cmd; }
 
-    void execute (void);
+    void execute (interpreter& interp);
 
   protected:
 
@@ -64,7 +66,7 @@
 
     octave_cmd_eval (const QFileInfo& info) : octave_cmd () { m_info = info; }
 
-    void execute (void);
+    void execute (interpreter& interp);
 
   protected:
 
@@ -78,7 +80,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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libgui/src/octave-dock-widget.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libgui/src/octave-dock-widget.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libgui/src/octave-gui.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libgui/src/octave-qt-link.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -195,11 +195,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 +211,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 +296,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 +328,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 ());
@@ -491,18 +483,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)
   {
--- a/libgui/src/octave-qt-link.h	Mon Jul 02 15:47:19 2018 +0200
+++ b/libgui/src/octave-qt-link.h	Mon Jul 02 15:48:14 2018 +0200
@@ -134,9 +134,6 @@
     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);
--- a/libgui/src/octave-settings.h	Mon Jul 02 15:47:19 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/qtinfo/webinfo.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libgui/src/qtinfo/webinfo.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -36,7 +36,6 @@
 
 #include "file-ops.h"
 #include "help.h"
-#include "defaults.h"
 #include "resource-manager.h"
 #include "shortcut-manager.h"
 
@@ -56,7 +55,7 @@
     hbox_layout->setSpacing (0);
     vbox_layout->addLayout (hbox_layout);
 
-    _tab_bar = new octave::tab_bar (this);
+    _tab_bar = new tab_bar (this);
     _tab_bar->setSizePolicy (QSizePolicy::Preferred,QSizePolicy::Preferred);
     _tab_bar->setExpanding (false);
     _tab_bar->setTabsClosable (true);
--- a/libgui/src/resource-manager.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libgui/src/resource-manager.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -55,11 +55,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 +94,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);
   }
 
--- a/libgui/src/settings-dialog.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libgui/src/settings-dialog.cc	Mon Jul 02 15:48:14 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 ();
 
@@ -688,8 +689,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);
     }
 }
 
--- a/libgui/src/settings-dialog.h	Mon Jul 02 15:47:19 2018 +0200
+++ b/libgui/src/settings-dialog.h	Mon Jul 02 15:48:14 2018 +0200
@@ -29,7 +29,7 @@
 #include <QRadioButton>
 
 #include "color-picker.h"
-#include "octave-settings.h"
+#include "editor-settings.h"
 
 namespace Ui
 {
--- a/libgui/src/settings-dialog.ui	Mon Jul 02 15:47:19 2018 +0200
+++ b/libgui/src/settings-dialog.ui	Mon Jul 02 15:48:14 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>-558</y>
             <width>645</width>
-            <height>1012</height>
+            <height>1131</height>
            </rect>
           </property>
           <layout class="QVBoxLayout" name="verticalLayout_16">
@@ -1735,6 +2016,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 +2061,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 +2285,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 +2523,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 +2845,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 +2893,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 +2941,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 +2989,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 +2997,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 +3021,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 +3029,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 +3051,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 +3083,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 +3309,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 +3341,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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libgui/src/shortcut-manager.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libgui/src/shortcut-manager.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libgui/src/terminal-dock-widget.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libgui/src/variable-editor-model.cc	Mon Jul 02 15:48:14 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.
--- a/libgui/src/variable-editor.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libgui/src/variable-editor.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libgui/src/variable-editor.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libgui/src/workspace-view.cc	Mon Jul 02 15:48:14 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."));
--- a/libinterp/corefcn/__dsearchn__.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/__dsearchn__.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -26,8 +26,6 @@
 
 #include <cmath>
 
-#include <iostream>
-#include <fstream>
 #include <string>
 
 #include "defun.h"
--- a/libinterp/corefcn/c-file-ptr-stream.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/c-file-ptr-stream.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/c-file-ptr-stream.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/call-stack.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/call-stack.h	Mon Jul 02 15:48:14 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/daspk.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/daspk.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -26,9 +26,6 @@
 
 #include <string>
 
-#include <iomanip>
-#include <iostream>
-
 #include "DASPK.h"
 
 #include "defun.h"
--- a/libinterp/corefcn/dasrt.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/dasrt.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -24,7 +24,6 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
 #include <string>
 
 #include "DASRT.h"
--- a/libinterp/corefcn/dassl.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/dassl.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -26,9 +26,6 @@
 
 #include <string>
 
-#include <iomanip>
-#include <iostream>
-
 #include "DASSL.h"
 
 #include "defun.h"
--- a/libinterp/corefcn/data.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/data.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -5204,6 +5204,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 +5908,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 +5939,6 @@
 (@dots{}((@var{x1} + @var{x2}) + @var{x3}) + @dots{})
 @end example
 
-At least one argument is required.
 @seealso{minus, uplus}
 @end deftypefn */)
 {
@@ -5939,6 +5946,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 +5981,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 +6102,6 @@
 (@dots{}((@var{x1} .* @var{x2}) .* @var{x3}) .* @dots{})
 @end example
 
-At least one argument is required.
 @seealso{mtimes, rdivide}
 @end deftypefn */)
 {
@@ -6150,7 +6166,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 +6187,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 +6756,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 +6847,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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/debug.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -80,8 +80,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{}
@@ -176,7 +176,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 +254,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 +304,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 +378,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 +396,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 +501,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 +510,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);
@@ -538,7 +544,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)
     {
@@ -607,8 +615,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 +643,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 +666,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 +696,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 +709,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 +721,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 +794,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 +1062,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 +1093,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 +1104,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 +1123,7 @@
           Vdebugging = false;
           Vtrack_line_num = true;
 
-          octave::tree_evaluator::dbstep_flag = n;
+          tw.set_dbstep_flag (n);
         }
     }
   else
@@ -1117,7 +1131,7 @@
       Vdebugging = false;
       Vtrack_line_num = true;
 
-      octave::tree_evaluator::dbstep_flag = 1;
+      tw.set_dbstep_flag (1);
     }
 
   return ovl ();
@@ -1125,8 +1139,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 +1155,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 +1180,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 +1202,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 +1221,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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/default-defs.in.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/defaults.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/defun.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/dirfns.cc	Mon Jul 02 15:48:14 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,9 +290,11 @@
           && ! 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)
--- a/libinterp/corefcn/dynamic-ld.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/dynamic-ld.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/environment.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/error.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -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 ();
     }
 }
 
@@ -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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/error.h	Mon Jul 02 15:48:14 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/fcn-info.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/fcn-info.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/fcn-info.h	Mon Jul 02 15:48:14 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/file-io.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/file-io.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -41,8 +41,7 @@
 #include <cerrno>
 #include <cstdio>
 
-#include <iostream>
-#include <limits>
+#include <iomanip>
 #include <stack>
 #include <string>
 #include <vector>
--- a/libinterp/corefcn/ft-text-renderer.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/ft-text-renderer.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/genprops.awk	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/gl-render.cc	Mon Jul 02 15:48:14 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
--- a/libinterp/corefcn/gl-render.h	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/gl-render.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/gl2ps-print.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -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);
@@ -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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/gl2ps-print.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/graphics.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -1728,13 +1728,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 +2200,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 +2313,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 +2617,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 +2643,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 +2671,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 +2697,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 +2811,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 +3135,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 +3398,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 +3881,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 +4707,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 +4717,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 +5072,6 @@
 
   gh_manager::free (hp.handle_value ());
 
-  base_properties::remove_child (hp.handle_value ());
-
   hp = val;
 
   adopt (hp.handle_value ());
@@ -5326,8 +5369,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 +5390,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 +5415,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 +8670,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 +8949,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 +9120,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 +9227,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 +9243,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 +9597,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__);
--- a/libinterp/corefcn/graphics.in.h	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/graphics.in.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 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	Mon Jul 02 15:47:19 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/gtk-manager.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/gtk-manager.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/gtk-manager.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/help.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -29,7 +29,7 @@
 
 #include <algorithm>
 #include <fstream>
-#include <iostream>
+#include <istream>
 #include <map>
 #include <sstream>
 #include <string>
@@ -61,7 +61,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 +553,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;
@@ -693,8 +692,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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/hook-fcn.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/hook-fcn.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/input.cc	Mon Jul 02 15:48:14 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,662 @@
   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;
 
-  octave::command_editor::set_completer_word_break_characters (s);
+                error ("__mfile_encoding__: conversion from codepage '%s' not supported",
+                       codepage.c_str ());
+              }
 
-  octave::command_editor::set_basic_quote_characters (R"(")");
+            octave_iconv_close_wrapper (codec);
+          }
+      }
+
+    return retval;
+  }
+
+  bool input_system::yes_or_no (const std::string& prompt)
+  {
+    std::string prompt_string = prompt + "(yes or no) ";
 
-  octave::command_editor::set_filename_quote_characters (" \t\n\\\"'@<>=;|&()#$`?*[!:{");
-  octave::command_editor::set_completer_quote_characters (R"('")");
+    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 ();
+
+    if (Vdrawnow_requested && octave::application::interactive ())
+      {
+        bool eval_error = false;
 
-  octave::command_editor::set_quoting_function (quoting_filename);
-}
+        try
+          {
+            Fdrawnow ();
+          }
+        catch (const octave::execution_exception& e)
+          {
+            eval_error = true;
+
+            std::string stack_trace = e.info ();
 
-static void
-execute_in_debugger_handler (const std::pair<std::string, int>& arg)
-{
-  octave_link::execute_in_debugger_event (arg.first, arg.second);
-}
+            if (! stack_trace.empty ())
+              std::cerr << stack_trace;
+
+            if (octave::application::interactive ())
+              octave::interpreter::recover_from_exception ();
+          }
+
+        octave::flush_stdout ();
+
+        // 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;
 
-static void
-get_debug_input (octave::interpreter& interp, const std::string& prompt)
-{
-  octave::unwind_protect frame;
+        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;
+
+    int read_as_string = 0;
+
+    if (args.length () == 2)
+      read_as_string++;
 
-  bool silent = octave::tree_evaluator::quiet_breakpoint_flag;
-  octave::tree_evaluator::quiet_breakpoint_flag = false;
+    std::string prompt = args(0).xstring_value ("input: unrecognized argument");
+
+    output_system& output_sys = __get_output_system__ ("do_sync");
+
+    output_sys.reset ();
+
+    octave_diary << prompt;
 
-  octave::call_stack& cs = interp.get_call_stack ();
+    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;
 
-  octave_user_code *caller = cs.caller_user_code ();
-  std::string nm;
-  int curr_debug_line;
+    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 (caller)
-    {
-      nm = caller->fcn_file_name ();
+        if (! Vdebugging && retval.empty ())
+          retval(0) = Matrix ();
+      }
+
+    return retval;
+  }
 
-      if (nm.empty ())
-        nm = caller->name ();
+  octave_value input_system::keyboard (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 ());
 
-      curr_debug_line = cs.caller_user_code_line ();
-    }
-  else
-    curr_debug_line = cs.current_line ();
+    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 ());
+
+    // 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::ostringstream buf;
+    std::string prompt = "debug> ";
+    if (nargin > 0)
+      prompt = args(0).string_value ();
+
+    get_debug_input (prompt);
+
+    return retval;
+  }
 
-  if (! nm.empty ())
-    {
-      if (Vgud_mode)
-        {
-          static char ctrl_z = 'Z' & 0x1f;
+  bool input_system::have_input_event_hooks (void) const
+  {
+    return ! m_input_event_hook_functions.empty ();
+  }
+
+  void input_system::add_input_event_hook (const hook_function& hook_fcn)
+  {
+    m_input_event_hook_functions.insert (hook_fcn.id (), hook_fcn);
+  }
 
-          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.
+  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;
+  }
+
+  void input_system::clear_input_event_hooks (void)
+  {
+    m_input_event_hook_functions.clear ();
+  }
 
-          if (! silent)
-            {
-              buf << "stopped in " << nm;
+  void input_system::run_input_event_hooks (void)
+  {
+    m_input_event_hook_functions.run ();
+  }
+
+  std::string
+  input_system::gnu_readline (const std::string& s, bool& eof) const
+  {
+    octave_quit ();
+
+    eof = false;
 
-              if (curr_debug_line > 0)
-                buf << " at line " << curr_debug_line;
-            }
+    std::string retval = octave::command_editor::readline (s, eof);
+
+    if (! eof && retval.empty ())
+      retval = "\n";
+
+    return retval;
+  }
+
+  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::enter_debugger_event (nm, curr_debug_line);
+  void input_system::get_debug_input (const std::string& prompt)
+  {
+    octave::unwind_protect frame;
+
+    octave::tree_evaluator& tw = m_interpreter.get_evaluator ();
 
-          octave_link::set_workspace ();
+    bool silent = tw.quiet_breakpoint_flag (false);
+
+    octave::call_stack& cs = m_interpreter.get_call_stack ();
+
+    octave_user_code *caller = cs.caller_user_code ();
+    std::string nm;
+    int curr_debug_line;
 
-          frame.add_fcn (execute_in_debugger_handler,
-                         std::pair<std::string, int> (nm, curr_debug_line));
+    if (caller)
+      {
+        nm = caller->fcn_file_name ();
+
+        if (nm.empty ())
+          nm = caller->name ();
 
-          if (! silent)
-            {
-              std::string line_buf;
+        curr_debug_line = cs.caller_user_code_line ();
+      }
+    else
+      curr_debug_line = cs.current_line ();
+
+    std::ostringstream buf;
+
+    if (! nm.empty ())
+      {
+        if (m_gud_mode)
+          {
+            static char ctrl_z = 'Z' & 0x1f;
 
-              if (caller)
-                line_buf = caller->get_code_line (curr_debug_line);
+            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;
+              }
+
+            octave_link::enter_debugger_event (nm, curr_debug_line);
+
+            octave_link::set_workspace ();
 
-              if (! line_buf.empty ())
-                buf << "\n" << curr_debug_line << ": " << line_buf;
-            }
-        }
-    }
+            frame.add_fcn (execute_in_debugger_handler,
+                           std::pair<std::string, int> (nm, curr_debug_line));
+
+            if (! silent)
+              {
+                std::string line_buf;
+
+                if (caller)
+                  line_buf = caller->get_code_line (curr_debug_line);
 
-  if (silent)
-    octave::command_editor::erase_empty_line (true);
+                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 ();
+
+    if (! msg.empty ())
+      std::cerr << msg << std::endl;
 
-  std::string msg = buf.str ();
+    frame.add_method (*this, &octave::input_system::set_PS1, m_PS1);
+    m_PS1 = prompt;
+
+    // FIXME: should debugging be possible in an embedded interpreter?
+
+    octave::application *app = octave::application::app ();
 
-  if (! msg.empty ())
-    std::cerr << msg << std::endl;
+    if (! app->interactive ())
+      {
+
+        frame.add_method (app, &octave::application::interactive,
+                          app->interactive ());
+
+        frame.add_method (app, &octave::application::forced_interactive,
+                          app->forced_interactive ());
 
-  frame.protect_var (VPS1);
-  VPS1 = prompt;
+        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 ();
+
+            int retval = curr_parser.run ();
 
-  octave::application *app = octave::application::app ();
+            if (octave::command_editor::interrupt (false))
+              break;
+            else
+              {
+                if (retval == 0 && curr_parser.m_stmt_list)
+                  {
+                    curr_parser.m_stmt_list->accept (tw);
 
-  if (! app->interactive ())
-    {
+                    if (octave_completion_matches_called)
+                      octave_completion_matches_called = false;
+                  }
+
+                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::interactive,
-                        app->interactive ());
+            // Ignore errors when in debugging mode;
+            octave::interpreter::recover_from_exception ();
+          }
+      }
+  }
+
+  std::string base_reader::octave_gets (bool& eof)
+  {
+    octave_quit ();
 
-      frame.add_method (app, &octave::application::forced_interactive,
-                        app->forced_interactive ());
+    eof = false;
+
+    std::string retval;
 
-      app->interactive (true);
+    // Process pre input event hook function prior to flushing output and
+    // printing the prompt.
+
+    if (application::interactive ())
+      {
+        if (! Vdebugging)
+          octave_link::exit_debugger_event ();
 
-      app->forced_interactive (true);
-    }
+        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);
+
+    pipe_handler_error_count = 0;
 
-  octave::parser curr_parser;
+    output_system& output_sys = __get_output_system__ ("do_sync");
+
+    output_sys.reset ();
+
+    octave_diary << prompt;
+
+    retval = input_sys.interactive_input (prompt, eof);
 
-  octave::tree_evaluator& tw = interp.get_evaluator ();
+    // 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);
+          }
+
+        octave_diary << retval;
 
-          reset_error_handler ();
+        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 ();
 
-          curr_parser.reset ();
+    return retval;
+  }
 
-          int retval = curr_parser.run ();
+  bool base_reader::reading_fcn_file (void) const
+  {
+    return m_lexer ? m_lexer->m_reading_fcn_file : false;
+  }
+
+  bool base_reader::reading_classdef_file (void) const
+  {
+    return m_lexer ? m_lexer->m_reading_classdef_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_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 (octave_completion_matches_called)
-                    octave_completion_matches_called = false;
-                }
+    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; }
+
+    bool input_from_file (void) const { return true; }
 
-              octave_quit ();
-            }
-        }
-      catch (const octave::execution_exception& e)
-        {
-          std::string stack_trace = e.info ();
+  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 +1104,40 @@
 
     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)
+    {
+      // 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 +1164,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 +1208,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 +1232,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 +1273,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 +1421,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 +1462,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 +1493,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 +1544,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 +1568,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 +1588,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 +1613,75 @@
   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 ();
+
+  return input_sys.mfile_encoding (args, nargout);
+}
 
-  if (nargin > 1)
-    print_usage ();
+#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
+
+void
+set_default_prompts (void)
+{
+  octave::input_system& input_sys
+    = octave::__get_input_system__ ("set_default_prompts");
 
-  octave_value_list retval;
+  input_sys.set_default_prompts ();
+}
+
+bool
+octave_yes_or_no (const std::string& prompt)
+{
+  octave::input_system& input_sys
+    = octave::__get_input_system__ ("set_default_prompts");
 
-  if (nargin == 0)
-    retval = ovl (Vgud_mode);
-  else
-    Vgud_mode = args(0).bool_value ();
+  input_sys.yes_or_no (prompt);
+}
+
+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);
+}
 
-  return retval;
+void
+remove_input_event_hook_functions (void)
+{
+  octave::input_system& input_sys
+    = octave::__get_input_system__ ("remove_input_event_hook_functions");
+
+  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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/input.h	Mon Jul 02 15:48:14 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,24 @@
   };
 }
 
+#if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
+
+OCTAVE_DEPRECATED (5, "use 'octave::input_system::set_default_prompts' instead")
+extern void set_default_prompts (void);
+
+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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/interpreter-private.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/interpreter-private.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/interpreter.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/interpreter.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/kron.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/load-path.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/load-path.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/load-save.cc	Mon Jul 02 15:48:14 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"
@@ -993,7 +992,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;
 
--- a/libinterp/corefcn/ls-ascii-helper.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/ls-ascii-helper.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/ls-hdf5.cc	Mon Jul 02 15:48:14 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"
--- a/libinterp/corefcn/ls-hdf5.h	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/ls-hdf5.h	Mon Jul 02 15:48:14 2018 +0200
@@ -25,7 +25,7 @@
 
 #include "octave-config.h"
 
-#include <iostream>
+#include <iosfwd>
 
 #include "oct-hdf5-types.h"
 #include "ov.h"
--- a/libinterp/corefcn/ls-mat-ascii.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/ls-mat-ascii.cc	Mon Jul 02 15:48:14 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"
--- a/libinterp/corefcn/ls-mat4.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/ls-mat4.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/ls-mat5.cc	Mon Jul 02 15:48:14 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"
@@ -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);
@@ -2178,7 +2177,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);
@@ -2186,7 +2185,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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/ls-oct-binary.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/ls-oct-text.cc	Mon Jul 02 15:48:14 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"
--- a/libinterp/corefcn/lsode.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/lsode.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -26,9 +26,6 @@
 
 #include <string>
 
-#include <iomanip>
-#include <iostream>
-
 #include "LSODE.h"
 #include "lo-mappers.h"
 
--- a/libinterp/corefcn/mappers.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/mappers.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/mex.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -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);
@@ -3662,7 +3662,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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/module.mk	Mon Jul 02 15:48:14 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 \
@@ -165,7 +165,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 +223,7 @@
   %reldir%/rcond.cc \
   %reldir%/regexp.cc \
   %reldir%/schur.cc \
+  %reldir%/settings.cc \
   %reldir%/sighandlers.cc \
   %reldir%/sparse-xdiv.cc \
   %reldir%/sparse-xpow.cc \
--- a/libinterp/corefcn/mxarray.in.h	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/mxarray.in.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/oct-hist.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/oct-iostrm.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/oct-map.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/oct-map.h	Mon Jul 02 15:48:14 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-procbuf.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/oct-procbuf.cc	Mon Jul 02 15:48:14 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
--- a/libinterp/corefcn/oct-stdstrm.h	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/oct-stdstrm.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/oct-stream.cc	Mon Jul 02 15:48:14 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;
@@ -124,7 +124,7 @@
     if (lo_ieee_isnan (d))
       ::error ("%s: NaN is invalid as size specification", who.c_str ());
 
-    if (octave::math::isinf (d))
+    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,7 +169,7 @@
       {
         dnr = size(0);
 
-        if (octave::math::isinf (dnr))
+        if (math::isinf (dnr))
           ::error ("%s: invalid size specification", who.c_str ());
 
         dnc = size(1);
@@ -3391,7 +3391,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 +4574,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 +4902,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 +5198,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 +5292,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 +5304,7 @@
       invalid_operation (who, "reading");
     else
       {
-        octave::textscan scanner (who);
+        textscan scanner (who);
 
         retval = scanner.scan (*isp, fmt, ntimes, options, read_count);
       }
@@ -5437,7 +5437,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 +5464,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 +5513,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;
 
@@ -5553,7 +5553,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 +5608,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 +5635,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 +5643,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 +6303,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 +6313,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 +6329,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 +6349,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 +6393,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>
@@ -6777,18 +6776,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 +7282,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 +7293,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 +7387,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 +7434,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.h	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/oct.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/octave-link.cc	Mon Jul 02 15:48:14 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;
--- a/libinterp/corefcn/octave-link.h	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/octave-link.h	Mon Jul 02 15:48:14 2018 +0200
@@ -368,13 +368,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;
@@ -619,9 +612,6 @@
                                      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_doc (const std::string& file) = 0;
--- a/libinterp/corefcn/pager.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/pager.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/pager.h	Mon Jul 02 15:48:14 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/procstream.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/procstream.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -24,7 +24,7 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <iomanip>
 
 #include "procstream.h"
 
--- a/libinterp/corefcn/procstream.h	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/procstream.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/quad.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -26,9 +26,6 @@
 
 #include <string>
 
-#include <iomanip>
-#include <iostream>
-
 #include "Quad.h"
 #include "lo-mappers.h"
 
--- a/libinterp/corefcn/rand.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/rand.cc	Mon Jul 02 15:48:14 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,13 +262,13 @@
               {
                 if (args(idx+1).is_string ()
                     && args(idx+1).string_value () == "reset")
-                  octave_rand::reset (fcn);
+                  octave::rand::reset (fcn);
                 else
                   {
                     ColumnVector s =
                       ColumnVector (args(idx+1).vector_value(false, true));
 
-                    octave_rand::state (s, fcn);
+                    octave::rand::state (s, fcn);
                   }
               }
             else
@@ -307,7 +307,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)
@@ -318,20 +318,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)
@@ -342,13 +342,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);
     }
 }
 
@@ -532,7 +532,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 -*-
@@ -1125,7 +1125,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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/regexp.cc	Mon Jul 02 15:48:14 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 () : "");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/corefcn/settings.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/sighandlers.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/sighandlers.h	Mon Jul 02 15:48:14 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/strfns.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/strfns.cc	Mon Jul 02 15:48:14 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"
@@ -828,6 +829,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/symscope.h	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/symscope.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/symtab.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/symtab.h	Mon Jul 02 15:48:14 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/sysdep.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/sysdep.cc	Mon Jul 02 15:48:14 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);
@@ -209,8 +210,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);
@@ -258,11 +260,11 @@
 
   bool retval = false;
 
-  const char *f1 = file1.c_str ();
-  const char *f2 = file2.c_str ();
+  const wchar_t *f1 = octave::sys::u8_to_wstring (file1).c_str ();
+  const wchar_t *f2 = octave::sys::u8_to_wstring (file2).c_str ();
 
-  bool f1_is_dir = GetFileAttributes (f1) & FILE_ATTRIBUTE_DIRECTORY;
-  bool f2_is_dir = GetFileAttributes (f2) & FILE_ATTRIBUTE_DIRECTORY;
+  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
@@ -270,14 +272,14 @@
   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);
+    = 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);
+        = CreateFileW (f2, 0, share, 0, OPEN_EXISTING,
+                       f2_is_dir ? FILE_FLAG_BACKUP_SEMANTICS : 0, 0);
 
       if (hfile2 != INVALID_HANDLE_VALUE)
         {
@@ -506,15 +508,22 @@
 octave_popen (const char *command, const char *mode)
 {
 #if defined (__MINGW32__) || defined (_MSC_VER)
-  if (mode && mode[0] && ! mode[1])
+  wchar_t *wcommand = u8_to_wchar (command);
+  wchar_t *wmode = u8_to_wchar (mode);
+
+  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
-      char tmode[3] = {mode[0], 'b', '\0'};
+      wchar_t tmode[3] = {wmode[0], L'b', L'\0'};
 
-      return _popen (command, tmode);
+      return _wpopen (wcommand, tmode);
     }
   else
-    return _popen (command, mode);
+    return _wpopen (wcommand, wmode);
 #else
   return popen (command, mode);
 #endif
@@ -728,7 +737,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,22 +748,25 @@
   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;
 }
@@ -766,22 +780,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++;
     }
--- a/libinterp/corefcn/toplev.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/toplev.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -26,8 +26,8 @@
 
 #include <cerrno>
 #include <cstdlib>
+
 #include <new>
-
 #include <sstream>
 #include <string>
 
--- a/libinterp/corefcn/txt-eng.h	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/txt-eng.h	Mon Jul 02 15:48:14 2018 +0200
@@ -122,7 +122,7 @@
   {
     while (! empty ())
       {
-        iterator it = begin ();
+        auto it = begin ();
         delete (*it);
         erase (it);
       }
--- a/libinterp/corefcn/url-handle-manager.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/url-handle-manager.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/urlwrite.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -31,7 +31,6 @@
 #include <string>
 #include <fstream>
 #include <iomanip>
-#include <iostream>
 
 #include "dir-ops.h"
 #include "file-ops.h"
--- a/libinterp/corefcn/utils.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/utils.cc	Mon Jul 02 15:48:14 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"
@@ -235,12 +234,6 @@
   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.
 
 std::string
@@ -539,80 +532,6 @@
   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.
-
-std::string
-oct_file_in_path (const std::string& name)
-{
-  std::string retval;
-
-  int len = name.length ();
-
-  if (len > 0)
-    {
-      if (octave::sys::env::absolute_pathname (name))
-        {
-          octave::sys::file_stat fs (name);
-
-          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");
-
-          retval = lp.find_oct_file (name.substr (0, len-4));
-        }
-      else
-        {
-          octave::load_path& lp = octave::__get_load_path__ ("oct_file_in_path");
-
-          retval = lp.find_oct_file (name);
-        }
-    }
-
-  return retval;
-}
-
-// 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.
-
-std::string
-mex_file_in_path (const std::string& name)
-{
-  std::string retval;
-
-  int len = name.length ();
-
-  if (len > 0)
-    {
-      if (octave::sys::env::absolute_pathname (name))
-        {
-          octave::sys::file_stat fs (name);
-
-          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");
-
-          retval = lp.find_mex_file (name.substr (0, len-4));
-        }
-      else
-        {
-          octave::load_path& lp = octave::__get_load_path__ ("mex_file_in_path");
-
-          retval = lp.find_mex_file (name);
-        }
-    }
-
-  return retval;
-}
-
 // Replace backslash escapes in a string with the real values.
 
 std::string
--- a/libinterp/corefcn/utils.h	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/utils.h	Mon Jul 02 15:48:14 2018 +0200
@@ -54,10 +54,6 @@
                       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);
-
 extern OCTINTERP_API std::string
 search_path_for_file (const std::string&, const string_vector&);
 
@@ -76,12 +72,6 @@
 
 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 (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);
 
 extern OCTINTERP_API const char * undo_string_escape (char c);
--- a/libinterp/corefcn/variables.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/variables.cc	Mon Jul 02 15:48:14 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)
 {
@@ -707,13 +547,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 +847,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 +988,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 +1164,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 +2648,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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/variables.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/corefcn/zfstream.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -34,7 +34,9 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <iomanip>
+#include <istream>
+#include <ostream>
 
 #include "zfstream.h"
 
--- a/libinterp/dldfcn/__init_fltk__.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/dldfcn/__init_fltk__.cc	Mon Jul 02 15:48:14 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/__ode15__.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/dldfcn/__ode15__.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -24,6 +24,8 @@
 #  include "config.h"
 #endif
 
+#include <iostream>
+
 #include "dColVector.h"
 #include "dMatrix.h"
 #include "dSparse.h"
--- a/libinterp/dldfcn/audioread.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/dldfcn/audioread.cc	Mon Jul 02 15:48:14 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/config-module.awk	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/dldfcn/config-module.awk	Mon Jul 02 15:48:14 2018 +0200
@@ -82,8 +82,10 @@
             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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/dldfcn/convhulln.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -33,7 +33,6 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
 #include <limits>
 #include <string>
 
--- a/libinterp/dldfcn/gzip.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/dldfcn/gzip.cc	Mon Jul 02 15:48:14 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/mk-version-h.in.sh	Mon Jul 02 15:47:19 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/module.mk	Mon Jul 02 15:48:14 2018 +0200
@@ -28,6 +28,8 @@
 
 octlib_LTLIBRARIES += %reldir%/liboctinterp.la
 
+%canon_reldir%_pkgconfig_DATA = %reldir%/octinterp.pc
+
 BUILT_SOURCES += \
   %reldir%/builtin-defun-decls.h \
   %reldir%/corefcn/default-defs.h \
@@ -37,8 +39,7 @@
   %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 \
@@ -75,8 +76,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 +86,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 +107,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 +124,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 +134,6 @@
 
 %canon_reldir%_liboctinterp_la_SOURCES = \
   %reldir%/octave.cc \
-  %reldir%/version.cc \
   $(LIBINTERP_OPERATORS_SRC) \
   $(TEMPLATE_INST_SRC)
 
@@ -155,8 +147,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 \
@@ -243,9 +234,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 +319,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 +331,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/ov-base-diag.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-base-diag.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-base-diag.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-base-int.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-base-mat.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-base-scalar.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-base-sparse.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-base.cc	Mon Jul 02 15:48:14 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"
@@ -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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-bool-mat.cc	Mon Jul 02 15:48:14 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-sparse.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-bool-sparse.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -25,8 +25,8 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
-#include <limits>
+#include <istream>
+#include <ostream>
 #include <vector>
 
 #include "dim-vector.h"
--- a/libinterp/octave-value/ov-bool.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-bool.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-cell.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -25,8 +25,8 @@
 #  include "config.h"
 #endif
 
-#include <iomanip>
-#include <iostream>
+#include <istream>
+#include <ostream>
 #include <sstream>
 #include <vector>
 #include <queue>
--- a/libinterp/octave-value/ov-ch-mat.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-ch-mat.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-class.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-classdef.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-classdef.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-colon.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-complex.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-cs-list.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-cx-mat.cc	Mon Jul 02 15:48:14 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-cx-sparse.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-cx-sparse.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -25,8 +25,8 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
-#include <limits>
+#include <istream>
+#include <ostream>
 #include <vector>
 
 #include "lo-specfun.h"
--- a/libinterp/octave-value/ov-fcn-handle.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-fcn-handle.cc	Mon Jul 02 15:48:14 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));
     }
@@ -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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-fcn-handle.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-fcn-inline.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -29,7 +29,7 @@
 #endif
 
 #include <istream>
-#include <iostream>
+#include <ostream>
 #include <sstream>
 #include <vector>
 
--- a/libinterp/octave-value/ov-float.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-float.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-flt-complex.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-flt-cx-mat.cc	Mon Jul 02 15:48:14 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-flt-re-mat.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-flt-re-mat.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -25,8 +25,9 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <istream>
 #include <limits>
+#include <ostream>
 #include <vector>
 
 #include "dNDArray.h"
--- a/libinterp/octave-value/ov-int16.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-int16.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-int32.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-int64.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-int8.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-java.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -34,9 +34,9 @@
 #endif
 
 #include <algorithm>
-#include <map>
+#include <fstream>
 #include <iostream>
-#include <fstream>
+#include <map>
 #include <string>
 #include <vector>
 
@@ -1431,7 +1431,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 +1921,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 +2067,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 +2142,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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-range.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -24,7 +24,9 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <istream>
+#include <ostream>
+#include <sstream>
 
 #include "dNDArray.h"
 #include "fNDArray.h"
--- a/libinterp/octave-value/ov-re-mat.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-re-mat.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -25,8 +25,9 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <istream>
 #include <limits>
+#include <ostream>
 #include <vector>
 
 #include "dNDArray.h"
--- a/libinterp/octave-value/ov-re-sparse.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-re-sparse.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -25,8 +25,9 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <istream>
 #include <limits>
+#include <ostream>
 #include <vector>
 
 #include "lo-specfun.h"
--- a/libinterp/octave-value/ov-scalar.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-scalar.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-str-mat.cc	Mon Jul 02 15:48:14 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"
 
 
--- a/libinterp/octave-value/ov-struct.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-struct.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -24,7 +24,8 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <istream>
+#include <ostream>
 
 #include "Cell.h"
 #include "builtin-defun-decls.h"
@@ -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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-typeinfo.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-uint16.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-uint32.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-uint64.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-uint8.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-usr-fcn.cc	Mon Jul 02 15:48:14 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
@@ -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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave-value/ov-usr-fcn.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/octave.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:48:14 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/parse-tree/bp-table.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/parse-tree/bp-table.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/parse-tree/bp-table.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/parse-tree/comment-list.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/parse-tree/jit-ir.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/parse-tree/jit-typeinfo.cc	Mon Jul 02 15:48:14 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;
@@ -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/lex.h	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/parse-tree/lex.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/parse-tree/lex.ll	Mon Jul 02 15:48:14 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]
@@ -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);
@@ -3407,10 +3362,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 +3578,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 +3586,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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/parse-tree/module.mk	Mon Jul 02 15:48:14 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 \
--- a/libinterp/parse-tree/oct-parse.in.yy	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/parse-tree/oct-parse.in.yy	Mon Jul 02 15:48:14 2018 +0200
@@ -55,7 +55,6 @@
 #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"
@@ -65,6 +64,7 @@
 #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"
@@ -2227,83 +2227,80 @@
     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
-{
+
+  // 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)
   {
@@ -4475,131 +4472,127 @@
 
     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)
+
+  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);
 
-              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
-{
+                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)
@@ -5083,13 +5076,16 @@
 @deftypefnx {} {} mfilename ("fullpathext")
 Return the name of the currently executing file.
 
-When called from outside an m-file return the empty string.
+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;
@@ -5125,7 +5121,7 @@
       size_t dpos = fname.rfind (octave::sys::file_ops::dir_sep_char ());
       size_t epos = fname.rfind ('.');
 
-      if (epos <= dpos)
+      if (epos <= dpos+1)
         epos = std::string::npos;
 
       fname = (epos != std::string::npos) ? fname.substr (0, epos) : fname;
@@ -5249,16 +5245,13 @@
 
     return ovl ();
   }
-}
-
-static octave_value_list
-get_feval_args (const octave_value_list& args)
-{
-  return args.slice (1, args.length () - 1, true);
-}
-
-namespace octave
-{
+
+  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.
   //!
@@ -5387,7 +5380,7 @@
   {
     octave_value_list retval;
 
-    parser parser (eval_str);
+    parser parser (eval_str, __get_interpreter__ ("eval_string"));
 
     do
       {
@@ -5416,9 +5409,9 @@
 
                     if (expr->is_identifier ())
                       {
-                        octave::symbol_scope scope = tw.get_current_scope ();
-
-                        octave::symbol_record::context_id context
+                        symbol_scope scope = tw.get_current_scope ();
+
+                        symbol_record::context_id context
                           = scope.current_context ();
 
                         tree_identifier *id
@@ -5442,9 +5435,7 @@
                 else
                   error ("eval: invalid use of statement list");
 
-                if (tree_return_command::returning
-                    || tree_break_command::breaking
-                    || tree_continue_command::continuing)
+                if (tw.returning () || tw.breaking () || tw.continuing ())
                   break;
               }
             else if (parser.m_lexer.m_end_of_input)
@@ -5975,8 +5966,8 @@
     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__");
+    = octave::parse_fcn_file (full_file, file, dir_name, "", "", true, false,
+                              false, false, "__parse_file__");
 
   return retval;
 }
--- a/libinterp/parse-tree/parse.h	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/parse-tree/parse.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/parse-tree/profiler.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/parse-tree/pt-arg-list.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/parse-tree/pt-arg-list.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/parse-tree/pt-array-list.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/parse-tree/pt-assign.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -24,7 +24,6 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
 #include <string>
 
 #include "error.h"
--- a/libinterp/parse-tree/pt-bp.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/parse-tree/pt-bp.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/parse-tree/pt-bp.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/parse-tree/pt-cbinop.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/parse-tree/pt-cell.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/parse-tree/pt-check.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/parse-tree/pt-classdef.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/parse-tree/pt-const.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/parse-tree/pt-decl.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/parse-tree/pt-eval.cc	Mon Jul 02 15:48:14 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;
   }
@@ -3064,22 +3365,15 @@
   {
     // 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 +3566,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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/parse-tree/pt-eval.h	Mon Jul 02 15:48:14 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;
@@ -481,8 +556,15 @@
 
     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 +573,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 +600,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 +624,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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/parse-tree/pt-exp.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/parse-tree/pt-exp.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/parse-tree/pt-fcn-handle.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/parse-tree/pt-id.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/parse-tree/pt-id.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/parse-tree/pt-idx.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/parse-tree/pt-idx.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/parse-tree/pt-jit.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/parse-tree/pt-jump.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/parse-tree/pt-mat.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/parse-tree/pt-misc.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/parse-tree/pt-pr-code.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/parse-tree/pt-select.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/parse-tree/pt-stmt.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/parse-tree/pt-tm-const.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/parse-tree/pt-tm-const.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/parse-tree/pt-unop.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/libinterp/parse-tree/pt.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -24,7 +24,6 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
 #include <sstream>
 #include <string>
 
--- a/libinterp/version.cc	Mon Jul 02 15:47:19 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	Mon Jul 02 15:47:19 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/array/Array.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/array/CColVector.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/array/CDiagMatrix.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -25,7 +25,7 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <ostream>
 
 #include "Array-util.h"
 #include "lo-error.h"
--- a/liboctave/array/CMatrix.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/array/CMatrix.cc	Mon Jul 02 15:48:14 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"
@@ -3819,7 +3820,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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/array/CNDArray.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -26,7 +26,8 @@
 #endif
 
 #include <complex>
-#include <iostream>
+#include <istream>
+#include <ostream>
 
 #include "Array-util.h"
 #include "CNDArray.h"
--- a/liboctave/array/CRowVector.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/array/CRowVector.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/array/CSparse.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -27,7 +27,8 @@
 #endif
 
 #include <complex>
-#include <iostream>
+#include <istream>
+#include <ostream>
 
 #include "quit.h"
 #include "lo-ieee.h"
--- a/liboctave/array/DiagArray2.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/array/DiagArray2.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -27,8 +27,6 @@
 
 #include <cassert>
 
-#include <iostream>
-
 #include <algorithm>
 
 #include "DiagArray2.h"
--- a/liboctave/array/MArray.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/array/MArray.cc	Mon Jul 02 15:48:14 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/Range.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/array/Range.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/array/Sparse.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/array/boolMatrix.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/array/boolSparse.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -26,7 +26,8 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <istream>
+#include <ostream>
 #include <vector>
 
 #include "quit.h"
--- a/liboctave/array/chMatrix.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/array/chMatrix.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -27,7 +27,7 @@
 
 #include <cstring>
 
-#include <iostream>
+#include <ostream>
 #include <string>
 
 #include "lo-error.h"
--- a/liboctave/array/dColVector.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/array/dColVector.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/array/dDiagMatrix.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -25,7 +25,7 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <ostream>
 
 #include "Array-util.h"
 #include "lo-error.h"
--- a/liboctave/array/dMatrix.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/array/dMatrix.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -27,8 +27,9 @@
 #endif
 
 #include <algorithm>
-#include <iostream>
+#include <istream>
 #include <limits>
+#include <ostream>
 
 #include "Array-util.h"
 #include "CColVector.h"
@@ -3210,7 +3211,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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/array/dNDArray.cc	Mon Jul 02 15:48:14 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"
--- a/liboctave/array/dRowVector.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/array/dRowVector.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/array/dSparse.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -26,7 +26,8 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <istream>
+#include <ostream>
 
 #include "quit.h"
 #include "lo-ieee.h"
--- a/liboctave/array/fCColVector.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/array/fCColVector.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/array/fCDiagMatrix.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -25,7 +25,7 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <ostream>
 
 #include "Array-util.h"
 #include "lo-error.h"
--- a/liboctave/array/fCMatrix.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/array/fCMatrix.cc	Mon Jul 02 15:48:14 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"
@@ -3848,7 +3849,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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/array/fCNDArray.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -26,7 +26,8 @@
 #endif
 
 #include <complex>
-#include <iostream>
+#include <istream>
+#include <ostream>
 
 #include "Array-util.h"
 #include "f77-fcn.h"
--- a/liboctave/array/fCRowVector.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/array/fCRowVector.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/array/fColVector.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/array/fDiagMatrix.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -25,7 +25,7 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <ostream>
 
 #include "Array-util.h"
 #include "lo-error.h"
--- a/liboctave/array/fMatrix.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/array/fMatrix.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -27,8 +27,9 @@
 #endif
 
 #include <algorithm>
-#include <iostream>
+#include <istream>
 #include <limits>
+#include <ostream>
 
 #include "Array-util.h"
 #include "DET.h"
@@ -3215,7 +3216,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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/array/fNDArray.cc	Mon Jul 02 15:48:14 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"
--- a/liboctave/array/fRowVector.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/array/fRowVector.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/array/idx-vector.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -28,7 +28,7 @@
 
 #include <cstdlib>
 
-#include <iostream>
+#include <ostream>
 
 #include "idx-vector.h"
 #include "Array.h"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/liboctave/mk-version-h.in.sh	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/module.mk	Mon Jul 02 15:48:14 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 =
@@ -23,16 +29,20 @@
 
 octlib_LTLIBRARIES += %reldir%/liboctave.la
 
+%canon_reldir%_pkgconfig_DATA = %reldir%/octave.pc
+
 BUILT_INCS = \
   $(BUILT_LIBOCTAVE_OPERATORS_INC) \
   $(LIBOCTAVE_OPT_INC)
 
 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 +55,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,7 +78,9 @@
 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 \
@@ -104,6 +118,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 +129,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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/numeric/CollocWt.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/numeric/eigs-base.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -25,7 +25,8 @@
 #endif
 
 #include <cmath>
-#include <iostream>
+
+#include <ostream>
 
 #include "Array.h"
 #include "CSparse.h"
@@ -641,10 +642,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 +934,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");
@@ -1221,10 +1222,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 (n != resid.numel ())
     (*current_liboctave_error_handler) ("eigs: opts.v0 must be n-by-1");
@@ -1485,10 +1486,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 +1841,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");
@@ -2199,10 +2200,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 (n != resid.numel ())
     (*current_liboctave_error_handler) ("eigs: opts.v0 must be n-by-1");
@@ -2527,14 +2528,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 +2832,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");
@@ -3139,14 +3140,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 (n != cresid.numel ())
     (*current_liboctave_error_handler) ("eigs: opts.v0 must be n-by-1");
--- a/liboctave/numeric/lo-mappers.h	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/numeric/lo-mappers.h	Mon Jul 02 15:48:14 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.h	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/numeric/lo-specfun.h	Mon Jul 02 15:48:14 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/oct-rand.cc	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/numeric/oct-rand.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/numeric/oct-rand.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/numeric/randgamma.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/numeric/randgamma.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/numeric/randmtzig.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/numeric/randmtzig.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/numeric/randpoisson.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/numeric/randpoisson.h	Mon Jul 02 15:48:14 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.h	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/numeric/sparse-chol.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/numeric/sparse-qr.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:48:14 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/system/dir-ops.h	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/system/dir-ops.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/system/file-ops.cc	Mon Jul 02 15:48:14 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"
@@ -549,12 +549,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 +593,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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/system/file-ops.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/system/file-stat.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/system/lo-sysdep.cc	Mon Jul 02 15:48:14 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,197 @@
 
       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;
+    }
+
+    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).
+      const wchar_t *w_orig_file_name = u8_to_wstring (orig_file_name).c_str ();
+      // get short filename (8.3) from UTF-16 filename
+      long length = GetShortPathNameW (w_orig_file_name, NULL, 0);
+
+      // Dynamically allocate the correct size 
+      // (terminating null char was included in length)
+      wchar_t *w_short_file_name = new wchar_t[length];
+      length = GetShortPathNameW (w_orig_file_name, w_short_file_name, length);
+ 
+      std::string short_file_name = u8_from_wstring (std::wstring (w_short_file_name));
+
+      if (short_file_name.compare (orig_file_name) != 0)
+        return short_file_name;
+
+      // 3. Create hard link with only-ASCII characters
+      // Get longest possible part of path that only contains ASCII chars.
+      size_t pos = (std::string (orig_file_name.begin (), first_non_ASCII)).
+                        find_last_of (octave::sys::file_ops::dir_sep_chars ());
+      std::string par_dir = orig_file_name.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 _filename_hash_ = canonicalize_file_name (filename_hash);
+      if (! _filename_hash_.empty ())
+        return _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, NULL))
+        return filename_hash;
+
+      return orig_file_name;
+
+#else
+      return orig_file_name;
+#endif
+    }
+
   }
 }
--- a/liboctave/system/lo-sysdep.h	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/system/lo-sysdep.h	Mon Jul 02 15:48:14 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/oct-env.h	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/system/oct-env.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/system/oct-group.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/system/oct-passwd.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/system/oct-syscalls.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/system/oct-time.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/system/oct-time.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/system/oct-uname.h	Mon Jul 02 15:48:14 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/caseless-str.h	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/util/caseless-str.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/util/cmd-edit.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/util/cmd-edit.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/util/cmd-hist.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -27,7 +27,6 @@
 #include <cstring>
 
 #include <fstream>
-#include <iostream>
 #include <sstream>
 #include <string>
 
--- a/liboctave/util/cmd-hist.h	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/util/cmd-hist.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/util/data-conv.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/util/data-conv.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/util/file-info.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -27,7 +27,6 @@
 
 #include <deque>
 #include <fstream>
-#include <iostream>
 
 #include "file-info.h"
 #include "file-stat.h"
--- a/liboctave/util/lo-array-errwarn.h	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/util/lo-array-errwarn.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 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	Mon Jul 02 15:47:19 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/util/lo-regexp.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/util/lo-regexp.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/util/lo-utils.cc	Mon Jul 02 15:48:14 2018 +0200
@@ -28,7 +28,9 @@
 #include <cstring>
 
 #include <complex>
+#include <istream>
 #include <limits>
+#include <ostream>
 #include <string>
 
 #include "quit.h"
--- a/liboctave/util/lo-utils.h	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/util/lo-utils.h	Mon Jul 02 15:48:14 2018 +0200
@@ -27,7 +27,7 @@
 
 #include <cstdio>
 
-#include <iostream>
+#include <iosfwd>
 #include <string>
 
 #include "lo-cutils.h"
--- a/liboctave/util/module.mk	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/util/module.mk	Mon Jul 02 15:48:14 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 \
@@ -71,7 +70,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 \
--- a/liboctave/util/oct-glob.h	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/util/oct-glob.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/util/oct-inttypes.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/util/oct-shlib.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/util/oct-shlib.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/util/oct-sort.cc	Mon Jul 02 15:48:14 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/pathsearch.h	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/util/pathsearch.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/util/quit.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/util/quit.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/util/str-vec.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/util/unwind-prot.h	Mon Jul 02 15:48:14 2018 +0200
@@ -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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/util/url-transfer.cc	Mon Jul 02 15:48:14 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,59 @@
 
         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::ifstream ifile (realfile.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;
--- a/liboctave/util/url-transfer.h	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/util/url-transfer.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:48:14 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	Mon Jul 02 15:48:14 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	Mon Jul 02 15:48:14 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	Mon Jul 02 15:48:14 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	Mon Jul 02 15:48:14 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	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/wrappers/module.mk	Mon Jul 02 15:48:14 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 \
--- a/liboctave/wrappers/stat-wrappers.c	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/wrappers/stat-wrappers.c	Mon Jul 02 15:48:14 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	Mon Jul 02 15:48:14 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	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/wrappers/uniconv-wrappers.c	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/wrappers/uniconv-wrappers.h	Mon Jul 02 15:48:14 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	Mon Jul 02 15:48:14 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	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/liboctave/wrappers/unistd-wrappers.c	Mon Jul 02 15:48:14 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/liboctave/wrappers/unistr-wrappers.c	Mon Jul 02 15:48:14 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	Mon Jul 02 15:48:14 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/pkg.m4	Mon Jul 02 15:47:19 2018 +0200
+++ b/m4/pkg.m4	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 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/mahalanobis.m	Mon Jul 02 15:47:19 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	Mon Jul 02 15:47:19 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/scripts/deprecated/module.mk	Mon Jul 02 15:48:14 2018 +0200
@@ -1,24 +1,15 @@
 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%/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	Mon Jul 02 15:47:19 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	Mon Jul 02 15:47:19 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/sleep.m	Mon Jul 02 15:47:19 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/usleep.m	Mon Jul 02 15:47:19 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	Mon Jul 02 15:47:19 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	Mon Jul 02 15:47:19 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/scripts/general/bitset.m	Mon Jul 02 15:48:14 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/logspace.m	Mon Jul 02 15:47:19 2018 +0200
+++ b/scripts/general/logspace.m	Mon Jul 02 15:48:14 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/nextpow2.m	Mon Jul 02 15:47:19 2018 +0200
+++ b/scripts/general/nextpow2.m	Mon Jul 02 15:48:14 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/geometry/delaunayn.m	Mon Jul 02 15:47:19 2018 +0200
+++ b/scripts/geometry/delaunayn.m	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/scripts/gui/uibuttongroup.m	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/scripts/gui/uicontrol.m	Mon Jul 02 15:48:14 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/linear-algebra/condest.m	Mon Jul 02 15:47:19 2018 +0200
+++ b/scripts/linear-algebra/condest.m	Mon Jul 02 15:48:14 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/ishermitian.m	Mon Jul 02 15:47:19 2018 +0200
+++ b/scripts/linear-algebra/ishermitian.m	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/scripts/linear-algebra/issymmetric.m	Mon Jul 02 15:48:14 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/miscellaneous/open.m	Mon Jul 02 15:47:19 2018 +0200
+++ b/scripts/miscellaneous/open.m	Mon Jul 02 15:48:14 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/optimization/fzero.m	Mon Jul 02 15:47:19 2018 +0200
+++ b/scripts/optimization/fzero.m	Mon Jul 02 15:48:14 2018 +0200
@@ -154,8 +154,8 @@
     ## For very small values, switch to absolute rather than relative search
     ifelse (abs (a) < .001, aa = sign (a) * 0.1, aa = a);
     ## Search in an ever-widening range around the initial point.
-    for srch = [-.01 +.025 -.05 +.10 -.25 +.50 -1 +2.5 -5 +10 -50 +100 -500 +1000] 
-      b = aa + aa*srch; 
+    for srch = [-.01 +.025 -.05 +.10 -.25 +.50 -1 +2.5 -5 +10 -50 +100 -500 +1000]
+      b = aa + aa*srch;
       fb = fun (b);
       nfev += 1;
       if (sign (fa) * sign (fb) <= 0)
--- a/scripts/pkg/pkg.m	Mon Jul 02 15:47:19 2018 +0200
+++ b/scripts/pkg/pkg.m	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/scripts/pkg/private/install.m	Mon Jul 02 15:48:14 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/draw/light.m	Mon Jul 02 15:47:19 2018 +0200
+++ b/scripts/plot/draw/light.m	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/scripts/plot/draw/patch.m	Mon Jul 02 15:48:14 2018 +0200
@@ -89,7 +89,7 @@
     print_usage ();
   endif
 
-  ## FIXME: ishold called this way is very slow. 
+  ## FIXME: ishold called this way is very slow.
   if (! ishold (hax))
     ## FIXME: This is a hack to get 'layer' command to work for 2D patches
     ##        Alternative is much more complicated surgery in graphics.cc.
@@ -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	Mon Jul 02 15:47:19 2018 +0200
+++ b/scripts/plot/draw/pie.m	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/scripts/plot/draw/pie3.m	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/scripts/plot/draw/private/__pie__.m	Mon Jul 02 15:48:14 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/draw/surface.m	Mon Jul 02 15:47:19 2018 +0200
+++ b/scripts/plot/draw/surface.m	Mon Jul 02 15:48:14 2018 +0200
@@ -189,7 +189,7 @@
   h = __go_surface__ (ax, "xdata", x, "ydata", y, "zdata", z, "cdata", c,
                       other_args{:});
 
-  ## FIXME: ishold called this way is very slow. 
+  ## FIXME: ishold called this way is very slow.
   if (! ishold (ax))
     set (ax, "view", [0, 90]);
   endif
--- a/scripts/plot/util/__gnuplot_drawnow__.m	Mon Jul 02 15:47:19 2018 +0200
+++ b/scripts/plot/util/__gnuplot_drawnow__.m	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/scripts/plot/util/hdl2struct.m	Mon Jul 02 15:48:14 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/private/__gnuplot_draw_axes__.m	Mon Jul 02 15:47:19 2018 +0200
+++ b/scripts/plot/util/private/__gnuplot_draw_axes__.m	Mon Jul 02 15:48:14 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/struct2hdl.m	Mon Jul 02 15:47:19 2018 +0200
+++ b/scripts/plot/util/struct2hdl.m	Mon Jul 02 15:48:14 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/sparse/nonzeros.m	Mon Jul 02 15:47:19 2018 +0200
+++ b/scripts/sparse/nonzeros.m	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/scripts/sparse/pcg.m	Mon Jul 02 15:48:14 2018 +0200
@@ -572,7 +572,7 @@
 %! [x, flag, relres, iter, resvec, eigest] = pcg (A, b, [], [], A, [], b);
 %! assert (flag, 0);
 %! assert (norm (b - A*x) / norm (b), 0, 1e-6);
-%! 
+%!
 %! assert (isnan (eigest), isnan ([NaN, NaN]));
 
 %!test
--- a/scripts/specfun/factor.m	Mon Jul 02 15:47:19 2018 +0200
+++ b/scripts/specfun/factor.m	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/scripts/specfun/primes.m	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/scripts/special-matrix/magic.m	Mon Jul 02 15:48:14 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/strings/base2dec.m	Mon Jul 02 15:47:19 2018 +0200
+++ b/scripts/strings/base2dec.m	Mon Jul 02 15:48:14 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/testfun/speed.m	Mon Jul 02 15:47:19 2018 +0200
+++ b/scripts/testfun/speed.m	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/scripts/testfun/test.m	Mon Jul 02 15:48:14 2018 +0200
@@ -293,6 +293,15 @@
     disp ([__signal_file, __file]);
   endif
 
+  ## Track file descriptor leaks
+  __fid_list_orig = fopen ("all");
+
+  ## Track variable leaks
+  __base_variables_orig = evalin ("base", "who");
+
+  ## Track variable leaks
+  __global_variables_orig = who ("global");
+
   ## Assume all tests will pass.
   __all_success = true;
 
@@ -729,9 +738,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	Mon Jul 02 15:47:19 2018 +0200
+++ b/src/main-cli.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/src/main-gui.cc	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/src/mkoctfile.in.cc	Mon Jul 02 15:48:14 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);
@@ -162,7 +180,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"]);
@@ -451,6 +477,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 +568,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 +672,8 @@
         }
       else if (arg == "-o" || arg == "-output" || arg == "--output")
         {
+          output_file_option = true;
+
           if (i < argc-1)
             {
               arg = argv[++i];
@@ -606,7 +707,7 @@
         }
       else if (arg == "-c" || arg == "-compile" || arg == "--compile")
         {
-          link = false;
+          compile_only = true;
         }
       else if (arg == "-g")
         {
@@ -666,6 +767,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 +786,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 +875,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 +916,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 +956,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 +992,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/test/deprecate-props.tst	Mon Jul 02 15:47:19 2018 +0200
+++ b/test/deprecate-props.tst	Mon Jul 02 15:48:14 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");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/mex/bug-51725.tst	Mon Jul 02 15:48:14 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	Mon Jul 02 15:48:14 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	Mon Jul 02 15:48:14 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	Mon Jul 02 15:48:14 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	Mon Jul 02 15:48:14 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	Mon Jul 02 15:47:19 2018 +0200
+++ b/test/module.mk	Mon Jul 02 15:48:14 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	Mon Jul 02 15:48:14 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	Mon Jul 02 15:48:14 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	Mon Jul 02 15:48:14 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	Mon Jul 02 15:48:14 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	Mon Jul 02 15:48:14 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	Mon Jul 02 15:48:14 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	Mon Jul 02 15:48:14 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	Mon Jul 02 15:48:14 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	Mon Jul 02 15:48:14 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	Mon Jul 02 15:48:14 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	Mon Jul 02 15:48:14 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	Mon Jul 02 15:48:14 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
+############################################################